toolbar-items.tsx 7.5 KB

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