toolbar-items.tsx 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. import { FC, memo, useCallback } from 'react'
  2. import { EditorSelection, EditorState } from '@codemirror/state'
  3. import { EditorView } from '@codemirror/view'
  4. import { useEditorContext } from '../../../../shared/context/editor-context'
  5. import useScopeEventEmitter from '../../../../shared/hooks/use-scope-event-emitter'
  6. import { useLayoutContext } from '../../../../shared/context/layout-context'
  7. import { withinFormattingCommand } from '../../utils/tree-operations/ancestors'
  8. import { ToolbarButton } from './toolbar-button'
  9. import { redo, undo } from '@codemirror/commands'
  10. import * as commands from '../../extensions/toolbar/commands'
  11. import { SectionHeadingDropdown } from './section-heading-dropdown'
  12. import { canAddComment } from '../../extensions/toolbar/comments'
  13. import getMeta from '../../../../utils/meta'
  14. import { InsertFigureDropdown } from './insert-figure-dropdown'
  15. import { useTranslation } from 'react-i18next'
  16. import { MathDropdown } from './math-dropdown'
  17. const isMac = /Mac/.test(window.navigator?.platform)
  18. export const ToolbarItems: FC<{
  19. state: EditorState
  20. overflowed?: Set<string>
  21. languageName?: string
  22. visual: boolean
  23. listDepth: number
  24. }> = memo(function ToolbarItems({
  25. state,
  26. overflowed,
  27. languageName,
  28. visual,
  29. listDepth,
  30. }) {
  31. const { t } = useTranslation()
  32. const { toggleSymbolPalette, showSymbolPalette } = useEditorContext()
  33. const isActive = withinFormattingCommand(state)
  34. const addCommentEmitter = useScopeEventEmitter('comment:start_adding')
  35. const { setReviewPanelOpen } = useLayoutContext()
  36. const splitTestVariants = getMeta('ol-splitTestVariants', {})
  37. const addComment = useCallback(
  38. (view: EditorView) => {
  39. const range = view.state.selection.main
  40. if (range.empty) {
  41. const line = view.state.doc.lineAt(range.head)
  42. view.dispatch({
  43. selection: EditorSelection.range(line.from, line.to),
  44. })
  45. }
  46. setReviewPanelOpen(true)
  47. addCommentEmitter()
  48. },
  49. [addCommentEmitter, setReviewPanelOpen]
  50. )
  51. const showFigureModal = splitTestVariants['figure-modal'] === 'enabled'
  52. const symbolPaletteAvailable = getMeta('ol-symbolPaletteAvailable')
  53. const showGroup = (group: string) => !overflowed || overflowed.has(group)
  54. return (
  55. <>
  56. {showGroup('group-history') && (
  57. <div className="ol-cm-toolbar-button-group">
  58. <ToolbarButton
  59. id="toolbar-undo"
  60. label={t('toolbar_undo')}
  61. command={undo}
  62. icon="undo"
  63. shortcut={isMac ? '⌘Z' : 'Ctrl+Z'}
  64. />
  65. <ToolbarButton
  66. id="toolbar-redo"
  67. label={t('toolbar_redo')}
  68. command={redo}
  69. icon="repeat"
  70. shortcut={isMac ? '⇧⌘Z' : 'Ctrl+Y'}
  71. />
  72. </div>
  73. )}
  74. {languageName === 'latex' && (
  75. <>
  76. {showGroup('group-section') && (
  77. <div
  78. className="ol-cm-toolbar-button-group"
  79. data-overflow="group-section"
  80. >
  81. <SectionHeadingDropdown />
  82. </div>
  83. )}
  84. {showGroup('group-format') && (
  85. <div className="ol-cm-toolbar-button-group">
  86. <ToolbarButton
  87. id="toolbar-format-bold"
  88. label={t('toolbar_format_bold')}
  89. command={commands.toggleBold}
  90. active={isActive('\\textbf')}
  91. icon="bold"
  92. shortcut={isMac ? '⌘B' : 'Ctrl+B'}
  93. />
  94. <ToolbarButton
  95. id="toolbar-format-italic"
  96. label={t('toolbar_format_italic')}
  97. command={commands.toggleItalic}
  98. active={isActive('\\textit')}
  99. icon="italic"
  100. shortcut={isMac ? '⌘I' : 'Ctrl+I'}
  101. />
  102. </div>
  103. )}
  104. {showGroup('group-math') && (
  105. <div
  106. className="ol-cm-toolbar-button-group"
  107. data-overflow="group-math"
  108. >
  109. <MathDropdown />
  110. {symbolPaletteAvailable && (
  111. <ToolbarButton
  112. id="toolbar-toggle-symbol-palette"
  113. label={t('toolbar_toggle_symbol_palette')}
  114. active={showSymbolPalette}
  115. command={toggleSymbolPalette}
  116. icon="Ω"
  117. textIcon
  118. className="ol-cm-toolbar-button-math"
  119. />
  120. )}
  121. </div>
  122. )}
  123. {showGroup('group-misc') && (
  124. <div
  125. className="ol-cm-toolbar-button-group"
  126. data-overflow="group-misc"
  127. >
  128. <ToolbarButton
  129. id="toolbar-href"
  130. label={t('toolbar_insert_link')}
  131. command={commands.wrapInHref}
  132. icon="link"
  133. />
  134. <ToolbarButton
  135. id="toolbar-ref"
  136. label={t('toolbar_insert_cross_reference')}
  137. command={commands.insertRef}
  138. icon="tag"
  139. />
  140. <ToolbarButton
  141. id="toolbar-cite"
  142. label={t('toolbar_insert_citation')}
  143. command={commands.insertCite}
  144. icon="book"
  145. />
  146. <ToolbarButton
  147. id="toolbar-add-comment"
  148. label={t('toolbar_add_comment')}
  149. command={addComment}
  150. disabled={!canAddComment(state)}
  151. icon="comment"
  152. hidden // enable this if an alternative to the floating "Add Comment" button is needed
  153. />
  154. {showFigureModal ? (
  155. <InsertFigureDropdown />
  156. ) : (
  157. <ToolbarButton
  158. id="toolbar-figure"
  159. label={t('toolbar_insert_figure')}
  160. command={commands.insertFigure}
  161. icon="picture-o"
  162. />
  163. )}
  164. <ToolbarButton
  165. id="toolbar-table"
  166. label={t('toolbar_insert_table')}
  167. command={commands.insertTable}
  168. icon="table"
  169. hidden
  170. />
  171. </div>
  172. )}
  173. {showGroup('group-list') && (
  174. <div
  175. className="ol-cm-toolbar-button-group"
  176. data-overflow="group-list"
  177. >
  178. <ToolbarButton
  179. id="toolbar-bullet-list"
  180. label={t('toolbar_bullet_list')}
  181. command={commands.toggleBulletList}
  182. icon="list-ul"
  183. />
  184. <ToolbarButton
  185. id="toolbar-numbered-list"
  186. label={t('toolbar_numbered_list')}
  187. command={commands.toggleNumberedList}
  188. icon="list-ol"
  189. />
  190. <ToolbarButton
  191. id="toolbar-format-indent-decrease"
  192. label={t('toolbar_decrease_indent')}
  193. command={commands.indentDecrease}
  194. icon="outdent"
  195. shortcut={visual ? (isMac ? '⌘[' : 'Ctrl+[') : undefined}
  196. disabled={listDepth < 2}
  197. />
  198. <ToolbarButton
  199. id="toolbar-format-indent-increase"
  200. label={t('toolbar_increase_indent')}
  201. command={commands.indentIncrease}
  202. icon="indent"
  203. shortcut={visual ? (isMac ? '⌘]' : 'Ctrl+]') : undefined}
  204. disabled={listDepth < 1}
  205. />
  206. </div>
  207. )}
  208. </>
  209. )}
  210. </>
  211. )
  212. })