@atlaskit/editor-plugin-table 7.16.11 → 7.16.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (254) hide show
  1. package/.eslintrc.js +3 -3
  2. package/CHANGELOG.md +16 -0
  3. package/dist/cjs/commands/misc.js +3 -3
  4. package/dist/cjs/nodeviews/TableCell.js +10 -10
  5. package/dist/cjs/nodeviews/TableContainer.js +83 -27
  6. package/dist/cjs/nodeviews/TableResizer.js +40 -19
  7. package/dist/cjs/nodeviews/TableRow.js +23 -23
  8. package/dist/cjs/pm-plugins/table-resizing/plugin.js +3 -3
  9. package/dist/cjs/pm-plugins/table-resizing/utils/resize-state.js +4 -4
  10. package/dist/cjs/pm-plugins/table-resizing/utils/scale-table.js +3 -3
  11. package/dist/cjs/ui/FloatingContextualMenu/styles.js +1 -1
  12. package/dist/cjs/ui/FloatingDragMenu/styles.js +1 -1
  13. package/dist/cjs/ui/common-styles.js +13 -13
  14. package/dist/cjs/ui/ui-styles.js +25 -25
  15. package/dist/cjs/utils/guidelines.js +7 -4
  16. package/dist/cjs/utils/merged-cells.js +3 -3
  17. package/dist/cjs/utils/snapping.js +7 -8
  18. package/dist/es2019/commands/misc.js +3 -3
  19. package/dist/es2019/nodeviews/TableContainer.js +70 -9
  20. package/dist/es2019/nodeviews/TableResizer.js +42 -21
  21. package/dist/es2019/nodeviews/TableRow.js +21 -21
  22. package/dist/es2019/pm-plugins/table-resizing/plugin.js +3 -3
  23. package/dist/es2019/pm-plugins/table-resizing/utils/resize-state.js +4 -4
  24. package/dist/es2019/pm-plugins/table-resizing/utils/scale-table.js +3 -3
  25. package/dist/es2019/ui/FloatingContextualMenu/styles.js +47 -47
  26. package/dist/es2019/ui/FloatingDragMenu/styles.js +30 -30
  27. package/dist/es2019/ui/common-styles.js +802 -816
  28. package/dist/es2019/ui/ui-styles.js +665 -678
  29. package/dist/es2019/utils/guidelines.js +5 -2
  30. package/dist/es2019/utils/merged-cells.js +3 -3
  31. package/dist/es2019/utils/snapping.js +5 -6
  32. package/dist/esm/commands/misc.js +3 -3
  33. package/dist/esm/nodeviews/TableCell.js +10 -10
  34. package/dist/esm/nodeviews/TableContainer.js +85 -29
  35. package/dist/esm/nodeviews/TableResizer.js +42 -21
  36. package/dist/esm/nodeviews/TableRow.js +23 -23
  37. package/dist/esm/pm-plugins/table-resizing/plugin.js +3 -3
  38. package/dist/esm/pm-plugins/table-resizing/utils/resize-state.js +4 -4
  39. package/dist/esm/pm-plugins/table-resizing/utils/scale-table.js +3 -3
  40. package/dist/esm/ui/FloatingContextualMenu/styles.js +1 -1
  41. package/dist/esm/ui/FloatingDragMenu/styles.js +1 -1
  42. package/dist/esm/ui/common-styles.js +13 -13
  43. package/dist/esm/ui/ui-styles.js +25 -25
  44. package/dist/esm/utils/guidelines.js +6 -3
  45. package/dist/esm/utils/merged-cells.js +3 -3
  46. package/dist/esm/utils/snapping.js +6 -7
  47. package/dist/types/nodeviews/TableResizer.d.ts +2 -1
  48. package/dist/types/pm-plugins/decorations/utils/index.d.ts +1 -1
  49. package/dist/types/pm-plugins/drag-and-drop/utils/autoscrollers.d.ts +1 -1
  50. package/dist/types/pm-plugins/drag-and-drop/utils/getDragBehaviour.d.ts +1 -1
  51. package/dist/types/pm-plugins/table-resizing/utils/index.d.ts +1 -1
  52. package/dist/types/ui/ColumnResizeWidget/index.d.ts +1 -1
  53. package/dist/types/ui/FloatingAlignmentButtons/FloatingAlignmentButtons.d.ts +1 -1
  54. package/dist/types/ui/FloatingToolbarLabel/FloatingToolbarLabel.d.ts +1 -1
  55. package/dist/types/ui/TableFloatingColumnControls/ColumnDropTargets/ColumnDropTarget.d.ts +1 -1
  56. package/dist/types/ui/TableFloatingControls/CornerControls/index.d.ts +1 -1
  57. package/dist/types/ui/icons/DragHandleDisabledIcon.d.ts +1 -1
  58. package/dist/types/utils/guidelines.d.ts +2 -1
  59. package/dist/types/utils/snapping.d.ts +3 -2
  60. package/dist/types-ts4.5/nodeviews/TableResizer.d.ts +2 -1
  61. package/dist/types-ts4.5/pm-plugins/decorations/utils/index.d.ts +1 -1
  62. package/dist/types-ts4.5/pm-plugins/drag-and-drop/utils/autoscrollers.d.ts +1 -1
  63. package/dist/types-ts4.5/pm-plugins/drag-and-drop/utils/getDragBehaviour.d.ts +1 -1
  64. package/dist/types-ts4.5/pm-plugins/table-resizing/utils/index.d.ts +1 -1
  65. package/dist/types-ts4.5/ui/ColumnResizeWidget/index.d.ts +1 -1
  66. package/dist/types-ts4.5/ui/FloatingAlignmentButtons/FloatingAlignmentButtons.d.ts +1 -1
  67. package/dist/types-ts4.5/ui/FloatingToolbarLabel/FloatingToolbarLabel.d.ts +1 -1
  68. package/dist/types-ts4.5/ui/TableFloatingColumnControls/ColumnDropTargets/ColumnDropTarget.d.ts +1 -1
  69. package/dist/types-ts4.5/ui/TableFloatingControls/CornerControls/index.d.ts +1 -1
  70. package/dist/types-ts4.5/ui/icons/DragHandleDisabledIcon.d.ts +1 -1
  71. package/dist/types-ts4.5/utils/guidelines.d.ts +2 -1
  72. package/dist/types-ts4.5/utils/snapping.d.ts +3 -2
  73. package/docs/0-intro.tsx +9 -7
  74. package/package.json +3 -3
  75. package/report.api.md +67 -66
  76. package/src/commands/clear.ts +36 -44
  77. package/src/commands/collapse.ts +8 -8
  78. package/src/commands/column-resize.ts +412 -452
  79. package/src/commands/delete.ts +14 -14
  80. package/src/commands/display-mode.ts +10 -11
  81. package/src/commands/go-to-next-cell.ts +48 -54
  82. package/src/commands/hover.ts +210 -227
  83. package/src/commands/index.ts +35 -35
  84. package/src/commands/insert.ts +208 -235
  85. package/src/commands/misc.ts +655 -748
  86. package/src/commands/referentiality.ts +9 -9
  87. package/src/commands/selection.ts +433 -563
  88. package/src/commands/sort.ts +68 -86
  89. package/src/commands/split-cell.ts +14 -14
  90. package/src/commands/toggle.ts +69 -67
  91. package/src/commands-with-analytics.ts +570 -639
  92. package/src/create-plugin-config.ts +13 -13
  93. package/src/event-handlers.ts +513 -612
  94. package/src/handlers.ts +120 -133
  95. package/src/nodeviews/ExternalDropTargets.tsx +68 -73
  96. package/src/nodeviews/OverflowShadowsObserver.ts +148 -157
  97. package/src/nodeviews/TableCell.ts +47 -54
  98. package/src/nodeviews/TableComponent.tsx +1018 -1112
  99. package/src/nodeviews/TableComponentWithSharedState.tsx +91 -94
  100. package/src/nodeviews/TableContainer.tsx +384 -340
  101. package/src/nodeviews/TableNodeViewBase.ts +19 -24
  102. package/src/nodeviews/TableResizer.tsx +642 -653
  103. package/src/nodeviews/TableRow.ts +580 -629
  104. package/src/nodeviews/TableStickyScrollbar.ts +173 -190
  105. package/src/nodeviews/__mocks__/OverflowShadowsObserver.ts +8 -8
  106. package/src/nodeviews/__mocks__/OverridableMock.ts +14 -15
  107. package/src/nodeviews/table.tsx +345 -375
  108. package/src/nodeviews/types.ts +21 -24
  109. package/src/nodeviews/update-overflow-shadows.ts +8 -14
  110. package/src/plugin.tsx +578 -603
  111. package/src/pm-plugins/analytics/actions.ts +10 -12
  112. package/src/pm-plugins/analytics/commands.ts +31 -37
  113. package/src/pm-plugins/analytics/plugin-factory.ts +4 -2
  114. package/src/pm-plugins/analytics/plugin-key.ts +1 -3
  115. package/src/pm-plugins/analytics/plugin.ts +60 -70
  116. package/src/pm-plugins/analytics/reducer.ts +19 -19
  117. package/src/pm-plugins/analytics/types.ts +10 -10
  118. package/src/pm-plugins/analytics/utils/moved-event.ts +38 -38
  119. package/src/pm-plugins/decorations/plugin.ts +58 -77
  120. package/src/pm-plugins/decorations/utils/column-controls.ts +59 -71
  121. package/src/pm-plugins/decorations/utils/column-resizing.ts +50 -57
  122. package/src/pm-plugins/decorations/utils/compose-decorations.ts +6 -6
  123. package/src/pm-plugins/decorations/utils/index.ts +3 -6
  124. package/src/pm-plugins/decorations/utils/types.ts +7 -12
  125. package/src/pm-plugins/default-table-selection.ts +3 -3
  126. package/src/pm-plugins/drag-and-drop/actions.ts +25 -25
  127. package/src/pm-plugins/drag-and-drop/commands-with-analytics.ts +158 -190
  128. package/src/pm-plugins/drag-and-drop/commands.ts +154 -170
  129. package/src/pm-plugins/drag-and-drop/consts.ts +4 -5
  130. package/src/pm-plugins/drag-and-drop/plugin-factory.ts +23 -20
  131. package/src/pm-plugins/drag-and-drop/plugin-key.ts +1 -3
  132. package/src/pm-plugins/drag-and-drop/plugin.ts +329 -383
  133. package/src/pm-plugins/drag-and-drop/reducer.ts +30 -30
  134. package/src/pm-plugins/drag-and-drop/types.ts +8 -8
  135. package/src/pm-plugins/drag-and-drop/utils/autoscrollers.ts +38 -41
  136. package/src/pm-plugins/drag-and-drop/utils/getDragBehaviour.ts +3 -6
  137. package/src/pm-plugins/drag-and-drop/utils/monitor.ts +57 -70
  138. package/src/pm-plugins/keymap.ts +208 -220
  139. package/src/pm-plugins/main.ts +348 -400
  140. package/src/pm-plugins/plugin-factory.ts +32 -34
  141. package/src/pm-plugins/safari-delete-composition-text-issue-workaround.ts +83 -97
  142. package/src/pm-plugins/sticky-headers/commands.ts +2 -6
  143. package/src/pm-plugins/sticky-headers/plugin-key.ts +1 -3
  144. package/src/pm-plugins/sticky-headers/plugin-state.ts +41 -44
  145. package/src/pm-plugins/sticky-headers/plugin.ts +4 -4
  146. package/src/pm-plugins/sticky-headers/types.ts +8 -8
  147. package/src/pm-plugins/sticky-headers/util.ts +10 -10
  148. package/src/pm-plugins/table-analytics.ts +70 -72
  149. package/src/pm-plugins/table-local-id.ts +180 -184
  150. package/src/pm-plugins/table-resizing/commands.ts +72 -85
  151. package/src/pm-plugins/table-resizing/event-handlers.ts +298 -317
  152. package/src/pm-plugins/table-resizing/plugin-factory.ts +10 -10
  153. package/src/pm-plugins/table-resizing/plugin-key.ts +1 -3
  154. package/src/pm-plugins/table-resizing/plugin.ts +61 -68
  155. package/src/pm-plugins/table-resizing/reducer.ts +30 -33
  156. package/src/pm-plugins/table-resizing/utils/colgroup.ts +84 -84
  157. package/src/pm-plugins/table-resizing/utils/column-state.ts +78 -81
  158. package/src/pm-plugins/table-resizing/utils/content-width.ts +94 -114
  159. package/src/pm-plugins/table-resizing/utils/dom.ts +93 -110
  160. package/src/pm-plugins/table-resizing/utils/index.ts +29 -34
  161. package/src/pm-plugins/table-resizing/utils/misc.ts +94 -119
  162. package/src/pm-plugins/table-resizing/utils/resize-column.ts +93 -106
  163. package/src/pm-plugins/table-resizing/utils/resize-logic.ts +240 -257
  164. package/src/pm-plugins/table-resizing/utils/resize-state.ts +343 -372
  165. package/src/pm-plugins/table-resizing/utils/scale-table.ts +202 -207
  166. package/src/pm-plugins/table-resizing/utils/types.ts +17 -17
  167. package/src/pm-plugins/table-resizing/utils/unit-to-number.ts +1 -2
  168. package/src/pm-plugins/table-selection-keymap.ts +25 -51
  169. package/src/pm-plugins/table-width.ts +191 -204
  170. package/src/pm-plugins/view-mode-sort/index.ts +223 -227
  171. package/src/pm-plugins/view-mode-sort/plugin-key.ts +3 -2
  172. package/src/pm-plugins/view-mode-sort/types.ts +12 -12
  173. package/src/pm-plugins/view-mode-sort/utils.ts +108 -117
  174. package/src/reducer.ts +139 -155
  175. package/src/toolbar.tsx +815 -905
  176. package/src/transforms/column-width.ts +186 -213
  177. package/src/transforms/delete-columns.ts +208 -222
  178. package/src/transforms/delete-rows.ts +117 -121
  179. package/src/transforms/fix-tables.ts +190 -215
  180. package/src/transforms/merge.ts +263 -269
  181. package/src/transforms/replace-table.ts +27 -43
  182. package/src/transforms/split.ts +65 -75
  183. package/src/types.ts +421 -427
  184. package/src/ui/ColumnResizeWidget/index.tsx +40 -47
  185. package/src/ui/DragHandle/HandleIconComponent.tsx +9 -13
  186. package/src/ui/DragHandle/index.tsx +221 -250
  187. package/src/ui/DragPreview/index.tsx +35 -35
  188. package/src/ui/FloatingAlignmentButtons/FloatingAlignmentButtons.tsx +33 -41
  189. package/src/ui/FloatingContextualButton/FixedButton.tsx +154 -157
  190. package/src/ui/FloatingContextualButton/index.tsx +109 -115
  191. package/src/ui/FloatingContextualButton/styles.ts +43 -46
  192. package/src/ui/FloatingContextualMenu/ContextualMenu.tsx +634 -694
  193. package/src/ui/FloatingContextualMenu/index.tsx +83 -101
  194. package/src/ui/FloatingContextualMenu/styles.ts +57 -65
  195. package/src/ui/FloatingDeleteButton/DeleteButton.tsx +37 -37
  196. package/src/ui/FloatingDeleteButton/getPopUpOptions.ts +47 -57
  197. package/src/ui/FloatingDeleteButton/index.tsx +319 -350
  198. package/src/ui/FloatingDragMenu/DragMenu.tsx +555 -596
  199. package/src/ui/FloatingDragMenu/DropdownMenu.tsx +152 -162
  200. package/src/ui/FloatingDragMenu/index.tsx +88 -102
  201. package/src/ui/FloatingDragMenu/styles.ts +51 -54
  202. package/src/ui/FloatingInsertButton/InsertButton.tsx +204 -217
  203. package/src/ui/FloatingInsertButton/getPopupOptions.ts +100 -115
  204. package/src/ui/FloatingInsertButton/index.tsx +248 -292
  205. package/src/ui/FloatingToolbarLabel/FloatingToolbarLabel.tsx +24 -29
  206. package/src/ui/TableFloatingColumnControls/ColumnControls/index.tsx +308 -329
  207. package/src/ui/TableFloatingColumnControls/ColumnDropTargets/ColumnDropTarget.tsx +85 -94
  208. package/src/ui/TableFloatingColumnControls/ColumnDropTargets/index.tsx +46 -46
  209. package/src/ui/TableFloatingColumnControls/index.tsx +116 -136
  210. package/src/ui/TableFloatingControls/CornerControls/ClassicCornerControls.tsx +79 -91
  211. package/src/ui/TableFloatingControls/CornerControls/DragCornerControls.tsx +95 -102
  212. package/src/ui/TableFloatingControls/CornerControls/index.tsx +1 -4
  213. package/src/ui/TableFloatingControls/CornerControls/types.ts +8 -8
  214. package/src/ui/TableFloatingControls/FloatingControlsWithSelection.tsx +50 -50
  215. package/src/ui/TableFloatingControls/NumberColumn/index.tsx +111 -124
  216. package/src/ui/TableFloatingControls/RowControls/ClassicControls.tsx +86 -105
  217. package/src/ui/TableFloatingControls/RowControls/DragControls.tsx +305 -341
  218. package/src/ui/TableFloatingControls/RowDropTarget/index.tsx +72 -75
  219. package/src/ui/TableFloatingControls/index.tsx +191 -193
  220. package/src/ui/TableFullWidthLabel/index.tsx +20 -20
  221. package/src/ui/common-styles.ts +880 -912
  222. package/src/ui/consts.ts +29 -74
  223. package/src/ui/icons/AddColLeftIcon.tsx +33 -39
  224. package/src/ui/icons/AddColRightIcon.tsx +33 -39
  225. package/src/ui/icons/AddRowAboveIcon.tsx +16 -22
  226. package/src/ui/icons/AddRowBelowIcon.tsx +33 -39
  227. package/src/ui/icons/DisplayModeIcon.tsx +31 -31
  228. package/src/ui/icons/DragHandleDisabledIcon.tsx +19 -21
  229. package/src/ui/icons/DragHandleIcon.tsx +12 -12
  230. package/src/ui/icons/DragInMotionIcon.tsx +45 -52
  231. package/src/ui/icons/MergeCellsIcon.tsx +22 -28
  232. package/src/ui/icons/MinimisedHandle.tsx +9 -9
  233. package/src/ui/icons/SplitCellIcon.tsx +30 -36
  234. package/src/ui/ui-styles.ts +769 -798
  235. package/src/utils/alignment.ts +1 -1
  236. package/src/utils/analytics.ts +192 -208
  237. package/src/utils/collapse.ts +55 -64
  238. package/src/utils/column-controls.ts +237 -254
  239. package/src/utils/create.ts +30 -30
  240. package/src/utils/decoration.ts +482 -502
  241. package/src/utils/dom.ts +127 -134
  242. package/src/utils/drag-menu.ts +322 -373
  243. package/src/utils/get-allow-add-column-custom-step.ts +4 -5
  244. package/src/utils/guidelines.ts +16 -21
  245. package/src/utils/index.ts +68 -68
  246. package/src/utils/merged-cells.ts +245 -254
  247. package/src/utils/nodes.ts +91 -106
  248. package/src/utils/paste.ts +119 -135
  249. package/src/utils/row-controls.ts +199 -213
  250. package/src/utils/selection.ts +77 -87
  251. package/src/utils/snapping.ts +87 -100
  252. package/src/utils/table.ts +44 -44
  253. package/src/utils/transforms.ts +5 -5
  254. package/src/utils/update-plugin-state-decorations.ts +5 -9
