@atlaskit/editor-plugin-table 2.1.7 → 2.3.0

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 (147) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/cjs/plugins/table/handlers.js +1 -0
  3. package/dist/cjs/plugins/table/index.js +41 -35
  4. package/dist/cjs/plugins/table/nodeviews/TableComponent.js +5 -4
  5. package/dist/cjs/plugins/table/nodeviews/TableContainer.js +50 -47
  6. package/dist/cjs/plugins/table/nodeviews/TableResizer.js +72 -28
  7. package/dist/cjs/plugins/table/nodeviews/table.js +12 -5
  8. package/dist/cjs/plugins/table/pm-plugins/decorations/plugin.js +14 -5
  9. package/dist/cjs/plugins/table/pm-plugins/decorations/utils/column-controls.js +2 -0
  10. package/dist/cjs/plugins/table/pm-plugins/main.js +2 -2
  11. package/dist/cjs/plugins/table/pm-plugins/table-resizing/plugin-factory.js +1 -1
  12. package/dist/cjs/plugins/table/pm-plugins/{table-add-width.js → table-width.js} +27 -4
  13. package/dist/cjs/plugins/table/toolbar.js +6 -1
  14. package/dist/cjs/plugins/table/ui/consts.js +6 -2
  15. package/dist/cjs/plugins/table/utils/collapse.js +2 -0
  16. package/dist/cjs/plugins/table/utils/decoration.js +2 -0
  17. package/dist/cjs/plugins/table/utils/guidelines.js +12 -0
  18. package/dist/cjs/plugins/table/utils/snapping.js +37 -0
  19. package/dist/cjs/version.json +1 -1
  20. package/dist/es2019/plugins/table/handlers.js +1 -0
  21. package/dist/es2019/plugins/table/index.js +19 -10
  22. package/dist/es2019/plugins/table/nodeviews/TableComponent.js +5 -4
  23. package/dist/es2019/plugins/table/nodeviews/TableContainer.js +25 -23
  24. package/dist/es2019/plugins/table/nodeviews/TableResizer.js +71 -29
  25. package/dist/es2019/plugins/table/nodeviews/table.js +12 -5
  26. package/dist/es2019/plugins/table/pm-plugins/decorations/plugin.js +18 -6
  27. package/dist/es2019/plugins/table/pm-plugins/decorations/utils/column-controls.js +2 -0
  28. package/dist/es2019/plugins/table/pm-plugins/main.js +2 -2
  29. package/dist/es2019/plugins/table/pm-plugins/table-resizing/plugin-factory.js +2 -0
  30. package/dist/es2019/plugins/table/pm-plugins/{table-add-width.js → table-width.js} +25 -3
  31. package/dist/es2019/plugins/table/toolbar.js +6 -1
  32. package/dist/es2019/plugins/table/ui/consts.js +3 -1
  33. package/dist/es2019/plugins/table/utils/collapse.js +2 -0
  34. package/dist/es2019/plugins/table/utils/decoration.js +2 -0
  35. package/dist/es2019/plugins/table/utils/guidelines.js +4 -0
  36. package/dist/es2019/plugins/table/utils/snapping.js +27 -0
  37. package/dist/es2019/version.json +1 -1
  38. package/dist/esm/plugins/table/handlers.js +1 -0
  39. package/dist/esm/plugins/table/index.js +41 -35
  40. package/dist/esm/plugins/table/nodeviews/TableComponent.js +5 -4
  41. package/dist/esm/plugins/table/nodeviews/TableContainer.js +50 -47
  42. package/dist/esm/plugins/table/nodeviews/TableResizer.js +69 -28
  43. package/dist/esm/plugins/table/nodeviews/table.js +12 -5
  44. package/dist/esm/plugins/table/pm-plugins/decorations/plugin.js +18 -6
  45. package/dist/esm/plugins/table/pm-plugins/decorations/utils/column-controls.js +2 -0
  46. package/dist/esm/plugins/table/pm-plugins/main.js +2 -2
  47. package/dist/esm/plugins/table/pm-plugins/table-resizing/plugin-factory.js +2 -0
  48. package/dist/esm/plugins/table/pm-plugins/{table-add-width.js → table-width.js} +25 -3
  49. package/dist/esm/plugins/table/toolbar.js +6 -1
  50. package/dist/esm/plugins/table/ui/consts.js +3 -1
  51. package/dist/esm/plugins/table/utils/collapse.js +2 -0
  52. package/dist/esm/plugins/table/utils/decoration.js +2 -0
  53. package/dist/esm/plugins/table/utils/guidelines.js +4 -0
  54. package/dist/esm/plugins/table/utils/snapping.js +30 -0
  55. package/dist/esm/version.json +1 -1
  56. package/dist/types/plugins/table/index.d.ts +3 -1
  57. package/dist/types/plugins/table/nodeviews/TableComponent.d.ts +3 -2
  58. package/dist/types/plugins/table/nodeviews/TableContainer.d.ts +5 -2
  59. package/dist/types/plugins/table/nodeviews/TableResizer.d.ts +3 -1
  60. package/dist/types/plugins/table/nodeviews/table.d.ts +2 -1
  61. package/dist/types/plugins/table/nodeviews/types.d.ts +2 -0
  62. package/dist/types/plugins/table/pm-plugins/decorations/plugin.d.ts +1 -1
  63. package/dist/types/plugins/table/pm-plugins/main.d.ts +2 -1
  64. package/dist/types/plugins/table/pm-plugins/table-width.d.ts +16 -0
  65. package/dist/types/plugins/table/types.d.ts +3 -0
  66. package/dist/types/plugins/table/ui/consts.d.ts +2 -0
  67. package/dist/types/plugins/table/utils/guidelines.d.ts +3 -0
  68. package/dist/types/plugins/table/utils/snapping.d.ts +8 -0
  69. package/dist/types-ts4.5/plugins/table/index.d.ts +3 -1
  70. package/dist/types-ts4.5/plugins/table/nodeviews/TableComponent.d.ts +3 -2
  71. package/dist/types-ts4.5/plugins/table/nodeviews/TableContainer.d.ts +5 -2
  72. package/dist/types-ts4.5/plugins/table/nodeviews/TableResizer.d.ts +3 -1
  73. package/dist/types-ts4.5/plugins/table/nodeviews/table.d.ts +2 -1
  74. package/dist/types-ts4.5/plugins/table/nodeviews/types.d.ts +2 -0
  75. package/dist/types-ts4.5/plugins/table/pm-plugins/decorations/plugin.d.ts +1 -1
  76. package/dist/types-ts4.5/plugins/table/pm-plugins/main.d.ts +2 -1
  77. package/dist/types-ts4.5/plugins/table/pm-plugins/table-width.d.ts +16 -0
  78. package/dist/types-ts4.5/plugins/table/types.d.ts +3 -0
  79. package/dist/types-ts4.5/plugins/table/ui/consts.d.ts +2 -0
  80. package/dist/types-ts4.5/plugins/table/utils/guidelines.d.ts +3 -0
  81. package/dist/types-ts4.5/plugins/table/utils/snapping.d.ts +8 -0
  82. package/package.json +4 -3
  83. package/report.api.md +2 -0
  84. package/src/__tests__/unit/analytics.ts +2 -0
  85. package/src/__tests__/unit/collab.ts +2 -0
  86. package/src/__tests__/unit/commands/go-to-next-cell.ts +2 -0
  87. package/src/__tests__/unit/commands/insert.ts +2 -0
  88. package/src/__tests__/unit/commands/misc.ts +2 -0
  89. package/src/__tests__/unit/commands/sort.ts +4 -0
  90. package/src/__tests__/unit/commands.ts +2 -0
  91. package/src/__tests__/unit/copy-paste.ts +2 -0
  92. package/src/__tests__/unit/event-handlers/index.ts +3 -0
  93. package/src/__tests__/unit/event-handlers.ts +3 -0
  94. package/src/__tests__/unit/fix-tables.ts +2 -0
  95. package/src/__tests__/unit/get-toolbar-config.ts +2 -0
  96. package/src/__tests__/unit/handlers.ts +2 -0
  97. package/src/__tests__/unit/hover-selection.ts +2 -0
  98. package/src/__tests__/unit/index.ts +2 -0
  99. package/src/__tests__/unit/layout.ts +2 -0
  100. package/src/__tests__/unit/nodeviews/cell.ts +2 -0
  101. package/src/__tests__/unit/nodeviews/table.ts +2 -0
  102. package/src/__tests__/unit/pm-plugins/decorations/column-resizing.ts +2 -0
  103. package/src/__tests__/unit/pm-plugins/decorations/plugin.ts +68 -0
  104. package/src/__tests__/unit/pm-plugins/main.ts +2 -0
  105. package/src/__tests__/unit/pm-plugins/safari-delete-composition-text-issue-workaround.ts +2 -0
  106. package/src/__tests__/unit/pm-plugins/sticky-headers/tableRow.tsx +3 -0
  107. package/src/__tests__/unit/pm-plugins/table-resizing/event-handlers.ts +2 -0
  108. package/src/__tests__/unit/sort-column.ts +2 -0
  109. package/src/__tests__/unit/toolbar.ts +2 -0
  110. package/src/__tests__/unit/transforms/delete-columns.ts +2 -0
  111. package/src/__tests__/unit/transforms/delete-rows.ts +2 -0
  112. package/src/__tests__/unit/transforms/merging.ts +2 -0
  113. package/src/__tests__/unit/ui/ContextualMenu.tsx +2 -0
  114. package/src/__tests__/unit/ui/CornerControls.tsx +2 -0
  115. package/src/__tests__/unit/ui/FloatingContextualButton.tsx +2 -0
  116. package/src/__tests__/unit/ui/FloatingContextualMenu.tsx +2 -0
  117. package/src/__tests__/unit/ui/RowControls.tsx +2 -0
  118. package/src/__tests__/unit/ui/TableFloatingControls.tsx +2 -0
  119. package/src/__tests__/unit/undo-redo.ts +2 -0
  120. package/src/__tests__/unit/utils/collapse.ts +2 -0
  121. package/src/__tests__/unit/utils/nodes.ts +2 -0
  122. package/src/__tests__/unit/utils/row-controls.ts +2 -0
  123. package/src/__tests__/unit/utils.ts +2 -0
  124. package/src/plugins/table/handlers.ts +1 -0
  125. package/src/plugins/table/index.tsx +38 -23
  126. package/src/plugins/table/nodeviews/TableComponent.tsx +6 -5
  127. package/src/plugins/table/nodeviews/TableContainer.tsx +31 -22
  128. package/src/plugins/table/nodeviews/TableResizer.tsx +107 -34
  129. package/src/plugins/table/nodeviews/table.tsx +16 -2
  130. package/src/plugins/table/nodeviews/types.ts +2 -0
  131. package/src/plugins/table/pm-plugins/decorations/plugin.ts +27 -4
  132. package/src/plugins/table/pm-plugins/decorations/utils/column-controls.ts +1 -0
  133. package/src/plugins/table/pm-plugins/decorations/utils/types.ts +1 -0
  134. package/src/plugins/table/pm-plugins/main.ts +3 -0
  135. package/src/plugins/table/pm-plugins/table-resizing/plugin-factory.ts +1 -0
  136. package/src/plugins/table/pm-plugins/table-resizing/utils/dom.ts +1 -0
  137. package/src/plugins/table/pm-plugins/{table-add-width.ts → table-width.ts} +33 -3
  138. package/src/plugins/table/toolbar.tsx +7 -1
  139. package/src/plugins/table/types.ts +4 -0
  140. package/src/plugins/table/ui/consts.ts +3 -0
  141. package/src/plugins/table/utils/collapse.ts +1 -0
  142. package/src/plugins/table/utils/decoration.ts +1 -0
  143. package/src/plugins/table/utils/guidelines.ts +17 -0
  144. package/src/plugins/table/utils/snapping.ts +38 -0
  145. package/tmp/api-report-tmp.d.ts +3 -1
  146. package/dist/types/plugins/table/pm-plugins/table-add-width.d.ts +0 -7
  147. package/dist/types-ts4.5/plugins/table/pm-plugins/table-add-width.d.ts +0 -7
