toolbar-items.tsx 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. import { FC, memo } from 'react'
  2. import { EditorState } from '@codemirror/state'
  3. import { useEditorContext } from '../../../../shared/context/editor-context'
  4. import { ToolbarButton } from './toolbar-button'
  5. import { redo, undo } from '@codemirror/commands'
  6. import * as commands from '../../extensions/toolbar/commands'
  7. import { SectionHeadingDropdown } from './section-heading-dropdown'
  8. import getMeta from '../../../../utils/meta'
  9. import { InsertFigureDropdown } from './insert-figure-dropdown'
  10. import { useTranslation } from 'react-i18next'
  11. import { MathDropdown } from './math-dropdown'
  12. import { TableInserterDropdown } from './table-inserter-dropdown'
  13. import { withinFormattingCommand } from '@/features/source-editor/utils/tree-operations/formatting'
  14. import { bsVersion } from '@/features/utils/bootstrap-5'
  15. import { isSplitTestEnabled } from '@/utils/splitTestUtils'
  16. import { isMac } from '@/shared/utils/os'
  17. export const ToolbarItems: FC<{
  18. state: EditorState
  19. overflowed?: Set<string>
  20. languageName?: string
  21. visual: boolean
  22. listDepth: number
  23. }> = memo(function ToolbarItems({
  24. state,
  25. overflowed,
  26. languageName,
  27. visual,
  28. listDepth,
  29. }) {
  30. const { t } = useTranslation()
  31. const { toggleSymbolPalette, showSymbolPalette } = useEditorContext()
  32. const isActive = withinFormattingCommand(state)
  33. const symbolPaletteAvailable = getMeta('ol-symbolPaletteAvailable')
  34. const showGroup = (group: string) => !overflowed || overflowed.has(group)
  35. return (
  36. <>
  37. {showGroup('group-history') && (
  38. <div
  39. className="ol-cm-toolbar-button-group"
  40. aria-label={t('toolbar_undo_redo_actions')}
  41. >
  42. <ToolbarButton
  43. id="toolbar-undo"
  44. label={t('toolbar_undo')}
  45. command={undo}
  46. icon={bsVersion({ bs5: 'undo', bs3: 'undo' })}
  47. shortcut={isMac ? '⌘Z' : 'Ctrl+Z'}
  48. />
  49. <ToolbarButton
  50. id="toolbar-redo"
  51. label={t('toolbar_redo')}
  52. command={redo}
  53. icon={bsVersion({ bs5: 'redo', bs3: 'repeat' })}
  54. shortcut={isMac ? '⇧⌘Z' : 'Ctrl+Y'}
  55. />
  56. </div>
  57. )}
  58. {languageName === 'latex' && (
  59. <>
  60. {showGroup('group-section') && (
  61. <div
  62. className="ol-cm-toolbar-button-group"
  63. data-overflow="group-section"
  64. aria-label={t('toolbar_text_formatting')}
  65. >
  66. <SectionHeadingDropdown />
  67. </div>
  68. )}
  69. {showGroup('group-format') && (
  70. <div
  71. className="ol-cm-toolbar-button-group"
  72. aria-label={t('toolbar_text_style')}
  73. >
  74. <ToolbarButton
  75. id="toolbar-format-bold"
  76. label={t('toolbar_format_bold')}
  77. command={commands.toggleBold}
  78. active={isActive('\\textbf')}
  79. icon={bsVersion({ bs5: 'format_bold', bs3: 'bold' })}
  80. shortcut={isMac ? '⌘B' : 'Ctrl+B'}
  81. />
  82. <ToolbarButton
  83. id="toolbar-format-italic"
  84. label={t('toolbar_format_italic')}
  85. command={commands.toggleItalic}
  86. active={isActive('\\textit')}
  87. icon={bsVersion({ bs5: 'format_italic', bs3: 'italic' })}
  88. shortcut={isMac ? '⌘I' : 'Ctrl+I'}
  89. />
  90. </div>
  91. )}
  92. {showGroup('group-math') && (
  93. <div
  94. className="ol-cm-toolbar-button-group"
  95. data-overflow="group-math"
  96. aria-label={t('toolbar_insert_math_and_symbols')}
  97. >
  98. <MathDropdown />
  99. {symbolPaletteAvailable && (
  100. <ToolbarButton
  101. id="toolbar-toggle-symbol-palette"
  102. label={t('toolbar_toggle_symbol_palette')}
  103. active={showSymbolPalette}
  104. command={toggleSymbolPalette}
  105. icon="Ω"
  106. textIcon
  107. className="ol-cm-toolbar-button-math"
  108. />
  109. )}
  110. </div>
  111. )}
  112. {showGroup('group-misc') && (
  113. <div
  114. className="ol-cm-toolbar-button-group"
  115. data-overflow="group-misc"
  116. aria-label={t('toolbar_insert_misc')}
  117. >
  118. <ToolbarButton
  119. id="toolbar-href"
  120. label={t('toolbar_insert_link')}
  121. command={commands.wrapInHref}
  122. icon={bsVersion({ bs5: 'add_link', bs3: 'link' })}
  123. />
  124. {isSplitTestEnabled('review-panel-redesign') && (
  125. <ToolbarButton
  126. id="toolbar-add-comment"
  127. label={t('add_comment')}
  128. disabled={state.selection.main.empty}
  129. command={commands.addComment}
  130. icon={bsVersion({ bs5: 'add_comment', bs3: 'comment' })}
  131. />
  132. )}
  133. <ToolbarButton
  134. id="toolbar-ref"
  135. label={t('toolbar_insert_cross_reference')}
  136. command={commands.insertRef}
  137. icon={bsVersion({ bs5: 'sell', bs3: 'tag' })}
  138. />
  139. <ToolbarButton
  140. id="toolbar-cite"
  141. label={t('toolbar_insert_citation')}
  142. command={commands.insertCite}
  143. icon={bsVersion({ bs5: 'book_5', bs3: 'book' })}
  144. />
  145. <InsertFigureDropdown />
  146. <TableInserterDropdown />
  147. </div>
  148. )}
  149. {showGroup('group-list') && (
  150. <div
  151. className="ol-cm-toolbar-button-group"
  152. data-overflow="group-list"
  153. aria-label={t('toolbar_list_indentation')}
  154. >
  155. <ToolbarButton
  156. id="toolbar-bullet-list"
  157. label={t('toolbar_bullet_list')}
  158. command={commands.toggleBulletList}
  159. icon={bsVersion({
  160. bs5: 'format_list_bulleted',
  161. bs3: 'list-ul',
  162. })}
  163. />
  164. <ToolbarButton
  165. id="toolbar-numbered-list"
  166. label={t('toolbar_numbered_list')}
  167. command={commands.toggleNumberedList}
  168. icon={bsVersion({
  169. bs5: 'format_list_numbered',
  170. bs3: 'list-ol',
  171. })}
  172. />
  173. <ToolbarButton
  174. id="toolbar-format-indent-decrease"
  175. label={t('toolbar_decrease_indent')}
  176. command={commands.indentDecrease}
  177. icon={bsVersion({
  178. bs5: 'format_indent_decrease',
  179. bs3: 'outdent',
  180. })}
  181. shortcut={visual ? (isMac ? '⌘[' : 'Ctrl+[') : undefined}
  182. disabled={listDepth < 2}
  183. />
  184. <ToolbarButton
  185. id="toolbar-format-indent-increase"
  186. label={t('toolbar_increase_indent')}
  187. command={commands.indentIncrease}
  188. icon={bsVersion({
  189. bs5: 'format_indent_increase',
  190. bs3: 'indent',
  191. })}
  192. shortcut={visual ? (isMac ? '⌘]' : 'Ctrl+]') : undefined}
  193. disabled={listDepth < 1}
  194. />
  195. </div>
  196. )}
  197. </>
  198. )}
  199. </>
  200. )
  201. })