@atlaskit/editor-plugin-table 7.16.11 → 7.16.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (242) hide show
  1. package/.eslintrc.js +3 -3
  2. package/CHANGELOG.md +8 -0
  3. package/dist/cjs/commands/misc.js +3 -3
  4. package/dist/cjs/nodeviews/TableCell.js +10 -10
  5. package/dist/cjs/nodeviews/TableContainer.js +41 -6
  6. package/dist/cjs/nodeviews/TableResizer.js +7 -7
  7. package/dist/cjs/nodeviews/TableRow.js +23 -23
  8. package/dist/cjs/pm-plugins/table-resizing/plugin.js +3 -3
  9. package/dist/cjs/pm-plugins/table-resizing/utils/resize-state.js +4 -4
  10. package/dist/cjs/pm-plugins/table-resizing/utils/scale-table.js +3 -3
  11. package/dist/cjs/ui/FloatingContextualMenu/styles.js +1 -1
  12. package/dist/cjs/ui/FloatingDragMenu/styles.js +1 -1
  13. package/dist/cjs/ui/common-styles.js +13 -13
  14. package/dist/cjs/ui/ui-styles.js +25 -25
  15. package/dist/cjs/utils/merged-cells.js +3 -3
  16. package/dist/es2019/commands/misc.js +3 -3
  17. package/dist/es2019/nodeviews/TableContainer.js +43 -5
  18. package/dist/es2019/nodeviews/TableResizer.js +7 -7
  19. package/dist/es2019/nodeviews/TableRow.js +21 -21
  20. package/dist/es2019/pm-plugins/table-resizing/plugin.js +3 -3
  21. package/dist/es2019/pm-plugins/table-resizing/utils/resize-state.js +4 -4
  22. package/dist/es2019/pm-plugins/table-resizing/utils/scale-table.js +3 -3
  23. package/dist/es2019/ui/FloatingContextualMenu/styles.js +47 -47
  24. package/dist/es2019/ui/FloatingDragMenu/styles.js +30 -30
  25. package/dist/es2019/ui/common-styles.js +802 -816
  26. package/dist/es2019/ui/ui-styles.js +665 -678
  27. package/dist/es2019/utils/merged-cells.js +3 -3
  28. package/dist/esm/commands/misc.js +3 -3
  29. package/dist/esm/nodeviews/TableCell.js +10 -10
  30. package/dist/esm/nodeviews/TableContainer.js +42 -7
  31. package/dist/esm/nodeviews/TableResizer.js +7 -7
  32. package/dist/esm/nodeviews/TableRow.js +23 -23
  33. package/dist/esm/pm-plugins/table-resizing/plugin.js +3 -3
  34. package/dist/esm/pm-plugins/table-resizing/utils/resize-state.js +4 -4
  35. package/dist/esm/pm-plugins/table-resizing/utils/scale-table.js +3 -3
  36. package/dist/esm/ui/FloatingContextualMenu/styles.js +1 -1
  37. package/dist/esm/ui/FloatingDragMenu/styles.js +1 -1
  38. package/dist/esm/ui/common-styles.js +13 -13
  39. package/dist/esm/ui/ui-styles.js +25 -25
  40. package/dist/esm/utils/merged-cells.js +3 -3
  41. package/dist/types/pm-plugins/decorations/utils/index.d.ts +1 -1
  42. package/dist/types/pm-plugins/drag-and-drop/utils/autoscrollers.d.ts +1 -1
  43. package/dist/types/pm-plugins/drag-and-drop/utils/getDragBehaviour.d.ts +1 -1
  44. package/dist/types/pm-plugins/table-resizing/utils/index.d.ts +1 -1
  45. package/dist/types/ui/ColumnResizeWidget/index.d.ts +1 -1
  46. package/dist/types/ui/FloatingAlignmentButtons/FloatingAlignmentButtons.d.ts +1 -1
  47. package/dist/types/ui/FloatingToolbarLabel/FloatingToolbarLabel.d.ts +1 -1
  48. package/dist/types/ui/TableFloatingColumnControls/ColumnDropTargets/ColumnDropTarget.d.ts +1 -1
  49. package/dist/types/ui/TableFloatingControls/CornerControls/index.d.ts +1 -1
  50. package/dist/types/ui/icons/DragHandleDisabledIcon.d.ts +1 -1
  51. package/dist/types-ts4.5/pm-plugins/decorations/utils/index.d.ts +1 -1
  52. package/dist/types-ts4.5/pm-plugins/drag-and-drop/utils/autoscrollers.d.ts +1 -1
  53. package/dist/types-ts4.5/pm-plugins/drag-and-drop/utils/getDragBehaviour.d.ts +1 -1
  54. package/dist/types-ts4.5/pm-plugins/table-resizing/utils/index.d.ts +1 -1
  55. package/dist/types-ts4.5/ui/ColumnResizeWidget/index.d.ts +1 -1
  56. package/dist/types-ts4.5/ui/FloatingAlignmentButtons/FloatingAlignmentButtons.d.ts +1 -1
  57. package/dist/types-ts4.5/ui/FloatingToolbarLabel/FloatingToolbarLabel.d.ts +1 -1
  58. package/dist/types-ts4.5/ui/TableFloatingColumnControls/ColumnDropTargets/ColumnDropTarget.d.ts +1 -1
  59. package/dist/types-ts4.5/ui/TableFloatingControls/CornerControls/index.d.ts +1 -1
  60. package/dist/types-ts4.5/ui/icons/DragHandleDisabledIcon.d.ts +1 -1
  61. package/docs/0-intro.tsx +9 -7
  62. package/package.json +2 -2
  63. package/report.api.md +67 -66
  64. package/src/commands/clear.ts +36 -44
  65. package/src/commands/collapse.ts +8 -8
  66. package/src/commands/column-resize.ts +412 -452
  67. package/src/commands/delete.ts +14 -14
  68. package/src/commands/display-mode.ts +10 -11
  69. package/src/commands/go-to-next-cell.ts +48 -54
  70. package/src/commands/hover.ts +210 -227
  71. package/src/commands/index.ts +35 -35
  72. package/src/commands/insert.ts +208 -235
  73. package/src/commands/misc.ts +655 -748
  74. package/src/commands/referentiality.ts +9 -9
  75. package/src/commands/selection.ts +433 -563
  76. package/src/commands/sort.ts +68 -86
  77. package/src/commands/split-cell.ts +14 -14
  78. package/src/commands/toggle.ts +69 -67
  79. package/src/commands-with-analytics.ts +570 -639
  80. package/src/create-plugin-config.ts +13 -13
  81. package/src/event-handlers.ts +513 -612
  82. package/src/handlers.ts +120 -133
  83. package/src/nodeviews/ExternalDropTargets.tsx +68 -73
  84. package/src/nodeviews/OverflowShadowsObserver.ts +148 -157
  85. package/src/nodeviews/TableCell.ts +47 -54
  86. package/src/nodeviews/TableComponent.tsx +1018 -1112
  87. package/src/nodeviews/TableComponentWithSharedState.tsx +91 -94
  88. package/src/nodeviews/TableContainer.tsx +363 -339
  89. package/src/nodeviews/TableNodeViewBase.ts +19 -24
  90. package/src/nodeviews/TableResizer.tsx +565 -657
  91. package/src/nodeviews/TableRow.ts +580 -629
  92. package/src/nodeviews/TableStickyScrollbar.ts +173 -190
  93. package/src/nodeviews/__mocks__/OverflowShadowsObserver.ts +8 -8
  94. package/src/nodeviews/__mocks__/OverridableMock.ts +14 -15
  95. package/src/nodeviews/table.tsx +345 -375
  96. package/src/nodeviews/types.ts +21 -24
  97. package/src/nodeviews/update-overflow-shadows.ts +8 -14
  98. package/src/plugin.tsx +578 -603
  99. package/src/pm-plugins/analytics/actions.ts +10 -12
  100. package/src/pm-plugins/analytics/commands.ts +31 -37
  101. package/src/pm-plugins/analytics/plugin-factory.ts +4 -2
  102. package/src/pm-plugins/analytics/plugin-key.ts +1 -3
  103. package/src/pm-plugins/analytics/plugin.ts +60 -70
  104. package/src/pm-plugins/analytics/reducer.ts +19 -19
  105. package/src/pm-plugins/analytics/types.ts +10 -10
  106. package/src/pm-plugins/analytics/utils/moved-event.ts +38 -38
  107. package/src/pm-plugins/decorations/plugin.ts +58 -77
  108. package/src/pm-plugins/decorations/utils/column-controls.ts +59 -71
  109. package/src/pm-plugins/decorations/utils/column-resizing.ts +50 -57
  110. package/src/pm-plugins/decorations/utils/compose-decorations.ts +6 -6
  111. package/src/pm-plugins/decorations/utils/index.ts +3 -6
  112. package/src/pm-plugins/decorations/utils/types.ts +7 -12
  113. package/src/pm-plugins/default-table-selection.ts +3 -3
  114. package/src/pm-plugins/drag-and-drop/actions.ts +25 -25
  115. package/src/pm-plugins/drag-and-drop/commands-with-analytics.ts +158 -190
  116. package/src/pm-plugins/drag-and-drop/commands.ts +154 -170
  117. package/src/pm-plugins/drag-and-drop/consts.ts +4 -5
  118. package/src/pm-plugins/drag-and-drop/plugin-factory.ts +23 -20
  119. package/src/pm-plugins/drag-and-drop/plugin-key.ts +1 -3
  120. package/src/pm-plugins/drag-and-drop/plugin.ts +329 -383
  121. package/src/pm-plugins/drag-and-drop/reducer.ts +30 -30
  122. package/src/pm-plugins/drag-and-drop/types.ts +8 -8
  123. package/src/pm-plugins/drag-and-drop/utils/autoscrollers.ts +38 -41
  124. package/src/pm-plugins/drag-and-drop/utils/getDragBehaviour.ts +3 -6
  125. package/src/pm-plugins/drag-and-drop/utils/monitor.ts +57 -70
  126. package/src/pm-plugins/keymap.ts +208 -220
  127. package/src/pm-plugins/main.ts +348 -400
  128. package/src/pm-plugins/plugin-factory.ts +32 -34
  129. package/src/pm-plugins/safari-delete-composition-text-issue-workaround.ts +83 -97
  130. package/src/pm-plugins/sticky-headers/commands.ts +2 -6
  131. package/src/pm-plugins/sticky-headers/plugin-key.ts +1 -3
  132. package/src/pm-plugins/sticky-headers/plugin-state.ts +41 -44
  133. package/src/pm-plugins/sticky-headers/plugin.ts +4 -4
  134. package/src/pm-plugins/sticky-headers/types.ts +8 -8
  135. package/src/pm-plugins/sticky-headers/util.ts +10 -10
  136. package/src/pm-plugins/table-analytics.ts +70 -72
  137. package/src/pm-plugins/table-local-id.ts +180 -184
  138. package/src/pm-plugins/table-resizing/commands.ts +72 -85
  139. package/src/pm-plugins/table-resizing/event-handlers.ts +298 -317
  140. package/src/pm-plugins/table-resizing/plugin-factory.ts +10 -10
  141. package/src/pm-plugins/table-resizing/plugin-key.ts +1 -3
  142. package/src/pm-plugins/table-resizing/plugin.ts +61 -68
  143. package/src/pm-plugins/table-resizing/reducer.ts +30 -33
  144. package/src/pm-plugins/table-resizing/utils/colgroup.ts +84 -84
  145. package/src/pm-plugins/table-resizing/utils/column-state.ts +78 -81
  146. package/src/pm-plugins/table-resizing/utils/content-width.ts +94 -114
  147. package/src/pm-plugins/table-resizing/utils/dom.ts +93 -110
  148. package/src/pm-plugins/table-resizing/utils/index.ts +29 -34
  149. package/src/pm-plugins/table-resizing/utils/misc.ts +94 -119
  150. package/src/pm-plugins/table-resizing/utils/resize-column.ts +93 -106
  151. package/src/pm-plugins/table-resizing/utils/resize-logic.ts +240 -257
  152. package/src/pm-plugins/table-resizing/utils/resize-state.ts +343 -372
  153. package/src/pm-plugins/table-resizing/utils/scale-table.ts +202 -207
  154. package/src/pm-plugins/table-resizing/utils/types.ts +17 -17
  155. package/src/pm-plugins/table-resizing/utils/unit-to-number.ts +1 -2
  156. package/src/pm-plugins/table-selection-keymap.ts +25 -51
  157. package/src/pm-plugins/table-width.ts +191 -204
  158. package/src/pm-plugins/view-mode-sort/index.ts +223 -227
  159. package/src/pm-plugins/view-mode-sort/plugin-key.ts +3 -2
  160. package/src/pm-plugins/view-mode-sort/types.ts +12 -12
  161. package/src/pm-plugins/view-mode-sort/utils.ts +108 -117
  162. package/src/reducer.ts +139 -155
  163. package/src/toolbar.tsx +815 -905
  164. package/src/transforms/column-width.ts +186 -213
  165. package/src/transforms/delete-columns.ts +208 -222
  166. package/src/transforms/delete-rows.ts +117 -121
  167. package/src/transforms/fix-tables.ts +190 -215
  168. package/src/transforms/merge.ts +263 -269
  169. package/src/transforms/replace-table.ts +27 -43
  170. package/src/transforms/split.ts +65 -75
  171. package/src/types.ts +421 -427
  172. package/src/ui/ColumnResizeWidget/index.tsx +40 -47
  173. package/src/ui/DragHandle/HandleIconComponent.tsx +9 -13
  174. package/src/ui/DragHandle/index.tsx +221 -250
  175. package/src/ui/DragPreview/index.tsx +35 -35
  176. package/src/ui/FloatingAlignmentButtons/FloatingAlignmentButtons.tsx +33 -41
  177. package/src/ui/FloatingContextualButton/FixedButton.tsx +154 -157
  178. package/src/ui/FloatingContextualButton/index.tsx +109 -115
  179. package/src/ui/FloatingContextualButton/styles.ts +43 -46
  180. package/src/ui/FloatingContextualMenu/ContextualMenu.tsx +634 -694
  181. package/src/ui/FloatingContextualMenu/index.tsx +83 -101
  182. package/src/ui/FloatingContextualMenu/styles.ts +57 -65
  183. package/src/ui/FloatingDeleteButton/DeleteButton.tsx +37 -37
  184. package/src/ui/FloatingDeleteButton/getPopUpOptions.ts +47 -57
  185. package/src/ui/FloatingDeleteButton/index.tsx +319 -350
  186. package/src/ui/FloatingDragMenu/DragMenu.tsx +555 -596
  187. package/src/ui/FloatingDragMenu/DropdownMenu.tsx +152 -162
  188. package/src/ui/FloatingDragMenu/index.tsx +88 -102
  189. package/src/ui/FloatingDragMenu/styles.ts +51 -54
  190. package/src/ui/FloatingInsertButton/InsertButton.tsx +204 -217
  191. package/src/ui/FloatingInsertButton/getPopupOptions.ts +100 -115
  192. package/src/ui/FloatingInsertButton/index.tsx +248 -292
  193. package/src/ui/FloatingToolbarLabel/FloatingToolbarLabel.tsx +24 -29
  194. package/src/ui/TableFloatingColumnControls/ColumnControls/index.tsx +308 -329
  195. package/src/ui/TableFloatingColumnControls/ColumnDropTargets/ColumnDropTarget.tsx +85 -94
  196. package/src/ui/TableFloatingColumnControls/ColumnDropTargets/index.tsx +46 -46
  197. package/src/ui/TableFloatingColumnControls/index.tsx +116 -136
  198. package/src/ui/TableFloatingControls/CornerControls/ClassicCornerControls.tsx +79 -91
  199. package/src/ui/TableFloatingControls/CornerControls/DragCornerControls.tsx +95 -102
  200. package/src/ui/TableFloatingControls/CornerControls/index.tsx +1 -4
  201. package/src/ui/TableFloatingControls/CornerControls/types.ts +8 -8
  202. package/src/ui/TableFloatingControls/FloatingControlsWithSelection.tsx +50 -50
  203. package/src/ui/TableFloatingControls/NumberColumn/index.tsx +111 -124
  204. package/src/ui/TableFloatingControls/RowControls/ClassicControls.tsx +86 -105
  205. package/src/ui/TableFloatingControls/RowControls/DragControls.tsx +305 -341
  206. package/src/ui/TableFloatingControls/RowDropTarget/index.tsx +72 -75
  207. package/src/ui/TableFloatingControls/index.tsx +191 -193
  208. package/src/ui/TableFullWidthLabel/index.tsx +20 -20
  209. package/src/ui/common-styles.ts +880 -912
  210. package/src/ui/consts.ts +29 -74
  211. package/src/ui/icons/AddColLeftIcon.tsx +33 -39
  212. package/src/ui/icons/AddColRightIcon.tsx +33 -39
  213. package/src/ui/icons/AddRowAboveIcon.tsx +16 -22
  214. package/src/ui/icons/AddRowBelowIcon.tsx +33 -39
  215. package/src/ui/icons/DisplayModeIcon.tsx +31 -31
  216. package/src/ui/icons/DragHandleDisabledIcon.tsx +19 -21
  217. package/src/ui/icons/DragHandleIcon.tsx +12 -12
  218. package/src/ui/icons/DragInMotionIcon.tsx +45 -52
  219. package/src/ui/icons/MergeCellsIcon.tsx +22 -28
  220. package/src/ui/icons/MinimisedHandle.tsx +9 -9
  221. package/src/ui/icons/SplitCellIcon.tsx +30 -36
  222. package/src/ui/ui-styles.ts +769 -798
  223. package/src/utils/alignment.ts +1 -1
  224. package/src/utils/analytics.ts +192 -208
  225. package/src/utils/collapse.ts +55 -64
  226. package/src/utils/column-controls.ts +237 -254
  227. package/src/utils/create.ts +30 -30
  228. package/src/utils/decoration.ts +482 -502
  229. package/src/utils/dom.ts +127 -134
  230. package/src/utils/drag-menu.ts +322 -373
  231. package/src/utils/get-allow-add-column-custom-step.ts +4 -5
  232. package/src/utils/guidelines.ts +10 -21
  233. package/src/utils/index.ts +68 -68
  234. package/src/utils/merged-cells.ts +245 -254
  235. package/src/utils/nodes.ts +91 -106
  236. package/src/utils/paste.ts +119 -135
  237. package/src/utils/row-controls.ts +199 -213
  238. package/src/utils/selection.ts +77 -87
  239. package/src/utils/snapping.ts +84 -97
  240. package/src/utils/table.ts +44 -44
  241. package/src/utils/transforms.ts +5 -5
  242. package/src/utils/update-plugin-state-decorations.ts +5 -9