@@ -11,17 +11,13 @@ import { getBooleanFF } from '@atlaskit/platform-feature-flags';
11
11
  import { getTableContainerWidth } from '@atlaskit/editor-common/node-width';
12
12
  import { EditorContainerWidth } from '@atlaskit/editor-common/types';
13
13
  import { calcTableWidth } from '@atlaskit/editor-common/styles';
14
+ import type { GuidelineConfig } from '@atlaskit/editor-plugin-guideline';
14
15
 
15
- import { TableCssClassName as ClassName } from '../types';
16
+ import { PluginInjectionAPI, TableCssClassName as ClassName } from '../types';
16
17
  import { TableResizer } from './TableResizer';
17
18
  import { TABLE_MAX_WIDTH } from '../pm-plugins/table-resizing/utils';
18
19
 
19
- interface GetMarginLeftOpts {
20
- lineLength: number;
21
- tableWidth: number | 'inherit';
22
- }
23
-
24
- const getMarginLeft = ({ lineLength, tableWidth }: GetMarginLeftOpts) => {
20
+ const getMarginLeft = (lineLength: number, tableWidth: number | 'inherit') => {
25
21
  let marginLeft;
26
22
  if (tableWidth !== 'inherit' && lineLength) {
27
23
  const containerWidth = tableWidth;
@@ -69,6 +65,7 @@ type ResizableTableContainerProps = {
69
65
  editorView: EditorView;
70
66
  getPos: () => number | undefined;
71
67
  tableRef: HTMLTableElement;
68
+ pluginInjectionApi?: PluginInjectionAPI;
72
69
  };
73
70
 
74
71
  export const ResizableTableContainer = ({
@@ -80,9 +77,11 @@ export const ResizableTableContainer = ({
80
77
  editorView,
81
78
  getPos,
82
79
  tableRef,
80
+ pluginInjectionApi,
83
81
  }: PropsWithChildren<ResizableTableContainerProps>) => {
84
82
  const containerRef = useRef<HTMLDivElement | null>(null);
85
83
  const innerContainerRef = useRef<HTMLDivElement | null>(null);
84
+ const marginLeftRef = useRef<number | undefined>(0);
86
85
 
87
86
  const updateWidth = useCallback(
88
87
  (width: number) => {
@@ -90,18 +89,30 @@ export const ResizableTableContainer = ({
90
89
  return;
91
90
  }
92
91
 
93
- const marginLeft = getMarginLeft({
94
- lineLength,
95
- tableWidth: width,
96
- });
92
+ const marginLeft = getMarginLeft(lineLength, width);
93
+
94
+ if (marginLeftRef.current !== marginLeft) {
95
+ marginLeftRef.current = marginLeft;
97
96
 
98
- if (marginLeft) {
99
- containerRef.current.style.marginLeft = `${marginLeft}px`;
97
+ if (Number.isFinite(marginLeft)) {
98
+ containerRef.current.style.marginLeft = `${marginLeft}px`;
99
+ }
100
100
  }
101
101
  },
102
102
  [lineLength],
103
103
  );
104
104
 
105
+ const displayGuideline = useCallback(
106
+ (guidelines: GuidelineConfig[]) => {
107
+ return (
108
+ pluginInjectionApi?.dependencies?.guideline?.actions?.displayGuideline(
109
+ editorView,
110
+ )({ guidelines }) ?? false
111
+ );
112
+ },
113
+ [pluginInjectionApi, editorView],
114
+ );
115
+
105
116
  const tableWidth = getTableContainerWidth(node);
106
117
 
107
118
  // 76 is currently an accepted padding value considering the spacing for resizer handle
@@ -109,16 +120,13 @@ export const ResizableTableContainer = ({
109
120
 
110
121
  const width = Math.min(tableWidth, responsiveContainerWidth);
111
122
 
112
- const marginLeft = getMarginLeft({
113
- lineLength,
114
- tableWidth: width,
115
- });
123
+ marginLeftRef.current = getMarginLeft(lineLength, width);
116
124
 
117
125
  const maxResizerWidth = Math.min(responsiveContainerWidth, TABLE_MAX_WIDTH);
118
126
 
119
127
  return (
120
128
  <div
121
- style={{ marginLeft, width }}
129
+ style={{ marginLeft: marginLeftRef.current, width }}
122
130
  className={ClassName.TABLE_RESIZER_CONTAINER}
123
131
  ref={containerRef}
124
132
  >
@@ -130,6 +138,7 @@ export const ResizableTableContainer = ({
130
138
  getPos={getPos}
131
139
  node={node}
132
140
  tableRef={tableRef}
141
+ displayGuideline={displayGuideline}
133
142
  >
134
143
  <InnerContainer
135
144
  ref={innerContainerRef}
@@ -156,6 +165,7 @@ type TableContainerProps = {
156
165
  getPos: () => number | undefined;
157
166
  tableRef: HTMLTableElement;
158
167
  isNested: boolean;
168
+ pluginInjectionApi?: PluginInjectionAPI;
159
169
  };
160
170
 
161
171
  export const TableContainer = ({
@@ -169,6 +179,7 @@ export const TableContainer = ({
169
179
  getPos,
170
180
  tableRef,
171
181
  isNested,
182
+ pluginInjectionApi,
172
183
  }: PropsWithChildren<TableContainerProps>) => {
173
184
  if (
174
185
  (isFullWidthModeEnabled || isBreakoutEnabled) &&
@@ -184,6 +195,7 @@ export const TableContainer = ({
184
195
  editorView={editorView}
185
196
  getPos={getPos}
186
197
  tableRef={tableRef}
198
+ pluginInjectionApi={pluginInjectionApi}
187
199
  >
188
200
  {children}
189
201
  </ResizableTableContainer>
@@ -200,10 +212,7 @@ export const TableContainer = ({
200
212
  className={className}
201
213
  style={{
202
214
  width: tableWidth,
203
- marginLeft: getMarginLeft({
204
- lineLength: lineLength!,
205
- tableWidth,
206
- }),
215
+ marginLeft: getMarginLeft(lineLength!, tableWidth),
207
216
  }}
208
217
  >
209
218
  {children}
@@ -1,12 +1,21 @@
1
- import React, { PropsWithChildren } from 'react';
1
+ import React, {
2
+ PropsWithChildren,
3
+ useCallback,
4
+ useRef,
5
+ useMemo,
6
+ useState,
7
+ } from 'react';
2
8
  import { EditorView } from 'prosemirror-view';
3
9
  import { Node as PMNode } from 'prosemirror-model';
4
10
  import rafSchd from 'raf-schd';
5
11
 
6
12
  import {
7
13
  HandleHeightSizeType,
14
+ HandleResize,
8
15
  ResizerNext,
9
16
  } from '@atlaskit/editor-common/resizer';
17
+ import { getGuidelinesWithHighlights } from '@atlaskit/editor-common/guideline';
18
+ import type { GuidelineConfig } from '@atlaskit/editor-plugin-guideline';
10
19
 
11
20
  import {
12
21
  scaleTable,
@@ -14,6 +23,10 @@ import {
14
23
  getColgroupChildrenLength,
15
24
  COLUMN_MIN_WIDTH,
16
25
  } from '../pm-plugins/table-resizing/utils';
26
+ import { pluginKey as tableWidthPluginKey } from '../pm-plugins/table-width';
27
+ import { defaultGuidelines, defaultGuidelineWidths } from '../utils/guidelines';
28
+ import { findClosestSnap } from '../utils/snapping';
29
+ import { TABLE_SNAP_GAP, TABLE_HIGHLIGHT_GAP } from '../ui/consts';
17
30
 
18
31
  interface TableResizerProps {
19
32
  width: number;
@@ -23,6 +36,7 @@ interface TableResizerProps {
23
36
  getPos: () => number | undefined;
24
37
  node: PMNode;
25
38
  tableRef: HTMLTableElement;
39
+ displayGuideline: (guideline: GuidelineConfig[]) => boolean;
26
40
  }
27
41
 
28
42
  const handles = { right: true };
@@ -37,6 +51,7 @@ export const TableResizer = ({
37
51
  getPos,
38
52
  node,
39
53
  tableRef,
54
+ displayGuideline,
40
55
  }: PropsWithChildren<TableResizerProps>) => {
41
56
  const currentColumnCount = getColgroupChildrenLength(node);
42
57
  const minColumnWidth =
@@ -60,6 +75,84 @@ export const TableResizer = ({
60
75
  } else if (tableHeight && tableHeight >= 96) {
61
76
  handleHeightSize = 'large';
62
77
  }
78
+ const currentGap = useRef(0);
79
+ const [snappingEnabled, setSnappingEnabled] = useState(false);
80
+
81
+ const updateActiveGuidelines = useCallback(
82
+ ({ gap, keys }: { gap: number; keys: string[] }) => {
83
+ if (gap !== currentGap.current) {
84
+ currentGap.current = gap;
85
+ displayGuideline(
86
+ getGuidelinesWithHighlights(
87
+ gap,
88
+ TABLE_SNAP_GAP,
89
+ keys,
90
+ defaultGuidelines,
91
+ ),
92
+ );
93
+ }
94
+ },
95
+ [displayGuideline],
96
+ );
97
+
98
+ const guidelineSnaps = useMemo(
99
+ () =>
100
+ snappingEnabled
101
+ ? {
102
+ x: defaultGuidelineWidths,
103
+ }
104
+ : undefined,
105
+ [snappingEnabled],
106
+ );
107
+
108
+ const handleResizeStart = useCallback(() => {
109
+ const {
110
+ dispatch,
111
+ state: { tr },
112
+ } = editorView;
113
+ dispatch(tr.setMeta(tableWidthPluginKey, { resizing: true }));
114
+
115
+ setSnappingEnabled(displayGuideline(defaultGuidelines));
116
+ return width;
117
+ }, [width, displayGuideline, editorView]);
118
+
119
+ const handleResizeStop = useCallback<HandleResize>(
120
+ (originalState, delta) => {
121
+ const newWidth = originalState.width + delta.width;
122
+ const { state, dispatch } = editorView;
123
+ const pos = getPos();
124
+
125
+ let tr = state.tr.setMeta(tableWidthPluginKey, { resizing: false });
126
+
127
+ if (typeof pos === 'number') {
128
+ tr = tr.setNodeMarkup(pos, undefined, {
129
+ ...node.attrs,
130
+ width: newWidth,
131
+ });
132
+
133
+ const newNode = tr.doc.nodeAt(pos)!;
134
+ tr = scaleTable(
135
+ tableRef,
136
+ {
137
+ node: newNode,
138
+ prevNode: node,
139
+ start: pos + 1,
140
+ parentWidth: newWidth,
141
+ },
142
+ editorView.domAtPos.bind(editorView),
143
+ )(tr);
144
+ }
145
+
146
+ dispatch(tr);
147
+
148
+ // Hide guidelines when resizing stops
149
+ displayGuideline([]);
150
+
151
+ updateWidth(newWidth);
152
+ return newWidth;
153
+ },
154
+ [updateWidth, editorView, getPos, node, tableRef, displayGuideline],
155
+ );
63
156
 
64
157
  return (
65
158
  <ResizerNext
@@ -68,7 +161,7 @@ export const TableResizer = ({
68
161
  handleAlignmentMethod="sticky"
69
162
  handleHeightSize={handleHeightSize}
70
163
  handleMarginTop={tableHandleMarginTop}
71
- handleResizeStart={() => width}
164
+ handleResizeStart={handleResizeStart}
72
165
  handleResize={rafSchd((originalState, delta) => {
73
166
  const newWidth = originalState.width + delta.width;
74
167
  const pos = getPos();
@@ -87,44 +180,24 @@ export const TableResizer = ({
87
180
  editorView.domAtPos.bind(editorView),
88
181
  );
89
182
 
90
- updateWidth(newWidth);
91
- return newWidth;
92
- })}
93
- handleResizeStop={(originalState, delta) => {
94
- const newWidth = originalState.width + delta.width;
95
-
96
- const { state, dispatch } = editorView;
97
- const pos = getPos();
98
-
99
- if (typeof pos !== 'number') {
100
- return;
101
- }
102
-
103
- let tr = state.tr.setNodeMarkup(pos, undefined, {
104
- ...node.attrs,
105
- width: newWidth,
106
- });
107
-
108
- const newNode = tr.doc.nodeAt(pos)!;
109
- tr = scaleTable(
110
- tableRef,
111
- {
112
- node: newNode,
113
- prevNode: node,
114
- start: pos + 1,
115
- parentWidth: newWidth,
116
- },
117
- editorView.domAtPos.bind(editorView),
118
- )(tr);
119
-
120
- dispatch(tr);
183
+ updateActiveGuidelines(
184
+ findClosestSnap(
185
+ newWidth,
186
+ defaultGuidelineWidths,
187
+ defaultGuidelines,
188
+ TABLE_HIGHLIGHT_GAP,
189
+ ),
190
+ );
121
191
 
122
192
  updateWidth(newWidth);
123
193
  return newWidth;
124
- }}
194
+ })}
195
+ handleResizeStop={handleResizeStop}
125
196
  resizeRatio={2}
126
197
  minWidth={minColumnWidth}
127
198
  maxWidth={maxWidth}
199
+ snapGap={TABLE_SNAP_GAP}
200
+ snap={guidelineSnaps}
128
201
  >
129
202
  {children}
130
203
  </ResizerNext>
@@ -24,6 +24,7 @@ import { pluginConfig as getPluginConfig } from '../create-plugin-config';
24
24
  import { getPluginState } from '../pm-plugins/plugin-factory';
25
25
  import { pluginKey } from '../pm-plugins/plugin-key';
26
26
  import { pluginKey as tableResizingPluginKey } from '../pm-plugins/table-resizing';
27
+ import { pluginKey as tableWidthPluginKey } from '../pm-plugins/table-width';
27
28
  import { generateColgroup } from '../pm-plugins/table-resizing/utils';
28
29
  import { TableMap } from '@atlaskit/editor-tables/table-map';
29
30
  import TableComponent from './TableComponent';
@@ -32,6 +33,7 @@ import type { TableColumnOrdering } from '@atlaskit/adf-schema/steps';
32
33
  import { getBooleanFF } from '@atlaskit/platform-feature-flags';
33
34
  import { getTableContainerWidth } from '@atlaskit/editor-common/node-width';
34
35
  import { isTableNested } from '../utils';
36
+ import { PluginInjectionAPI } from '../types';
35
37
 
36
38
  type ForwardRef = (node: HTMLElement | null) => void;
37
39
 
@@ -156,6 +158,7 @@ export default class TableView extends ReactNodeView<Props> {
156
158
  plugins={{
157
159
  pluginState: pluginKey,
158
160
  tableResizingPluginState: tableResizingPluginKey,
161
+ tableWidthPluginState: tableWidthPluginKey,
159
162
  widthPlugin: fakePluginKey,
160
163
  mediaState: fakeMediaPluginKey,
161
164
  }}
@@ -163,12 +166,20 @@ export default class TableView extends ReactNodeView<Props> {
163
166
  render={(pluginStates) => {
164
167
  const {
165
168
  tableResizingPluginState,
169
+ tableWidthPluginState,
166
170
  pluginState,
167
171
  // containerWidth,
168
172
  mediaState,
169
173
  } = pluginStates;
170
- const tableActive = props.getPos() === pluginState!.tablePos;
171
174
  const containerWidth = props.getEditorContainerWidth();
175
+
176
+ const isTableResizing = tableWidthPluginState?.resizing;
177
+ const isResizing = Boolean(
178
+ tableResizingPluginState?.dragging || isTableResizing,
179
+ );
180
+ const tableActive =
181
+ props.getPos() === pluginState!.tablePos && !isTableResizing;
182
+
172
183
  return (
173
184
  <TableComponent
174
185
  view={props.view}
@@ -182,11 +193,12 @@ export default class TableView extends ReactNodeView<Props> {
182
193
  isHeaderColumnEnabled={pluginState!.isHeaderColumnEnabled}
183
194
  tableActive={tableActive}
184
195
  ordering={pluginState!.ordering as TableColumnOrdering}
185
- tableResizingPluginState={tableResizingPluginState}
196
+ isResizing={isResizing}
186
197
  getNode={this.getNode}
187
198
  containerWidth={containerWidth!}
188
199
  contentDOM={forwardRef}
189
200
  getEditorFeatureFlags={props.getEditorFeatureFlags}
201
+ pluginInjectionApi={props.pluginInjectionApi}
190
202
  />
191
203
  );
192
204
  }}
@@ -280,6 +292,7 @@ export const createTableView = (
280
292
  options: TableOptions,
281
293
  getEditorContainerWidth: GetEditorContainerWidth,
282
294
  getEditorFeatureFlags: GetEditorFeatureFlags,
295
+ pluginInjectionApi?: PluginInjectionAPI,
283
296
  ): NodeView => {
284
297
  const { pluginConfig } = getPluginState(view.state);
285
298
  const { allowColumnResizing } = getPluginConfig(pluginConfig);
@@ -298,5 +311,6 @@ export const createTableView = (
298
311
  getEditorContainerWidth,
299
312
  getEditorFeatureFlags,
300
313
  hasIntlContext,
314
+ pluginInjectionApi,
301
315
  }).init();
302
316
  };
@@ -7,6 +7,7 @@ import type {
7
7
  } from '@atlaskit/editor-common/types';
8
8
  import { EventDispatcher } from '@atlaskit/editor-common/event-dispatcher';
9
9
  import type { PortalProviderAPI } from '@atlaskit/editor-common/portal-provider';
10
+ import type { PluginInjectionAPI } from '../types';
10
11
 
11
12
  export type TableOptions = {
12
13
  isBreakoutEnabled?: boolean;
@@ -27,4 +28,5 @@ export interface Props {
27
28
  getEditorContainerWidth: GetEditorContainerWidth;
28
29
  getEditorFeatureFlags: GetEditorFeatureFlags;
29
30
  hasIntlContext: boolean;
31
+ pluginInjectionApi?: PluginInjectionAPI;
30
32
  }
@@ -3,12 +3,14 @@ import {
3
3
  EditorState,
4
4
  PluginKey,
5
5
  Transaction,
6
+ // @ts-ignore -- ReadonlyTransaction is a local declaration and will cause a TS2305 error in CCFE typecheck
6
7
  ReadonlyTransaction,
7
8
  } from 'prosemirror-state';
8
9
  import { CellSelection } from '@atlaskit/editor-tables/cell-selection';
9
10
  import { DecorationSet } from 'prosemirror-view';
10
11
 
11
12
  import { pluginKey as tablePluginKey } from '../plugin-key';
13
+ import { pluginKey as tableWidthPluginKey } from '../table-width';
12
14
 
13
15
  import {
14
16
  buildColumnControlsDecorations,
@@ -24,8 +26,20 @@ export const handleDocOrSelectionChanged = (
24
26
  tr: Transaction | ReadonlyTransaction,
25
27
  decorationSet: DecorationSet,
26
28
  oldState: EditorState,
29
+ newState: EditorState,
27
30
  ): DecorationSet => {
28
- if (tr.docChanged || tr.selection instanceof CellSelection) {
31
+ const isResizing = tableWidthPluginKey.getState(newState)?.resizing;
32
+ const wasResizing = tableWidthPluginKey.getState(oldState)?.resizing;
33
+ const changedResizing = isResizing !== wasResizing;
34
+
35
+ // Remove column controls when resizing
36
+ if (isResizing) {
37
+ return DecorationSet.empty;
38
+ } else if (
39
+ tr.docChanged ||
40
+ tr.selection instanceof CellSelection ||
41
+ changedResizing
42
+ ) {
29
43
  return buildColumnControlsDecorations({
30
44
  decorationSet,
31
45
  tr,
@@ -52,16 +66,25 @@ export const createPlugin = () => {
52
66
  state: {
53
67
  init: () => DecorationSet.empty,
54
68
 
55
- apply: (tr, decorationSet, oldState) => {
69
+ apply: (tr, decorationSet, oldState, newState) => {
56
70
  let pluginState = decorationSet;
57
71
  const meta = tr.getMeta(tablePluginKey);
58
72
  if (meta && meta.data && meta.data.decorationSet) {
59
73
  pluginState = meta.data.decorationSet;
60
74
  }
61
75
 
62
- if (tr.docChanged || tr.selectionSet) {
76
+ if (
77
+ tr.docChanged ||
78
+ tr.selectionSet ||
79
+ tr.getMeta(tableWidthPluginKey)
80
+ ) {
63
81
  pluginState = pluginState.map(tr.mapping, tr.doc);
64
- return handleDocOrSelectionChanged(tr, pluginState, oldState);
82
+ return handleDocOrSelectionChanged(
83
+ tr,
84
+ pluginState,
85
+ oldState,
86
+ newState,
87
+ );
65
88
  }
66
89
 
67
90
  return pluginState;
@@ -1,3 +1,4 @@
1
+ // @ts-ignore -- ReadonlyTransaction is a local declaration and will cause a TS2305 error in CCFE typecheck
1
2
  import { ReadonlyTransaction, Transaction } from 'prosemirror-state';
2
3
  import { CellSelection } from '@atlaskit/editor-tables/cell-selection';
3
4
  import { findTable } from '@atlaskit/editor-tables/utils';
@@ -1,3 +1,4 @@
1
+ // @ts-ignore -- ReadonlyTransaction is a local declaration and will cause a TS2305 error in CCFE typecheck
1
2
  import { ReadonlyTransaction, Transaction } from 'prosemirror-state';
2
3
  import { DecorationSet } from 'prosemirror-view';
3
4
 
@@ -80,6 +80,7 @@ import type {
80
80
  GetEditorFeatureFlags,
81
81
  } from '@atlaskit/editor-common/types';
82
82
  import type { getPosHandler } from '@atlaskit/editor-common/types';
83
+ import type { PluginInjectionAPI } from '../types';
83
84
 
84
85
  let isBreakoutEnabled: boolean | undefined;
85
86
  let isFullWidthModeEnabled: boolean | undefined;
@@ -97,6 +98,7 @@ export const createPlugin = (
97
98
  fullWidthModeEnabled?: boolean,
98
99
  previousFullWidthModeEnabled?: boolean,
99
100
  editorAnalyticsAPI?: EditorAnalyticsAPI,
101
+ pluginInjectionApi?: PluginInjectionAPI,
100
102
  ) => {
101
103
  isBreakoutEnabled = breakoutEnabled;
102
104
  isFullWidthModeEnabled = fullWidthModeEnabled;
@@ -374,6 +376,7 @@ export const createPlugin = (
374
376
  },
375
377
  getEditorContainerWidth,
376
378
  getEditorFeatureFlags,
379
+ pluginInjectionApi,
377
380
  ),
378
381
  },
379
382
 
@@ -1,3 +1,4 @@
1
+ // @ts-ignore -- ReadonlyTransaction is a local declaration and will cause a TS2305 error in CCFE typecheck
1
2
  import { ReadonlyTransaction } from 'prosemirror-state';
2
3
 
3
4
  import { pluginFactory } from '@atlaskit/editor-common/utils';
@@ -118,6 +118,7 @@ export const updateStickyMargins = (table: HTMLElement) => {
118
118
  };
119
119
 
120
120
  export const applyColWidthsToStickyRow = (
121
+ // @ts-ignore - CCFE error TS6133: 'colGroup' is declared but its value is never read.
121
122
  colGroup: HTMLTableColElement | null,
122
123
  headerRow: HTMLTableRowElement,
123
124
  ) => {
@@ -1,6 +1,7 @@
1
1
  /**
2
- * A plugin for scan the document, add width value to table's width attribute when necessary
3
- *
2
+ * A plugin for handle table custom widths
3
+ * Has login to scan the document, add width value to table's width attribute when necessary
4
+ * Also holds resizing state to hide / show table controls
4
5
  */
5
6
  import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
6
7
  import {
@@ -9,6 +10,8 @@ import {
9
10
  } from '@atlaskit/editor-shared-styles';
10
11
  import { SetAttrsStep } from '@atlaskit/adf-schema/steps';
11
12
  import { ReplaceStep } from 'prosemirror-transform';
13
+ import { PluginKey } from 'prosemirror-state';
14
+ import { Dispatch } from '@atlaskit/editor-common/event-dispatcher';
12
15
 
13
16
  type __ReplaceStep = ReplaceStep & {
14
17
  // Properties `to` and `from` are private attributes of ReplaceStep.
@@ -16,8 +19,35 @@ type __ReplaceStep = ReplaceStep & {
16
19
  from: number;
17
20
  };
18
21
 
19
- const createPlugin = (fullWidthEnabled: boolean) =>
22
+ type TableWidthPluginState = {
23
+ resizing: boolean;
24
+ };
25
+
26
+ export const pluginKey = new PluginKey<TableWidthPluginState>(
27
+ 'tableWidthPlugin',
28
+ );
29
+
30
+ const createPlugin = (dispatch: Dispatch, fullWidthEnabled: boolean) =>
20
31
  new SafePlugin({
32
+ key: pluginKey,
33
+ state: {
34
+ init() {
35
+ return {
36
+ resizing: false,
37
+ };
38
+ },
39
+ apply(tr, pluginState) {
40
+ const meta = tr.getMeta(pluginKey);
41
+ if (meta && meta.resizing !== pluginState.resizing) {
42
+ const newState = { resizing: meta.resizing };
43
+
44
+ dispatch(pluginKey, newState);
45
+ return newState;
46
+ }
47
+
48
+ return pluginState;
49
+ },
50
+ },
21
51
  appendTransaction: (transactions, _oldState, newState) => {
22
52
  // When document first load in Confluence, initially it is an empty document
23
53
  // and Collab service triggers a transaction to replace the empty document with the real document that should be rendered.
@@ -44,6 +44,7 @@ import {
44
44
  } from './commands-with-analytics';
45
45
  import { getPluginState } from './pm-plugins/plugin-factory';
46
46
  import { pluginKey as tableResizingPluginKey } from './pm-plugins/table-resizing';
47
+ import { pluginKey as tableWidthPluginKey } from './pm-plugins/table-width';
47
48
  import {
48
49
  ToolbarMenuConfig,
49
50
  ToolbarMenuState,
@@ -440,7 +441,12 @@ export const getToolbarConfig =
440
441
  const tableObject = findTable(state.selection);
441
442
  const pluginState = getPluginState(state);
442
443
  const resizeState = tableResizingPluginKey.getState(state);
443
- if (tableObject && pluginState.editorHasFocus) {
444
+ const tableWidthState = tableWidthPluginKey.getState(state);
445
+
446
+ // We don't want to show floating toolbar while resizing the table
447
+ const isWidthResizing = tableWidthState?.resizing;
448
+
449
+ if (tableObject && pluginState.editorHasFocus && !isWidthResizing) {
444
450
  const nodeType = state.schema.nodes.table;
445
451
  const menu = getToolbarMenuConfig(
446
452
  config,
@@ -14,6 +14,8 @@ import { TableSharedCssClassName } from '@atlaskit/editor-common/styles';
14
14
  import { TableColumnOrdering } from '@atlaskit/adf-schema/steps';
15
15
 
16
16
  import { INPUT_METHOD } from '@atlaskit/editor-common/analytics';
17
+ import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
18
+ import type tablePlugin from './index';
17
19
 
18
20
  export const RESIZE_HANDLE_AREA_DECORATION_GAP = 30;
19
21
  export type RowInsertPosition = 'TOP' | 'BOTTOM';
@@ -27,6 +29,8 @@ export interface InsertRowOptions {
27
29
  moveCursorToInsertedRow: boolean;
28
30
  }
29
31
 
32
+ export type PluginInjectionAPI = ExtractInjectionAPI<typeof tablePlugin>;
33
+
30
34
  export type InsertRowMethods =
31
35
  | INPUT_METHOD.CONTEXT_MENU
32
36
  | INPUT_METHOD.BUTTON
@@ -104,3 +104,6 @@ export const contextualMenuDropdownWidth = 180;
104
104
  export const stickyRowZIndex = resizeHandlerZIndex + 2;
105
105
  export const stickyRowOffsetTop = 8;
106
106
  export const stickyHeaderBorderBottomWidth = 1;
107
+
108
+ export const TABLE_SNAP_GAP = 5;
109
+ export const TABLE_HIGHLIGHT_GAP = 10;
@@ -1,4 +1,5 @@
1
1
  import { NodeType, NodeRange } from 'prosemirror-model';
2
+ // @ts-ignore -- ReadonlyTransaction is a local declaration and will cause a TS2305 error in CCFE typecheck
2
3
  import { Transaction, ReadonlyTransaction } from 'prosemirror-state';
3
4
  import { findWrapping } from 'prosemirror-transform';
4
5
 
@@ -1,4 +1,5 @@
1
1
  import { Node as PmNode } from 'prosemirror-model';
2
+ // @ts-ignore -- ReadonlyTransaction is a local declaration and will cause a TS2305 error in CCFE typecheck
2
3
  import { Selection, Transaction, ReadonlyTransaction } from 'prosemirror-state';
3
4
  import { Rect, TableMap } from '@atlaskit/editor-tables/table-map';
4
5
  import { ContentNodeWithPos } from 'prosemirror-utils';
@@ -0,0 +1,17 @@
1
+ import type { GuidelineConfig } from '@atlaskit/editor-plugin-guideline';
2
+ import { createFixedGuidelinesFromLengths } from '@atlaskit/editor-common/guideline';
3
+ import {
4
+ akEditorDefaultLayoutWidth,
5
+ akEditorWideLayoutWidth,
6
+ akEditorFullWidthLayoutWidth,
7
+ } from '@atlaskit/editor-shared-styles';
8
+
9
+ export const defaultGuidelineWidths = [
10
+ akEditorDefaultLayoutWidth,
11
+ akEditorWideLayoutWidth,
12
+ akEditorFullWidthLayoutWidth,
13
+ ];
14
+
15
+ export const defaultGuidelines = createFixedGuidelinesFromLengths(
16
+ defaultGuidelineWidths,
17
+ ) as GuidelineConfig[];