@@ -4,31 +4,24 @@
4
4
  import React, { useEffect, useState } from 'react';
5
5
 
6
6
  import { jsx } from '@emotion/react';
7
- import type {
8
- IntlShape,
9
- MessageDescriptor,
10
- WrappedComponentProps,
11
- } from 'react-intl-next';
7
+ import type { IntlShape, MessageDescriptor, WrappedComponentProps } from 'react-intl-next';
12
8
  import { injectIntl } from 'react-intl-next';
13
9
 
14
10
  import type { EditorAnalyticsAPI } from '@atlaskit/editor-common/analytics';
15
11
  import { INPUT_METHOD } from '@atlaskit/editor-common/analytics';
16
12
  import { tableMessages as messages } from '@atlaskit/editor-common/messages';
17
13
  import { DropdownMenuSharedCssClassName } from '@atlaskit/editor-common/styles';
18
- import type {
19
- Command,
20
- GetEditorContainerWidth,
21
- } from '@atlaskit/editor-common/types';
14
+ import type { Command, GetEditorContainerWidth } from '@atlaskit/editor-common/types';
22
15
  import { withOuterListeners } from '@atlaskit/editor-common/ui';
23
16
  import {
24
- backgroundPaletteTooltipMessages,
25
- cellBackgroundColorPalette,
26
- ColorPalette,
27
- getSelectedRowAndColumnFromPalette,
17
+ backgroundPaletteTooltipMessages,
18
+ cellBackgroundColorPalette,
19
+ ColorPalette,
20
+ getSelectedRowAndColumnFromPalette,
28
21
  } from '@atlaskit/editor-common/ui-color';