@@ -3,850 +3,757 @@ import isEqual from 'lodash/isEqual';
3
3
  import type { CellAttributes, TableLayout } from '@atlaskit/adf-schema';
4
4
  import type { Command, EditorCommand } from '@atlaskit/editor-common/types';
5
5
  import {
6
- closestElement,
7
- isParagraph,
8
- isTextSelection,
9
- mapSlice,
6
+ closestElement,
7
+ isParagraph,
8
+ isTextSelection,
9
+ mapSlice,
10
10
  } from '@atlaskit/editor-common/utils';
11
- import type {
12
- Node as PMNode,
13
- Schema,
14
- Slice,
15
- } from '@atlaskit/editor-prosemirror/model';
11
+ import type { Node as PMNode, Schema, Slice } from '@atlaskit/editor-prosemirror/model';
16
12
  import { TextSelection } from '@atlaskit/editor-prosemirror/state';
17
- import type {
18
- EditorState,
19
- Selection,
20
- Transaction,
21
- } from '@atlaskit/editor-prosemirror/state';
22
- import type {
23
- ContentNodeWithPos,
24
- NodeWithPos,
25
- } from '@atlaskit/editor-prosemirror/utils';
13
+ import type { EditorState, Selection, Transaction } from '@atlaskit/editor-prosemirror/state';
14
+ import type { ContentNodeWithPos, NodeWithPos } from '@atlaskit/editor-prosemirror/utils';
26
15
  import type { EditorView } from '@atlaskit/editor-prosemirror/view';
