@atlaskit/editor-plugin-table 7.16.11 → 7.16.13

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