@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
@@ -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
+ };