@atlaskit/editor-plugin-table 7.16.11 → 7.16.12

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 (242) hide show
  1. package/.eslintrc.js +3 -3
  2. package/CHANGELOG.md +8 -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 +41 -6
  6. package/dist/cjs/nodeviews/TableResizer.js +7 -7
  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/merged-cells.js +3 -3
  16. package/dist/es2019/commands/misc.js +3 -3
  17. package/dist/es2019/nodeviews/TableContainer.js +43 -5
  18. package/dist/es2019/nodeviews/TableResizer.js +7 -7
  19. package/dist/es2019/nodeviews/TableRow.js +21 -21
  20. package/dist/es2019/pm-plugins/table-resizing/plugin.js +3 -3
  21. package/dist/es2019/pm-plugins/table-resizing/utils/resize-state.js +4 -4
  22. package/dist/es2019/pm-plugins/table-resizing/utils/scale-table.js +3 -3
  23. package/dist/es2019/ui/FloatingContextualMenu/styles.js +47 -47
  24. package/dist/es2019/ui/FloatingDragMenu/styles.js +30 -30
  25. package/dist/es2019/ui/common-styles.js +802 -816
  26. package/dist/es2019/ui/ui-styles.js +665 -678
  27. package/dist/es2019/utils/merged-cells.js +3 -3
  28. package/dist/esm/commands/misc.js +3 -3
  29. package/dist/esm/nodeviews/TableCell.js +10 -10
  30. package/dist/esm/nodeviews/TableContainer.js +42 -7
  31. package/dist/esm/nodeviews/TableResizer.js +7 -7
  32. package/dist/esm/nodeviews/TableRow.js +23 -23
  33. package/dist/esm/pm-plugins/table-resizing/plugin.js +3 -3
  34. package/dist/esm/pm-plugins/table-resizing/utils/resize-state.js +4 -4
  35. package/dist/esm/pm-plugins/table-resizing/utils/scale-table.js +3 -3
  36. package/dist/esm/ui/FloatingContextualMenu/styles.js +1 -1
  37. package/dist/esm/ui/FloatingDragMenu/styles.js +1 -1
  38. package/dist/esm/ui/common-styles.js +13 -13
  39. package/dist/esm/ui/ui-styles.js +25 -25
  40. package/dist/esm/utils/merged-cells.js +3 -3
  41. package/dist/types/pm-plugins/decorations/utils/index.d.ts +1 -1
  42. package/dist/types/pm-plugins/drag-and-drop/utils/autoscrollers.d.ts +1 -1
  43. package/dist/types/pm-plugins/drag-and-drop/utils/getDragBehaviour.d.ts +1 -1
  44. package/dist/types/pm-plugins/table-resizing/utils/index.d.ts +1 -1
  45. package/dist/types/ui/ColumnResizeWidget/index.d.ts +1 -1
  46. package/dist/types/ui/FloatingAlignmentButtons/FloatingAlignmentButtons.d.ts +1 -1
  47. package/dist/types/ui/FloatingToolbarLabel/FloatingToolbarLabel.d.ts +1 -1
  48. package/dist/types/ui/TableFloatingColumnControls/ColumnDropTargets/ColumnDropTarget.d.ts +1 -1
  49. package/dist/types/ui/TableFloatingControls/CornerControls/index.d.ts +1 -1
  50. package/dist/types/ui/icons/DragHandleDisabledIcon.d.ts +1 -1
  51. package/dist/types-ts4.5/pm-plugins/decorations/utils/index.d.ts +1 -1
  52. package/dist/types-ts4.5/pm-plugins/drag-and-drop/utils/autoscrollers.d.ts +1 -1
  53. package/dist/types-ts4.5/pm-plugins/drag-and-drop/utils/getDragBehaviour.d.ts +1 -1
  54. package/dist/types-ts4.5/pm-plugins/table-resizing/utils/index.d.ts +1 -1
  55. package/dist/types-ts4.5/ui/ColumnResizeWidget/index.d.ts +1 -1
  56. package/dist/types-ts4.5/ui/FloatingAlignmentButtons/FloatingAlignmentButtons.d.ts +1 -1
  57. package/dist/types-ts4.5/ui/FloatingToolbarLabel/FloatingToolbarLabel.d.ts +1 -1
  58. package/dist/types-ts4.5/ui/TableFloatingColumnControls/ColumnDropTargets/ColumnDropTarget.d.ts +1 -1
  59. package/dist/types-ts4.5/ui/TableFloatingControls/CornerControls/index.d.ts +1 -1
  60. package/dist/types-ts4.5/ui/icons/DragHandleDisabledIcon.d.ts +1 -1
  61. package/docs/0-intro.tsx +9 -7
  62. package/package.json +2 -2
  63. package/report.api.md +67 -66
  64. package/src/commands/clear.ts +36 -44
  65. package/src/commands/collapse.ts +8 -8
  66. package/src/commands/column-resize.ts +412 -452
  67. package/src/commands/delete.ts +14 -14
  68. package/src/commands/display-mode.ts +10 -11
  69. package/src/commands/go-to-next-cell.ts +48 -54
  70. package/src/commands/hover.ts +210 -227
  71. package/src/commands/index.ts +35 -35
  72. package/src/commands/insert.ts +208 -235
  73. package/src/commands/misc.ts +655 -748
  74. package/src/commands/referentiality.ts +9 -9
  75. package/src/commands/selection.ts +433 -563
  76. package/src/commands/sort.ts +68 -86
  77. package/src/commands/split-cell.ts +14 -14
  78. package/src/commands/toggle.ts +69 -67
  79. package/src/commands-with-analytics.ts +570 -639
  80. package/src/create-plugin-config.ts +13 -13
  81. package/src/event-handlers.ts +513 -612
  82. package/src/handlers.ts +120 -133
  83. package/src/nodeviews/ExternalDropTargets.tsx +68 -73
  84. package/src/nodeviews/OverflowShadowsObserver.ts +148 -157
  85. package/src/nodeviews/TableCell.ts +47 -54
  86. package/src/nodeviews/TableComponent.tsx +1018 -1112
  87. package/src/nodeviews/TableComponentWithSharedState.tsx +91 -94
  88. package/src/nodeviews/TableContainer.tsx +363 -339
  89. package/src/nodeviews/TableNodeViewBase.ts +19 -24
  90. package/src/nodeviews/TableResizer.tsx +565 -657
  91. package/src/nodeviews/TableRow.ts +580 -629
  92. package/src/nodeviews/TableStickyScrollbar.ts +173 -190
  93. package/src/nodeviews/__mocks__/OverflowShadowsObserver.ts +8 -8
  94. package/src/nodeviews/__mocks__/OverridableMock.ts +14 -15
  95. package/src/nodeviews/table.tsx +345 -375
  96. package/src/nodeviews/types.ts +21 -24
  97. package/src/nodeviews/update-overflow-shadows.ts +8 -14
  98. package/src/plugin.tsx +578 -603
  99. package/src/pm-plugins/analytics/actions.ts +10 -12
  100. package/src/pm-plugins/analytics/commands.ts +31 -37
  101. package/src/pm-plugins/analytics/plugin-factory.ts +4 -2
  102. package/src/pm-plugins/analytics/plugin-key.ts +1 -3
  103. package/src/pm-plugins/analytics/plugin.ts +60 -70
  104. package/src/pm-plugins/analytics/reducer.ts +19 -19
  105. package/src/pm-plugins/analytics/types.ts +10 -10
  106. package/src/pm-plugins/analytics/utils/moved-event.ts +38 -38
  107. package/src/pm-plugins/decorations/plugin.ts +58 -77
  108. package/src/pm-plugins/decorations/utils/column-controls.ts +59 -71
  109. package/src/pm-plugins/decorations/utils/column-resizing.ts +50 -57
  110. package/src/pm-plugins/decorations/utils/compose-decorations.ts +6 -6
  111. package/src/pm-plugins/decorations/utils/index.ts +3 -6
  112. package/src/pm-plugins/decorations/utils/types.ts +7 -12
  113. package/src/pm-plugins/default-table-selection.ts +3 -3
  114. package/src/pm-plugins/drag-and-drop/actions.ts +25 -25
  115. package/src/pm-plugins/drag-and-drop/commands-with-analytics.ts +158 -190
  116. package/src/pm-plugins/drag-and-drop/commands.ts +154 -170
  117. package/src/pm-plugins/drag-and-drop/consts.ts +4 -5
  118. package/src/pm-plugins/drag-and-drop/plugin-factory.ts +23 -20
  119. package/src/pm-plugins/drag-and-drop/plugin-key.ts +1 -3
  120. package/src/pm-plugins/drag-and-drop/plugin.ts +329 -383
  121. package/src/pm-plugins/drag-and-drop/reducer.ts +30 -30
  122. package/src/pm-plugins/drag-and-drop/types.ts +8 -8
  123. package/src/pm-plugins/drag-and-drop/utils/autoscrollers.ts +38 -41
  124. package/src/pm-plugins/drag-and-drop/utils/getDragBehaviour.ts +3 -6
  125. package/src/pm-plugins/drag-and-drop/utils/monitor.ts +57 -70
  126. package/src/pm-plugins/keymap.ts +208 -220
  127. package/src/pm-plugins/main.ts +348 -400
  128. package/src/pm-plugins/plugin-factory.ts +32 -34
  129. package/src/pm-plugins/safari-delete-composition-text-issue-workaround.ts +83 -97
  130. package/src/pm-plugins/sticky-headers/commands.ts +2 -6
  131. package/src/pm-plugins/sticky-headers/plugin-key.ts +1 -3
  132. package/src/pm-plugins/sticky-headers/plugin-state.ts +41 -44
  133. package/src/pm-plugins/sticky-headers/plugin.ts +4 -4
  134. package/src/pm-plugins/sticky-headers/types.ts +8 -8
  135. package/src/pm-plugins/sticky-headers/util.ts +10 -10
  136. package/src/pm-plugins/table-analytics.ts +70 -72
  137. package/src/pm-plugins/table-local-id.ts +180 -184
  138. package/src/pm-plugins/table-resizing/commands.ts +72 -85
  139. package/src/pm-plugins/table-resizing/event-handlers.ts +298 -317
  140. package/src/pm-plugins/table-resizing/plugin-factory.ts +10 -10
  141. package/src/pm-plugins/table-resizing/plugin-key.ts +1 -3
  142. package/src/pm-plugins/table-resizing/plugin.ts +61 -68
  143. package/src/pm-plugins/table-resizing/reducer.ts +30 -33
  144. package/src/pm-plugins/table-resizing/utils/colgroup.ts +84 -84
  145. package/src/pm-plugins/table-resizing/utils/column-state.ts +78 -81
  146. package/src/pm-plugins/table-resizing/utils/content-width.ts +94 -114
  147. package/src/pm-plugins/table-resizing/utils/dom.ts +93 -110
  148. package/src/pm-plugins/table-resizing/utils/index.ts +29 -34
  149. package/src/pm-plugins/table-resizing/utils/misc.ts +94 -119
  150. package/src/pm-plugins/table-resizing/utils/resize-column.ts +93 -106
  151. package/src/pm-plugins/table-resizing/utils/resize-logic.ts +240 -257
  152. package/src/pm-plugins/table-resizing/utils/resize-state.ts +343 -372
  153. package/src/pm-plugins/table-resizing/utils/scale-table.ts +202 -207
  154. package/src/pm-plugins/table-resizing/utils/types.ts +17 -17
  155. package/src/pm-plugins/table-resizing/utils/unit-to-number.ts +1 -2
  156. package/src/pm-plugins/table-selection-keymap.ts +25 -51
  157. package/src/pm-plugins/table-width.ts +191 -204
  158. package/src/pm-plugins/view-mode-sort/index.ts +223 -227
  159. package/src/pm-plugins/view-mode-sort/plugin-key.ts +3 -2
  160. package/src/pm-plugins/view-mode-sort/types.ts +12 -12
  161. package/src/pm-plugins/view-mode-sort/utils.ts +108 -117
  162. package/src/reducer.ts +139 -155
  163. package/src/toolbar.tsx +815 -905
  164. package/src/transforms/column-width.ts +186 -213
  165. package/src/transforms/delete-columns.ts +208 -222
  166. package/src/transforms/delete-rows.ts +117 -121
  167. package/src/transforms/fix-tables.ts +190 -215
  168. package/src/transforms/merge.ts +263 -269
  169. package/src/transforms/replace-table.ts +27 -43
  170. package/src/transforms/split.ts +65 -75
  171. package/src/types.ts +421 -427
  172. package/src/ui/ColumnResizeWidget/index.tsx +40 -47
  173. package/src/ui/DragHandle/HandleIconComponent.tsx +9 -13
  174. package/src/ui/DragHandle/index.tsx +221 -250
  175. package/src/ui/DragPreview/index.tsx +35 -35
  176. package/src/ui/FloatingAlignmentButtons/FloatingAlignmentButtons.tsx +33 -41
  177. package/src/ui/FloatingContextualButton/FixedButton.tsx +154 -157
  178. package/src/ui/FloatingContextualButton/index.tsx +109 -115
  179. package/src/ui/FloatingContextualButton/styles.ts +43 -46
  180. package/src/ui/FloatingContextualMenu/ContextualMenu.tsx +634 -694
  181. package/src/ui/FloatingContextualMenu/index.tsx +83 -101
  182. package/src/ui/FloatingContextualMenu/styles.ts +57 -65
  183. package/src/ui/FloatingDeleteButton/DeleteButton.tsx +37 -37
  184. package/src/ui/FloatingDeleteButton/getPopUpOptions.ts +47 -57
  185. package/src/ui/FloatingDeleteButton/index.tsx +319 -350
  186. package/src/ui/FloatingDragMenu/DragMenu.tsx +555 -596
  187. package/src/ui/FloatingDragMenu/DropdownMenu.tsx +152 -162
  188. package/src/ui/FloatingDragMenu/index.tsx +88 -102
  189. package/src/ui/FloatingDragMenu/styles.ts +51 -54
  190. package/src/ui/FloatingInsertButton/InsertButton.tsx +204 -217
  191. package/src/ui/FloatingInsertButton/getPopupOptions.ts +100 -115
  192. package/src/ui/FloatingInsertButton/index.tsx +248 -292
  193. package/src/ui/FloatingToolbarLabel/FloatingToolbarLabel.tsx +24 -29
  194. package/src/ui/TableFloatingColumnControls/ColumnControls/index.tsx +308 -329
  195. package/src/ui/TableFloatingColumnControls/ColumnDropTargets/ColumnDropTarget.tsx +85 -94
  196. package/src/ui/TableFloatingColumnControls/ColumnDropTargets/index.tsx +46 -46
  197. package/src/ui/TableFloatingColumnControls/index.tsx +116 -136
  198. package/src/ui/TableFloatingControls/CornerControls/ClassicCornerControls.tsx +79 -91
  199. package/src/ui/TableFloatingControls/CornerControls/DragCornerControls.tsx +95 -102
  200. package/src/ui/TableFloatingControls/CornerControls/index.tsx +1 -4
  201. package/src/ui/TableFloatingControls/CornerControls/types.ts +8 -8
  202. package/src/ui/TableFloatingControls/FloatingControlsWithSelection.tsx +50 -50
  203. package/src/ui/TableFloatingControls/NumberColumn/index.tsx +111 -124
  204. package/src/ui/TableFloatingControls/RowControls/ClassicControls.tsx +86 -105
  205. package/src/ui/TableFloatingControls/RowControls/DragControls.tsx +305 -341
  206. package/src/ui/TableFloatingControls/RowDropTarget/index.tsx +72 -75
  207. package/src/ui/TableFloatingControls/index.tsx +191 -193
  208. package/src/ui/TableFullWidthLabel/index.tsx +20 -20
  209. package/src/ui/common-styles.ts +880 -912
  210. package/src/ui/consts.ts +29 -74
  211. package/src/ui/icons/AddColLeftIcon.tsx +33 -39
  212. package/src/ui/icons/AddColRightIcon.tsx +33 -39
  213. package/src/ui/icons/AddRowAboveIcon.tsx +16 -22
  214. package/src/ui/icons/AddRowBelowIcon.tsx +33 -39
  215. package/src/ui/icons/DisplayModeIcon.tsx +31 -31
  216. package/src/ui/icons/DragHandleDisabledIcon.tsx +19 -21
  217. package/src/ui/icons/DragHandleIcon.tsx +12 -12
  218. package/src/ui/icons/DragInMotionIcon.tsx +45 -52
  219. package/src/ui/icons/MergeCellsIcon.tsx +22 -28
  220. package/src/ui/icons/MinimisedHandle.tsx +9 -9
  221. package/src/ui/icons/SplitCellIcon.tsx +30 -36
  222. package/src/ui/ui-styles.ts +769 -798
  223. package/src/utils/alignment.ts +1 -1
  224. package/src/utils/analytics.ts +192 -208
  225. package/src/utils/collapse.ts +55 -64
  226. package/src/utils/column-controls.ts +237 -254
  227. package/src/utils/create.ts +30 -30
  228. package/src/utils/decoration.ts +482 -502
  229. package/src/utils/dom.ts +127 -134
  230. package/src/utils/drag-menu.ts +322 -373
  231. package/src/utils/get-allow-add-column-custom-step.ts +4 -5
  232. package/src/utils/guidelines.ts +10 -21
  233. package/src/utils/index.ts +68 -68
  234. package/src/utils/merged-cells.ts +245 -254
  235. package/src/utils/nodes.ts +91 -106
  236. package/src/utils/paste.ts +119 -135
  237. package/src/utils/row-controls.ts +199 -213
  238. package/src/utils/selection.ts +77 -87
  239. package/src/utils/snapping.ts +84 -97
  240. package/src/utils/table.ts +44 -44
  241. package/src/utils/transforms.ts +5 -5
  242. 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);