27
16
  import { CellSelection } from '@atlaskit/editor-tables/cell-selection';
28
17
  import { TableMap } from '@atlaskit/editor-tables/table-map';
29
18
  import {
30
- findCellClosestToPos,
31
- findTable,
32
- getCellsInColumn,
33
- getCellsInRow,
34
- getSelectionRect,
35
- isSelectionType,
36
- isTableSelected,
37
- removeTable,
38
- selectColumns as selectColumnsTransform,
39
- selectColumn as selectColumnTransform,
40
- selectionCell,
41
- selectRows as selectRowsTransform,
42
- selectRow as selectRowTransform,
43
- setCellAttrs,
19
+ findCellClosestToPos,
20
+ findTable,
21
+ getCellsInColumn,
22
+ getCellsInRow,
23
+ getSelectionRect,
24
+ isSelectionType,
25
+ isTableSelected,
26
+ removeTable,
27
+ selectColumns as selectColumnsTransform,
28
+ selectColumn as selectColumnTransform,
29
+ selectionCell,
30
+ selectRows as selectRowsTransform,
31
+ selectRow as selectRowTransform,
32
+ setCellAttrs,
44
33
  } from '@atlaskit/editor-tables/utils';
45
34
 
46
35
  import { getDecorations } from '../pm-plugins/decorations/plugin';
47
36
  import {
48
- buildColumnResizingDecorations,
49
- clearColumnResizingDecorations,
37
+ buildColumnResizingDecorations,
38
+ clearColumnResizingDecorations,
50
39
  } from '../pm-plugins/decorations/utils';
51
40
  import { createCommand, getPluginState } from '../pm-plugins/plugin-factory';
52
41
  import { fixAutoSizedTable } from '../transforms';
53
42
  import type { WidthToWidest } from '../types';
54
43
  import { TableCssClassName as ClassName, TableDecorations } from '../types';
55
44
  import {
56
- createColumnControlsDecoration,
57
- createColumnSelectedDecoration,
45
+ createColumnControlsDecoration,
46
+ createColumnSelectedDecoration,
58
47
  } from '../utils/decoration';
59
48
  import {
60
- checkIfHeaderColumnEnabled,
61
- checkIfHeaderRowEnabled,
62
- checkIfNumberColumnEnabled,
63
- isIsolating,
49
+ checkIfHeaderColumnEnabled,
50
+ checkIfHeaderRowEnabled,
51
+ checkIfNumberColumnEnabled,
52
+ isIsolating,
64
53
  } from '../utils/nodes';
65
54
  import { updatePluginStateDecorations } from '../utils/update-plugin-state-decorations';
66
55
 
67
56
  export const setEditorFocus = (editorHasFocus: boolean) =>
68
- createCommand({
69
- type: 'SET_EDITOR_FOCUS',
70
- data: {
71
- editorHasFocus,
72
- },
73
- });
57
+ createCommand({
58
+ type: 'SET_EDITOR_FOCUS',
59
+ data: {
60
+ editorHasFocus,
61
+ },
62
+ });
74
63
 
75
64
  export const setTableRef = (ref?: HTMLTableElement) =>
76
- createCommand(
77
- (state) => {
78
- const tableRef = ref;
79
- const foundTable = findTable(state.selection);
80
- const tableNode = ref && foundTable ? foundTable.node : undefined;
81
- const tablePos = ref && foundTable ? foundTable.pos : undefined;
82
- const tableWrapperTarget =
83
- closestElement(tableRef, `.${ClassName.TABLE_NODE_WRAPPER}`) ||
84
- undefined;
85
- const { isDragAndDropEnabled } = getPluginState(state);
86
-
87
- return {
88
- type: 'SET_TABLE_REF',
89
- data: {
90
- tableRef,
91
- tableNode,
92
- tablePos,
93
- tableWrapperTarget,
94
- isNumberColumnEnabled: checkIfNumberColumnEnabled(state.selection),
95
- isHeaderRowEnabled: checkIfHeaderRowEnabled(state.selection),
96
- isHeaderColumnEnabled: checkIfHeaderColumnEnabled(state.selection),
97
- // decoration set is drawn by the decoration plugin, skip this for DnD as all controls are floating
98
- decorationSet: !isDragAndDropEnabled
99
- ? updatePluginStateDecorations(
100
- state,
101
- createColumnControlsDecoration(state.selection),
102
- TableDecorations.COLUMN_CONTROLS_DECORATIONS,
103
- )
104
- : undefined,
105
- resizeHandleRowIndex: undefined,
106
- resizeHandleColumnIndex: undefined,
107
- },
108
- };
109
- },
110
- (tr) => tr.setMeta('addToHistory', false),
111
- );
65
+ createCommand(
66
+ (state) => {
67
+ const tableRef = ref;
68
+ const foundTable = findTable(state.selection);
69
+ const tableNode = ref && foundTable ? foundTable.node : undefined;
70
+ const tablePos = ref && foundTable ? foundTable.pos : undefined;
71
+ const tableWrapperTarget =
72
+ closestElement(tableRef, `.${ClassName.TABLE_NODE_WRAPPER}`) || undefined;
73
+ const { isDragAndDropEnabled } = getPluginState(state);
74
+
75
+ return {
76
+ type: 'SET_TABLE_REF',
77
+ data: {
78
+ tableRef,
79
+ tableNode,
80
+ tablePos,
81
+ tableWrapperTarget,
82
+ isNumberColumnEnabled: checkIfNumberColumnEnabled(state.selection),
83
+ isHeaderRowEnabled: checkIfHeaderRowEnabled(state.selection),
84
+ isHeaderColumnEnabled: checkIfHeaderColumnEnabled(state.selection),
85
+ // decoration set is drawn by the decoration plugin, skip this for DnD as all controls are floating
86
+ decorationSet: !isDragAndDropEnabled
87
+ ? updatePluginStateDecorations(
88
+ state,
89
+ createColumnControlsDecoration(state.selection),
90
+ TableDecorations.COLUMN_CONTROLS_DECORATIONS,
91
+ )
92
+ : undefined,
93
+ resizeHandleRowIndex: undefined,
94
+ resizeHandleColumnIndex: undefined,
95
+ },
96
+ };
97
+ },
98
+ (tr) => tr.setMeta('addToHistory', false),
99
+ );
112
100
 
113
101
  export const setCellAttr =
114
- (name: string, value: any): Command =>
115
- (state, dispatch) => {
116
- const { tr, selection } = state;
117
- if (selection instanceof CellSelection) {
118
- let updated = false;
119
- selection.forEachCell((cell, pos) => {
120
- if (cell.attrs[name] !== value) {
121
- tr.setNodeMarkup(pos, cell.type, { ...cell.attrs, [name]: value });
122
- updated = true;
123
- }
124
- });
125
- if (updated) {
126
- if (dispatch) {
127
- dispatch(tr);
128
- }
129
- return true;
130
- }
131
- } else {
132
- const cell = selectionCell(state.selection);
133
- if (cell) {
134
- if (dispatch) {
135
- dispatch(
136
- tr.setNodeMarkup(cell.pos, cell.nodeAfter?.type, {
137
- ...cell.nodeAfter?.attrs,
138
- [name]: value,
139
- }),
140
- );
141
- }
142
- return true;
143
- }
144
- }
145
- return false;
146
- };
102
+ (name: string, value: any): Command =>
103
+ (state, dispatch) => {
104
+ const { tr, selection } = state;
105
+ if (selection instanceof CellSelection) {
106
+ let updated = false;
107
+ selection.forEachCell((cell, pos) => {
108
+ if (cell.attrs[name] !== value) {
109
+ tr.setNodeMarkup(pos, cell.type, { ...cell.attrs, [name]: value });
110
+ updated = true;
111
+ }
112
+ });
113
+ if (updated) {
114
+ if (dispatch) {
115
+ dispatch(tr);
116
+ }
117
+ return true;
118
+ }
119
+ } else {
120
+ const cell = selectionCell(state.selection);
121
+ if (cell) {
122
+ if (dispatch) {
123
+ dispatch(
124
+ tr.setNodeMarkup(cell.pos, cell.nodeAfter?.type, {
125
+ ...cell.nodeAfter?.attrs,
126
+ [name]: value,
127
+ }),
128
+ );
129
+ }
130
+ return true;
131
+ }
132
+ }
133
+ return false;
134
+ };
147
135
 