29
22
  import {
30
- ArrowKeyNavigationProvider,
31
- ArrowKeyNavigationType,
23
+ ArrowKeyNavigationProvider,
24
+ ArrowKeyNavigationType,
32
25
  } from '@atlaskit/editor-common/ui-menu';
33
26
  import type { MenuItem } from '@atlaskit/editor-common/ui-menu';
34
27
  import { closestElement } from '@atlaskit/editor-common/utils';
@@ -40,9 +33,9 @@ import { shortcutStyle } from '@atlaskit/editor-shared-styles/shortcut';
40
33
  import type { Rect } from '@atlaskit/editor-tables/table-map';
41
34
  import { TableMap } from '@atlaskit/editor-tables/table-map';
42
35
  import {
43
- findCellRectClosestToPos,
44
- getSelectionRect,
45
- isSelectionType,
36
+ findCellRectClosestToPos,
37
+ getSelectionRect,
38
+ isSelectionType,
46
39
  } from '@atlaskit/editor-tables/utils';
47
40
  import EditorBackgroundColorIcon from '@atlaskit/icon/glyph/editor/background-color';
48
41
  import { getBooleanFF } from '@atlaskit/platform-feature-flags';
@@ -50,10 +43,10 @@ import Toggle from '@atlaskit/toggle';
50
43
 
51
44
  import { clearHoverSelection, hoverColumns, hoverRows } from '../../commands';
52
45
  import {
53
- setColorWithAnalytics,
54
- toggleHeaderColumnWithAnalytics,
55
- toggleHeaderRowWithAnalytics,
56
- toggleNumberColumnWithAnalytics,
46
+ setColorWithAnalytics,
47
+ toggleHeaderColumnWithAnalytics,
48
+ toggleHeaderRowWithAnalytics,
49
+ toggleNumberColumnWithAnalytics,
57
50
  } from '../../commands-with-analytics';
58
51
  import { toggleDragMenu } from '../../pm-plugins/drag-and-drop/commands';
59
52
  import { getPluginState } from '../../pm-plugins/drag-and-drop/plugin-factory';
@@ -61,606 +54,572 @@ import { getPluginState as getTablePluginState } from '../../pm-plugins/plugin-f
61
54
  import type { PluginConfig, TableDirection } from '../../types';
62
55
  import { TableCssClassName as ClassName } from '../../types';
63
56
  import {
64
- checkIfHeaderColumnEnabled,
65
- checkIfHeaderRowEnabled,
66
- checkIfNumberColumnEnabled,
67
- getMergedCellsPositions,
68
- getSelectedColumnIndexes,
69
- getSelectedRowIndexes,
70
- hasMergedCellsInColumn,
71
- hasMergedCellsInRow,
57
+ checkIfHeaderColumnEnabled,
58
+ checkIfHeaderRowEnabled,
59
+ checkIfNumberColumnEnabled,
60
+ getMergedCellsPositions,
61
+ getSelectedColumnIndexes,
62
+ getSelectedRowIndexes,
63
+ hasMergedCellsInColumn,
64
+ hasMergedCellsInRow,
72
65
  } from '../../utils';
