toolbar-items.tsx 7.0 KB

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