148
136
  export const triggerUnlessTableHeader =
149
- (command: Command): Command =>
150
- (state, dispatch, view) => {
151
- const {
152
- selection,
153
- schema: {
154
- nodes: { tableHeader },
155
- },
156
- } = state;
157
-
158
- if (selection instanceof TextSelection) {
159
- const cell = findCellClosestToPos(selection.$from);
160
- if (cell && cell.node.type !== tableHeader) {
161
- return command(state, dispatch, view);
162
- }
163
- }
164
-
165
- if (selection instanceof CellSelection) {
166
- const rect = getSelectionRect(selection);
167
- if (!checkIfHeaderRowEnabled(selection) || (rect && rect.top > 0)) {
168
- return command(state, dispatch, view);
169
- }
170
- }
171
-
172
- return false;
173
- };
174
-
175
- export const transformSliceRemoveCellBackgroundColor = (
176
- slice: Slice,
177
- schema: Schema,
178
- ): Slice => {
179
- const { tableCell, tableHeader } = schema.nodes;
180
- return mapSlice(slice, (maybeCell) => {
181
- if (maybeCell.type === tableCell || maybeCell.type === tableHeader) {
182
- const cellAttrs: CellAttributes = { ...maybeCell.attrs };
183
- cellAttrs.background = undefined;
184
- return maybeCell.type.createChecked(
185
- cellAttrs,
186
- maybeCell.content,
187
- maybeCell.marks,
188
- );
189
- }
190
- return maybeCell;
191
- });
137
+ (command: Command): Command =>
138
+ (state, dispatch, view) => {
139
+ const {
140
+ selection,
141
+ schema: {
142
+ nodes: { tableHeader },
143
+ },
144
+ } = state;
145
+
146
+ if (selection instanceof TextSelection) {
147
+ const cell = findCellClosestToPos(selection.$from);
148
+ if (cell && cell.node.type !== tableHeader) {
149
+ return command(state, dispatch, view);
150
+ }
151
+ }
152
+
153
+ if (selection instanceof CellSelection) {
154
+ const rect = getSelectionRect(selection);
155
+ if (!checkIfHeaderRowEnabled(selection) || (rect && rect.top > 0)) {
156
+ return command(state, dispatch, view);
157
+ }
158
+ }
159
+
160
+ return false;
161
+ };
162
+
163
+ export const transformSliceRemoveCellBackgroundColor = (slice: Slice, schema: Schema): Slice => {
164
+ const { tableCell, tableHeader } = schema.nodes;
165
+ return mapSlice(slice, (maybeCell) => {
166
+ if (maybeCell.type === tableCell || maybeCell.type === tableHeader) {
167
+ const cellAttrs: CellAttributes = { ...maybeCell.attrs };
168
+ cellAttrs.background = undefined;
169
+ return maybeCell.type.createChecked(cellAttrs, maybeCell.content, maybeCell.marks);
170
+ }
171
+ return maybeCell;
172
+ });
192
173
  };
193
174
 
194
- export const transformSliceToAddTableHeaders = (
195
- slice: Slice,
196
- schema: Schema,
197
- ): Slice => {
198
- const { table, tableHeader, tableRow } = schema.nodes;
199
-
200
- return mapSlice(slice, (maybeTable) => {
201
- if (maybeTable.type === table) {
202
- const firstRow = maybeTable.firstChild;
203
- if (firstRow) {
204
- const headerCols = [] as PMNode[];
205
- firstRow.forEach((oldCol) => {
206
- headerCols.push(
207
- tableHeader.createChecked(
208
- oldCol.attrs,
209
- oldCol.content,
210
- oldCol.marks,
211
- ),
212
- );
213
- });
214
- const headerRow = tableRow.createChecked(
215
- firstRow.attrs,
216
- headerCols,
217
- firstRow.marks,
218
- );
219
- return maybeTable.copy(maybeTable.content.replaceChild(0, headerRow));
220
- }
221
- }
222
- return maybeTable;
223
- });
175
+ export const transformSliceToAddTableHeaders = (slice: Slice, schema: Schema): Slice => {
176
+ const { table, tableHeader, tableRow } = schema.nodes;
177
+
178
+ return mapSlice(slice, (maybeTable) => {
179
+ if (maybeTable.type === table) {
180
+ const firstRow = maybeTable.firstChild;
181
+ if (firstRow) {
182
+ const headerCols = [] as PMNode[];
183
+ firstRow.forEach((oldCol) => {
184
+ headerCols.push(tableHeader.createChecked(oldCol.attrs, oldCol.content, oldCol.marks));
185
+ });
186
+ const headerRow = tableRow.createChecked(firstRow.attrs, headerCols, firstRow.marks);
187
+ return maybeTable.copy(maybeTable.content.replaceChild(0, headerRow));
188
+ }
189
+ }
190
+ return maybeTable;
191
+ });
224
192
  };
225
193
 
226
- export const transformSliceToRemoveColumnsWidths = (
227
- slice: Slice,
228
- schema: Schema,
229
- ): Slice => {
230
- const { tableHeader, tableCell } = schema.nodes;
231
-
232
- return mapSlice(slice, (maybeCell) => {
233
- if (maybeCell.type === tableCell || maybeCell.type === tableHeader) {
234
- if (!maybeCell.attrs.colwidth) {
235
- return maybeCell;
236
- }
237
- return maybeCell.type.createChecked(
238
- { ...maybeCell.attrs, colwidth: undefined },
239
- maybeCell.content,
240
- maybeCell.marks,
241
- );
242
- }
243
- return maybeCell;
244
- });
194
+ export const transformSliceToRemoveColumnsWidths = (slice: Slice, schema: Schema): Slice => {
195
+ const { tableHeader, tableCell } = schema.nodes;
196
+
197
+ return mapSlice(slice, (maybeCell) => {
198
+ if (maybeCell.type === tableCell || maybeCell.type === tableHeader) {
199
+ if (!maybeCell.attrs.colwidth) {
200
+ return maybeCell;
201
+ }
202
+ return maybeCell.type.createChecked(
203
+ { ...maybeCell.attrs, colwidth: undefined },
204
+ maybeCell.content,
205
+ maybeCell.marks,
206
+ );
207
+ }
208
+ return maybeCell;
209
+ });
245
210
  };
246
211
 
247
- export const countCellsInSlice = (
248
- slice: Slice,
249
- schema: Schema,
250
- type?: 'row' | 'column',
251
- ) => {
252
- const { tableHeader, tableCell } = schema.nodes;
253
- let count = 0;
212
+ export const countCellsInSlice = (slice: Slice, schema: Schema, type?: 'row' | 'column') => {
213
+ const { tableHeader, tableCell } = schema.nodes;
214
+ let count = 0;
254
215
 
255
- if (!type) {
256
- return count;
257
- }
216
+ if (!type) {
217
+ return count;
218
+ }
258
219
 
259
- slice.content.descendants((maybeCell) => {
260
- if (maybeCell.type === tableCell || maybeCell.type === tableHeader) {
261
- count +=
262
- type === 'row' ? maybeCell.attrs.colspan : maybeCell.attrs.rowspan;
220
+ slice.content.descendants((maybeCell) => {
221
+ if (maybeCell.type === tableCell || maybeCell.type === tableHeader) {
222
+ count += type === 'row' ? maybeCell.attrs.colspan : maybeCell.attrs.rowspan;
263
223
 
264
- return false;
265
- }
266
- });
224
+ return false;
225
+ }
226
+ });
267
227
 
268
- return count;
228
+ return count;
269
229
  };
270
230
 
271
231
  export const getTableSelectionType = (selection: Selection) => {
272
- if (selection instanceof CellSelection) {
273
- return selection.isRowSelection()
274
- ? 'row'
275
- : selection.isColSelection()
276
- ? 'column'
277
- : undefined;
278
- }
232
+ if (selection instanceof CellSelection) {
233
+ return selection.isRowSelection() ? 'row' : selection.isColSelection() ? 'column' : undefined;
234
+ }
279
235
  };
280
236
 
281
- export const getTableElementMoveTypeBySlice = (
282
- slice: Slice,
283
- state: EditorState,
284
- ) => {
285
- const {
286
- schema: {
287
- nodes: { tableRow, table },
288
- },
289
- } = state;
290
- const currentTable = findTable(state.tr.selection);
291
-
292
- // check if copied slice is a table or table row
293
- if (
294
- !slice.content.firstChild ||
295
- (slice.content.firstChild.type !== table &&
296
- slice.content.firstChild.type !== tableRow) ||
297
- !currentTable
298
- ) {
299
- return undefined;
300
- }
301
-
302
- // if the slice only contains one table row, assume it's a row
303
- if (
304
- slice.content.childCount === 1 &&
305
- slice.content.firstChild.type === tableRow
306
- ) {
307
- return 'row';
308
- }
309
-
310
- // `TableMap.get` can throw if the content is invalid - in which case we should just
311
- // return undefined
312
- try {
313
- const map = TableMap.get(currentTable.node);
314
- const slicedMap = TableMap.get(slice.content.firstChild);
315
-
316
- return map.width === slicedMap.width
317
- ? 'row'
318
- : map.height === slicedMap.height
319
- ? 'column'
320
- : undefined;
321
- } catch (e) {
322
- return undefined;
323
- }
237
+ export const getTableElementMoveTypeBySlice = (slice: Slice, state: EditorState) => {
238
+ const {
239
+ schema: {
240
+ nodes: { tableRow, table },
241
+ },
242
+ } = state;
243
+ const currentTable = findTable(state.tr.selection);
244
+
245
+ // check if copied slice is a table or table row
246
+ if (
247
+ !slice.content.firstChild ||
248
+ (slice.content.firstChild.type !== table && slice.content.firstChild.type !== tableRow) ||
249
+ !currentTable
250
+ ) {
251
+ return undefined;
252
+ }
253
+
254
+ // if the slice only contains one table row, assume it's a row
255
+ if (slice.content.childCount === 1 && slice.content.firstChild.type === tableRow) {
256
+ return 'row';
257
+ }
258
+
259
+ // `TableMap.get` can throw if the content is invalid - in which case we should just
260
+ // return undefined
261
+ try {
262
+ const map = TableMap.get(currentTable.node);
263
+ const slicedMap = TableMap.get(slice.content.firstChild);
264
+
265
+ return map.width === slicedMap.width
266
+ ? 'row'
267
+ : map.height === slicedMap.height
268
+ ? 'column'
269
+ : undefined;
270
+ } catch (e) {
271
+ return undefined;
272
+ }
324
273
  };
325
274
 
326
- export const isInsideFirstCellOfRowOrColumn = (
327
- selection: Selection,
328
- type?: 'row' | 'column',
329
- ) => {
330
- const table = findTable(selection);
331
-
332
- if (!table || !type) {
333
- return false;
334
- }
335
-
336
- const map = TableMap.get(table.node!);
337
- const cell = findCellClosestToPos(selection.$anchor);
338
- if (!cell) {
339
- return false;
340
- }
341
- const pos = cell.pos - table.pos - 1;
342
- // cell positions in table map always start at 1, as they're offsets not positions
343
- const index = map.map.findIndex((value) => value === pos);
344
-
345
- return type === 'row' ? index % map.width === 0 : index < map.width;
275
+ export const isInsideFirstCellOfRowOrColumn = (selection: Selection, type?: 'row' | 'column') => {
276
+ const table = findTable(selection);
277
+
278
+ if (!table || !type) {
279
+ return false;
280
+ }
281
+
282
+ const map = TableMap.get(table.node!);
283
+ const cell = findCellClosestToPos(selection.$anchor);
284
+ if (!cell) {
285
+ return false;
286
+ }
287
+ const pos = cell.pos - table.pos - 1;
288
+ // cell positions in table map always start at 1, as they're offsets not positions
289
+ const index = map.map.findIndex((value) => value === pos);
290
+
291
+ return type === 'row' ? index % map.width === 0 : index < map.width;
346
292
  };
347
293
 
348
294
  export const deleteTable: Command = (state, dispatch) => {
349
- if (dispatch) {
350
- dispatch(removeTable(state.tr));
351
- }
352
- return true;
295
+ if (dispatch) {
296
+ dispatch(removeTable(state.tr));
297
+ }
298
+ return true;
353
299
  };
354
300
 
355
301
  export const deleteTableIfSelected: Command = (state, dispatch) => {
356
- if (isTableSelected(state.selection)) {
357
- return deleteTable(state, dispatch);
358
- }
359
- return false;
302
+ if (isTableSelected(state.selection)) {
303
+ return deleteTable(state, dispatch);
304
+ }
305
+ return false;
360
306
  };
361
307
 
362
308
  export const convertFirstRowToHeader =
363
- (schema: Schema) =>
364
- (tr: Transaction): Transaction => {
365
- const table = findTable(tr.selection)!;
366
- const map = TableMap.get(table.node);
367
- for (let i = 0; i < map.width; i++) {
368
- const cell = table.node.child(0).child(i);
369
- tr.setNodeMarkup(
370
- table.start + map.map[i],
371
- schema.nodes.tableHeader,
372
- cell.attrs,
373
- );
374
- }
375
- return tr;
376
- };
309
+ (schema: Schema) =>
310
+ (tr: Transaction): Transaction => {
311
+ const table = findTable(tr.selection)!;
312
+ const map = TableMap.get(table.node);
313
+ for (let i = 0; i < map.width; i++) {
314
+ const cell = table.node.child(0).child(i);
315
+ tr.setNodeMarkup(table.start + map.map[i], schema.nodes.tableHeader, cell.attrs);
316
+ }
317
+ return tr;
318
+ };
377
319
 
378
320
  export const moveCursorBackward: Command = (state, dispatch) => {
379
- const { $cursor } = state.selection as TextSelection;
380
- // if cursor is in the middle of a text node, do nothing
381
- if (!$cursor || $cursor.parentOffset > 0) {
382
- return false;
383
- }
384
-
385
- // find the node before the cursor
386
- let before;
387
- let cut: number | undefined;
388
- if (!isIsolating($cursor.parent)) {
389
- for (let i = $cursor.depth - 1; !before && i >= 0; i--) {
390
- if ($cursor.index(i) > 0) {
391
- cut = $cursor.before(i + 1);
392
- before = $cursor.node(i).child($cursor.index(i) - 1);
393
- }
394
- if (isIsolating($cursor.node(i))) {
395
- break;
396
- }
397
- }
398
- }
399
-
400
- // if the node before is not a table node - do nothing
401
- if (!before || before.type !== state.schema.nodes.table) {
402
- return false;
403
- }
404
-
405
- /*
321
+ const { $cursor } = state.selection as TextSelection;
322
+ // if cursor is in the middle of a text node, do nothing
323
+ if (!$cursor || $cursor.parentOffset > 0) {
324
+ return false;
325
+ }
326
+
327
+ // find the node before the cursor
328
+ let before;
329
+ let cut: number | undefined;
330
+ if (!isIsolating($cursor.parent)) {
331
+ for (let i = $cursor.depth - 1; !before && i >= 0; i--) {
332
+ if ($cursor.index(i) > 0) {
333
+ cut = $cursor.before(i + 1);
334
+ before = $cursor.node(i).child($cursor.index(i) - 1);
335
+ }
336
+ if (isIsolating($cursor.node(i))) {
337
+ break;
338
+ }
339
+ }
340
+ }
341
+
342
+ // if the node before is not a table node - do nothing
343
+ if (!before || before.type !== state.schema.nodes.table) {
344
+ return false;
345
+ }
346
+
347
+ /*
406
348
  ensure we're just at a top level paragraph
407
349
  otherwise, perform regular backspace behaviour
408
350
  */
409
- const grandparent = $cursor.node($cursor.depth - 1);
410
- if (
411
- $cursor.parent.type !== state.schema.nodes.paragraph ||
412
- (grandparent && grandparent.type !== state.schema.nodes.doc)
413
- ) {
414
- return false;
415
- }
416
-
417
- const { tr } = state;
418
- const lastCellPos = (cut || 0) - 4;
419
- // need to move cursor inside the table to be able to calculate table's offset
420
- tr.setSelection(new TextSelection(state.doc.resolve(lastCellPos)));
421
- const { $from } = tr.selection;
422
- const start = $from.start(-1);
423
- const pos = start + $from.parent.nodeSize - 1;
424
-
425
- // move cursor to the last cell
426
- // it doesn't join node before (last cell) with node after (content after the cursor)
427
- // due to ridiculous amount of PM code that would have been required to overwrite
428
- tr.setSelection(new TextSelection(state.doc.resolve(pos)));
429
-
430
- // if we are inside an empty paragraph not at the end of the doc we delete it
431
- const cursorNode = $cursor.node();
432
- const docEnd = state.doc.content.size;
433
- const paragraphWrapStart = $cursor.pos - 1;
434
- const paragraphWrapEnd = $cursor.pos + 1;
435
- if (cursorNode.content.size === 0 && $cursor.pos + 1 !== docEnd) {
436
- tr.delete(paragraphWrapStart, paragraphWrapEnd);
437
- }
438
-
439
- if (dispatch) {
440
- dispatch(tr);
441
- }
442
-
443
- return true;
351
+ const grandparent = $cursor.node($cursor.depth - 1);
352
+ if (
353
+ $cursor.parent.type !== state.schema.nodes.paragraph ||
354
+ (grandparent && grandparent.type !== state.schema.nodes.doc)
355
+ ) {
356
+ return false;
357
+ }
358
+
359
+ const { tr } = state;
360
+ const lastCellPos = (cut || 0) - 4;
361
+ // need to move cursor inside the table to be able to calculate table's offset
362
+ tr.setSelection(new TextSelection(state.doc.resolve(lastCellPos)));
363
+ const { $from } = tr.selection;
364
+ const start = $from.start(-1);
365
+ const pos = start + $from.parent.nodeSize - 1;
366
+
367
+ // move cursor to the last cell
368
+ // it doesn't join node before (last cell) with node after (content after the cursor)
369
+ // due to ridiculous amount of PM code that would have been required to overwrite
370
+ tr.setSelection(new TextSelection(state.doc.resolve(pos)));
371
+
372
+ // if we are inside an empty paragraph not at the end of the doc we delete it
373
+ const cursorNode = $cursor.node();
374
+ const docEnd = state.doc.content.size;
375
+ const paragraphWrapStart = $cursor.pos - 1;
376
+ const paragraphWrapEnd = $cursor.pos + 1;
377
+ if (cursorNode.content.size === 0 && $cursor.pos + 1 !== docEnd) {
378
+ tr.delete(paragraphWrapStart, paragraphWrapEnd);
379
+ }
380
+
381
+ if (dispatch) {
382
+ dispatch(tr);
383
+ }
384
+
385
+ return true;
444
386
  };
445
387
 
446
388
  export const setMultipleCellAttrs =
447
- (
448
- attrs: Object,
449
- targetCellPosition?: number,
450
- editorView?: EditorView | null,
451
- ): Command =>
452
- (state, dispatch) => {
453
- let cursorPos: number | undefined;
454
- let { tr } = state;
455
-
456
- if (isSelectionType(tr.selection, 'cell')) {
457
- const selection = tr.selection as any as CellSelection;
458
- selection.forEachCell((_cell, pos) => {
459
- const $pos = tr.doc.resolve(tr.mapping.map(pos + 1));
460
- tr = setCellAttrs(findCellClosestToPos($pos)!, attrs)(tr);
461
- });
462
- cursorPos = selection.$headCell.pos;
463
- } else if (targetCellPosition) {
464
- const cell = findCellClosestToPos(
465
- tr.doc.resolve(targetCellPosition + 1),
466
- )!;
467
- tr = setCellAttrs(cell, attrs)(tr);
468
- cursorPos = cell.pos;
469
- }
470
-
471
- if (tr.docChanged && cursorPos !== undefined) {
472
- if (dispatch) {
473
- if (cursorPos !== undefined) {
474
- editorView?.focus();
475
- tr.setSelection(new TextSelection(tr.doc.resolve(cursorPos)));
476
- }
477
- dispatch(tr);
478
- }
479
- return true;
480
- }
481
- return false;
482
- };
483
-
484
- export const selectColumn = (
485
- column: number,
486
- expand?: boolean,
487
- triggeredByKeyboard = false,
488
- ) =>
489
- createCommand(
490
- (state) => {
491
- const cells = getCellsInColumn(column)(state.tr.selection);
492
- if (!cells || !cells.length || typeof cells[0].pos !== 'number') {
493
- return false;
494
- }
495
-
496
- const decorations = createColumnSelectedDecoration(
497
- selectColumnTransform(column, expand)(state.tr),
498
- );
499
- const decorationSet = updatePluginStateDecorations(
500
- state,
501
- decorations,
502
- TableDecorations.COLUMN_SELECTED,
503
- );
504
- const targetCellPosition = cells[0].pos;
505
-
506
- return {
507
- type: 'SELECT_COLUMN',
508
- data: { targetCellPosition, decorationSet },
509
- };
510
- },
511
- (tr: Transaction) =>
512
- selectColumnTransform(column, expand)(tr)
513
- .setMeta('addToHistory', false)
514
- .setMeta('selectedColumnViaKeyboard', triggeredByKeyboard),
515
- );
389
+ (attrs: Object, targetCellPosition?: number, editorView?: EditorView | null): Command =>
390
+ (state, dispatch) => {
391
+ let cursorPos: number | undefined;
392
+ let { tr } = state;
393
+
394
+ if (isSelectionType(tr.selection, 'cell')) {
395
+ const selection = tr.selection as any as CellSelection;
396
+ selection.forEachCell((_cell, pos) => {
397
+ const $pos = tr.doc.resolve(tr.mapping.map(pos + 1));
398
+ tr = setCellAttrs(findCellClosestToPos($pos)!, attrs)(tr);
399
+ });
400
+ cursorPos = selection.$headCell.pos;
401
+ } else if (targetCellPosition) {
402
+ const cell = findCellClosestToPos(tr.doc.resolve(targetCellPosition + 1))!;
403
+ tr = setCellAttrs(cell, attrs)(tr);
404
+ cursorPos = cell.pos;
405
+ }
406
+
407
+ if (tr.docChanged && cursorPos !== undefined) {
408
+ if (dispatch) {
409
+ if (cursorPos !== undefined) {
410
+ editorView?.focus();
411
+ tr.setSelection(new TextSelection(tr.doc.resolve(cursorPos)));
412
+ }
413
+ dispatch(tr);
414
+ }
415
+ return true;
416
+ }
417
+ return false;
418
+ };
419
+
420
+ export const selectColumn = (column: number, expand?: boolean, triggeredByKeyboard = false) =>
421
+ createCommand(
422
+ (state) => {
423
+ const cells = getCellsInColumn(column)(state.tr.selection);
424
+ if (!cells || !cells.length || typeof cells[0].pos !== 'number') {
425
+ return false;
426
+ }
427
+
428
+ const decorations = createColumnSelectedDecoration(
429
+ selectColumnTransform(column, expand)(state.tr),
430
+ );
431
+ const decorationSet = updatePluginStateDecorations(
432
+ state,
433
+ decorations,
434
+ TableDecorations.COLUMN_SELECTED,
435
+ );
436
+ const targetCellPosition = cells[0].pos;
437
+
438
+ return {
439
+ type: 'SELECT_COLUMN',
440
+ data: { targetCellPosition, decorationSet },
441
+ };
442
+ },
443
+ (tr: Transaction) =>
444
+ selectColumnTransform(column, expand)(tr)
445
+ .setMeta('addToHistory', false)
446
+ .setMeta('selectedColumnViaKeyboard', triggeredByKeyboard),
447
+ );
516
448
 
517
449
  export const selectColumns = (columnIndexes: number[]) =>
518
- createCommand(
519
- (state) => {
520
- if (!columnIndexes) {
521
- return false;
522
- }
523
- const cells = columnIndexes
524
- .map((column) => getCellsInColumn(column)(state.tr.selection))
525
- .flat();
526
- if (
527
- !cells ||
528
- !cells.length ||
529
- cells.some((cell) => cell && typeof cell.pos !== 'number')
530
- ) {
531
- return false;
532
- }
533
- const decorations = createColumnSelectedDecoration(
534
- selectColumnsTransform(columnIndexes)(state.tr),
535
- );
536
-
537
- const decorationSet = updatePluginStateDecorations(
538
- state,
539
- decorations,
540
- TableDecorations.COLUMN_SELECTED,
541
- );
542
-
543
- const cellsInFirstColumn = getCellsInColumn(Math.min(...columnIndexes))(
544
- state.tr.selection,
545
- );
546
- if (!cellsInFirstColumn || cellsInFirstColumn.length === 0) {
547
- return false;
548
- }
549
- const targetCellPosition = cellsInFirstColumn[0].pos;
550
-
551
- return {
552
- type: 'SELECT_COLUMN',
553
- data: { targetCellPosition, decorationSet },
554
- };
555
- },
556
- (tr: Transaction) => {
557
- return selectColumnsTransform(columnIndexes)(tr).setMeta(
558
- 'addToHistory',
559
- false,
560
- );
561
- },
562
- );
563
-
564
- export const selectRow = (
565
- row: number,
566
- expand?: boolean,
567
- triggeredByKeyboard = false,
568
- ) =>
569
- createCommand(
570
- (state) => {
571
- let targetCellPosition;
572
- const cells = getCellsInRow(row)(state.tr.selection);
573
- if (cells && cells.length) {
574
- targetCellPosition = cells[0].pos;
575
- }
576
-
577
- return { type: 'SET_TARGET_CELL_POSITION', data: { targetCellPosition } };
578
- },
579
- (tr) =>
580
- selectRowTransform(row, expand)(tr)
581
- .setMeta('addToHistory', false)
582
- .setMeta('selectedRowViaKeyboard', triggeredByKeyboard),
583
- );
450
+ createCommand(
451
+ (state) => {
452
+ if (!columnIndexes) {
453
+ return false;
454
+ }
455
+ const cells = columnIndexes
456
+ .map((column) => getCellsInColumn(column)(state.tr.selection))
457
+ .flat();
458
+ if (!cells || !cells.length || cells.some((cell) => cell && typeof cell.pos !== 'number')) {
459
+ return false;
460
+ }
461
+ const decorations = createColumnSelectedDecoration(
462
+ selectColumnsTransform(columnIndexes)(state.tr),
463
+ );
464
+
465
+ const decorationSet = updatePluginStateDecorations(
466
+ state,
467
+ decorations,
468
+ TableDecorations.COLUMN_SELECTED,
469
+ );
470
+
471
+ const cellsInFirstColumn = getCellsInColumn(Math.min(...columnIndexes))(state.tr.selection);
472
+ if (!cellsInFirstColumn || cellsInFirstColumn.length === 0) {
473
+ return false;
474
+ }
475
+ const targetCellPosition = cellsInFirstColumn[0].pos;
476
+
477
+ return {
478
+ type: 'SELECT_COLUMN',
479
+ data: { targetCellPosition, decorationSet },
480
+ };
481
+ },
482
+ (tr: Transaction) => {
483
+ return selectColumnsTransform(columnIndexes)(tr).setMeta('addToHistory', false);
484
+ },
485
+ );
486
+
487
+ export const selectRow = (row: number, expand?: boolean, triggeredByKeyboard = false) =>
488
+ createCommand(
489
+ (state) => {
490
+ let targetCellPosition;
491
+ const cells = getCellsInRow(row)(state.tr.selection);
492
+ if (cells && cells.length) {
493
+ targetCellPosition = cells[0].pos;
494
+ }
495
+
496
+ return { type: 'SET_TARGET_CELL_POSITION', data: { targetCellPosition } };
497
+ },
498
+ (tr) =>
499
+ selectRowTransform(row, expand)(tr)
500
+ .setMeta('addToHistory', false)
501
+ .setMeta('selectedRowViaKeyboard', triggeredByKeyboard),
502
+ );
584
503
 
585
504
  export const selectRows = (rowIndexes: number[]) =>
586
- createCommand(
587
- (state) => {
588
- if (rowIndexes.length === 0) {
589
- return false;
590
- }
591
- const cells = rowIndexes
592
- .map((row) => getCellsInRow(row)(state.tr.selection))
593
- .flat();
594
- if (
595
- !cells ||
596
- !cells.length ||
597
- cells.some((cell) => cell && typeof cell.pos !== 'number')
598
- ) {
599
- return false;
600
- }
601
- const cellsInFirstRow = getCellsInRow(Math.min(...rowIndexes))(
602
- state.tr.selection,
603
- );
604
- if (!cellsInFirstRow || cellsInFirstRow.length === 0) {
605
- return false;
606
- }
607
- const targetCellPosition = cellsInFirstRow[0].pos;
608
-
609
- return { type: 'SET_TARGET_CELL_POSITION', data: { targetCellPosition } };
610
- },
611
- (tr) => selectRowsTransform(rowIndexes)(tr).setMeta('addToHistory', false),
612
- );
505
+ createCommand(
506
+ (state) => {
507
+ if (rowIndexes.length === 0) {
508
+ return false;
509
+ }
510
+ const cells = rowIndexes.map((row) => getCellsInRow(row)(state.tr.selection)).flat();
511
+ if (!cells || !cells.length || cells.some((cell) => cell && typeof cell.pos !== 'number')) {
512
+ return false;
513
+ }
514
+ const cellsInFirstRow = getCellsInRow(Math.min(...rowIndexes))(state.tr.selection);
515
+ if (!cellsInFirstRow || cellsInFirstRow.length === 0) {
516
+ return false;
517
+ }
518
+ const targetCellPosition = cellsInFirstRow[0].pos;
519
+
520
+ return { type: 'SET_TARGET_CELL_POSITION', data: { targetCellPosition } };
521
+ },
522
+ (tr) => selectRowsTransform(rowIndexes)(tr).setMeta('addToHistory', false),
523
+ );
613
524
 
614
525
  export const showInsertColumnButton = (columnIndex: number) =>
615
- createCommand(
616
- (_) =>
617
- columnIndex > -1
618
- ? {
619
- type: 'SHOW_INSERT_COLUMN_BUTTON',
620
- data: { insertColumnButtonIndex: columnIndex },
621
- }
622
- : false,
623
- (tr) => tr.setMeta('addToHistory', false),
624
- );
526
+ createCommand(
527
+ (_) =>
528
+ columnIndex > -1
529
+ ? {
530
+ type: 'SHOW_INSERT_COLUMN_BUTTON',
531
+ data: { insertColumnButtonIndex: columnIndex },
532
+ }
533
+ : false,
534
+ (tr) => tr.setMeta('addToHistory', false),
535
+ );
625
536
 
626
537
  export const showInsertRowButton = (rowIndex: number) =>
627
- createCommand(
628
- (_) =>
629
- rowIndex > -1
630
- ? {
631
- type: 'SHOW_INSERT_ROW_BUTTON',
632
- data: { insertRowButtonIndex: rowIndex },
633
- }
634
- : false,
635
- (tr) => tr.setMeta('addToHistory', false),
636
- );
538
+ createCommand(
539
+ (_) =>
540
+ rowIndex > -1
541
+ ? {
542
+ type: 'SHOW_INSERT_ROW_BUTTON',
543
+ data: { insertRowButtonIndex: rowIndex },
544
+ }
545
+ : false,
546
+ (tr) => tr.setMeta('addToHistory', false),
547
+ );
637
548
 
638
549
  export const hideInsertColumnOrRowButton = () =>
639
- createCommand(
640
- {
641
- type: 'HIDE_INSERT_COLUMN_OR_ROW_BUTTON',
642
- },
643
- (tr) => tr.setMeta('addToHistory', false),
644
- );
550
+ createCommand(
551
+ {
552
+ type: 'HIDE_INSERT_COLUMN_OR_ROW_BUTTON',
553
+ },
554
+ (tr) => tr.setMeta('addToHistory', false),
555
+ );
645
556
 
646
557
  export const addResizeHandleDecorations = (
647
- rowIndex: number,
648
- columnIndex: number,
649
- includeTooltip: boolean,
650
- isKeyboardResize?: boolean,
558
+ rowIndex: number,
559
+ columnIndex: number,
560
+ includeTooltip: boolean,
561
+ isKeyboardResize?: boolean,
651
562
  ) =>
652
- createCommand(
653
- (state) => {
654
- const tableNode = findTable(state.selection);
655
- const {
656
- pluginConfig: { allowColumnResizing },
657
- getIntl,
658
- } = getPluginState(state);
659
-
660
- if (!tableNode || !allowColumnResizing) {
661
- return false;
662
- }
663
-
664
- return {
665
- type: 'ADD_RESIZE_HANDLE_DECORATIONS',
666
- data: {
667
- decorationSet: buildColumnResizingDecorations(
668
- rowIndex,
669
- columnIndex,
670
- includeTooltip,
671
- getIntl,
672
- )({
673
- tr: state.tr,
674
- decorationSet: getDecorations(state),
675
- }),
676
- resizeHandleRowIndex: rowIndex,
677
- resizeHandleColumnIndex: columnIndex,
678
- resizeHandleIncludeTooltip: includeTooltip,
679
- isKeyboardResize: isKeyboardResize || false,
680
- },
681
- };
682
- },
683
- (tr: Transaction) => tr.setMeta('addToHistory', false),
684
- );
563
+ createCommand(
564
+ (state) => {
565
+ const tableNode = findTable(state.selection);
566
+ const {
567
+ pluginConfig: { allowColumnResizing },
568
+ getIntl,
569
+ } = getPluginState(state);
570
+
571
+ if (!tableNode || !allowColumnResizing) {
572
+ return false;
573
+ }
574
+
575
+ return {
576
+ type: 'ADD_RESIZE_HANDLE_DECORATIONS',
577
+ data: {
578
+ decorationSet: buildColumnResizingDecorations(
579
+ rowIndex,
580
+ columnIndex,
581
+ includeTooltip,
582
+ getIntl,
583
+ )({
584
+ tr: state.tr,
585
+ decorationSet: getDecorations(state),
586
+ }),
587
+ resizeHandleRowIndex: rowIndex,
588
+ resizeHandleColumnIndex: columnIndex,
589
+ resizeHandleIncludeTooltip: includeTooltip,
590
+ isKeyboardResize: isKeyboardResize || false,
591
+ },
592
+ };
593
+ },
594
+ (tr: Transaction) => tr.setMeta('addToHistory', false),
595
+ );
685
596
 
686
597
  export const updateResizeHandleDecorations = (
687
- rowIndex?: number,
688
- columnIndex?: number,
689
- includeTooltip?: boolean,
598
+ rowIndex?: number,
599
+ columnIndex?: number,
600
+ includeTooltip?: boolean,
690
601
  ) =>
691
- createCommand(
692
- (state) => {
693
- const tableNode = findTable(state.selection);
694
- const {
695
- resizeHandleRowIndex,
696
- resizeHandleColumnIndex,
697
- resizeHandleIncludeTooltip,
698
- pluginConfig: { allowColumnResizing },
699
- getIntl,
700
- } = getPluginState(state);
701
-
702
- if (!tableNode || !allowColumnResizing) {
703
- return false;
704
- }
705
-
706
- const resolvedRowIndex = rowIndex ?? resizeHandleRowIndex;
707
- const resolvedColumnIndex = columnIndex ?? resizeHandleColumnIndex;
708
- const resolvedIncludeTooltip =
709
- includeTooltip ?? resizeHandleIncludeTooltip;
710
-
711
- if (
712
- resolvedRowIndex === undefined ||
713
- resolvedColumnIndex === undefined ||
714
- resolvedIncludeTooltip === undefined
715
- ) {
716
- return false;
717
- }
718
-
719
- return {
720
- type: 'UPDATE_RESIZE_HANDLE_DECORATIONS',
721
- data: {
722
- decorationSet: buildColumnResizingDecorations(
723
- resolvedRowIndex,
724
- resolvedColumnIndex,
725
- resolvedIncludeTooltip,
726
- getIntl,
727
- )({
728
- tr: state.tr,
729
- decorationSet: getDecorations(state),
730
- }),
731
- resizeHandleRowIndex: rowIndex,
732
- resizeHandleColumnIndex: columnIndex,
733
- resizeHandleIncludeTooltip: includeTooltip,
734
- },
735
- };
736
- },
737
- (tr: Transaction) => tr.setMeta('addToHistory', false),
738
- );
602
+ createCommand(
603
+ (state) => {
604
+ const tableNode = findTable(state.selection);
605
+ const {
606
+ resizeHandleRowIndex,
607
+ resizeHandleColumnIndex,
608
+ resizeHandleIncludeTooltip,
609
+ pluginConfig: { allowColumnResizing },
610
+ getIntl,
611
+ } = getPluginState(state);
612
+
613
+ if (!tableNode || !allowColumnResizing) {
614
+ return false;
615
+ }
616
+
617
+ const resolvedRowIndex = rowIndex ?? resizeHandleRowIndex;
618
+ const resolvedColumnIndex = columnIndex ?? resizeHandleColumnIndex;
619
+ const resolvedIncludeTooltip = includeTooltip ?? resizeHandleIncludeTooltip;
620
+
621
+ if (
622
+ resolvedRowIndex === undefined ||
623
+ resolvedColumnIndex === undefined ||
624
+ resolvedIncludeTooltip === undefined
625
+ ) {
626
+ return false;
627
+ }
628
+
629
+ return {
630
+ type: 'UPDATE_RESIZE_HANDLE_DECORATIONS',
631
+ data: {
632
+ decorationSet: buildColumnResizingDecorations(
633
+ resolvedRowIndex,
634
+ resolvedColumnIndex,
635
+ resolvedIncludeTooltip,
636
+ getIntl,
637
+ )({
638
+ tr: state.tr,
639
+ decorationSet: getDecorations(state),
640
+ }),
641
+ resizeHandleRowIndex: rowIndex,
642
+ resizeHandleColumnIndex: columnIndex,
643
+ resizeHandleIncludeTooltip: includeTooltip,
644
+ },
645
+ };
646
+ },
647
+ (tr: Transaction) => tr.setMeta('addToHistory', false),
648
+ );
739
649
 
740
650
  export const removeResizeHandleDecorations = () =>
741
- createCommand(
742
- (state) => ({
743
- type: 'REMOVE_RESIZE_HANDLE_DECORATIONS',
744
- data: {
745
- decorationSet: clearColumnResizingDecorations()({
746
- tr: state.tr,
747
- decorationSet: getDecorations(state),
748
- }),
749
- },
750
- }),
751
- (tr) => tr.setMeta('addToHistory', false),
752
- );
651
+ createCommand(
652
+ (state) => ({
653
+ type: 'REMOVE_RESIZE_HANDLE_DECORATIONS',
654
+ data: {
655
+ decorationSet: clearColumnResizingDecorations()({
656
+ tr: state.tr,
657
+ decorationSet: getDecorations(state),
658
+ }),
659
+ },
660
+ }),
661
+ (tr) => tr.setMeta('addToHistory', false),
662
+ );
753
663
 
754
664
  export const autoSizeTable = (
755
- view: EditorView,
756
- node: PMNode,
757
- table: HTMLTableElement,
758
- basePos: number | undefined,
759
- opts: { containerWidth: number },
665
+ view: EditorView,
666
+ node: PMNode,
667
+ table: HTMLTableElement,
668
+ basePos: number | undefined,
669
+ opts: { containerWidth: number },
760
670
  ) => {
761
- if (typeof basePos !== 'number') {
762
- return false;
763
- }
671
+ if (typeof basePos !== 'number') {
672
+ return false;
673
+ }
764
674
 
765
- view.dispatch(fixAutoSizedTable(view, node, table, basePos, opts));
766
- return true;
675
+ view.dispatch(fixAutoSizedTable(view, node, table, basePos, opts));
676
+ return true;
767
677
  };
768
678
 
769
679
  export const addBoldInEmptyHeaderCells =
770
- (tableCellHeader: ContentNodeWithPos): Command =>
771
- (state, dispatch): boolean => {
772
- const { tr } = state;
773
- if (
774
- // Avoid infinite loop when the current selection is not a TextSelection
775
- isTextSelection(tr.selection) &&
776
- tr.selection.$cursor &&
777
- // When storedMark is null that means this is the initial state
778
- // if the user press to remove the mark storedMark will be an empty array
779
- // and we shouldn't apply the strong mark
780
- tr.storedMarks == null &&
781
- // Check if the current node is a direct child from paragraph
782
- tr.selection.$from.depth === tableCellHeader.depth + 1 &&
783
- // this logic is applied only for empty paragraph
784
- tableCellHeader.node.nodeSize === 4 &&
785
- isParagraph(tableCellHeader.node.firstChild, state.schema)
786
- ) {
787
- const { strong } = state.schema.marks;
788
- tr.setStoredMarks([strong.create()]).setMeta('addToHistory', false);
789
-
790
- if (dispatch) {
791
- dispatch(tr);
792
- }
793
-
794
- return true;
795
- }
796
-
797
- return false;
798
- };
680
+ (tableCellHeader: ContentNodeWithPos): Command =>
681
+ (state, dispatch): boolean => {
682
+ const { tr } = state;
683
+ if (
684
+ // Avoid infinite loop when the current selection is not a TextSelection
685
+ isTextSelection(tr.selection) &&
686
+ tr.selection.$cursor &&
687
+ // When storedMark is null that means this is the initial state
688
+ // if the user press to remove the mark storedMark will be an empty array
689
+ // and we shouldn't apply the strong mark
690
+ tr.storedMarks == null &&
691
+ // Check if the current node is a direct child from paragraph
692
+ tr.selection.$from.depth === tableCellHeader.depth + 1 &&
693
+ // this logic is applied only for empty paragraph
694
+ tableCellHeader.node.nodeSize === 4 &&
695
+ isParagraph(tableCellHeader.node.firstChild, state.schema)
696
+ ) {
697
+ const { strong } = state.schema.marks;
698
+ tr.setStoredMarks([strong.create()]).setMeta('addToHistory', false);
699
+
700
+ if (dispatch) {
701
+ dispatch(tr);
702
+ }
703
+
704
+ return true;
705
+ }
706
+
707
+ return false;
708
+ };
799
709
 
800
710
  export const updateWidthToWidest = (widthToWidest: WidthToWidest) =>
801
- createCommand((state) => {
802
- let { widthToWidest: prevWidthToWidest } = getPluginState(state);
711
+ createCommand((state) => {
712
+ let { widthToWidest: prevWidthToWidest } = getPluginState(state);
803
713
 
804
- if (isEqual(widthToWidest, prevWidthToWidest)) {
805
- return false;
806
- }
714
+ if (isEqual(widthToWidest, prevWidthToWidest)) {
715
+ return false;
716
+ }
807
717
 
808
- return {
809
- type: 'UPDATE_TABLE_WIDTH_TO_WIDEST',
810
- data: {
811
- widthToWidest: { ...prevWidthToWidest, ...widthToWidest },
812
- },
813
- };
814
- });
718
+ return {
719
+ type: 'UPDATE_TABLE_WIDTH_TO_WIDEST',
720
+ data: {
721
+ widthToWidest: { ...prevWidthToWidest, ...widthToWidest },
722
+ },
723
+ };
724
+ });
815
725
 
816
726
  export const setTableAlignment =
817
- (newAlignment: TableLayout): EditorCommand =>
818
- ({ tr }) => {
819
- const tableObject = findTable(tr.selection);
727
+ (newAlignment: TableLayout): EditorCommand =>
728
+ ({ tr }) => {
729
+ const tableObject = findTable(tr.selection);
820
730
 
821
- if (!tableObject) {
822
- return null;
823
- }
731
+ if (!tableObject) {
732
+ return null;
733
+ }
824
734
 
825
- const nextTableAttrs = {
826
- ...tableObject.node.attrs,
827
- layout: newAlignment,
828
- };
735
+ const nextTableAttrs = {
736
+ ...tableObject.node.attrs,
737
+ layout: newAlignment,
738
+ };
829
739
 
830
- tr.setNodeMarkup(tableObject.pos, undefined, nextTableAttrs).setMeta(
831
- 'scrollIntoView',
832
- false,
833
- );
740
+ tr.setNodeMarkup(tableObject.pos, undefined, nextTableAttrs).setMeta('scrollIntoView', false);
834
741
 
835
- return tr;
836
- };
742
+ return tr;
743
+ };
837
744
 
838
745
  export const setTableAlignmentWithTableContentWithPos =
839
- (newAlignment: TableLayout, tableNodeWithPos: NodeWithPos): EditorCommand =>
840
- ({ tr }) => {
841
- const nextTableAttrs = {
842
- ...tableNodeWithPos.node.attrs,
843
- layout: newAlignment,
844
- };
845
-
846
- tr.setNodeMarkup(tableNodeWithPos.pos, undefined, nextTableAttrs).setMeta(
847
- 'scrollIntoView',
848
- false,
849
- );
850
-
851
- return tr;
852
- };
746
+ (newAlignment: TableLayout, tableNodeWithPos: NodeWithPos): EditorCommand =>
747
+ ({ tr }) => {
748
+ const nextTableAttrs = {
749
+ ...tableNodeWithPos.node.attrs,
750
+ layout: newAlignment,
751
+ };
752
+
753
+ tr.setNodeMarkup(tableNodeWithPos.pos, undefined, nextTableAttrs).setMeta(
754
+ 'scrollIntoView',
755
+ false,
756
+ );
757
+
758
+ return tr;
759
+ };