73
- import type {
74
- DragMenuConfig,
75
- DragMenuOptionIdType,
76
- } from '../../utils/drag-menu';
66
+ import type { DragMenuConfig, DragMenuOptionIdType } from '../../utils/drag-menu';
77
67
  import { getDragMenuConfig } from '../../utils/drag-menu';
78
68
  import { colorPalletteColumns } from '../consts';
79
69
 
80
70
  import { DropdownMenu } from './DropdownMenu';
81
71
  import {
82
- cellColourPreviewStyles,
83
- dragMenuBackgroundColorStyles,
84
- elementBeforeIconStyles,
85
- toggleStyles,
72
+ cellColourPreviewStyles,
73
+ dragMenuBackgroundColorStyles,
74
+ elementBeforeIconStyles,
75
+ toggleStyles,
86
76
  } from './styles';
87
77
 
88
78
  type DragMenuProps = {
89
- direction?: TableDirection;
90
- index?: number;
91
- target?: Element;
92
- tableNode?: PmNode;
93
- editorView: EditorView;
94
- isOpen?: boolean;
95
- targetCellPosition?: number;
96
- pluginConfig?: PluginConfig;
97
- getEditorContainerWidth: GetEditorContainerWidth;
98
- editorAnalyticsAPI?: EditorAnalyticsAPI;
99
- fitWidth?: number;
100
- fitHeight?: number;
101
- mountPoint?: HTMLElement;
102
- boundariesElement?: HTMLElement;
103
- scrollableElement?: HTMLElement;
104
- isTableScalingEnabled?: boolean;
105
- tableDuplicateCellColouring?: boolean;
79
+ direction?: TableDirection;
80
+ index?: number;
81
+ target?: Element;
82
+ tableNode?: PmNode;
83
+ editorView: EditorView;
84
+ isOpen?: boolean;
85
+ targetCellPosition?: number;
86
+ pluginConfig?: PluginConfig;
87
+ getEditorContainerWidth: GetEditorContainerWidth;
88
+ editorAnalyticsAPI?: EditorAnalyticsAPI;
89
+ fitWidth?: number;
90
+ fitHeight?: number;
91
+ mountPoint?: HTMLElement;
92
+ boundariesElement?: HTMLElement;
93
+ scrollableElement?: HTMLElement;
94
+ isTableScalingEnabled?: boolean;
95
+ tableDuplicateCellColouring?: boolean;
106
96
  };
107
97
 
108
98
  type PluralOptionType = 'noOfCols' | 'noOfRows' | 'noOfCells' | null;
109
99
  interface MessageType {
110
- message: MessageDescriptor;
111
- plural: PluralOptionType;
100
+ message: MessageDescriptor;
101
+ plural: PluralOptionType;
112
102
  }
113
103
 
114
- const MapDragMenuOptionIdToMessage: Record<DragMenuOptionIdType, MessageType> =
115
- {
116
- add_row_above: {
117
- message: messages.addRowAbove,
118
- plural: null,
119
- },
120
- add_row_below: {
121
- message: messages.addRowBelow,
122
- plural: null,
123
- },
124
- add_column_left: {
125
- message: messages.addColumnLeft,
126
- plural: null,
127
- },
128
- add_column_right: {
129
- message: messages.addColumnRight,
130
- plural: null,
131
- },
132
- distribute_columns: {
133
- message: messages.distributeColumns,
134
- plural: 'noOfCols',
135
- },
136
- clear_cells: {
137
- message: messages.clearCells,
138
- plural: 'noOfCells',
139
- },
140
- delete_row: {
141
- message: messages.removeRows,
142
- plural: 'noOfRows',
143
- },
144
- delete_column: {
145
- message: messages.removeColumns,
146
- plural: 'noOfCols',
147
- },
148
- move_column_left: {
149
- message: messages.moveColumnLeft,
150
- plural: 'noOfCols',
151
- },
152
- move_column_right: {
153
- message: messages.moveColumnRight,
154
- plural: 'noOfCols',
155
- },
156
- move_row_up: {
157
- message: messages.moveRowUp,
158
- plural: 'noOfRows',
159
- },
160
- move_row_down: {
161
- message: messages.moveRowDown,
162
- plural: 'noOfRows',
163
- },
164
- sort_column_asc: {
165
- message: messages.sortColumnIncreasing,
166
- plural: null,
167
- },
168
- sort_column_desc: {
169
- message: messages.sortColumnDecreasing,
170
- plural: null,
171
- },
172
- };
104
+ const MapDragMenuOptionIdToMessage: Record<DragMenuOptionIdType, MessageType> = {
105
+ add_row_above: {
106
+ message: messages.addRowAbove,
107
+ plural: null,
108
+ },
109
+ add_row_below: {
110
+ message: messages.addRowBelow,
111
+ plural: null,
112
+ },
113
+ add_column_left: {
114
+ message: messages.addColumnLeft,
115
+ plural: null,
116
+ },
117
+ add_column_right: {
118
+ message: messages.addColumnRight,
119
+ plural: null,
120
+ },
121
+ distribute_columns: {
122
+ message: messages.distributeColumns,
123
+ plural: 'noOfCols',
124
+ },
125
+ clear_cells: {
126
+ message: messages.clearCells,
127
+ plural: 'noOfCells',
128
+ },
129
+ delete_row: {
130
+ message: messages.removeRows,
131
+ plural: 'noOfRows',
132
+ },
133
+ delete_column: {
134
+ message: messages.removeColumns,
135
+ plural: 'noOfCols',
136
+ },
137
+ move_column_left: {
138
+ message: messages.moveColumnLeft,
139
+ plural: 'noOfCols',
140
+ },
141
+ move_column_right: {
142
+ message: messages.moveColumnRight,
143
+ plural: 'noOfCols',
144
+ },
145
+ move_row_up: {
146
+ message: messages.moveRowUp,
147
+ plural: 'noOfRows',
148
+ },
149
+ move_row_down: {
150
+ message: messages.moveRowDown,
151
+ plural: 'noOfRows',
152
+ },
153
+ sort_column_asc: {
154
+ message: messages.sortColumnIncreasing,
155
+ plural: null,
156
+ },
157
+ sort_column_desc: {
158
+ message: messages.sortColumnDecreasing,
159
+ plural: null,
160
+ },
161
+ };
173
162
 
174
163
  const groupedDragMenuConfig: DragMenuOptionIdType[][] = [
175
- [
176
- 'add_row_above',
177
- 'add_row_below',
178
- 'add_column_left',
179
- 'add_column_right',
180
- 'distribute_columns',
181
- 'clear_cells',
182
- 'delete_row',
183
- 'delete_column',
184
- ],
185
- ['move_column_left', 'move_column_right', 'move_row_up', 'move_row_down'],
186
- ['sort_column_asc', 'sort_column_desc'],
164
+ [
165
+ 'add_row_above',
166
+ 'add_row_below',
167
+ 'add_column_left',
168
+ 'add_column_right',
169
+ 'distribute_columns',
170
+ 'clear_cells',
171
+ 'delete_row',
172
+ 'delete_column',
173
+ ],
174
+ ['move_column_left', 'move_column_right', 'move_row_up', 'move_row_down'],
175
+ ['sort_column_asc', 'sort_column_desc'],
187
176
  ];
188
177
 
