@atlaskit/editor-plugin-table 7.16.10 → 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 (244) hide show
  1. package/.eslintrc.js +3 -3
  2. package/CHANGELOG.md +1836 -1831
  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 +19 -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 +808 -814
  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 +19 -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 +5 -4
  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 +881 -903
  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
  243. package/tsconfig.app.json +107 -107
  244. package/tsconfig.dev.json +47 -47
@@ -1,702 +1,603 @@
1
1
  import rafSchedule from 'raf-schd';
2
2
 
3
3
  import type { EditorAnalyticsAPI } from '@atlaskit/editor-common/analytics';
4
+ import { ACTION_SUBJECT, EVENT_TYPE, TABLE_ACTION } from '@atlaskit/editor-common/analytics';
4
5
  import {
5
- ACTION_SUBJECT,
6
- EVENT_TYPE,
7
- TABLE_ACTION,
8
- } from '@atlaskit/editor-common/analytics';
9
- import {
10
- browser,
11
- closestElement,
12
- isElementInTableCell,
13
- isLastItemMediaGroup,
14
- setNodeSelection,
6
+ browser,
7
+ closestElement,
8
+ isElementInTableCell,
9
+ isLastItemMediaGroup,
10
+ setNodeSelection,
15
11
  } from '@atlaskit/editor-common/utils';
16
12
  import type { Node as PmNode } from '@atlaskit/editor-prosemirror/model';
17
- import type {
18
- EditorState,
19
- Transaction,
20
- } from '@atlaskit/editor-prosemirror/state';
13
+ import type { EditorState, Transaction } from '@atlaskit/editor-prosemirror/state';
21
14
  import { Selection, TextSelection } from '@atlaskit/editor-prosemirror/state';
22
15
  import type { EditorView } from '@atlaskit/editor-prosemirror/view';
23
16
  import { CellSelection } from '@atlaskit/editor-tables/cell-selection';
24
17
  import { TableMap } from '@atlaskit/editor-tables/table-map';
25
18
  import {
26
- cellAround,
27
- findCellRectClosestToPos,
28
- findTable,
29
- getSelectionRect,
30
- removeTable,
19
+ cellAround,
20
+ findCellRectClosestToPos,
21
+ findTable,
22
+ getSelectionRect,
23
+ removeTable,
31
24
  } from '@atlaskit/editor-tables/utils';
32
25
  import { getBooleanFF } from '@atlaskit/platform-feature-flags';
33
26
 
34
27
  import {
35
- addResizeHandleDecorations,
36
- clearHoverSelection,
37
- hideInsertColumnOrRowButton,
38
- hideResizeHandleLine,
39
- hoverCell,
40
- hoverColumns,
41
- selectColumn,
42
- setEditorFocus,
43
- setTableHovered,
44
- showInsertColumnButton,
45
- showInsertRowButton,
46
- showResizeHandleLine,
28
+ addResizeHandleDecorations,
29
+ clearHoverSelection,
30
+ hideInsertColumnOrRowButton,
31
+ hideResizeHandleLine,
32
+ hoverCell,
33
+ hoverColumns,
34
+ selectColumn,
35
+ setEditorFocus,
36
+ setTableHovered,
37
+ showInsertColumnButton,
38
+ showInsertRowButton,
39
+ showResizeHandleLine,
47
40
  } from './commands';
48
41
  import { getPluginState as getDragDropPluginState } from './pm-plugins/drag-and-drop/plugin-factory';
49
42
  import { getPluginState } from './pm-plugins/plugin-factory';
50
43
  import { getPluginState as getResizePluginState } from './pm-plugins/table-resizing/plugin-factory';
51
44
  import { deleteColumns, deleteRows } from './transforms';
45
+ import { TableCssClassName as ClassName, RESIZE_HANDLE_AREA_DECORATION_GAP } from './types';
52
46
  import {
53
- TableCssClassName as ClassName,
54
- RESIZE_HANDLE_AREA_DECORATION_GAP,
55
- } from './types';
56
- import {
57
- convertHTMLCellIndexToColumnIndex,
58
- getColumnIndexMappedToColumnIndexInFirstRow,
59
- getColumnOrRowIndex,
60
- getMousePositionHorizontalRelativeByElement,
61
- getMousePositionVerticalRelativeByElement,
62
- getSelectedCellInfo,
63
- hasResizeHandler,
64
- isCell,
65
- isColumnControlsDecorations,
66
- isCornerButton,
67
- isDragColumnFloatingInsertDot,
68
- isDragCornerButton,
69
- isDragRowFloatingInsertDot,
70
- isInsertRowButton,
71
- isResizeHandleDecoration,
72
- isRowControlsButton,
73
- isTableContainerOrWrapper,
74
- isTableControlsButton,
47
+ convertHTMLCellIndexToColumnIndex,
48
+ getColumnIndexMappedToColumnIndexInFirstRow,
49
+ getColumnOrRowIndex,
50
+ getMousePositionHorizontalRelativeByElement,
51
+ getMousePositionVerticalRelativeByElement,
52
+ getSelectedCellInfo,
53
+ hasResizeHandler,
54
+ isCell,
55
+ isColumnControlsDecorations,
56
+ isCornerButton,
57
+ isDragColumnFloatingInsertDot,
58
+ isDragCornerButton,
59
+ isDragRowFloatingInsertDot,
60
+ isInsertRowButton,
61
+ isResizeHandleDecoration,
62
+ isRowControlsButton,
63
+ isTableContainerOrWrapper,
64
+ isTableControlsButton,
75
65
  } from './utils';
76
66
  import { getAllowAddColumnCustomStep } from './utils/get-allow-add-column-custom-step';
77
67
 
78
68
  const isFocusingCalendar = (event: Event) =>
79
- event instanceof FocusEvent &&
80
- event.relatedTarget instanceof HTMLElement &&
81
- event.relatedTarget.getAttribute('aria-label') === 'calendar';
69
+ event instanceof FocusEvent &&
70
+ event.relatedTarget instanceof HTMLElement &&
71
+ event.relatedTarget.getAttribute('aria-label') === 'calendar';
82
72
 
83
73
  const isFocusingModal = (event: Event) =>
