toolbar-items.tsx 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  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. import { useEditorPropertiesContext } from '@/features/ide-react/context/editor-properties-context'
  19. import { usePermissionsContext } from '@/features/ide-react/context/permissions-context'
  20. export const ToolbarItems: FC<{
  21. state: EditorState
  22. overflowed?: Set<string>
  23. languageName?: string
  24. visual: boolean
  25. listDepth: number
  26. }> = memo(function ToolbarItems({
  27. state,
  28. overflowed,
  29. languageName,
  30. visual,
  31. listDepth,
  32. }) {
  33. const { t } = useTranslation()
  34. const { showSymbolPalette, toggleSymbolPalette } =
  35. useEditorPropertiesContext()
  36. const { writefullInstance } = useEditorContext()
  37. const { features } = useProjectContext()
  38. const permissions = usePermissionsContext()
  39. const isActive = withinFormattingCommand(state)
  40. const symbolPaletteAvailable = getMeta('ol-symbolPaletteAvailable')
  41. const showGroup = (group: string) => !overflowed || overflowed.has(group)
  42. const wfRebrandEnabled = isSplitTestEnabled('overleaf-assist-bundle')
  43. return (
  44. <>
  45. {showGroup('group-history') && (
  46. <div
  47. className="ol-cm-toolbar-button-group"
  48. aria-label={t('toolbar_undo_redo_actions')}
  49. >
  50. <ToolbarButton
  51. id="toolbar-undo"
  52. label={t('toolbar_undo')}
  53. command={undo}
  54. icon="undo"
  55. shortcut={isMac ? '⌘Z' : 'Ctrl+Z'}
  56. />
  57. <ToolbarButton
  58. id="toolbar-redo"
  59. label={t('toolbar_redo')}
  60. command={redo}
  61. icon="redo"
  62. shortcut={isMac ? '⇧⌘Z' : 'Ctrl+Y'}
  63. />
  64. </div>
  65. )}
  66. {languageName === 'latex' && (
  67. <>
  68. {showGroup('group-section') && (
  69. <div
  70. className="ol-cm-toolbar-button-group"
  71. data-overflow="group-section"
  72. aria-label={t('toolbar_text_formatting')}
  73. >
  74. <SectionHeadingDropdown />
  75. </div>
  76. )}
  77. {showGroup('group-format') && (
  78. <div
  79. className="ol-cm-toolbar-button-group"
  80. aria-label={t('toolbar_text_style')}
  81. >
  82. <ToolbarButton
  83. id="toolbar-format-bold"
  84. label={t('toolbar_format_bold')}
  85. command={commands.toggleBold}
  86. active={isActive('\\textbf')}
  87. icon="format_bold"
  88. shortcut={isMac ? '⌘B' : 'Ctrl+B'}
  89. />
  90. <ToolbarButton
  91. id="toolbar-format-italic"
  92. label={t('toolbar_format_italic')}
  93. command={commands.toggleItalic}
  94. active={isActive('\\textit')}
  95. icon="format_italic"
  96. shortcut={isMac ? '⌘I' : 'Ctrl+I'}
  97. />
  98. </div>
  99. )}
  100. {showGroup('group-math') && (
  101. <div
  102. className="ol-cm-toolbar-button-group"
  103. data-overflow="group-math"
  104. aria-label={t('toolbar_insert_math_and_symbols')}
  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. aria-label={t('toolbar_insert_misc')}
  125. >
  126. <ToolbarButton
  127. id="toolbar-href"
  128. label={t('toolbar_insert_link')}
  129. command={commands.wrapInHref}
  130. icon="add_link"
  131. />
  132. {features.trackChangesVisible && permissions.comment && (
  133. <ToolbarButton
  134. id="toolbar-add-comment"
  135. label={t('add_comment')}
  136. disabled={state.selection.main.empty}
  137. command={commands.addComment}
  138. icon="add_comment"
  139. />
  140. )}
  141. <ToolbarButton
  142. id="toolbar-ref"
  143. label={t('toolbar_insert_cross_reference')}
  144. command={commands.insertRef}
  145. icon="sell"
  146. />
  147. <ToolbarButton
  148. id="toolbar-cite"
  149. label={t('toolbar_insert_citation')}
  150. command={commands.insertCite}
  151. icon="book_5"
  152. />
  153. <InsertFigureDropdown />
  154. {wfRebrandEnabled && writefullInstance ? (
  155. <TableDropdown />
  156. ) : (
  157. <LegacyTableDropdown />
  158. )}
  159. </div>
  160. )}
  161. {showGroup('group-list') && (
  162. <div
  163. className="ol-cm-toolbar-button-group"
  164. data-overflow="group-list"
  165. aria-label={t('toolbar_list_indentation')}
  166. >
  167. <ToolbarButton
  168. id="toolbar-bullet-list"
  169. label={t('toolbar_bullet_list')}
  170. command={commands.toggleBulletList}
  171. icon="format_list_bulleted"
  172. />
  173. <ToolbarButton
  174. id="toolbar-numbered-list"
  175. label={t('toolbar_numbered_list')}
  176. command={commands.toggleNumberedList}
  177. icon="format_list_numbered"
  178. />
  179. <ToolbarButton
  180. id="toolbar-format-indent-decrease"
  181. label={t('toolbar_decrease_indent')}
  182. command={commands.indentDecrease}
  183. icon="format_indent_decrease"
  184. shortcut={visual ? (isMac ? '⌘[' : 'Ctrl+[') : undefined}
  185. disabled={listDepth < 2}
  186. />
  187. <ToolbarButton
  188. id="toolbar-format-indent-increase"
  189. label={t('toolbar_increase_indent')}
  190. command={commands.indentIncrease}
  191. icon="format_indent_increase"
  192. shortcut={visual ? (isMac ? '⌘]' : 'Ctrl+]') : undefined}
  193. disabled={listDepth < 1}
  194. />
  195. </div>
  196. )}
  197. </>
  198. )}
  199. </>
  200. )
  201. })