189
178
  const convertToDropdownItems = (
190
- dragMenuConfig: DragMenuConfig[],
191
- formatMessage: IntlShape['formatMessage'],
192
- selectionRect?: Rect,
179
+ dragMenuConfig: DragMenuConfig[],
180
+ formatMessage: IntlShape['formatMessage'],
181
+ selectionRect?: Rect,
193
182
  ) => {
194
- let menuItemsArr: MenuItem[][] = [...Array(groupedDragMenuConfig.length)].map(
195
- () => [],
196
- );
197
- let menuCallback: { [key: string]: Command } = {};
198
- dragMenuConfig.forEach((item) => {
199
- const menuGroupIndex = groupedDragMenuConfig.findIndex((group) =>
200
- group.includes(item.id),
201
- );
202
-
203
- if (menuGroupIndex === -1) {
204
- return;
205
- }
206
-
207
- const isPlural = Boolean(MapDragMenuOptionIdToMessage[item.id]?.plural);
208
- let plural = 0;
209
-
210
- if (isPlural && selectionRect) {
211
- const { top, bottom, right, left } = selectionRect;
212
- switch (
213
- MapDragMenuOptionIdToMessage[item.id].plural as PluralOptionType
214
- ) {
215
- case 'noOfCols': {
216
- plural = right - left;
217
- break;
218
- }
219
- case 'noOfRows': {
220
- plural = bottom - top;
221
- break;
222
- }
223
- case 'noOfCells': {
224
- plural = Math.max(right - left, bottom - top);
225
- break;
226
- }
227
- }
228
- }
229
-
230
- const options = isPlural ? { 0: plural } : undefined;
231
-
232
- menuItemsArr[menuGroupIndex].push({
233
- key: item.id,
234
- content: formatMessage(
235
- MapDragMenuOptionIdToMessage[item.id].message,
236
- options,
237
- ),
238
- value: { name: item.id },
239
- isDisabled: item.disabled,
240
- elemBefore: item.icon ? (
241
- <span css={elementBeforeIconStyles}>
242
- <item.icon
243
- label={formatMessage(
244
- MapDragMenuOptionIdToMessage[item.id].message,
245
- options,
246
- )}
247
- />
248
- </span>
249
- ) : undefined,
250
- elemAfter: item.keymap ? (
251
- <div css={shortcutStyle}>{item.keymap}</div>
252
- ) : undefined,
253
- });
254
- item.onClick && (menuCallback[item.id] = item.onClick);
255
- });
256
-
257
- const menuItems = menuItemsArr.reduce((acc, curr) => {
258
- curr?.length > 0 && acc.push({ items: curr });
259
- return acc;
260
- }, [] as { items: MenuItem[] }[]);
261
- return { menuItems, menuCallback };
183
+ let menuItemsArr: MenuItem[][] = [...Array(groupedDragMenuConfig.length)].map(() => []);
184
+ let menuCallback: { [key: string]: Command } = {};
185
+ dragMenuConfig.forEach((item) => {
186
+ const menuGroupIndex = groupedDragMenuConfig.findIndex((group) => group.includes(item.id));
187
+
188
+ if (menuGroupIndex === -1) {
189
+ return;
190
+ }
191
+
192
+ const isPlural = Boolean(MapDragMenuOptionIdToMessage[item.id]?.plural);
193
+ let plural = 0;
194
+
195
+ if (isPlural && selectionRect) {
196
+ const { top, bottom, right, left } = selectionRect;
197
+ switch (MapDragMenuOptionIdToMessage[item.id].plural as PluralOptionType) {
198
+ case 'noOfCols': {
199
+ plural = right - left;
200
+ break;
201
+ }
202
+ case 'noOfRows': {
203
+ plural = bottom - top;
204
+ break;
205
+ }
206
+ case 'noOfCells': {
207
+ plural = Math.max(right - left, bottom - top);
208
+ break;
209
+ }
210
+ }
211
+ }
212
+
213
+ const options = isPlural ? { 0: plural } : undefined;
214
+
215
+ menuItemsArr[menuGroupIndex].push({
216
+ key: item.id,
217
+ content: formatMessage(MapDragMenuOptionIdToMessage[item.id].message, options),
218
+ value: { name: item.id },
219
+ isDisabled: item.disabled,
220
+ elemBefore: item.icon ? (
221
+ <span css={elementBeforeIconStyles}>
222
+ <item.icon
223
+ label={formatMessage(MapDragMenuOptionIdToMessage[item.id].message, options)}
224
+ />
225
+ </span>
226
+ ) : undefined,
227
+ elemAfter: item.keymap ? <div css={shortcutStyle}>{item.keymap}</div> : undefined,
228
+ });
229
+ item.onClick && (menuCallback[item.id] = item.onClick);
230
+ });
231
+
232
+ const menuItems = menuItemsArr.reduce(
233
+ (acc, curr) => {
234
+ curr?.length > 0 && acc.push({ items: curr });
235
+ return acc;
236
+ },
237
+ [] as { items: MenuItem[] }[],
238
+ );
239
+ return { menuItems, menuCallback };
262
240
  };
263
241
 
264
242
  const ColorPaletteWithListeners = withOuterListeners(ColorPalette);
265
243
 