84
- event instanceof FocusEvent &&
85
- event.relatedTarget instanceof HTMLElement &&
86
- event.relatedTarget.closest('[role="dialog"]');
74
+ event instanceof FocusEvent &&
75
+ event.relatedTarget instanceof HTMLElement &&
76
+ event.relatedTarget.closest('[role="dialog"]');
87
77
 
88
78
  const isFocusingFloatingToolbar = (event: Event) =>
89
- event instanceof FocusEvent &&
90
- event.relatedTarget instanceof HTMLElement &&
91
- event.relatedTarget.closest('[role="toolbar"]');
79
+ event instanceof FocusEvent &&
80
+ event.relatedTarget instanceof HTMLElement &&
81
+ event.relatedTarget.closest('[role="toolbar"]');
92
82
 
93
83
  const isFocusingDragHandles = (event: Event) =>
94
- event instanceof FocusEvent &&
95
- event.relatedTarget instanceof HTMLElement &&
96
- event.relatedTarget.closest('button') &&
97
- event.relatedTarget.getAttribute('draggable') === 'true';
84
+ event instanceof FocusEvent &&
85
+ event.relatedTarget instanceof HTMLElement &&
86
+ event.relatedTarget.closest('button') &&
87
+ event.relatedTarget.getAttribute('draggable') === 'true';
98
88
 
99
89
  const isFocusingDragHandlesClickableZone = (event: Event) =>
100
- event instanceof FocusEvent &&
101
- event.relatedTarget instanceof HTMLElement &&
102
- event.relatedTarget.closest('button') &&
103
- event.relatedTarget.classList.contains(
104
- ClassName.DRAG_HANDLE_BUTTON_CLICKABLE_ZONE,
105
- );
90
+ event instanceof FocusEvent &&
91
+ event.relatedTarget instanceof HTMLElement &&
92
+ event.relatedTarget.closest('button') &&
93
+ event.relatedTarget.classList.contains(ClassName.DRAG_HANDLE_BUTTON_CLICKABLE_ZONE);
106
94
 
107
95
  export const handleBlur = (view: EditorView, event: Event): boolean => {
108
- const { state, dispatch } = view;
109
- // IE version check for ED-4665
110
- // Calendar focus check for ED-10466
111
- if (
112
- browser.ie_version !== 11 &&
113
- !isFocusingCalendar(event) &&
114
- !isFocusingModal(event) &&
115
- !isFocusingFloatingToolbar(event) &&
116
- !isFocusingDragHandles(event) &&
117
- !isFocusingDragHandlesClickableZone(event)
118
- ) {
119
- setEditorFocus(false)(state, dispatch);
120
- }
121
- event.preventDefault();
122
- return false;
96
+ const { state, dispatch } = view;
97
+ // IE version check for ED-4665
98
+ // Calendar focus check for ED-10466
99
+ if (
100
+ browser.ie_version !== 11 &&
101
+ !isFocusingCalendar(event) &&
102
+ !isFocusingModal(event) &&
103
+ !isFocusingFloatingToolbar(event) &&
104
+ !isFocusingDragHandles(event) &&
105
+ !isFocusingDragHandlesClickableZone(event)
106
+ ) {
107
+ setEditorFocus(false)(state, dispatch);
108
+ }
109
+ event.preventDefault();
110
+ return false;
123
111
  };
124
112
 
125
113
  export const handleFocus = (view: EditorView, event: Event): boolean => {
126
- const { state, dispatch } = view;
127
- setEditorFocus(true)(state, dispatch);
128
- event.preventDefault();
129
- return false;
114
+ const { state, dispatch } = view;
115
+ setEditorFocus(true)(state, dispatch);
116
+ event.preventDefault();
117
+ return false;
130
118
  };
131
119
 
132
120
  type HTMLElementIE9 = Omit<HTMLElement, 'matches'> & {
133
- matches?: HTMLElement['matches']; // WARNING: 'matches' is optional in IE9
134
- msMatchesSelector?: (selectors: string) => boolean;
121
+ matches?: HTMLElement['matches']; // WARNING: 'matches' is optional in IE9
122
+ msMatchesSelector?: (selectors: string) => boolean;
135
123
  };
136
124
 
137
125
  export const handleClick = (view: EditorView, event: Event): boolean => {
138
- if (!(event.target instanceof HTMLElement)) {
139
- return false;
140
- }
141
- const element = event.target as HTMLElementIE9;
142
- const table = findTable(view.state.selection)!;
143
-
144
- if (
145
- event instanceof MouseEvent &&
146
- isColumnControlsDecorations(element as HTMLElement)
147
- ) {
148
- const [startIndex] = getColumnOrRowIndex(element as HTMLElement);
149
- const { state, dispatch } = view;
150
-
151
- return selectColumn(startIndex, event.shiftKey)(state, dispatch);
152
- }
153
-
154
- const matchfn = element.matches ? element.matches : element.msMatchesSelector;
155
-
156
- // check if the table cell with an image is clicked and its not the image itself
157
- if (
158
- !table ||
159
- !isElementInTableCell(element as HTMLElement) ||
160
- !matchfn ||
161
- matchfn.call(element, 'table .image, table p, table .image div')
162
- ) {
163
- return false;
164
- }
165
- const map = TableMap.get(table.node);
166
-
167
- /** Getting the offset of current item clicked */
168
- const colElement = (closestElement(element as HTMLElement, 'td') ||
169
- closestElement(element as HTMLElement, 'th')) as HTMLTableDataCellElement;
170
- const colIndex = colElement && colElement.cellIndex;
171
- const rowElement = closestElement(
172
- element as HTMLElement,
173
- 'tr',
174
- ) as HTMLTableRowElement;
175
- const rowIndex = rowElement && rowElement.rowIndex;
176
- const cellIndex = map.width * rowIndex + colIndex;
177
- const {
178
- dispatch,
179
- state: {
180
- tr,
181
- schema: {
182
- nodes: { paragraph },
183
- },
184
- },
185
- } = view;
186
- const cellPos = map.map[cellIndex];
187
- if (isNaN(cellPos) || cellPos === undefined || typeof cellPos !== 'number') {
188
- return false;
189
- }
190
-
191
- const editorElement = table.node.nodeAt(cellPos) as PmNode;
192
- /** Only if the last item is media group, insert a paragraph */
193
- if (isLastItemMediaGroup(editorElement)) {
194
- const posInTable = map.map[cellIndex] + editorElement.nodeSize;
195
- tr.insert(posInTable + table.pos, paragraph.create());
196
- dispatch(tr);
197
- setNodeSelection(view, posInTable + table.pos);
198
- }
199
- return true;
126
+ if (!(event.target instanceof HTMLElement)) {
127
+ return false;
128
+ }
129
+ const element = event.target as HTMLElementIE9;
130
+ const table = findTable(view.state.selection)!;
131
+
132
+ if (event instanceof MouseEvent && isColumnControlsDecorations(element as HTMLElement)) {
133
+ const [startIndex] = getColumnOrRowIndex(element as HTMLElement);
134
+ const { state, dispatch } = view;
135
+
136
+ return selectColumn(startIndex, event.shiftKey)(state, dispatch);
137
+ }
138
+
139
+ const matchfn = element.matches ? element.matches : element.msMatchesSelector;
140
+
141
+ // check if the table cell with an image is clicked and its not the image itself
142
+ if (
143
+ !table ||
144
+ !isElementInTableCell(element as HTMLElement) ||
145
+ !matchfn ||
146
+ matchfn.call(element, 'table .image, table p, table .image div')
147
+ ) {
148
+ return false;
149
+ }
150
+ const map = TableMap.get(table.node);
151
+
152
+ /** Getting the offset of current item clicked */
153
+ const colElement = (closestElement(element as HTMLElement, 'td') ||
154
+ closestElement(element as HTMLElement, 'th')) as HTMLTableDataCellElement;
155
+ const colIndex = colElement && colElement.cellIndex;
156
+ const rowElement = closestElement(element as HTMLElement, 'tr') as HTMLTableRowElement;
157
+ const rowIndex = rowElement && rowElement.rowIndex;
158
+ const cellIndex = map.width * rowIndex + colIndex;
159
+ const {
160
+ dispatch,
161
+ state: {
162
+ tr,
163
+ schema: {
164
+ nodes: { paragraph },
165
+ },
166
+ },
167
+ } = view;
168
+ const cellPos = map.map[cellIndex];
169
+ if (isNaN(cellPos) || cellPos === undefined || typeof cellPos !== 'number') {
170
+ return false;
171
+ }
172
+
173
+ const editorElement = table.node.nodeAt(cellPos) as PmNode;
174
+ /** Only if the last item is media group, insert a paragraph */
175
+ if (isLastItemMediaGroup(editorElement)) {
176
+ const posInTable = map.map[cellIndex] + editorElement.nodeSize;
177
+ tr.insert(posInTable + table.pos, paragraph.create());
178
+ dispatch(tr);
179
+ setNodeSelection(view, posInTable + table.pos);
180
+ }
181
+ return true;
200
182
  };
201
183
 