266
244
  export const DragMenu = React.memo(
267
- ({
268
- direction = 'row',
269
- index,
270
- target,
271
- isOpen,
272
- editorView,
273
- tableNode,
274
- targetCellPosition,
275
- getEditorContainerWidth,
276
- editorAnalyticsAPI,
277
- pluginConfig,
278
- intl: { formatMessage },
279
- fitHeight,
280
- fitWidth,
281
- mountPoint,
282
- scrollableElement,
283
- boundariesElement,
284
- isTableScalingEnabled,
285
- tableDuplicateCellColouring,
286
- }: DragMenuProps & WrappedComponentProps) => {
287
- const { state, dispatch } = editorView;
288
- const { selection } = state;
289
- const tableMap = tableNode ? TableMap.get(tableNode) : undefined;
290
- const [isSubmenuOpen, setIsSubmenuOpen] = useState(false);
291
- const { isKeyboardModeActive } = getPluginState(state);
292
-
293
- const selectionRect = isSelectionType(selection, 'cell')
294
- ? getSelectionRect(selection)!
295
- : findCellRectClosestToPos(selection.$from);
296
-
297
- let shouldMoveDisabled;
298
- let hasMergedCellsInTable;
299
- if (
300
- getBooleanFF('platform.editor.table.drag-move-options-logic-update_fp7xw')
301
- ) {
302
- shouldMoveDisabled = false;
303
- hasMergedCellsInTable = tableMap?.hasMergedCells() ?? false;
304
- } else {
305
- const hasMergedCells =
306
- direction === 'row' ? hasMergedCellsInRow : hasMergedCellsInColumn;
307
-
308
- shouldMoveDisabled =
309
- index !== undefined && hasMergedCells(index)(selection);
310
-
311
- hasMergedCellsInTable = getMergedCellsPositions(state.tr).length > 0;
312
- }
313
-
314
- const allowBackgroundColor = pluginConfig?.allowBackgroundColor ?? false;
315
-
316
- const dragMenuConfig = getDragMenuConfig(
317
- direction,
318
- getEditorContainerWidth,
319
- !shouldMoveDisabled,
320
- hasMergedCellsInTable,
321
- editorView,
322
- tableMap,
323
- index,
324
- targetCellPosition,
325
- selectionRect,
326
- editorAnalyticsAPI,
327
- pluginConfig?.isHeaderRowRequired,
328
- isTableScalingEnabled,
329
- tableDuplicateCellColouring,
330
- );
331
-
332
- const { menuItems, menuCallback } = convertToDropdownItems(
333
- dragMenuConfig,
334
- formatMessage,
335
- selectionRect,
336
- );
337
-
338
- const handleSubMenuRef = (ref: HTMLDivElement | null) => {
339
- const parent = closestElement(
340
- editorView.dom as HTMLElement,
341
- '.fabric-editor-popup-scroll-parent',
342
- );
343
- if (!(parent && ref)) {
344
- return;
345
- }
346
- const boundariesRect = parent.getBoundingClientRect();
347
- const rect = ref.getBoundingClientRect();
348
- if (rect.left + rect.width > boundariesRect.width) {
349
- ref.style.left = `-${rect.width}px`;
350
- }
351
- };
352
-
353
- const setColor = (color: string) => {
354
- const { targetCellPosition } = getTablePluginState(editorView.state);
355
- const { state, dispatch } = editorView;
356
- setColorWithAnalytics(editorAnalyticsAPI)(
357
- INPUT_METHOD.CONTEXT_MENU,
358
- color,
359
- targetCellPosition,
360
- )(state, dispatch);
361
- closeMenu();
362
- setIsSubmenuOpen(false);
363
- };
364
-
365
- const createBackgroundColorMenuItem = () => {
366
- const { targetCellPosition } = getTablePluginState(editorView.state);
367
- const node = targetCellPosition
368
- ? state.doc.nodeAt(targetCellPosition)
369
- : null;
370
- const background = hexToEditorBackgroundPaletteColor(
371
- node?.attrs?.background || '#ffffff',
372
- );
373
-
374
- const { selectedRowIndex, selectedColumnIndex } =
375
- getSelectedRowAndColumnFromPalette(
376
- cellBackgroundColorPalette,
377
- background,
378
- colorPalletteColumns,
379
- );
380
-
381
- return {
382
- key: 'background',
383
- content: formatMessage(messages.backgroundColor),
384
- value: { name: 'background' },
385
- elemBefore: (
386
- <span css={elementBeforeIconStyles}>
387
- <EditorBackgroundColorIcon
388
- label={formatMessage(messages.backgroundColor)}
389
- size="medium"
390
- />
391
- </span>
392
- ),
393
- elemAfter: (
394
- <div
395
- // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
396
- className={DropdownMenuSharedCssClassName.SUBMENU}
397
- css={dragMenuBackgroundColorStyles}
398
- >
399
- <div
400
- css={cellColourPreviewStyles(background)}
401
- // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
402
- className={ClassName.DRAG_SUBMENU_ICON}
403
- />
404
- {isSubmenuOpen && (
405
- // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
406
- <div className={ClassName.DRAG_SUBMENU} ref={handleSubMenuRef}>
407
- <ArrowKeyNavigationProvider
408
- type={ArrowKeyNavigationType.COLOR}
409
- selectedRowIndex={selectedRowIndex}
410
- selectedColumnIndex={selectedColumnIndex}
411
- handleClose={() => {
412
- const keyboardEvent = new KeyboardEvent('keydown', {
413
- key: 'ArrowDown',
414
- bubbles: true,
415
- });
416
- setIsSubmenuOpen(false);
417
- (target as HTMLElement)?.focus();
418
- target?.dispatchEvent(keyboardEvent);
419
- }}
420
- isPopupPositioned={true}
421
- isOpenedByKeyboard={isKeyboardModeActive}
422
- >
423
- <ColorPaletteWithListeners
424
- cols={colorPalletteColumns}
425
- onClick={(color) => {
426
- setColor(color);
427
- }}
428
- selectedColor={background}
429
- paletteOptions={{
430
- palette: cellBackgroundColorPalette,
431
- paletteColorTooltipMessages:
432
- backgroundPaletteTooltipMessages,
433
- hexToPaletteColor: hexToEditorBackgroundPaletteColor,
434
- }}
435
- />
436
- </ArrowKeyNavigationProvider>
437
- </div>
438
- )}
439
- </div>
440
- ),
441
- } as MenuItem;
442
- };
443
-
444
- const toggleHeaderColumn = () => {
445
- toggleHeaderColumnWithAnalytics(editorAnalyticsAPI)(state, dispatch);
446
- };
447
-
448
- const toggleHeaderRow = () => {
449
- toggleHeaderRowWithAnalytics(editorAnalyticsAPI)(state, dispatch);
450
- };
451
-
452
- const toggleRowNumbers = () => {
453
- toggleNumberColumnWithAnalytics(editorAnalyticsAPI)(state, dispatch);
454
- };
455
-
456
- const createHeaderRowColumnMenuItem = (direction: TableDirection) => {
457
- return direction === 'column'
458
- ? ({
459
- key: 'header_column',
460
- content: formatMessage(messages.headerColumn),
461
- value: { name: 'header_column' },
462
- elemAfter: (
463
- <div css={toggleStyles}>
464
- <Toggle
465
- id="toggle-header-column"
466
- onChange={toggleHeaderColumn}
467
- isChecked={checkIfHeaderColumnEnabled(selection)}
468
- />
469
- </div>
470
- ),
471
- } as MenuItem)
472
- : ({
473
- key: 'header_row',
474
- content: formatMessage(messages.headerRow),
475
- value: { name: 'header_row' },
476
- elemAfter: (
477
- <div css={toggleStyles}>
478
- <Toggle
479
- id="toggle-header-row"
480
- onChange={toggleHeaderRow}
481
- isChecked={checkIfHeaderRowEnabled(selection)}
482
- />
483
- </div>
484
- ),
485
- } as MenuItem);
486
- };
487
-
488
- const createRowNumbersMenuItem = () => {
489
- return {
490
- key: 'row_numbers',
491
- content: formatMessage(messages.rowNumbers),
492
- value: { name: 'row_numbers' },
493
- elemAfter: (
494
- <div css={toggleStyles}>
495
- <Toggle
496
- id="toggle-row-numbers"
497
- onChange={toggleRowNumbers}
498
- isChecked={checkIfNumberColumnEnabled(selection)}
499
- />
500
- </div>
501
- ),
502
- } as MenuItem;
503
- };
504
-
505
- /**
506
- * This function is to check if the menu should be closed or not.
507
- * As when continously clicking on tyle handle on different rows/columns,
508
- * should open the menu corresponding to the position of the drag handle.
509
- * @returns true when the menu should be closed, false otherwise
510
- */
511
- const shouldCloseMenu = (state: EditorState) => {
512
- let {
513
- isDragMenuOpen: previousOpenState,
514
- dragMenuDirection: previousDragMenuDirection,
515
- dragMenuIndex: previousDragMenuIndex,
516
- } = getPluginState(state);
517
-
518
- // menu open but menu direction changed, means user clicked on drag handle of different row/column
519
- // menu open menu direction not changed, but index changed, means user clicked on drag handle of same row/column, different cells.
520
- // 2 scenarios above , menu should not be closed.
521
- if (
522
- (previousOpenState === true &&
523
- previousDragMenuDirection !== direction) ||
524
- (previousOpenState === true &&
525
- previousDragMenuDirection === direction &&
526
- previousDragMenuIndex !== index)
527
- ) {
528
- return false;
529
- } else {
530
- return true;
531
- }
532
- };
533
-
534
- const closeMenu = (focusTarget: 'editor' | 'handle' = 'handle') => {
535
- const { state, dispatch } = editorView;
536
- if (shouldCloseMenu(state)) {
537
- if (target && focusTarget === 'handle') {
538
- (target as HTMLElement | null)?.focus();
539
- } else {
540
- editorView.dom.focus();
541
- }
542
- toggleDragMenu(false, direction, index)(state, dispatch);
543
- }
544
- };
545
-
546
- const handleMenuItemActivated = ({ item }: { item: MenuItem }) => {
547
- menuCallback[item.value.name]?.(state, dispatch);
548
-
549
- switch (item.value.name) {
550
- case 'background':
551
- setIsSubmenuOpen(!isSubmenuOpen);
552
- break;
553
- case 'header_column':
554
- toggleHeaderColumn();
555
- break;
556
- case 'header_row':
557
- toggleHeaderRow();
558
- break;
559
- case 'row_numbers':
560
- toggleRowNumbers();
561
- break;
562
- default:
563
- break;
564
- }
565
-
566
- if (
567
- ['header_column', 'header_row', 'row_numbers', 'background'].indexOf(
568
- item.value.name,
569
- ) <= -1
570
- ) {
571
- closeMenu('editor');
572
- }
573
- };
574
-
575
- const handleItemMouseEnter = ({ item }: { item: MenuItem }) => {
576
- if (!selectionRect) {
577
- return;
578
- }
579
-
580
- if (item.value.name === 'background' && !isSubmenuOpen) {
581
- setIsSubmenuOpen(true);
582
- }
583
-
584
- if (!item.value.name?.startsWith('delete')) {
585
- return;
586
- }
587
-
588
- (item.value.name === 'delete_column'
589
- ? hoverColumns(getSelectedColumnIndexes(selectionRect), true)
590
- : hoverRows(getSelectedRowIndexes(selectionRect), true))(
591
- state,
592
- dispatch,
593
- );
594
- };
595
-
596
- const handleItemMouseLeave = ({ item }: { item: any }) => {
597
- if (item.value.name === 'background' && isSubmenuOpen) {
598
- setIsSubmenuOpen(false);
599
- }
600
-
601
- if (
602
- [
603
- 'sort_column_asc',
604
- 'sort_column_desc',
605
- 'delete_column',
606
- 'delete_row',
607
- ].indexOf(item.value.name) > -1
608
- ) {
609
- clearHoverSelection()(state, dispatch);
610
- }
611
- };
612
-
613
- useEffect(() => {
614
- // focus on first menu item automatically when menu renders
615
- // and user is using keyboard
616
- if (isOpen && target && isKeyboardModeActive) {
617
- const keyboardEvent = new KeyboardEvent('keydown', {
618
- key: 'ArrowDown',
619
- bubbles: true,
620
- });
621
- target.dispatchEvent(keyboardEvent);
622
- }
623
- }, [isOpen, target, isKeyboardModeActive]);
624
-
625
- if (!menuItems) {
626
- return null;
627
- }
628
-
629
- if (allowBackgroundColor) {
630
- menuItems[0].items.unshift(createBackgroundColorMenuItem());
631
- }
632
-
633
- // If first row, add toggle for Header row, default is true
634
- // If first column, add toggle for Header column, default is false
635
- if (index === 0) {
636
- menuItems.push({ items: [createHeaderRowColumnMenuItem(direction)] });
637
- }
638
-
639
- // All rows, add toggle for numbered rows, default is false
640
- if (direction === 'row') {
641
- index === 0
642
- ? menuItems[menuItems.length - 1].items.push(createRowNumbersMenuItem())
643
- : menuItems.push({ items: [createRowNumbersMenuItem()] });
644
- }
645
-
646
- return (
647
- <DropdownMenu
648
- disableKeyboardHandling={isSubmenuOpen}
649
- section={{ hasSeparator: true }}
650
- items={menuItems}
651
- onItemActivated={handleMenuItemActivated}
652
- onMouseEnter={handleItemMouseEnter}
653
- onMouseLeave={handleItemMouseLeave}
654
- handleClose={closeMenu}
655
- fitHeight={fitHeight}
656
- fitWidth={fitWidth}
657
- direction={direction}
658
- mountPoint={mountPoint}
659
- boundariesElement={boundariesElement}
660
- scrollableElement={scrollableElement}
661
- />
662
- );
663
- },
245
+ ({
246
+ direction = 'row',
247
+ index,
248
+ target,
249
+ isOpen,
250
+ editorView,
251
+ tableNode,
252
+ targetCellPosition,
253
+ getEditorContainerWidth,
254
+ editorAnalyticsAPI,
255
+ pluginConfig,
256
+ intl: { formatMessage },
257
+ fitHeight,
258
+ fitWidth,
259
+ mountPoint,
260
+ scrollableElement,
261
+ boundariesElement,
262
+ isTableScalingEnabled,
263
+ tableDuplicateCellColouring,
264
+ }: DragMenuProps & WrappedComponentProps) => {
265
+ const { state, dispatch } = editorView;
266
+ const { selection } = state;
267
+ const tableMap = tableNode ? TableMap.get(tableNode) : undefined;
268
+ const [isSubmenuOpen, setIsSubmenuOpen] = useState(false);
269
+ const { isKeyboardModeActive } = getPluginState(state);
270
+
271
+ const selectionRect = isSelectionType(selection, 'cell')
272
+ ? getSelectionRect(selection)!
273
+ : findCellRectClosestToPos(selection.$from);
274
+
275
+ let shouldMoveDisabled;
276
+ let hasMergedCellsInTable;
277
+ if (getBooleanFF('platform.editor.table.drag-move-options-logic-update_fp7xw')) {
278
+ shouldMoveDisabled = false;
279
+ hasMergedCellsInTable = tableMap?.hasMergedCells() ?? false;
280
+ } else {
281
+ const hasMergedCells = direction === 'row' ? hasMergedCellsInRow : hasMergedCellsInColumn;
282
+
283
+ shouldMoveDisabled = index !== undefined && hasMergedCells(index)(selection);
284
+
285
+ hasMergedCellsInTable = getMergedCellsPositions(state.tr).length > 0;
286
+ }
287
+
288
+ const allowBackgroundColor = pluginConfig?.allowBackgroundColor ?? false;
289
+
290
+ const dragMenuConfig = getDragMenuConfig(
291
+ direction,
292
+ getEditorContainerWidth,
293
+ !shouldMoveDisabled,
294
+ hasMergedCellsInTable,
295
+ editorView,
296
+ tableMap,
297
+ index,
298
+ targetCellPosition,
299
+ selectionRect,
300
+ editorAnalyticsAPI,
301
+ pluginConfig?.isHeaderRowRequired,
302
+ isTableScalingEnabled,
303
+ tableDuplicateCellColouring,
304
+ );
305
+
306
+ const { menuItems, menuCallback } = convertToDropdownItems(
307
+ dragMenuConfig,
308
+ formatMessage,
309
+ selectionRect,
310
+ );
311
+
312
+ const handleSubMenuRef = (ref: HTMLDivElement | null) => {
313
+ const parent = closestElement(
314
+ editorView.dom as HTMLElement,
315
+ '.fabric-editor-popup-scroll-parent',
316
+ );
317
+ if (!(parent && ref)) {
318
+ return;
319
+ }
320
+ const boundariesRect = parent.getBoundingClientRect();
321
+ const rect = ref.getBoundingClientRect();
322
+ if (rect.left + rect.width > boundariesRect.width) {
323
+ ref.style.left = `-${rect.width}px`;
324
+ }
325
+ };
326
+
327
+ const setColor = (color: string) => {
328
+ const { targetCellPosition } = getTablePluginState(editorView.state);
329
+ const { state, dispatch } = editorView;
330
+ setColorWithAnalytics(editorAnalyticsAPI)(
331
+ INPUT_METHOD.CONTEXT_MENU,
332
+ color,
333
+ targetCellPosition,
334
+ )(state, dispatch);
335
+ closeMenu();
336
+ setIsSubmenuOpen(false);
337
+ };
338
+
339
+ const createBackgroundColorMenuItem = () => {
340
+ const { targetCellPosition } = getTablePluginState(editorView.state);
341
+ const node = targetCellPosition ? state.doc.nodeAt(targetCellPosition) : null;
342
+ const background = hexToEditorBackgroundPaletteColor(node?.attrs?.background || '#ffffff');
343
+
344
+ const { selectedRowIndex, selectedColumnIndex } = getSelectedRowAndColumnFromPalette(
345
+ cellBackgroundColorPalette,
346
+ background,
347
+ colorPalletteColumns,
348
+ );
349
+
350
+ return {
351
+ key: 'background',
352
+ content: formatMessage(messages.backgroundColor),
353
+ value: { name: 'background' },
354
+ elemBefore: (
355
+ <span css={elementBeforeIconStyles}>
356
+ <EditorBackgroundColorIcon
357
+ label={formatMessage(messages.backgroundColor)}
358
+ size="medium"
359
+ />
360
+ </span>
361
+ ),
362
+ elemAfter: (
363
+ <div
364
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
365
+ className={DropdownMenuSharedCssClassName.SUBMENU}
366
+ css={dragMenuBackgroundColorStyles}
367
+ >
368
+ <div
369
+ css={cellColourPreviewStyles(background)}
370
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
371
+ className={ClassName.DRAG_SUBMENU_ICON}
372
+ />
373
+ {isSubmenuOpen && (
374
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
375
+ <div className={ClassName.DRAG_SUBMENU} ref={handleSubMenuRef}>
376
+ <ArrowKeyNavigationProvider
377
+ type={ArrowKeyNavigationType.COLOR}
378
+ selectedRowIndex={selectedRowIndex}
379
+ selectedColumnIndex={selectedColumnIndex}
380
+ handleClose={() => {
381
+ const keyboardEvent = new KeyboardEvent('keydown', {
382
+ key: 'ArrowDown',
383
+ bubbles: true,
384
+ });
385
+ setIsSubmenuOpen(false);
386
+ (target as HTMLElement)?.focus();
387
+ target?.dispatchEvent(keyboardEvent);
388
+ }}
389
+ isPopupPositioned={true}
390
+ isOpenedByKeyboard={isKeyboardModeActive}
391
+ >
392
+ <ColorPaletteWithListeners
393
+ cols={colorPalletteColumns}
394
+ onClick={(color) => {
395
+ setColor(color);
396
+ }}
397
+ selectedColor={background}
398
+ paletteOptions={{
399
+ palette: cellBackgroundColorPalette,
400
+ paletteColorTooltipMessages: backgroundPaletteTooltipMessages,
401
+ hexToPaletteColor: hexToEditorBackgroundPaletteColor,
402
+ }}
403
+ />
404
+ </ArrowKeyNavigationProvider>
405
+ </div>
406
+ )}
407
+ </div>
408
+ ),
409
+ } as MenuItem;
410
+ };
411
+
412
+ const toggleHeaderColumn = () => {
413
+ toggleHeaderColumnWithAnalytics(editorAnalyticsAPI)(state, dispatch);
414
+ };
415
+
416
+ const toggleHeaderRow = () => {
417
+ toggleHeaderRowWithAnalytics(editorAnalyticsAPI)(state, dispatch);
418
+ };
419
+
420
+ const toggleRowNumbers = () => {
421
+ toggleNumberColumnWithAnalytics(editorAnalyticsAPI)(state, dispatch);
422
+ };
423
+
424
+ const createHeaderRowColumnMenuItem = (direction: TableDirection) => {
425
+ return direction === 'column'
426
+ ? ({
427
+ key: 'header_column',
428
+ content: formatMessage(messages.headerColumn),
429
+ value: { name: 'header_column' },
430
+ elemAfter: (
431
+ <div css={toggleStyles}>
432
+ <Toggle
433
+ id="toggle-header-column"
434
+ onChange={toggleHeaderColumn}
435
+ isChecked={checkIfHeaderColumnEnabled(selection)}
436
+ />
437
+ </div>
438
+ ),
439
+ } as MenuItem)
440
+ : ({
441
+ key: 'header_row',
442
+ content: formatMessage(messages.headerRow),
443
+ value: { name: 'header_row' },
444
+ elemAfter: (
445
+ <div css={toggleStyles}>
446
+ <Toggle
447
+ id="toggle-header-row"
448
+ onChange={toggleHeaderRow}
449
+ isChecked={checkIfHeaderRowEnabled(selection)}
450
+ />
451
+ </div>
452
+ ),
453
+ } as MenuItem);
454
+ };
455
+
456
+ const createRowNumbersMenuItem = () => {
457
+ return {
458
+ key: 'row_numbers',
459
+ content: formatMessage(messages.rowNumbers),
460
+ value: { name: 'row_numbers' },
461
+ elemAfter: (
462
+ <div css={toggleStyles}>
463
+ <Toggle
464
+ id="toggle-row-numbers"
465
+ onChange={toggleRowNumbers}
466
+ isChecked={checkIfNumberColumnEnabled(selection)}
467
+ />
468
+ </div>
469
+ ),
470
+ } as MenuItem;
471
+ };
472
+
473
+ /**
474
+ * This function is to check if the menu should be closed or not.
475
+ * As when continously clicking on tyle handle on different rows/columns,
476
+ * should open the menu corresponding to the position of the drag handle.
477
+ * @returns true when the menu should be closed, false otherwise
478
+ */
479
+ const shouldCloseMenu = (state: EditorState) => {
480
+ let {
481
+ isDragMenuOpen: previousOpenState,
482
+ dragMenuDirection: previousDragMenuDirection,
483
+ dragMenuIndex: previousDragMenuIndex,
484
+ } = getPluginState(state);
485
+
486
+ // menu open but menu direction changed, means user clicked on drag handle of different row/column
487
+ // menu open menu direction not changed, but index changed, means user clicked on drag handle of same row/column, different cells.
488
+ // 2 scenarios above , menu should not be closed.
489
+ if (
490
+ (previousOpenState === true && previousDragMenuDirection !== direction) ||
491
+ (previousOpenState === true &&
492
+ previousDragMenuDirection === direction &&
493
+ previousDragMenuIndex !== index)
494
+ ) {
495
+ return false;
496
+ } else {
497
+ return true;
498
+ }
499
+ };
500
+
501
+ const closeMenu = (focusTarget: 'editor' | 'handle' = 'handle') => {
502
+ const { state, dispatch } = editorView;
503
+ if (shouldCloseMenu(state)) {
504
+ if (target && focusTarget === 'handle') {
505
+ (target as HTMLElement | null)?.focus();
506
+ } else {
507
+ editorView.dom.focus();
508
+ }
509
+ toggleDragMenu(false, direction, index)(state, dispatch);
510
+ }
511
+ };
512
+
513
+ const handleMenuItemActivated = ({ item }: { item: MenuItem }) => {
514
+ menuCallback[item.value.name]?.(state, dispatch);
515
+
516
+ switch (item.value.name) {
517
+ case 'background':
518
+ setIsSubmenuOpen(!isSubmenuOpen);
519
+ break;
520
+ case 'header_column':
521
+ toggleHeaderColumn();
522
+ break;
523
+ case 'header_row':
524
+ toggleHeaderRow();
525
+ break;
526
+ case 'row_numbers':
527
+ toggleRowNumbers();
528
+ break;
529
+ default:
530
+ break;
531
+ }
532
+
533
+ if (
534
+ ['header_column', 'header_row', 'row_numbers', 'background'].indexOf(item.value.name) <= -1
535
+ ) {
536
+ closeMenu('editor');
537
+ }
538
+ };
539
+
540
+ const handleItemMouseEnter = ({ item }: { item: MenuItem }) => {
541
+ if (!selectionRect) {
542
+ return;
543
+ }
544
+
545
+ if (item.value.name === 'background' && !isSubmenuOpen) {
546
+ setIsSubmenuOpen(true);
547
+ }
548
+
549
+ if (!item.value.name?.startsWith('delete')) {
550
+ return;
551
+ }
552
+
553
+ (item.value.name === 'delete_column'
554
+ ? hoverColumns(getSelectedColumnIndexes(selectionRect), true)
555
+ : hoverRows(getSelectedRowIndexes(selectionRect), true))(state, dispatch);
556
+ };
557
+
558
+ const handleItemMouseLeave = ({ item }: { item: any }) => {
559
+ if (item.value.name === 'background' && isSubmenuOpen) {
560
+ setIsSubmenuOpen(false);
561
+ }
562
+
563
+ if (
564
+ ['sort_column_asc', 'sort_column_desc', 'delete_column', 'delete_row'].indexOf(
565
+ item.value.name,
566
+ ) > -1
567
+ ) {
568
+ clearHoverSelection()(state, dispatch);
569
+ }
570
+ };
571
+
572
+ useEffect(() => {
573
+ // focus on first menu item automatically when menu renders
574
+ // and user is using keyboard
575
+ if (isOpen && target && isKeyboardModeActive) {
576
+ const keyboardEvent = new KeyboardEvent('keydown', {
577
+ key: 'ArrowDown',
578
+ bubbles: true,
579
+ });
580
+ target.dispatchEvent(keyboardEvent);
581
+ }
582
+ }, [isOpen, target, isKeyboardModeActive]);
583
+
584
+ if (!menuItems) {
585
+ return null;
586
+ }
587
+
588
+ if (allowBackgroundColor) {
589
+ menuItems[0].items.unshift(createBackgroundColorMenuItem());
590
+ }
591
+
592
+ // If first row, add toggle for Header row, default is true
593
+ // If first column, add toggle for Header column, default is false
594
+ if (index === 0) {
595
+ menuItems.push({ items: [createHeaderRowColumnMenuItem(direction)] });
596
+ }
597
+
598
+ // All rows, add toggle for numbered rows, default is false
599
+ if (direction === 'row') {
600
+ index === 0
601
+ ? menuItems[menuItems.length - 1].items.push(createRowNumbersMenuItem())
602
+ : menuItems.push({ items: [createRowNumbersMenuItem()] });
603
+ }
604
+
605
+ return (
606
+ <DropdownMenu
607
+ disableKeyboardHandling={isSubmenuOpen}
608
+ section={{ hasSeparator: true }}
609
+ items={menuItems}
610
+ onItemActivated={handleMenuItemActivated}
611
+ onMouseEnter={handleItemMouseEnter}
612
+ onMouseLeave={handleItemMouseLeave}
613
+ handleClose={closeMenu}
614
+ fitHeight={fitHeight}
615
+ fitWidth={fitWidth}
616
+ direction={direction}
617
+ mountPoint={mountPoint}
618
+ boundariesElement={boundariesElement}
619
+ scrollableElement={scrollableElement}
620
+ />
621
+ );
622
+ },
664
623
  );
665
624
 
666
625
  export default injectIntl(DragMenu);