202
- export const handleMouseOver = (
203
- view: EditorView,
204
- mouseEvent: Event,
205
- ): boolean => {
206
- if (!(mouseEvent.target instanceof HTMLElement)) {
207
- return false;
208
- }
209
- const { state, dispatch } = view;
210
- const target = mouseEvent.target;
211
- const { insertColumnButtonIndex, insertRowButtonIndex, isTableHovered } =
212
- getPluginState(state);
213
-
214
- if (isInsertRowButton(target)) {
215
- const [startIndex, endIndex] = getColumnOrRowIndex(target);
216
-
217
- const positionRow =
218
- getMousePositionVerticalRelativeByElement(mouseEvent as MouseEvent) ===
219
- 'bottom'
220
- ? endIndex
221
- : startIndex;
222
- return showInsertRowButton(positionRow)(state, dispatch);
223
- }
224
-
225
- if (isColumnControlsDecorations(target)) {
226
- const [startIndex] = getColumnOrRowIndex(target);
227
- const { state, dispatch } = view;
228
-
229
- return hoverColumns([startIndex], false)(state, dispatch);
230
- }
231
-
232
- if (
233
- (isCell(target) || isCornerButton(target)) &&
234
- (typeof insertColumnButtonIndex === 'number' ||
235
- typeof insertRowButtonIndex === 'number')
236
- ) {
237
- return hideInsertColumnOrRowButton()(state, dispatch);
238
- }
239
-
240
- if (isResizeHandleDecoration(target)) {
241
- const [startIndex, endIndex] = getColumnOrRowIndex(target);
242
- return showResizeHandleLine({ left: startIndex, right: endIndex })(
243
- state,
244
- dispatch,
245
- );
246
- }
247
-
248
- if (!isTableHovered) {
249
- return setTableHovered(true)(state, dispatch);
250
- }
251
-
252
- return false;
184
+ export const handleMouseOver = (view: EditorView, mouseEvent: Event): boolean => {
185
+ if (!(mouseEvent.target instanceof HTMLElement)) {
186
+ return false;
187
+ }
188
+ const { state, dispatch } = view;
189
+ const target = mouseEvent.target;
190
+ const { insertColumnButtonIndex, insertRowButtonIndex, isTableHovered } = getPluginState(state);
191
+
192
+ if (isInsertRowButton(target)) {
193
+ const [startIndex, endIndex] = getColumnOrRowIndex(target);
194
+
195
+ const positionRow =
196
+ getMousePositionVerticalRelativeByElement(mouseEvent as MouseEvent) === 'bottom'
197
+ ? endIndex
198
+ : startIndex;
199
+ return showInsertRowButton(positionRow)(state, dispatch);
200
+ }
201
+
202
+ if (isColumnControlsDecorations(target)) {
203
+ const [startIndex] = getColumnOrRowIndex(target);
204
+ const { state, dispatch } = view;
205
+
206
+ return hoverColumns([startIndex], false)(state, dispatch);
207
+ }
208
+
209
+ if (
210
+ (isCell(target) || isCornerButton(target)) &&
211
+ (typeof insertColumnButtonIndex === 'number' || typeof insertRowButtonIndex === 'number')
212
+ ) {
213
+ return hideInsertColumnOrRowButton()(state, dispatch);
214
+ }
215
+
216
+ if (isResizeHandleDecoration(target)) {
217
+ const [startIndex, endIndex] = getColumnOrRowIndex(target);
218
+ return showResizeHandleLine({ left: startIndex, right: endIndex })(state, dispatch);
219
+ }
220
+
221
+ if (!isTableHovered) {
222
+ return setTableHovered(true)(state, dispatch);
223
+ }
224
+
225
+ return false;
253
226
  };
254
227
 
255
228
  export const handleMouseUp = (view: EditorView, mouseEvent: Event): boolean => {
256
- if (
257
- !getBooleanFF('platform.editor.table.insert-last-column-btn-stays-in-place')
258
- ) {
259
- return false;
260
- }
261
-
262
- if (!(mouseEvent instanceof MouseEvent)) {
263
- return false;
264
- }
265
- const { state, dispatch } = view;
266
- const { insertColumnButtonIndex, tableNode, tableRef } =
267
- getPluginState(state);
268
-
269
- if (
270
- insertColumnButtonIndex !== undefined &&
271
- tableRef &&
272
- tableRef.parentElement &&
273
- tableNode
274
- ) {
275
- const { width } = TableMap.get(tableNode);
276
- const newInsertColumnButtonIndex = insertColumnButtonIndex + 1;
277
- if (width === newInsertColumnButtonIndex) {
278
- const tableWidth = tableRef.clientWidth;
279
- tableRef.parentElement.scrollTo(tableWidth, 0);
280
-
281
- return showInsertColumnButton(newInsertColumnButtonIndex)(
282
- state,
283
- dispatch,
284
- );
285
- }
286
- }
287
-
288
- return false;
229
+ if (!getBooleanFF('platform.editor.table.insert-last-column-btn-stays-in-place')) {
230
+ return false;
231
+ }
232
+
233
+ if (!(mouseEvent instanceof MouseEvent)) {
234
+ return false;
235
+ }
236
+ const { state, dispatch } = view;
237
+ const { insertColumnButtonIndex, tableNode, tableRef } = getPluginState(state);
238
+
239
+ if (insertColumnButtonIndex !== undefined && tableRef && tableRef.parentElement && tableNode) {
240
+ const { width } = TableMap.get(tableNode);
241
+ const newInsertColumnButtonIndex = insertColumnButtonIndex + 1;
242
+ if (width === newInsertColumnButtonIndex) {
243
+ const tableWidth = tableRef.clientWidth;
244
+ tableRef.parentElement.scrollTo(tableWidth, 0);
245
+
246
+ return showInsertColumnButton(newInsertColumnButtonIndex)(state, dispatch);
247
+ }
248
+ }
249
+
250
+ return false;
289
251
  };
290
252
 
291
253
  // Ignore any `mousedown` `event` from control and numbered column buttons
292
254
  // PM end up changing selection during shift selection if not prevented
293
255
  export const handleMouseDown = (_: EditorView, event: Event) => {
294
- const isControl = !!(
295
- event.target &&
296
- event.target instanceof HTMLElement &&
297
- (isTableContainerOrWrapper(event.target) ||
298
- isColumnControlsDecorations(event.target) ||
299
- isRowControlsButton(event.target) ||
300
- isDragCornerButton(event.target))
301
- );
302
-
303
- if (isControl) {
304
- event.preventDefault();
305
- }
306
-
307
- return isControl;
256
+ const isControl = !!(
257
+ event.target &&
258
+ event.target instanceof HTMLElement &&
259
+ (isTableContainerOrWrapper(event.target) ||
260
+ isColumnControlsDecorations(event.target) ||
261
+ isRowControlsButton(event.target) ||
262
+ isDragCornerButton(event.target))
263
+ );
264
+
265
+ if (isControl) {
266
+ event.preventDefault();
267
+ }
268
+
269
+ return isControl;
308
270
  };
309
271
 
310
- export const handleMouseOut = (
311
- view: EditorView,
312
- mouseEvent: Event,
313
- ): boolean => {
314
- if (
315
- !(mouseEvent instanceof MouseEvent) ||
316
- !(mouseEvent.target instanceof HTMLElement)
317
- ) {
318
- return false;
319
- }
320
-
321
- const target = mouseEvent.target;
322
-
323
- if (isColumnControlsDecorations(target)) {
324
- const { state, dispatch } = view;
325
- return clearHoverSelection()(state, dispatch);
326
- }
327
-
328
- const relatedTarget = mouseEvent.relatedTarget as HTMLElement | null;
329
- // In case the user is moving between cell at the same column
330
- // we don't need to hide the resize handle decoration
331
- if (
332
- isResizeHandleDecoration(target) &&
333
- !isResizeHandleDecoration(relatedTarget)
334
- ) {
335
- const { state, dispatch } = view;
336
- if (getBooleanFF('platform.editor.a11y-column-resizing_emcvz')) {
337
- const { isKeyboardResize } = getPluginState(state);
338
- if (isKeyboardResize) {
339
- // no need to hide decoration if column resizing started by keyboard
340
- return false;
341
- }
342
- return hideResizeHandleLine()(state, dispatch);
343
- } else {
344
- return hideResizeHandleLine()(state, dispatch);
345
- }
346
- }
347
-
348
- return false;
272
+ export const handleMouseOut = (view: EditorView, mouseEvent: Event): boolean => {
273
+ if (!(mouseEvent instanceof MouseEvent) || !(mouseEvent.target instanceof HTMLElement)) {
274
+ return false;
275
+ }
276
+
277
+ const target = mouseEvent.target;
278
+
279
+ if (isColumnControlsDecorations(target)) {
280
+ const { state, dispatch } = view;
281
+ return clearHoverSelection()(state, dispatch);
282
+ }
283
+
284
+ const relatedTarget = mouseEvent.relatedTarget as HTMLElement | null;
285
+ // In case the user is moving between cell at the same column
286
+ // we don't need to hide the resize handle decoration
287
+ if (isResizeHandleDecoration(target) && !isResizeHandleDecoration(relatedTarget)) {
288
+ const { state, dispatch } = view;
289
+ if (getBooleanFF('platform.editor.a11y-column-resizing_emcvz')) {
290
+ const { isKeyboardResize } = getPluginState(state);
291
+ if (isKeyboardResize) {
292
+ // no need to hide decoration if column resizing started by keyboard
293
+ return false;
294
+ }
295
+ return hideResizeHandleLine()(state, dispatch);
296
+ } else {
297
+ return hideResizeHandleLine()(state, dispatch);
298
+ }
299
+ }
300
+
301
+ return false;
349
302
  };
350
303
 
351
- export const handleMouseEnter = (
352
- view: EditorView,
353
- mouseEvent: Event,
354
- ): boolean => {
355
- const { state, dispatch } = view;
304
+ export const handleMouseEnter = (view: EditorView, mouseEvent: Event): boolean => {
305
+ const { state, dispatch } = view;
356
306
 
357
- const { isTableHovered } = getPluginState(state);
307
+ const { isTableHovered } = getPluginState(state);
358
308
 
359
- if (!isTableHovered) {
360
- return setTableHovered(true)(state, dispatch);
361
- }
309
+ if (!isTableHovered) {
310
+ return setTableHovered(true)(state, dispatch);
311
+ }
362
312
 
363
- return false;
313
+ return false;
364
314
  };
365
315
 
366
316
  export const handleMouseLeave = (view: EditorView, event: Event): boolean => {
367
- if (!(event.target instanceof HTMLElement)) {
368
- return false;
369
- }
370
-
371
- const { state, dispatch } = view;
372
- const {
373
- insertColumnButtonIndex,
374
- insertRowButtonIndex,
375
- isDragAndDropEnabled,
376
- isTableHovered,
377
- } = getPluginState(state);
378
-
379
- if (isTableHovered) {
380
- if (isDragAndDropEnabled) {
381
- const { isDragMenuOpen } = getDragDropPluginState(state);
382
- !isDragMenuOpen && setTableHovered(false)(state, dispatch);
383
- } else {
384
- setTableHovered(false)(state, dispatch);
385
- }
386
- return true;
387
- }
388
-
389
- // If this table doesn't have focus then we want to skip everything after this.
390
- if (!isTableInFocus(view)) {
391
- return false;
392
- }
393
-
394
- const target = event.target;
395
- if (isTableControlsButton(target)) {
396
- return true;
397
- }
398
-
399
- if (
400
- (typeof insertColumnButtonIndex !== 'undefined' ||
401
- typeof insertRowButtonIndex !== 'undefined') &&
402
- hideInsertColumnOrRowButton()(state, dispatch)
403
- ) {
404
- return true;
405
- }
406
-
407
- return false;
317
+ if (!(event.target instanceof HTMLElement)) {
318
+ return false;
319
+ }
320
+
321
+ const { state, dispatch } = view;
322
+ const { insertColumnButtonIndex, insertRowButtonIndex, isDragAndDropEnabled, isTableHovered } =
323
+ getPluginState(state);
324
+
325
+ if (isTableHovered) {
326
+ if (isDragAndDropEnabled) {
327
+ const { isDragMenuOpen } = getDragDropPluginState(state);
328
+ !isDragMenuOpen && setTableHovered(false)(state, dispatch);
329
+ } else {
330
+ setTableHovered(false)(state, dispatch);
331
+ }
332
+ return true;
333
+ }
334
+
335
+ // If this table doesn't have focus then we want to skip everything after this.
336
+ if (!isTableInFocus(view)) {
337
+ return false;
338
+ }
339
+
340
+ const target = event.target;
341
+ if (isTableControlsButton(target)) {
342
+ return true;
343
+ }
344
+
345
+ if (
346
+ (typeof insertColumnButtonIndex !== 'undefined' ||
347
+ typeof insertRowButtonIndex !== 'undefined') &&
348
+ hideInsertColumnOrRowButton()(state, dispatch)
349
+ ) {
350
+ return true;
351
+ }
352
+
353
+ return false;
408
354
  };
409
355
 
410
356
  // IMPORTANT: The mouse move handler has been setup with RAF schedule to avoid Reflows which will occur as some methods
411
357
  // need to access the mouse event offset position and also the target clientWidth vallue.
412
358
  const handleMouseMoveDebounce = rafSchedule(
413
- (view: EditorView, event: MouseEvent, offsetX: number) => {
414
- if (!(event.target instanceof HTMLElement)) {
415
- return false;
416
- }
417
- const element = event.target;
418
-
419
- if (
420
- isColumnControlsDecorations(element) ||
421
- isDragColumnFloatingInsertDot(element)
422
- ) {
423
- const { state, dispatch } = view;
424
- const { insertColumnButtonIndex } = getPluginState(state);
425
- const [startIndex, endIndex] = getColumnOrRowIndex(element);
426
-
427
- const positionColumn =
428
- getMousePositionHorizontalRelativeByElement(
429
- event,
430
- offsetX,
431
- undefined,
432
- ) === 'right'
433
- ? endIndex
434
- : startIndex;
435
-
436
- if (positionColumn !== insertColumnButtonIndex) {
437
- return showInsertColumnButton(positionColumn)(state, dispatch);
438
- }
439
- }
440
-
441
- if (isRowControlsButton(element) || isDragRowFloatingInsertDot(element)) {
442
- const { state, dispatch } = view;
443
- const { insertRowButtonIndex } = getPluginState(state);
444
- const [startIndex, endIndex] = getColumnOrRowIndex(element);
445
-
446
- const positionRow =
447
- getMousePositionVerticalRelativeByElement(event) === 'bottom'
448
- ? endIndex
449
- : startIndex;
450
-
451
- if (positionRow !== insertRowButtonIndex) {
452
- return showInsertRowButton(positionRow)(state, dispatch);
453
- }
454
- }
455
-
456
- if (!isResizeHandleDecoration(element) && isCell(element)) {
457
- const positionColumn = getMousePositionHorizontalRelativeByElement(
458
- event,
459
- offsetX,
460
- RESIZE_HANDLE_AREA_DECORATION_GAP,
461
- );
462
-
463
- if (positionColumn !== null) {
464
- const { state, dispatch } = view;
465
- const { resizeHandleColumnIndex, resizeHandleRowIndex } =
466
- getPluginState(state);
467
-
468
- const isKeyboardResize = getBooleanFF(
469
- 'platform.editor.a11y-column-resizing_emcvz',
470
- )
471
- ? getPluginState(state).isKeyboardResize
472
- : false;
473
- const tableCell = closestElement(
474
- element,
475
- 'td, th',
476
- ) as HTMLTableCellElement;
477
- const cellStartPosition = view.posAtDOM(tableCell, 0);
478
- const rect = findCellRectClosestToPos(
479
- state.doc.resolve(cellStartPosition),
480
- );
481
-
482
- if (rect) {
483
- const columnEndIndexTarget =
484
- positionColumn === 'left' ? rect.left : rect.right;
485
-
486
- const rowIndexTarget = rect.top;
487
-
488
- if (
489
- (columnEndIndexTarget !== resizeHandleColumnIndex ||
490
- rowIndexTarget !== resizeHandleRowIndex ||
491
- !hasResizeHandler({ target: element, columnEndIndexTarget })) &&
492
- !isKeyboardResize // if initiated by keyboard don't need to react on hover for other resize sliders
493
- ) {
494
- return addResizeHandleDecorations(
495
- rowIndexTarget,
496
- columnEndIndexTarget,
497
- true,
498
- )(state, dispatch);
499
- }
500
- }
501
- }
502
- }
503
-
504
- return false;
505
- },
359
+ (view: EditorView, event: MouseEvent, offsetX: number) => {
360
+ if (!(event.target instanceof HTMLElement)) {
361
+ return false;
362
+ }
363
+ const element = event.target;
364
+
365
+ if (isColumnControlsDecorations(element) || isDragColumnFloatingInsertDot(element)) {
366
+ const { state, dispatch } = view;
367
+ const { insertColumnButtonIndex } = getPluginState(state);
368
+ const [startIndex, endIndex] = getColumnOrRowIndex(element);
369
+
370
+ const positionColumn =
371
+ getMousePositionHorizontalRelativeByElement(event, offsetX, undefined) === 'right'
372
+ ? endIndex
373
+ : startIndex;
374
+
375
+ if (positionColumn !== insertColumnButtonIndex) {
376
+ return showInsertColumnButton(positionColumn)(state, dispatch);
377
+ }
378
+ }
379
+
380
+ if (isRowControlsButton(element) || isDragRowFloatingInsertDot(element)) {
381
+ const { state, dispatch } = view;
382
+ const { insertRowButtonIndex } = getPluginState(state);
383
+ const [startIndex, endIndex] = getColumnOrRowIndex(element);
384
+
385
+ const positionRow =
386
+ getMousePositionVerticalRelativeByElement(event) === 'bottom' ? endIndex : startIndex;
387
+
388
+ if (positionRow !== insertRowButtonIndex) {
389
+ return showInsertRowButton(positionRow)(state, dispatch);
390
+ }
391
+ }
392
+
393
+ if (!isResizeHandleDecoration(element) && isCell(element)) {
394
+ const positionColumn = getMousePositionHorizontalRelativeByElement(
395
+ event,
396
+ offsetX,
397
+ RESIZE_HANDLE_AREA_DECORATION_GAP,
398
+ );
399
+
400
+ if (positionColumn !== null) {
401
+ const { state, dispatch } = view;
402
+ const { resizeHandleColumnIndex, resizeHandleRowIndex } = getPluginState(state);
403
+
404
+ const isKeyboardResize = getBooleanFF('platform.editor.a11y-column-resizing_emcvz')
405
+ ? getPluginState(state).isKeyboardResize
406
+ : false;
407
+ const tableCell = closestElement(element, 'td, th') as HTMLTableCellElement;
408
+ const cellStartPosition = view.posAtDOM(tableCell, 0);
409
+ const rect = findCellRectClosestToPos(state.doc.resolve(cellStartPosition));
410
+
411
+ if (rect) {
412
+ const columnEndIndexTarget = positionColumn === 'left' ? rect.left : rect.right;
413
+
414
+ const rowIndexTarget = rect.top;
415
+
416
+ if (
417
+ (columnEndIndexTarget !== resizeHandleColumnIndex ||
418
+ rowIndexTarget !== resizeHandleRowIndex ||
419
+ !hasResizeHandler({ target: element, columnEndIndexTarget })) &&
420
+ !isKeyboardResize // if initiated by keyboard don't need to react on hover for other resize sliders
421
+ ) {
422
+ return addResizeHandleDecorations(
423
+ rowIndexTarget,
424
+ columnEndIndexTarget,
425
+ true,
426
+ )(state, dispatch);
427
+ }
428
+ }
429
+ }
430
+ }
431
+
432
+ return false;
433
+ },
506
434
  );
507
435
 
508
436
  export const handleMouseMove = (view: EditorView, event: Event) => {
509
- if (!(event.target instanceof HTMLElement)) {
510
- return false;
511
- }
512
-
513
- // NOTE: When accessing offsetX in gecko from a deferred callback, it will return 0. However it will be non-zero if accessed
514
- // within the scope of it's initial mouse move handler. Also Chrome does return the correct value, however it could trigger
515
- // a reflow. So for now this will just grab the offsetX value immediately for gecko and chrome will calculate later
516
- // in the deferred callback handler.
517
- // Bug Tracking: https://bugzilla.mozilla.org/show_bug.cgi?id=1882903
518
- handleMouseMoveDebounce(
519
- view,
520
- event as MouseEvent,
521
- browser.gecko ? (event as MouseEvent).offsetX : NaN,
522
- );
523
- return false;
437
+ if (!(event.target instanceof HTMLElement)) {
438
+ return false;
439
+ }
440
+
441
+ // NOTE: When accessing offsetX in gecko from a deferred callback, it will return 0. However it will be non-zero if accessed
442
+ // within the scope of it's initial mouse move handler. Also Chrome does return the correct value, however it could trigger
443
+ // a reflow. So for now this will just grab the offsetX value immediately for gecko and chrome will calculate later
444
+ // in the deferred callback handler.
445
+ // Bug Tracking: https://bugzilla.mozilla.org/show_bug.cgi?id=1882903
446
+ handleMouseMoveDebounce(
447
+ view,
448
+ event as MouseEvent,
449
+ browser.gecko ? (event as MouseEvent).offsetX : NaN,
450
+ );
451
+ return false;
524
452
  };
525
453
 
526
454
  export function handleTripleClick(view: EditorView, pos: number) {
527
- const { state, dispatch } = view;
528
- const $cellPos = cellAround(state.doc.resolve(pos));
529
- if (!$cellPos) {
530
- return false;
531
- }
532
-
533
- const cell = state.doc.nodeAt($cellPos.pos);
534
- if (cell) {
535
- const selFrom = Selection.findFrom($cellPos, 1, true);
536
- const selTo = Selection.findFrom(
537
- state.doc.resolve($cellPos.pos + cell.nodeSize),
538
- -1,
539
- true,
540
- );
541
- if (selFrom && selTo) {
542
- dispatch(
543
- state.tr.setSelection(new TextSelection(selFrom.$from, selTo.$to)),
544
- );
545
- return true;
546
- }
547
- }
548
-
549
- return false;
455
+ const { state, dispatch } = view;
456
+ const $cellPos = cellAround(state.doc.resolve(pos));
457
+ if (!$cellPos) {
458
+ return false;
459
+ }
460
+
461
+ const cell = state.doc.nodeAt($cellPos.pos);
462
+ if (cell) {
463
+ const selFrom = Selection.findFrom($cellPos, 1, true);
464
+ const selTo = Selection.findFrom(state.doc.resolve($cellPos.pos + cell.nodeSize), -1, true);
465
+ if (selFrom && selTo) {
466
+ dispatch(state.tr.setSelection(new TextSelection(selFrom.$from, selTo.$to)));
467
+ return true;
468
+ }
469
+ }
470
+
471
+ return false;
550
472
  }
551
473
  export const handleCut = (
552
- oldTr: Transaction,
553
- oldState: EditorState,
554
- newState: EditorState,
555
- editorAnalyticsAPI?: EditorAnalyticsAPI,
556
- editorView?: EditorView,
557
- isTableScalingEnabled = false,
474
+ oldTr: Transaction,
475
+ oldState: EditorState,
476
+ newState: EditorState,
477
+ editorAnalyticsAPI?: EditorAnalyticsAPI,
478
+ editorView?: EditorView,
479
+ isTableScalingEnabled = false,
558
480
  ): Transaction => {
559
- const oldSelection = oldState.tr.selection;
560
- let { tr } = newState;
561
- if (oldSelection instanceof CellSelection) {
562
- const $anchorCell = oldTr.doc.resolve(
563
- oldTr.mapping.map(oldSelection.$anchorCell.pos),
564
- );
565
- const $headCell = oldTr.doc.resolve(
566
- oldTr.mapping.map(oldSelection.$headCell.pos),
567
- );
568
-
569
- const cellSelection = new CellSelection($anchorCell, $headCell);
570
- tr.setSelection(cellSelection);
571
-
572
- if (tr.selection instanceof CellSelection) {
573
- const rect = getSelectionRect(cellSelection);
574
- if (rect) {
575
- const {
576
- verticalCells,
577
- horizontalCells,
578
- totalCells,
579
- totalRowCount,
580
- totalColumnCount,
581
- } = getSelectedCellInfo(tr.selection);
582
-
583
- // Reassigning to make it more obvious and consistent
584
- editorAnalyticsAPI?.attachAnalyticsEvent({
585
- action: TABLE_ACTION.CUT,
586
- actionSubject: ACTION_SUBJECT.TABLE,
587
- actionSubjectId: null,
588
- attributes: {
589
- verticalCells,
590
- horizontalCells,
591
- totalCells,
592
- totalRowCount,
593
- totalColumnCount,
594
- },
595
- eventType: EVENT_TYPE.TRACK,
596
- })(tr);
597
-
598
- // Need this check again since we are overriding the tr in previous statement
599
- if (tr.selection instanceof CellSelection) {
600
- const isTableSelected =
601
- tr.selection.isRowSelection() && tr.selection.isColSelection();
602
- if (isTableSelected) {
603
- tr = removeTable(tr);
604
- } else if (tr.selection.isRowSelection()) {
605
- const {
606
- pluginConfig: { isHeaderRowRequired },
607
- } = getPluginState(newState);
608
- tr = deleteRows(rect, isHeaderRowRequired)(tr);
609
- } else if (tr.selection.isColSelection()) {
610
- tr = deleteColumns(
611
- rect,
612
- getAllowAddColumnCustomStep(oldState),
613
- editorView,
614
- isTableScalingEnabled,
615
- )(tr);
616
- }
617
- }
618
- }
619
- }
620
- }
621
-
622
- return tr;
481
+ const oldSelection = oldState.tr.selection;
482
+ let { tr } = newState;
483
+ if (oldSelection instanceof CellSelection) {
484
+ const $anchorCell = oldTr.doc.resolve(oldTr.mapping.map(oldSelection.$anchorCell.pos));
485
+ const $headCell = oldTr.doc.resolve(oldTr.mapping.map(oldSelection.$headCell.pos));
486
+
487
+ const cellSelection = new CellSelection($anchorCell, $headCell);
488
+ tr.setSelection(cellSelection);
489
+
490
+ if (tr.selection instanceof CellSelection) {
491
+ const rect = getSelectionRect(cellSelection);
492
+ if (rect) {
493
+ const { verticalCells, horizontalCells, totalCells, totalRowCount, totalColumnCount } =
494
+ getSelectedCellInfo(tr.selection);
495
+
496
+ // Reassigning to make it more obvious and consistent
497
+ editorAnalyticsAPI?.attachAnalyticsEvent({
498
+ action: TABLE_ACTION.CUT,
499
+ actionSubject: ACTION_SUBJECT.TABLE,
500
+ actionSubjectId: null,
501
+ attributes: {
502
+ verticalCells,
503
+ horizontalCells,
504
+ totalCells,
505
+ totalRowCount,
506
+ totalColumnCount,
507
+ },
508
+ eventType: EVENT_TYPE.TRACK,
509
+ })(tr);
510
+
511
+ // Need this check again since we are overriding the tr in previous statement
512
+ if (tr.selection instanceof CellSelection) {
513
+ const isTableSelected = tr.selection.isRowSelection() && tr.selection.isColSelection();
514
+ if (isTableSelected) {
515
+ tr = removeTable(tr);
516
+ } else if (tr.selection.isRowSelection()) {
517
+ const {
518
+ pluginConfig: { isHeaderRowRequired },
519
+ } = getPluginState(newState);
520
+ tr = deleteRows(rect, isHeaderRowRequired)(tr);
521
+ } else if (tr.selection.isColSelection()) {
522
+ tr = deleteColumns(
523
+ rect,
524
+ getAllowAddColumnCustomStep(oldState),
525
+ editorView,
526
+ isTableScalingEnabled,
527
+ )(tr);
528
+ }
529
+ }
530
+ }
531
+ }
532
+ }
533
+
534
+ return tr;
623
535
  };
624
536
 
625
537
  export const isTableInFocus = (view: EditorView) => {
626
- return (
627
- !!getPluginState(view.state)?.tableNode &&
628
- !getResizePluginState(view.state)?.dragging
629
- );
538
+ return !!getPluginState(view.state)?.tableNode && !getResizePluginState(view.state)?.dragging;
630
539
  };
631
540
 
632
541
  export const whenTableInFocus =
633
- (eventHandler: (view: EditorView, mouseEvent: Event) => boolean) =>
634
- (view: EditorView, mouseEvent: Event): boolean => {
635
- if (!isTableInFocus(view)) {
636
- return false;
637
- }
542
+ (eventHandler: (view: EditorView, mouseEvent: Event) => boolean) =>
543
+ (view: EditorView, mouseEvent: Event): boolean => {
544
+ if (!isTableInFocus(view)) {
545
+ return false;
546
+ }
638
547
 
639
- return eventHandler(view, mouseEvent);
640
- };
548
+ return eventHandler(view, mouseEvent);
549
+ };
641
550
 
642
551
  const trackCellLocation = (view: EditorView, mouseEvent: Event) => {
643
- const target = mouseEvent.target;
644
- const maybeTableCell = isElementInTableCell(
645
- target as HTMLElement,
646
- ) as HTMLTableCellElement | null;
647
- const { tableNode, tableRef } = getPluginState(view.state);
648
-
649
- const tableElement = closestElement(
650
- target as HTMLElement,
651
- 'table',
652
- ) as HTMLTableElement;
653
-
654
- // hover will only trigger if target localId is the same with selected localId
655
- if (
656
- tableElement?.dataset?.tableLocalId &&
657
- tableElement.dataset.tableLocalId !== tableNode?.attrs.localId
658
- ) {
659
- return;
660
- }
661
-
662
- if (!maybeTableCell || !tableRef) {
663
- return;
664
- }
665
-
666
- const htmlColIndex = maybeTableCell.cellIndex;
667
- const rowElement = closestElement(
668
- target as HTMLElement,
669
- 'tr',
670
- ) as HTMLTableRowElement;
671
- const htmlRowIndex = rowElement && rowElement.rowIndex;
672
-
673
- const tableMap = tableNode && TableMap.get(tableNode);
674
- let colIndex = htmlColIndex;
675
- if (tableMap) {
676
- const convertedColIndex = convertHTMLCellIndexToColumnIndex(
677
- htmlColIndex,
678
- htmlRowIndex,
679
- tableMap,
680
- );
681
-
682
- colIndex = getColumnIndexMappedToColumnIndexInFirstRow(
683
- convertedColIndex,
684
- htmlRowIndex,
685
- tableMap,
686
- );
687
- }
688
-
689
- hoverCell(htmlRowIndex, colIndex)(view.state, view.dispatch);
552
+ const target = mouseEvent.target;
553
+ const maybeTableCell = isElementInTableCell(target as HTMLElement) as HTMLTableCellElement | null;
554
+ const { tableNode, tableRef } = getPluginState(view.state);
555
+
556
+ const tableElement = closestElement(target as HTMLElement, 'table') as HTMLTableElement;
557
+
558
+ // hover will only trigger if target localId is the same with selected localId
559
+ if (
560
+ tableElement?.dataset?.tableLocalId &&
561
+ tableElement.dataset.tableLocalId !== tableNode?.attrs.localId
562
+ ) {
563
+ return;
564
+ }
565
+
566
+ if (!maybeTableCell || !tableRef) {
567
+ return;
568
+ }
569
+
570
+ const htmlColIndex = maybeTableCell.cellIndex;
571
+ const rowElement = closestElement(target as HTMLElement, 'tr') as HTMLTableRowElement;
572
+ const htmlRowIndex = rowElement && rowElement.rowIndex;
573
+
574
+ const tableMap = tableNode && TableMap.get(tableNode);
575
+ let colIndex = htmlColIndex;
576
+ if (tableMap) {
577
+ const convertedColIndex = convertHTMLCellIndexToColumnIndex(
578
+ htmlColIndex,
579
+ htmlRowIndex,
580
+ tableMap,
581
+ );
582
+
583
+ colIndex = getColumnIndexMappedToColumnIndexInFirstRow(
584
+ convertedColIndex,
585
+ htmlRowIndex,
586
+ tableMap,
587
+ );
588
+ }
589
+
590
+ hoverCell(htmlRowIndex, colIndex)(view.state, view.dispatch);
690
591
  };
691
592
 
692
593
  export const withCellTracking =
693
- (eventHandler: (view: EditorView, mouseEvent: Event) => boolean) =>
694
- (view: EditorView, mouseEvent: Event): boolean => {
695
- if (
696
- getPluginState(view.state).isDragAndDropEnabled &&
697
- !getDragDropPluginState(view.state).isDragging
698
- ) {
699
- trackCellLocation(view, mouseEvent);
700
- }
701
- return eventHandler(view, mouseEvent);
702
- };
594
+ (eventHandler: (view: EditorView, mouseEvent: Event) => boolean) =>
595
+ (view: EditorView, mouseEvent: Event): boolean => {
596
+ if (
597
+ getPluginState(view.state).isDragAndDropEnabled &&
598
+ !getDragDropPluginState(view.state).isDragging
599
+ ) {
600
+ trackCellLocation(view, mouseEvent);
601
+ }
602
+ return eventHandler(view, mouseEvent);
603
+ };