@atlaskit/editor-plugin-table 8.4.9 → 8.4.11

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # @atlaskit/editor-plugin-table
2
2
 
3
+ ## 8.4.11
4
+
5
+ ### Patch Changes
6
+
7
+ - [#181547](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/181547)
8
+ [`40f89a75c9468`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/40f89a75c9468) -
9
+ make guideline plugin optional to media and table plugins
10
+
11
+ ## 8.4.10
12
+
13
+ ### Patch Changes
14
+
15
+ - [#179922](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/179922)
16
+ [`3fac1d870e06c`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/3fac1d870e06c) -
17
+ [ux] ED-25985 Table pasting logic for nested tables - prevents pasted tables from exceeding
18
+ nesting depth of 1 by either flattening deeply nested tables or moving the paste location to under
19
+ the destination table
20
+
3
21
  ## 8.4.9
4
22
 
5
23
  ### Patch Changes
@@ -14,6 +14,7 @@ var _utils = require("@atlaskit/editor-common/utils");
14
14
  var _utils2 = require("@atlaskit/editor-prosemirror/utils");
15
15
  var _editorTables = require("@atlaskit/editor-tables");
16
16
  var _utils3 = require("@atlaskit/editor-tables/utils");
17
+ var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
17
18
  var _lazyNodeViews = require("../nodeviews/lazy-node-views");
18
19
  var _plugin = require("../pm-plugins/decorations/plugin");
19
20
  var _types = require("../types");
@@ -207,6 +208,9 @@ var createPlugin = exports.createPlugin = function createPlugin(dispatchAnalytic
207
208
  slice = (0, _misc.transformSliceRemoveCellBackgroundColor)(slice, schema);
208
209
  }
209
210
  slice = (0, _transforms.transformSliceToRemoveOpenNestedExpand)(slice, schema);
211
+ if ((0, _platformFeatureFlags.fg)('platform_editor_use_nested_table_pm_nodes')) {
212
+ slice = (0, _paste.transformSliceToRemoveNestedTables)(slice, schema, editorState.selection);
213
+ }
210
214
  return slice;
211
215
  },
212
216
  handleClick: function handleClick(_ref2, _pos, event) {
@@ -5,12 +5,14 @@ Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
7
  exports.isHeaderRowRequired = isHeaderRowRequired;
8
- exports.unwrapContentFromTable = exports.transformSliceToRemoveOpenTable = exports.transformSliceToFixHardBreakProblemOnCopyFromCell = exports.transformSliceToCorrectEmptyTableCells = exports.transformSliceTableLayoutDefaultToCenter = exports.removeTableFromLastChild = exports.removeTableFromFirstChild = void 0;
8
+ exports.unwrapContentFromTable = exports.transformSliceToRemoveOpenTable = exports.transformSliceToRemoveNestedTables = exports.transformSliceToFixHardBreakProblemOnCopyFromCell = exports.transformSliceToCorrectEmptyTableCells = exports.transformSliceTableLayoutDefaultToCenter = exports.removeTableFromLastChild = exports.removeTableFromFirstChild = void 0;
9
9
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
10
10
  var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
11
+ var _nesting = require("@atlaskit/editor-common/nesting");
11
12
  var _utils = require("@atlaskit/editor-common/utils");
12
13
  var _model = require("@atlaskit/editor-prosemirror/model");
13
14
  var _utils2 = require("@atlaskit/editor-prosemirror/utils");
15
+ var _experiments = require("@atlaskit/tmp-editor-statsig/experiments");
14
16
  var _pluginFactory = require("../plugin-factory");
15
17
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
16
18
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
@@ -34,12 +36,112 @@ var unwrapContentFromTable = exports.unwrapContentFromTable = function unwrapCon
34
36
  }
35
37
  return maybeTable;
36
38
  };
39
+
40
+ // Flattens nested tables after a given nesting depth
41
+ // If this looks familiar, it's a heavily modified version of `mapFragment` which has been
42
+ // adjusted to support tracking nesting depth. This wasn't possible by using `mapFragment` directly
43
+ var unwrapNestedTables = function unwrapNestedTables(content, schema, unwrapNestDepth) {
44
+ var currentNestDepth = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0;
45
+ var flattenNested = function flattenNested(node, tableDepth) {
46
+ if (node.type === schema.nodes.table) {
47
+ if (tableDepth >= unwrapNestDepth) {
48
+ return unwrapContentFromTable(node);
49
+ }
50
+ return node;
51
+ }
52
+ return node;
53
+ };
54
+ var children = [];
55
+ for (var i = 0, size = content.childCount; i < size; i++) {
56
+ var node = content.child(i);
57
+ var transformed = node.isLeaf ? flattenNested(node, currentNestDepth) : flattenNested(node.copy(_model.Fragment.fromArray(unwrapNestedTables(node.content, schema, unwrapNestDepth, node.type === schema.nodes.table ? currentNestDepth + 1 : currentNestDepth))), currentNestDepth);
58
+ if (transformed) {
59
+ if (Array.isArray(transformed)) {
60
+ children.push.apply(children, (0, _toConsumableArray2.default)(transformed));
61
+ } else {
62
+ children.push(transformed);
63
+ }
64
+ }
65
+ }
66
+ return children;
67
+ };
37
68
  var removeTableFromFirstChild = exports.removeTableFromFirstChild = function removeTableFromFirstChild(node, i) {
38
69
  return i === 0 ? unwrapContentFromTable(node) : node;
39
70
  };
40
71
  var removeTableFromLastChild = exports.removeTableFromLastChild = function removeTableFromLastChild(node, i, fragment) {
41
72
  return i === fragment.childCount - 1 ? unwrapContentFromTable(node) : node;
42
73
  };
74
+ var transformSliceToRemoveNestedTables = exports.transformSliceToRemoveNestedTables = function transformSliceToRemoveNestedTables(slice, schema, selection) {
75
+ var isNestingAllowed = (0, _experiments.editorExperiment)('nested-tables-in-tables', true);
76
+ var _schema$nodes2 = schema.nodes,
77
+ table = _schema$nodes2.table,
78
+ tableCell = _schema$nodes2.tableCell,
79
+ tableHeader = _schema$nodes2.tableHeader;
80
+ var openEnd = slice.openEnd;
81
+ var newFragment = (0, _utils.flatmap)(slice.content, function (node, i, fragment) {
82
+ // if pasted content is a node that supports nesting a table
83
+ // such as layoutSection or expand allow 1 level by default
84
+ var allowedTableNesting = 1;
85
+ if (isNestingAllowed) {
86
+ var _slice$content$firstC, _slice$content$lastCh;
87
+ var isPasteInTable = (0, _utils2.hasParentNodeOfType)([table, tableCell, tableHeader])(selection);
88
+ var isPasteInNestedTable = (0, _nesting.getParentOfTypeCount)(schema.nodes.table)(selection.$from) > 1;
89
+ var isCellPaste = isPasteInTable && slice.content.childCount === 1 && ((_slice$content$firstC = slice.content.firstChild) === null || _slice$content$firstC === void 0 ? void 0 : _slice$content$firstC.type) === table;
90
+
91
+ // if nesting is allowed we bump up the default nesting allowance to 2 to support
92
+ // two levels of nesting in nodes that support table nesting already such as layoutSection and expands
93
+ allowedTableNesting = 2;
94
+
95
+ // however if pasted content is a table, allow just one level
96
+ if (node.type === schema.nodes.table) {
97
+ allowedTableNesting = 1;
98
+
99
+ // if paste is inside a table, allow no further nesting
100
+ if (isPasteInTable) {
101
+ allowedTableNesting = 0;
102
+ }
103
+
104
+ // unless we are pasting inside a nested table, then bounce back to 1 level
105
+ // because editor-plugin-paste will lift the table to the parent table (just below it)
106
+ if (isPasteInNestedTable) {
107
+ allowedTableNesting = 1;
108
+ }
109
+
110
+ // paste of table cells into a table cell - content is spread across multiple cells
111
+ // by editor-tables so needs to be treated a little differently
112
+ if (isCellPaste) {
113
+ allowedTableNesting = 1;
114
+ if (isPasteInNestedTable) {
115
+ allowedTableNesting = 0;
116
+ }
117
+ }
118
+ }
119
+
120
+ // Prevent invalid openEnd after pasting tables with a selection that ends inside a nested table cell.
121
+ // If the slice ends with a selection that ends inside a nested table, and we paste inside a table we
122
+ // need to adjust the openEnd because it is no longer correct. If we don't, Prosemirror fires an exception
123
+ // because it iterates to a non-existent depth and the transform will not be applied
124
+ if (slice.openEnd >= 7 &&
125
+ // depth of a nested table cell
126
+ slice.content.childCount > 1 && ((_slice$content$lastCh = slice.content.lastChild) === null || _slice$content$lastCh === void 0 ? void 0 : _slice$content$lastCh.type) === table && isPasteInTable) {
127
+ // re-point the slice's openEnd to non-nested table cell depth
128
+ openEnd = 4;
129
+ }
130
+ } else {
131
+ // for layouts and expands, we start with 1 level of nesting as set above
132
+
133
+ // if pasted content is a table, don't allow further nesting
134
+ if (node.type === schema.nodes.table) {
135
+ allowedTableNesting = 0;
136
+ }
137
+ }
138
+
139
+ // after we've worked out what the allowed nesting depth is, unwrap nested tables
140
+ var newChildren = unwrapNestedTables(node.content, schema, allowedTableNesting);
141
+ return node.copy(_model.Fragment.fromArray(newChildren));
142
+ });
143
+ return new _model.Slice(newFragment, slice.openStart, openEnd);
144
+ };
43
145
 
44
146
  /**
45
147
  * When we copy from a table cell with a hardBreak at the end,
@@ -47,10 +149,10 @@ var removeTableFromLastChild = exports.removeTableFromLastChild = function remov
47
149
  * This code will look for that pattern and fix it.
48
150
  */
49
151
  var transformSliceToFixHardBreakProblemOnCopyFromCell = exports.transformSliceToFixHardBreakProblemOnCopyFromCell = function transformSliceToFixHardBreakProblemOnCopyFromCell(slice, schema) {
50
- var _schema$nodes2 = schema.nodes,
51
- paragraph = _schema$nodes2.paragraph,
52
- table = _schema$nodes2.table,
53
- hardBreak = _schema$nodes2.hardBreak;
152
+ var _schema$nodes3 = schema.nodes,
153
+ paragraph = _schema$nodes3.paragraph,
154
+ table = _schema$nodes3.table,
155
+ hardBreak = _schema$nodes3.hardBreak;
54
156
  var emptyParagraphNode = paragraph.createAndFill();
55
157
  var hardBreakNode = hardBreak === null || hardBreak === void 0 ? void 0 : hardBreak.createAndFill();
56
158
  var paragraphNodeSize = emptyParagraphNode ? emptyParagraphNode.nodeSize : 0;
@@ -67,7 +169,7 @@ var transformSliceToFixHardBreakProblemOnCopyFromCell = exports.transformSliceTo
67
169
  return slice;
68
170
  };
69
171
  var transformSliceToRemoveOpenTable = exports.transformSliceToRemoveOpenTable = function transformSliceToRemoveOpenTable(slice, schema) {
70
- var _slice$content$firstC2;
172
+ var _slice$content$firstC3;
71
173
  // we're removing the table, tableRow and tableCell reducing the open depth by 3
72
174
  var depthDecrement = 3;
73
175
 
@@ -77,14 +179,14 @@ var transformSliceToRemoveOpenTable = exports.transformSliceToRemoveOpenTable =
77
179
  slice.openStart >= 4 && slice.openEnd >= 4 &&
78
180
  // slice is a table node
79
181
  slice.content.childCount === 1 && slice.content.firstChild.type === schema.nodes.table) {
80
- var _slice$content$firstC;
182
+ var _slice$content$firstC2;
81
183
  // prosemirror-view has a bug that it duplicates table entry when selecting multiple paragraphs in a table cell.
82
184
  // https://github.com/ProseMirror/prosemirror/issues/1270
83
185
  // The structure becomes
84
186
  // table(genuine) > tableRow(genuine) > table(duplicated) > tableRow(duplicated) > tableCell/tableHeader(genuine) > contents(genuine)
85
187
  // As we are removing wrapping table anyway, we keep duplicated table and tableRow for simplicity
86
188
  var cleaned = slice;
87
- if (((_slice$content$firstC = slice.content.firstChild) === null || _slice$content$firstC === void 0 || (_slice$content$firstC = _slice$content$firstC.content) === null || _slice$content$firstC === void 0 || (_slice$content$firstC = _slice$content$firstC.firstChild) === null || _slice$content$firstC === void 0 || (_slice$content$firstC = _slice$content$firstC.content) === null || _slice$content$firstC === void 0 || (_slice$content$firstC = _slice$content$firstC.firstChild) === null || _slice$content$firstC === void 0 ? void 0 : _slice$content$firstC.type) === schema.nodes.table) {
189
+ if (((_slice$content$firstC2 = slice.content.firstChild) === null || _slice$content$firstC2 === void 0 || (_slice$content$firstC2 = _slice$content$firstC2.content) === null || _slice$content$firstC2 === void 0 || (_slice$content$firstC2 = _slice$content$firstC2.firstChild) === null || _slice$content$firstC2 === void 0 || (_slice$content$firstC2 = _slice$content$firstC2.content) === null || _slice$content$firstC2 === void 0 || (_slice$content$firstC2 = _slice$content$firstC2.firstChild) === null || _slice$content$firstC2 === void 0 ? void 0 : _slice$content$firstC2.type) === schema.nodes.table) {
88
190
  cleaned = new _model.Slice(slice.content.firstChild.content.firstChild.content, slice.openStart - 2, slice.openEnd - 2);
89
191
  }
90
192
  return new _model.Slice((0, _utils.flatmap)(cleaned.content, unwrapContentFromTable), cleaned.openStart - depthDecrement, cleaned.openEnd - depthDecrement);
@@ -95,7 +197,7 @@ var transformSliceToRemoveOpenTable = exports.transformSliceToRemoveOpenTable =
95
197
  // starts inside of a cell but ends outside of the starting table
96
198
  slice.openStart >= 4 &&
97
199
  // slice starts from a table node (and spans across more than one node)
98
- slice.content.childCount > 1 && ((_slice$content$firstC2 = slice.content.firstChild) === null || _slice$content$firstC2 === void 0 ? void 0 : _slice$content$firstC2.type) === schema.nodes.table) {
200
+ slice.content.childCount > 1 && ((_slice$content$firstC3 = slice.content.firstChild) === null || _slice$content$firstC3 === void 0 ? void 0 : _slice$content$firstC3.type) === schema.nodes.table) {
99
201
  // repoint the slice's cutting depth so that cell content where the slice starts
100
202
  // does not get lifted out of the cell on paste
101
203
  return new _model.Slice(slice.content, 1, slice.openEnd);
@@ -103,9 +205,9 @@ var transformSliceToRemoveOpenTable = exports.transformSliceToRemoveOpenTable =
103
205
  return slice;
104
206
  };
105
207
  var transformSliceToCorrectEmptyTableCells = exports.transformSliceToCorrectEmptyTableCells = function transformSliceToCorrectEmptyTableCells(slice, schema) {
106
- var _schema$nodes3 = schema.nodes,
107
- tableCell = _schema$nodes3.tableCell,
108
- tableHeader = _schema$nodes3.tableHeader;
208
+ var _schema$nodes4 = schema.nodes,
209
+ tableCell = _schema$nodes4.tableCell,
210
+ tableHeader = _schema$nodes4.tableHeader;
109
211
  return (0, _utils.mapSlice)(slice, function (node) {
110
212
  if (node && (node.type === tableCell || node.type === tableHeader) && !node.content.childCount) {
111
213
  return node.type.createAndFill(node.attrs) || node;
@@ -6,6 +6,7 @@ import { browser, closestElement } from '@atlaskit/editor-common/utils';
6
6
  import { findParentDomRefOfType, findParentNodeOfType } from '@atlaskit/editor-prosemirror/utils';
7
7
  import { TableMap } from '@atlaskit/editor-tables';
8
8
  import { findTable } from '@atlaskit/editor-tables/utils';
9
+ import { fg } from '@atlaskit/platform-feature-flags';
9
10
  import { lazyTableCellView, lazyTableHeaderView, lazyTableRowView, lazyTableView } from '../nodeviews/lazy-node-views';
10
11
  import { pluginKey as decorationsPluginKey } from '../pm-plugins/decorations/plugin';
11
12
  import { TableCssClassName as ClassName } from '../types';
@@ -18,7 +19,7 @@ import { createPluginState, getPluginState } from './plugin-factory';
18
19
  import { pluginKey } from './plugin-key';
19
20
  import { fixTables, replaceSelectedTable } from './transforms';
20
21
  import { findControlsHoverDecoration, transformSliceToCorrectEmptyTableCells, transformSliceToFixHardBreakProblemOnCopyFromCell, transformSliceToRemoveOpenTable } from './utils';
21
- import { isHeaderRowRequired, transformSliceTableLayoutDefaultToCenter } from './utils/paste';
22
+ import { isHeaderRowRequired, transformSliceTableLayoutDefaultToCenter, transformSliceToRemoveNestedTables } from './utils/paste';
22
23
  export const createPlugin = (dispatchAnalyticsEvent, dispatch, portalProviderAPI, nodeViewPortalProviderAPI, eventDispatcher, pluginConfig, getEditorContainerWidth, getEditorFeatureFlags, getIntl, fullWidthModeEnabled, previousFullWidthModeEnabled, dragAndDropEnabled, editorAnalyticsAPI, pluginInjectionApi, isTableScalingEnabled, shouldUseIncreasedScalingPercent, isCommentEditor, isChromelessEditor) => {
23
24
  var _accessibilityUtils;
24
25
  const state = createPluginState(dispatch, {
@@ -199,6 +200,9 @@ export const createPlugin = (dispatchAnalyticsEvent, dispatch, portalProviderAPI
199
200
  slice = transformSliceRemoveCellBackgroundColor(slice, schema);
200
201
  }
201
202
  slice = transformSliceToRemoveOpenNestedExpand(slice, schema);
203
+ if (fg('platform_editor_use_nested_table_pm_nodes')) {
204
+ slice = transformSliceToRemoveNestedTables(slice, schema, editorState.selection);
205
+ }
202
206
  return slice;
203
207
  },
204
208
  handleClick: ({
@@ -1,6 +1,8 @@
1
+ import { getParentOfTypeCount } from '@atlaskit/editor-common/nesting';
1
2
  import { flatmap, mapChildren, mapSlice } from '@atlaskit/editor-common/utils';
2
- import { Fragment, Slice } from '@atlaskit/editor-prosemirror/model';
3
- import { flatten } from '@atlaskit/editor-prosemirror/utils';
3
+ import { Slice, Fragment } from '@atlaskit/editor-prosemirror/model';
4
+ import { flatten, hasParentNodeOfType } from '@atlaskit/editor-prosemirror/utils';
5
+ import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
4
6
  import { getPluginState } from '../plugin-factory';
5
7
 
6
8
  // lifts up the content of each cell, returning an array of nodes
@@ -24,12 +26,112 @@ export const unwrapContentFromTable = maybeTable => {
24
26
  }
25
27
  return maybeTable;
26
28
  };
29
+
30
+ // Flattens nested tables after a given nesting depth
31
+ // If this looks familiar, it's a heavily modified version of `mapFragment` which has been
32
+ // adjusted to support tracking nesting depth. This wasn't possible by using `mapFragment` directly
33
+ const unwrapNestedTables = (content, schema, unwrapNestDepth, currentNestDepth = 0) => {
34
+ const flattenNested = (node, tableDepth) => {
35
+ if (node.type === schema.nodes.table) {
36
+ if (tableDepth >= unwrapNestDepth) {
37
+ return unwrapContentFromTable(node);
38
+ }
39
+ return node;
40
+ }
41
+ return node;
42
+ };
43
+ const children = [];
44
+ for (let i = 0, size = content.childCount; i < size; i++) {
45
+ const node = content.child(i);
46
+ const transformed = node.isLeaf ? flattenNested(node, currentNestDepth) : flattenNested(node.copy(Fragment.fromArray(unwrapNestedTables(node.content, schema, unwrapNestDepth, node.type === schema.nodes.table ? currentNestDepth + 1 : currentNestDepth))), currentNestDepth);
47
+ if (transformed) {
48
+ if (Array.isArray(transformed)) {
49
+ children.push(...transformed);
50
+ } else {
51
+ children.push(transformed);
52
+ }
53
+ }
54
+ }
55
+ return children;
56
+ };
27
57
  export const removeTableFromFirstChild = (node, i) => {
28
58
  return i === 0 ? unwrapContentFromTable(node) : node;
29
59
  };
30
60
  export const removeTableFromLastChild = (node, i, fragment) => {
31
61
  return i === fragment.childCount - 1 ? unwrapContentFromTable(node) : node;
32
62
  };
63
+ export const transformSliceToRemoveNestedTables = (slice, schema, selection) => {
64
+ const isNestingAllowed = editorExperiment('nested-tables-in-tables', true);
65
+ const {
66
+ table,
67
+ tableCell,
68
+ tableHeader
69
+ } = schema.nodes;
70
+ let openEnd = slice.openEnd;
71
+ const newFragment = flatmap(slice.content, (node, i, fragment) => {
72
+ // if pasted content is a node that supports nesting a table
73
+ // such as layoutSection or expand allow 1 level by default
74
+ let allowedTableNesting = 1;
75
+ if (isNestingAllowed) {
76
+ var _slice$content$firstC, _slice$content$lastCh;
77
+ const isPasteInTable = hasParentNodeOfType([table, tableCell, tableHeader])(selection);
78
+ const isPasteInNestedTable = getParentOfTypeCount(schema.nodes.table)(selection.$from) > 1;
79
+ const isCellPaste = isPasteInTable && slice.content.childCount === 1 && ((_slice$content$firstC = slice.content.firstChild) === null || _slice$content$firstC === void 0 ? void 0 : _slice$content$firstC.type) === table;
80
+
81
+ // if nesting is allowed we bump up the default nesting allowance to 2 to support
82
+ // two levels of nesting in nodes that support table nesting already such as layoutSection and expands
83
+ allowedTableNesting = 2;
84
+
85
+ // however if pasted content is a table, allow just one level
86
+ if (node.type === schema.nodes.table) {
87
+ allowedTableNesting = 1;
88
+
89
+ // if paste is inside a table, allow no further nesting
90
+ if (isPasteInTable) {
91
+ allowedTableNesting = 0;
92
+ }
93
+
94
+ // unless we are pasting inside a nested table, then bounce back to 1 level
95
+ // because editor-plugin-paste will lift the table to the parent table (just below it)
96
+ if (isPasteInNestedTable) {
97
+ allowedTableNesting = 1;
98
+ }
99
+
100
+ // paste of table cells into a table cell - content is spread across multiple cells
101
+ // by editor-tables so needs to be treated a little differently
102
+ if (isCellPaste) {
103
+ allowedTableNesting = 1;
104
+ if (isPasteInNestedTable) {
105
+ allowedTableNesting = 0;
106
+ }
107
+ }
108
+ }
109
+
110
+ // Prevent invalid openEnd after pasting tables with a selection that ends inside a nested table cell.
111
+ // If the slice ends with a selection that ends inside a nested table, and we paste inside a table we
112
+ // need to adjust the openEnd because it is no longer correct. If we don't, Prosemirror fires an exception
113
+ // because it iterates to a non-existent depth and the transform will not be applied
114
+ if (slice.openEnd >= 7 &&
115
+ // depth of a nested table cell
116
+ slice.content.childCount > 1 && ((_slice$content$lastCh = slice.content.lastChild) === null || _slice$content$lastCh === void 0 ? void 0 : _slice$content$lastCh.type) === table && isPasteInTable) {
117
+ // re-point the slice's openEnd to non-nested table cell depth
118
+ openEnd = 4;
119
+ }
120
+ } else {
121
+ // for layouts and expands, we start with 1 level of nesting as set above
122
+
123
+ // if pasted content is a table, don't allow further nesting
124
+ if (node.type === schema.nodes.table) {
125
+ allowedTableNesting = 0;
126
+ }
127
+ }
128
+
129
+ // after we've worked out what the allowed nesting depth is, unwrap nested tables
130
+ const newChildren = unwrapNestedTables(node.content, schema, allowedTableNesting);
131
+ return node.copy(Fragment.fromArray(newChildren));
132
+ });
133
+ return new Slice(newFragment, slice.openStart, openEnd);
134
+ };
33
135
 
34
136
  /**
35
137
  * When we copy from a table cell with a hardBreak at the end,
@@ -58,7 +160,7 @@ export const transformSliceToFixHardBreakProblemOnCopyFromCell = (slice, schema)
58
160
  return slice;
59
161
  };
60
162
  export const transformSliceToRemoveOpenTable = (slice, schema) => {
61
- var _slice$content$firstC6;
163
+ var _slice$content$firstC7;
62
164
  // we're removing the table, tableRow and tableCell reducing the open depth by 3
63
165
  const depthDecrement = 3;
64
166
 
@@ -68,14 +170,14 @@ export const transformSliceToRemoveOpenTable = (slice, schema) => {
68
170
  slice.openStart >= 4 && slice.openEnd >= 4 &&
69
171
  // slice is a table node
70
172
  slice.content.childCount === 1 && slice.content.firstChild.type === schema.nodes.table) {
71
- var _slice$content$firstC, _slice$content$firstC2, _slice$content$firstC3, _slice$content$firstC4, _slice$content$firstC5;
173
+ var _slice$content$firstC2, _slice$content$firstC3, _slice$content$firstC4, _slice$content$firstC5, _slice$content$firstC6;
72
174
  // prosemirror-view has a bug that it duplicates table entry when selecting multiple paragraphs in a table cell.
73
175
  // https://github.com/ProseMirror/prosemirror/issues/1270
74
176
  // The structure becomes
75
177
  // table(genuine) > tableRow(genuine) > table(duplicated) > tableRow(duplicated) > tableCell/tableHeader(genuine) > contents(genuine)
76
178
  // As we are removing wrapping table anyway, we keep duplicated table and tableRow for simplicity
77
179
  let cleaned = slice;
78
- if (((_slice$content$firstC = slice.content.firstChild) === null || _slice$content$firstC === void 0 ? void 0 : (_slice$content$firstC2 = _slice$content$firstC.content) === null || _slice$content$firstC2 === void 0 ? void 0 : (_slice$content$firstC3 = _slice$content$firstC2.firstChild) === null || _slice$content$firstC3 === void 0 ? void 0 : (_slice$content$firstC4 = _slice$content$firstC3.content) === null || _slice$content$firstC4 === void 0 ? void 0 : (_slice$content$firstC5 = _slice$content$firstC4.firstChild) === null || _slice$content$firstC5 === void 0 ? void 0 : _slice$content$firstC5.type) === schema.nodes.table) {
180
+ if (((_slice$content$firstC2 = slice.content.firstChild) === null || _slice$content$firstC2 === void 0 ? void 0 : (_slice$content$firstC3 = _slice$content$firstC2.content) === null || _slice$content$firstC3 === void 0 ? void 0 : (_slice$content$firstC4 = _slice$content$firstC3.firstChild) === null || _slice$content$firstC4 === void 0 ? void 0 : (_slice$content$firstC5 = _slice$content$firstC4.content) === null || _slice$content$firstC5 === void 0 ? void 0 : (_slice$content$firstC6 = _slice$content$firstC5.firstChild) === null || _slice$content$firstC6 === void 0 ? void 0 : _slice$content$firstC6.type) === schema.nodes.table) {
79
181
  cleaned = new Slice(slice.content.firstChild.content.firstChild.content, slice.openStart - 2, slice.openEnd - 2);
80
182
  }
81
183
  return new Slice(flatmap(cleaned.content, unwrapContentFromTable), cleaned.openStart - depthDecrement, cleaned.openEnd - depthDecrement);
@@ -86,7 +188,7 @@ export const transformSliceToRemoveOpenTable = (slice, schema) => {
86
188
  // starts inside of a cell but ends outside of the starting table
87
189
  slice.openStart >= 4 &&
88
190
  // slice starts from a table node (and spans across more than one node)
89
- slice.content.childCount > 1 && ((_slice$content$firstC6 = slice.content.firstChild) === null || _slice$content$firstC6 === void 0 ? void 0 : _slice$content$firstC6.type) === schema.nodes.table) {
191
+ slice.content.childCount > 1 && ((_slice$content$firstC7 = slice.content.firstChild) === null || _slice$content$firstC7 === void 0 ? void 0 : _slice$content$firstC7.type) === schema.nodes.table) {
90
192
  // repoint the slice's cutting depth so that cell content where the slice starts
91
193
  // does not get lifted out of the cell on paste
92
194
  return new Slice(slice.content, 1, slice.openEnd);
@@ -9,6 +9,7 @@ import { browser, closestElement } from '@atlaskit/editor-common/utils';
9
9
  import { findParentDomRefOfType, findParentNodeOfType } from '@atlaskit/editor-prosemirror/utils';
10
10
  import { TableMap } from '@atlaskit/editor-tables';
11
11
  import { findTable } from '@atlaskit/editor-tables/utils';
12
+ import { fg } from '@atlaskit/platform-feature-flags';
12
13
  import { lazyTableCellView, lazyTableHeaderView, lazyTableRowView, lazyTableView } from '../nodeviews/lazy-node-views';
13
14
  import { pluginKey as decorationsPluginKey } from '../pm-plugins/decorations/plugin';
14
15
  import { TableCssClassName as ClassName } from '../types';
@@ -21,7 +22,7 @@ import { createPluginState, getPluginState } from './plugin-factory';
21
22
  import { pluginKey } from './plugin-key';
22
23
  import { fixTables, replaceSelectedTable } from './transforms';
23
24
  import { findControlsHoverDecoration, transformSliceToCorrectEmptyTableCells, transformSliceToFixHardBreakProblemOnCopyFromCell, transformSliceToRemoveOpenTable } from './utils';
24
- import { isHeaderRowRequired, transformSliceTableLayoutDefaultToCenter } from './utils/paste';
25
+ import { isHeaderRowRequired, transformSliceTableLayoutDefaultToCenter, transformSliceToRemoveNestedTables } from './utils/paste';
25
26
  export var createPlugin = function createPlugin(dispatchAnalyticsEvent, dispatch, portalProviderAPI, nodeViewPortalProviderAPI, eventDispatcher, pluginConfig, getEditorContainerWidth, getEditorFeatureFlags, getIntl, fullWidthModeEnabled, previousFullWidthModeEnabled, dragAndDropEnabled, editorAnalyticsAPI, pluginInjectionApi, isTableScalingEnabled, shouldUseIncreasedScalingPercent, isCommentEditor, isChromelessEditor) {
26
27
  var _accessibilityUtils;
27
28
  var state = createPluginState(dispatch, _objectSpread(_objectSpread(_objectSpread({
@@ -200,6 +201,9 @@ export var createPlugin = function createPlugin(dispatchAnalyticsEvent, dispatch
200
201
  slice = transformSliceRemoveCellBackgroundColor(slice, schema);
201
202
  }
202
203
  slice = transformSliceToRemoveOpenNestedExpand(slice, schema);
204
+ if (fg('platform_editor_use_nested_table_pm_nodes')) {
205
+ slice = transformSliceToRemoveNestedTables(slice, schema, editorState.selection);
206
+ }
203
207
  return slice;
204
208
  },
205
209
  handleClick: function handleClick(_ref2, _pos, event) {
@@ -2,9 +2,11 @@ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
2
  import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
3
3
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
4
4
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
5
+ import { getParentOfTypeCount } from '@atlaskit/editor-common/nesting';
5
6
  import { flatmap, mapChildren, mapSlice } from '@atlaskit/editor-common/utils';
6
- import { Fragment, Slice } from '@atlaskit/editor-prosemirror/model';
7
- import { flatten } from '@atlaskit/editor-prosemirror/utils';
7
+ import { Slice, Fragment } from '@atlaskit/editor-prosemirror/model';
8
+ import { flatten, hasParentNodeOfType } from '@atlaskit/editor-prosemirror/utils';
9
+ import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
8
10
  import { getPluginState } from '../plugin-factory';
9
11
 
10
12
  // lifts up the content of each cell, returning an array of nodes
@@ -27,12 +29,112 @@ export var unwrapContentFromTable = function unwrapContentFromTable(maybeTable)
27
29
  }
28
30
  return maybeTable;
29
31
  };
32
+
33
+ // Flattens nested tables after a given nesting depth
34
+ // If this looks familiar, it's a heavily modified version of `mapFragment` which has been
35
+ // adjusted to support tracking nesting depth. This wasn't possible by using `mapFragment` directly
36
+ var unwrapNestedTables = function unwrapNestedTables(content, schema, unwrapNestDepth) {
37
+ var currentNestDepth = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0;
38
+ var flattenNested = function flattenNested(node, tableDepth) {
39
+ if (node.type === schema.nodes.table) {
40
+ if (tableDepth >= unwrapNestDepth) {
41
+ return unwrapContentFromTable(node);
42
+ }
43
+ return node;
44
+ }
45
+ return node;
46
+ };
47
+ var children = [];
48
+ for (var i = 0, size = content.childCount; i < size; i++) {
49
+ var node = content.child(i);
50
+ var transformed = node.isLeaf ? flattenNested(node, currentNestDepth) : flattenNested(node.copy(Fragment.fromArray(unwrapNestedTables(node.content, schema, unwrapNestDepth, node.type === schema.nodes.table ? currentNestDepth + 1 : currentNestDepth))), currentNestDepth);
51
+ if (transformed) {
52
+ if (Array.isArray(transformed)) {
53
+ children.push.apply(children, _toConsumableArray(transformed));
54
+ } else {
55
+ children.push(transformed);
56
+ }
57
+ }
58
+ }
59
+ return children;
60
+ };
30
61
  export var removeTableFromFirstChild = function removeTableFromFirstChild(node, i) {
31
62
  return i === 0 ? unwrapContentFromTable(node) : node;
32
63
  };
33
64
  export var removeTableFromLastChild = function removeTableFromLastChild(node, i, fragment) {
34
65
  return i === fragment.childCount - 1 ? unwrapContentFromTable(node) : node;
35
66
  };
67
+ export var transformSliceToRemoveNestedTables = function transformSliceToRemoveNestedTables(slice, schema, selection) {
68
+ var isNestingAllowed = editorExperiment('nested-tables-in-tables', true);
69
+ var _schema$nodes2 = schema.nodes,
70
+ table = _schema$nodes2.table,
71
+ tableCell = _schema$nodes2.tableCell,
72
+ tableHeader = _schema$nodes2.tableHeader;
73
+ var openEnd = slice.openEnd;
74
+ var newFragment = flatmap(slice.content, function (node, i, fragment) {
75
+ // if pasted content is a node that supports nesting a table
76
+ // such as layoutSection or expand allow 1 level by default
77
+ var allowedTableNesting = 1;
78
+ if (isNestingAllowed) {
79
+ var _slice$content$firstC, _slice$content$lastCh;
80
+ var isPasteInTable = hasParentNodeOfType([table, tableCell, tableHeader])(selection);
81
+ var isPasteInNestedTable = getParentOfTypeCount(schema.nodes.table)(selection.$from) > 1;
82
+ var isCellPaste = isPasteInTable && slice.content.childCount === 1 && ((_slice$content$firstC = slice.content.firstChild) === null || _slice$content$firstC === void 0 ? void 0 : _slice$content$firstC.type) === table;
83
+
84
+ // if nesting is allowed we bump up the default nesting allowance to 2 to support
85
+ // two levels of nesting in nodes that support table nesting already such as layoutSection and expands
86
+ allowedTableNesting = 2;
87
+
88
+ // however if pasted content is a table, allow just one level
89
+ if (node.type === schema.nodes.table) {
90
+ allowedTableNesting = 1;
91
+
92
+ // if paste is inside a table, allow no further nesting
93
+ if (isPasteInTable) {
94
+ allowedTableNesting = 0;
95
+ }
96
+
97
+ // unless we are pasting inside a nested table, then bounce back to 1 level
98
+ // because editor-plugin-paste will lift the table to the parent table (just below it)
99
+ if (isPasteInNestedTable) {
100
+ allowedTableNesting = 1;
101
+ }
102
+
103
+ // paste of table cells into a table cell - content is spread across multiple cells
104
+ // by editor-tables so needs to be treated a little differently
105
+ if (isCellPaste) {
106
+ allowedTableNesting = 1;
107
+ if (isPasteInNestedTable) {
108
+ allowedTableNesting = 0;
109
+ }
110
+ }
111
+ }
112
+
113
+ // Prevent invalid openEnd after pasting tables with a selection that ends inside a nested table cell.
114
+ // If the slice ends with a selection that ends inside a nested table, and we paste inside a table we
115
+ // need to adjust the openEnd because it is no longer correct. If we don't, Prosemirror fires an exception
116
+ // because it iterates to a non-existent depth and the transform will not be applied
117
+ if (slice.openEnd >= 7 &&
118
+ // depth of a nested table cell
119
+ slice.content.childCount > 1 && ((_slice$content$lastCh = slice.content.lastChild) === null || _slice$content$lastCh === void 0 ? void 0 : _slice$content$lastCh.type) === table && isPasteInTable) {
120
+ // re-point the slice's openEnd to non-nested table cell depth
121
+ openEnd = 4;
122
+ }
123
+ } else {
124
+ // for layouts and expands, we start with 1 level of nesting as set above
125
+
126
+ // if pasted content is a table, don't allow further nesting
127
+ if (node.type === schema.nodes.table) {
128
+ allowedTableNesting = 0;
129
+ }
130
+ }
131
+
132
+ // after we've worked out what the allowed nesting depth is, unwrap nested tables
133
+ var newChildren = unwrapNestedTables(node.content, schema, allowedTableNesting);
134
+ return node.copy(Fragment.fromArray(newChildren));
135
+ });
136
+ return new Slice(newFragment, slice.openStart, openEnd);
137
+ };
36
138
 
37
139
  /**
38
140
  * When we copy from a table cell with a hardBreak at the end,
@@ -40,10 +142,10 @@ export var removeTableFromLastChild = function removeTableFromLastChild(node, i,
40
142
  * This code will look for that pattern and fix it.
41
143
  */
42
144
  export var transformSliceToFixHardBreakProblemOnCopyFromCell = function transformSliceToFixHardBreakProblemOnCopyFromCell(slice, schema) {
43
- var _schema$nodes2 = schema.nodes,
44
- paragraph = _schema$nodes2.paragraph,
45
- table = _schema$nodes2.table,
46
- hardBreak = _schema$nodes2.hardBreak;
145
+ var _schema$nodes3 = schema.nodes,
146
+ paragraph = _schema$nodes3.paragraph,
147
+ table = _schema$nodes3.table,
148
+ hardBreak = _schema$nodes3.hardBreak;
47
149
  var emptyParagraphNode = paragraph.createAndFill();
48
150
  var hardBreakNode = hardBreak === null || hardBreak === void 0 ? void 0 : hardBreak.createAndFill();
49
151
  var paragraphNodeSize = emptyParagraphNode ? emptyParagraphNode.nodeSize : 0;
@@ -60,7 +162,7 @@ export var transformSliceToFixHardBreakProblemOnCopyFromCell = function transfor
60
162
  return slice;
61
163
  };
62
164
  export var transformSliceToRemoveOpenTable = function transformSliceToRemoveOpenTable(slice, schema) {
63
- var _slice$content$firstC2;
165
+ var _slice$content$firstC3;
64
166
  // we're removing the table, tableRow and tableCell reducing the open depth by 3
65
167
  var depthDecrement = 3;
66
168
 
@@ -70,14 +172,14 @@ export var transformSliceToRemoveOpenTable = function transformSliceToRemoveOpen
70
172
  slice.openStart >= 4 && slice.openEnd >= 4 &&
71
173
  // slice is a table node
72
174
  slice.content.childCount === 1 && slice.content.firstChild.type === schema.nodes.table) {
73
- var _slice$content$firstC;
175
+ var _slice$content$firstC2;
74
176
  // prosemirror-view has a bug that it duplicates table entry when selecting multiple paragraphs in a table cell.
75
177
  // https://github.com/ProseMirror/prosemirror/issues/1270
76
178
  // The structure becomes
77
179
  // table(genuine) > tableRow(genuine) > table(duplicated) > tableRow(duplicated) > tableCell/tableHeader(genuine) > contents(genuine)
78
180
  // As we are removing wrapping table anyway, we keep duplicated table and tableRow for simplicity
79
181
  var cleaned = slice;
80
- if (((_slice$content$firstC = slice.content.firstChild) === null || _slice$content$firstC === void 0 || (_slice$content$firstC = _slice$content$firstC.content) === null || _slice$content$firstC === void 0 || (_slice$content$firstC = _slice$content$firstC.firstChild) === null || _slice$content$firstC === void 0 || (_slice$content$firstC = _slice$content$firstC.content) === null || _slice$content$firstC === void 0 || (_slice$content$firstC = _slice$content$firstC.firstChild) === null || _slice$content$firstC === void 0 ? void 0 : _slice$content$firstC.type) === schema.nodes.table) {
182
+ if (((_slice$content$firstC2 = slice.content.firstChild) === null || _slice$content$firstC2 === void 0 || (_slice$content$firstC2 = _slice$content$firstC2.content) === null || _slice$content$firstC2 === void 0 || (_slice$content$firstC2 = _slice$content$firstC2.firstChild) === null || _slice$content$firstC2 === void 0 || (_slice$content$firstC2 = _slice$content$firstC2.content) === null || _slice$content$firstC2 === void 0 || (_slice$content$firstC2 = _slice$content$firstC2.firstChild) === null || _slice$content$firstC2 === void 0 ? void 0 : _slice$content$firstC2.type) === schema.nodes.table) {
81
183
  cleaned = new Slice(slice.content.firstChild.content.firstChild.content, slice.openStart - 2, slice.openEnd - 2);
82
184
  }
83
185
  return new Slice(flatmap(cleaned.content, unwrapContentFromTable), cleaned.openStart - depthDecrement, cleaned.openEnd - depthDecrement);
@@ -88,7 +190,7 @@ export var transformSliceToRemoveOpenTable = function transformSliceToRemoveOpen
88
190
  // starts inside of a cell but ends outside of the starting table
89
191
  slice.openStart >= 4 &&
90
192
  // slice starts from a table node (and spans across more than one node)
91
- slice.content.childCount > 1 && ((_slice$content$firstC2 = slice.content.firstChild) === null || _slice$content$firstC2 === void 0 ? void 0 : _slice$content$firstC2.type) === schema.nodes.table) {
193
+ slice.content.childCount > 1 && ((_slice$content$firstC3 = slice.content.firstChild) === null || _slice$content$firstC3 === void 0 ? void 0 : _slice$content$firstC3.type) === schema.nodes.table) {
92
194
  // repoint the slice's cutting depth so that cell content where the slice starts
93
195
  // does not get lifted out of the cell on paste
94
196
  return new Slice(slice.content, 1, slice.openEnd);
@@ -96,9 +198,9 @@ export var transformSliceToRemoveOpenTable = function transformSliceToRemoveOpen
96
198
  return slice;
97
199
  };
98
200
  export var transformSliceToCorrectEmptyTableCells = function transformSliceToCorrectEmptyTableCells(slice, schema) {
99
- var _schema$nodes3 = schema.nodes,
100
- tableCell = _schema$nodes3.tableCell,
101
- tableHeader = _schema$nodes3.tableHeader;
201
+ var _schema$nodes4 = schema.nodes,
202
+ tableCell = _schema$nodes4.tableCell,
203
+ tableHeader = _schema$nodes4.tableHeader;
102
204
  return mapSlice(slice, function (node) {
103
205
  if (node && (node.type === tableCell || node.type === tableHeader) && !node.content.childCount) {
104
206
  return node.type.createAndFill(node.attrs) || node;
@@ -1,9 +1,10 @@
1
- import type { Node as PMNode, Schema } from '@atlaskit/editor-prosemirror/model';
2
- import { Fragment, Slice } from '@atlaskit/editor-prosemirror/model';
3
- import type { EditorState } from '@atlaskit/editor-prosemirror/state';
1
+ import type { Schema } from '@atlaskit/editor-prosemirror/model';
2
+ import { Slice, Fragment, Node as PMNode } from '@atlaskit/editor-prosemirror/model';
3
+ import type { EditorState, Selection } from '@atlaskit/editor-prosemirror/state';
4
4
  export declare const unwrapContentFromTable: (maybeTable: PMNode) => PMNode | PMNode[];
5
5
  export declare const removeTableFromFirstChild: (node: PMNode, i: number) => PMNode | PMNode[];
6
6
  export declare const removeTableFromLastChild: (node: PMNode, i: number, fragment: Fragment) => PMNode | PMNode[];
7
+ export declare const transformSliceToRemoveNestedTables: (slice: Slice, schema: Schema, selection: Selection) => Slice;
7
8
  /**
8
9
  * When we copy from a table cell with a hardBreak at the end,
9
10
  * the slice generated will come with a hardBreak outside of the table.
@@ -43,8 +43,8 @@ export type TablePlugin = NextEditorPlugin<'table', {
43
43
  AnalyticsPlugin,
44
44
  ContentInsertionPlugin,
45
45
  WidthPlugin,
46
- GuidelinePlugin,
47
46
  SelectionPlugin,
47
+ OptionalPlugin<GuidelinePlugin>,
48
48
  OptionalPlugin<BatchAttributeUpdatesPlugin>,
49
49
  OptionalPlugin<AccessibilityUtilsPlugin>,
50
50
  OptionalPlugin<MediaPlugin>,
@@ -58,14 +58,6 @@ export declare const ColumnControls: ({ editorView, tableActive, tableRef, hover
58
58
  }, import("@atlaskit/editor-plugin-analytics").AnalyticsPluginOptions>];
59
59
  } & import("@atlaskit/editor-plugin-content-insertion").InsertNodeAPI, undefined>, import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"width", {
60
60
  sharedState: import("@atlaskit/editor-common/types").EditorContainerWidth | undefined;
61
- }, undefined>, import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"guideline", {
62
- dependencies: [import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"width", {
63
- sharedState: import("@atlaskit/editor-common/types").EditorContainerWidth | undefined;
64
- }, undefined>];
65
- sharedState: import("@atlaskit/editor-common/guideline").GuidelinePluginState | null;
66
- actions: {
67
- displayGuideline: import("@atlaskit/editor-common/guideline").DisplayGuideline;
68
- };
69
61
  }, undefined>, import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"selection", {
70
62
  pluginConfiguration: import("@atlaskit/editor-plugin-selection").SelectionPluginOptions | undefined;
71
63
  actions: import("@atlaskit/editor-plugin-selection").EditorSelectionAPI;
@@ -73,7 +65,15 @@ export declare const ColumnControls: ({ editorView, tableActive, tableRef, hover
73
65
  displayGapCursor: (toggle: boolean) => import("@atlaskit/editor-common/types").EditorCommand;
74
66
  };
75
67
  sharedState: import("@atlaskit/editor-common/selection").SelectionSharedState;
76
- }, import("@atlaskit/editor-plugin-selection").SelectionPluginOptions | undefined>, import("@atlaskit/editor-common/types").OptionalPlugin<import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"batchAttributeUpdates", {
68
+ }, import("@atlaskit/editor-plugin-selection").SelectionPluginOptions | undefined>, import("@atlaskit/editor-common/types").OptionalPlugin<import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"guideline", {
69
+ dependencies: [import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"width", {
70
+ sharedState: import("@atlaskit/editor-common/types").EditorContainerWidth | undefined;
71
+ }, undefined>];
72
+ sharedState: import("@atlaskit/editor-common/guideline").GuidelinePluginState | null;
73
+ actions: {
74
+ displayGuideline: import("@atlaskit/editor-common/guideline").DisplayGuideline;
75
+ };
76
+ }, undefined>>, import("@atlaskit/editor-common/types").OptionalPlugin<import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"batchAttributeUpdates", {
77
77
  actions: {
78
78
  batchSteps: import("@atlaskit/editor-plugin-batch-attribute-updates").BatchStepsAction;
79
79
  };
@@ -39,14 +39,6 @@ export declare const DragCornerControlsWithSelection: React.FC<import("react-int
39
39
  }, import("@atlaskit/editor-plugin-analytics").AnalyticsPluginOptions>];
40
40
  } & import("@atlaskit/editor-plugin-content-insertion").InsertNodeAPI, undefined>, import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"width", {
41
41
  sharedState: import("@atlaskit/editor-common/types").EditorContainerWidth | undefined;
42
- }, undefined>, import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"guideline", {
43
- dependencies: [import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"width", {
44
- sharedState: import("@atlaskit/editor-common/types").EditorContainerWidth | undefined;
45
- }, undefined>];
46
- sharedState: import("@atlaskit/editor-common/guideline").GuidelinePluginState | null;
47
- actions: {
48
- displayGuideline: import("@atlaskit/editor-common/guideline").DisplayGuideline;
49
- };
50
42
  }, undefined>, import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"selection", {
51
43
  pluginConfiguration: import("@atlaskit/editor-plugin-selection").SelectionPluginOptions | undefined;
52
44
  actions: import("@atlaskit/editor-plugin-selection").EditorSelectionAPI;
@@ -54,7 +46,15 @@ export declare const DragCornerControlsWithSelection: React.FC<import("react-int
54
46
  displayGapCursor: (toggle: boolean) => import("@atlaskit/editor-common/types").EditorCommand;
55
47
  };
56
48
  sharedState: import("@atlaskit/editor-common/selection").SelectionSharedState;
57
- }, import("@atlaskit/editor-plugin-selection").SelectionPluginOptions | undefined>, import("@atlaskit/editor-common/types").OptionalPlugin<import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"batchAttributeUpdates", {
49
+ }, import("@atlaskit/editor-plugin-selection").SelectionPluginOptions | undefined>, import("@atlaskit/editor-common/types").OptionalPlugin<import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"guideline", {
50
+ dependencies: [import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"width", {
51
+ sharedState: import("@atlaskit/editor-common/types").EditorContainerWidth | undefined;
52
+ }, undefined>];
53
+ sharedState: import("@atlaskit/editor-common/guideline").GuidelinePluginState | null;
54
+ actions: {
55
+ displayGuideline: import("@atlaskit/editor-common/guideline").DisplayGuideline;
56
+ };
57
+ }, undefined>>, import("@atlaskit/editor-common/types").OptionalPlugin<import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"batchAttributeUpdates", {
58
58
  actions: {
59
59
  batchSteps: import("@atlaskit/editor-plugin-batch-attribute-updates").BatchStepsAction;
60
60
  };
@@ -125,14 +125,6 @@ export declare const DragCornerControlsWithSelection: React.FC<import("react-int
125
125
  }, import("@atlaskit/editor-plugin-analytics").AnalyticsPluginOptions>];
126
126
  } & import("@atlaskit/editor-plugin-content-insertion").InsertNodeAPI, undefined>, import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"width", {
127
127
  sharedState: import("@atlaskit/editor-common/types").EditorContainerWidth | undefined;
128
- }, undefined>, import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"guideline", {
129
- dependencies: [import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"width", {
130
- sharedState: import("@atlaskit/editor-common/types").EditorContainerWidth | undefined;
131
- }, undefined>];
132
- sharedState: import("@atlaskit/editor-common/guideline").GuidelinePluginState | null;
133
- actions: {
134
- displayGuideline: import("@atlaskit/editor-common/guideline").DisplayGuideline;
135
- };
136
128
  }, undefined>, import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"selection", {
137
129
  pluginConfiguration: import("@atlaskit/editor-plugin-selection").SelectionPluginOptions | undefined;
138
130
  actions: import("@atlaskit/editor-plugin-selection").EditorSelectionAPI;
@@ -140,7 +132,15 @@ export declare const DragCornerControlsWithSelection: React.FC<import("react-int
140
132
  displayGapCursor: (toggle: boolean) => import("@atlaskit/editor-common/types").EditorCommand;
141
133
  };
142
134
  sharedState: import("@atlaskit/editor-common/selection").SelectionSharedState;
143
- }, import("@atlaskit/editor-plugin-selection").SelectionPluginOptions | undefined>, import("@atlaskit/editor-common/types").OptionalPlugin<import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"batchAttributeUpdates", {
135
+ }, import("@atlaskit/editor-plugin-selection").SelectionPluginOptions | undefined>, import("@atlaskit/editor-common/types").OptionalPlugin<import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"guideline", {
136
+ dependencies: [import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"width", {
137
+ sharedState: import("@atlaskit/editor-common/types").EditorContainerWidth | undefined;
138
+ }, undefined>];
139
+ sharedState: import("@atlaskit/editor-common/guideline").GuidelinePluginState | null;
140
+ actions: {
141
+ displayGuideline: import("@atlaskit/editor-common/guideline").DisplayGuideline;
142
+ };
143
+ }, undefined>>, import("@atlaskit/editor-common/types").OptionalPlugin<import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"batchAttributeUpdates", {
144
144
  actions: {
145
145
  batchSteps: import("@atlaskit/editor-plugin-batch-attribute-updates").BatchStepsAction;
146
146
  };
@@ -68,14 +68,6 @@ export declare const TableFloatingControls: ({ editorView, tableRef, tableNode,
68
68
  }, import("@atlaskit/editor-plugin-analytics").AnalyticsPluginOptions>];
69
69
  } & import("@atlaskit/editor-plugin-content-insertion").InsertNodeAPI, undefined>, import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"width", {
70
70
  sharedState: import("@atlaskit/editor-common/types").EditorContainerWidth | undefined;
71
- }, undefined>, import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"guideline", {
72
- dependencies: [import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"width", {
73
- sharedState: import("@atlaskit/editor-common/types").EditorContainerWidth | undefined;
74
- }, undefined>];
75
- sharedState: import("@atlaskit/editor-common/guideline").GuidelinePluginState | null;
76
- actions: {
77
- displayGuideline: import("@atlaskit/editor-common/guideline").DisplayGuideline;
78
- };
79
71
  }, undefined>, import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"selection", {
80
72
  pluginConfiguration: import("@atlaskit/editor-plugin-selection").SelectionPluginOptions | undefined;
81
73
  actions: import("@atlaskit/editor-plugin-selection").EditorSelectionAPI;
@@ -83,7 +75,15 @@ export declare const TableFloatingControls: ({ editorView, tableRef, tableNode,
83
75
  displayGapCursor: (toggle: boolean) => import("@atlaskit/editor-common/types").EditorCommand;
84
76
  };
85
77
  sharedState: import("@atlaskit/editor-common/selection").SelectionSharedState;
86
- }, import("@atlaskit/editor-plugin-selection").SelectionPluginOptions | undefined>, import("@atlaskit/editor-common/types").OptionalPlugin<import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"batchAttributeUpdates", {
78
+ }, import("@atlaskit/editor-plugin-selection").SelectionPluginOptions | undefined>, import("@atlaskit/editor-common/types").OptionalPlugin<import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"guideline", {
79
+ dependencies: [import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"width", {
80
+ sharedState: import("@atlaskit/editor-common/types").EditorContainerWidth | undefined;
81
+ }, undefined>];
82
+ sharedState: import("@atlaskit/editor-common/guideline").GuidelinePluginState | null;
83
+ actions: {
84
+ displayGuideline: import("@atlaskit/editor-common/guideline").DisplayGuideline;
85
+ };
86
+ }, undefined>>, import("@atlaskit/editor-common/types").OptionalPlugin<import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"batchAttributeUpdates", {
87
87
  actions: {
88
88
  batchSteps: import("@atlaskit/editor-plugin-batch-attribute-updates").BatchStepsAction;
89
89
  };
@@ -1,9 +1,10 @@
1
- import type { Node as PMNode, Schema } from '@atlaskit/editor-prosemirror/model';
2
- import { Fragment, Slice } from '@atlaskit/editor-prosemirror/model';
3
- import type { EditorState } from '@atlaskit/editor-prosemirror/state';
1
+ import type { Schema } from '@atlaskit/editor-prosemirror/model';
2
+ import { Slice, Fragment, Node as PMNode } from '@atlaskit/editor-prosemirror/model';
3
+ import type { EditorState, Selection } from '@atlaskit/editor-prosemirror/state';
4
4
  export declare const unwrapContentFromTable: (maybeTable: PMNode) => PMNode | PMNode[];
5
5
  export declare const removeTableFromFirstChild: (node: PMNode, i: number) => PMNode | PMNode[];
6
6
  export declare const removeTableFromLastChild: (node: PMNode, i: number, fragment: Fragment) => PMNode | PMNode[];
7
+ export declare const transformSliceToRemoveNestedTables: (slice: Slice, schema: Schema, selection: Selection) => Slice;
7
8
  /**
8
9
  * When we copy from a table cell with a hardBreak at the end,
9
10
  * the slice generated will come with a hardBreak outside of the table.
@@ -43,8 +43,8 @@ export type TablePlugin = NextEditorPlugin<'table', {
43
43
  AnalyticsPlugin,
44
44
  ContentInsertionPlugin,
45
45
  WidthPlugin,
46
- GuidelinePlugin,
47
46
  SelectionPlugin,
47
+ OptionalPlugin<GuidelinePlugin>,
48
48
  OptionalPlugin<BatchAttributeUpdatesPlugin>,
49
49
  OptionalPlugin<AccessibilityUtilsPlugin>,
50
50
  OptionalPlugin<MediaPlugin>,
@@ -68,7 +68,15 @@ export declare const ColumnControls: ({ editorView, tableActive, tableRef, hover
68
68
  import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"width", {
69
69
  sharedState: import("@atlaskit/editor-common/types").EditorContainerWidth | undefined;
70
70
  }, undefined>,
71
- import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"guideline", {
71
+ import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"selection", {
72
+ pluginConfiguration: import("@atlaskit/editor-plugin-selection").SelectionPluginOptions | undefined;
73
+ actions: import("@atlaskit/editor-plugin-selection").EditorSelectionAPI;
74
+ commands: {
75
+ displayGapCursor: (toggle: boolean) => import("@atlaskit/editor-common/types").EditorCommand;
76
+ };
77
+ sharedState: import("@atlaskit/editor-common/selection").SelectionSharedState;
78
+ }, import("@atlaskit/editor-plugin-selection").SelectionPluginOptions | undefined>,
79
+ import("@atlaskit/editor-common/types").OptionalPlugin<import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"guideline", {
72
80
  dependencies: [
73
81
  import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"width", {
74
82
  sharedState: import("@atlaskit/editor-common/types").EditorContainerWidth | undefined;
@@ -78,15 +86,7 @@ export declare const ColumnControls: ({ editorView, tableActive, tableRef, hover
78
86
  actions: {
79
87
  displayGuideline: import("@atlaskit/editor-common/guideline").DisplayGuideline;
80
88
  };
81
- }, undefined>,
82
- import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"selection", {
83
- pluginConfiguration: import("@atlaskit/editor-plugin-selection").SelectionPluginOptions | undefined;
84
- actions: import("@atlaskit/editor-plugin-selection").EditorSelectionAPI;
85
- commands: {
86
- displayGapCursor: (toggle: boolean) => import("@atlaskit/editor-common/types").EditorCommand;
87
- };
88
- sharedState: import("@atlaskit/editor-common/selection").SelectionSharedState;
89
- }, import("@atlaskit/editor-plugin-selection").SelectionPluginOptions | undefined>,
89
+ }, undefined>>,
90
90
  import("@atlaskit/editor-common/types").OptionalPlugin<import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"batchAttributeUpdates", {
91
91
  actions: {
92
92
  batchSteps: import("@atlaskit/editor-plugin-batch-attribute-updates").BatchStepsAction;
@@ -49,7 +49,15 @@ export declare const DragCornerControlsWithSelection: React.FC<import("react-int
49
49
  import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"width", {
50
50
  sharedState: import("@atlaskit/editor-common/types").EditorContainerWidth | undefined;
51
51
  }, undefined>,
52
- import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"guideline", {
52
+ import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"selection", {
53
+ pluginConfiguration: import("@atlaskit/editor-plugin-selection").SelectionPluginOptions | undefined;
54
+ actions: import("@atlaskit/editor-plugin-selection").EditorSelectionAPI;
55
+ commands: {
56
+ displayGapCursor: (toggle: boolean) => import("@atlaskit/editor-common/types").EditorCommand;
57
+ };
58
+ sharedState: import("@atlaskit/editor-common/selection").SelectionSharedState;
59
+ }, import("@atlaskit/editor-plugin-selection").SelectionPluginOptions | undefined>,
60
+ import("@atlaskit/editor-common/types").OptionalPlugin<import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"guideline", {
53
61
  dependencies: [
54
62
  import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"width", {
55
63
  sharedState: import("@atlaskit/editor-common/types").EditorContainerWidth | undefined;
@@ -59,15 +67,7 @@ export declare const DragCornerControlsWithSelection: React.FC<import("react-int
59
67
  actions: {
60
68
  displayGuideline: import("@atlaskit/editor-common/guideline").DisplayGuideline;
61
69
  };
62
- }, undefined>,
63
- import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"selection", {
64
- pluginConfiguration: import("@atlaskit/editor-plugin-selection").SelectionPluginOptions | undefined;
65
- actions: import("@atlaskit/editor-plugin-selection").EditorSelectionAPI;
66
- commands: {
67
- displayGapCursor: (toggle: boolean) => import("@atlaskit/editor-common/types").EditorCommand;
68
- };
69
- sharedState: import("@atlaskit/editor-common/selection").SelectionSharedState;
70
- }, import("@atlaskit/editor-plugin-selection").SelectionPluginOptions | undefined>,
70
+ }, undefined>>,
71
71
  import("@atlaskit/editor-common/types").OptionalPlugin<import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"batchAttributeUpdates", {
72
72
  actions: {
73
73
  batchSteps: import("@atlaskit/editor-plugin-batch-attribute-updates").BatchStepsAction;
@@ -156,7 +156,15 @@ export declare const DragCornerControlsWithSelection: React.FC<import("react-int
156
156
  import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"width", {
157
157
  sharedState: import("@atlaskit/editor-common/types").EditorContainerWidth | undefined;
158
158
  }, undefined>,
159
- import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"guideline", {
159
+ import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"selection", {
160
+ pluginConfiguration: import("@atlaskit/editor-plugin-selection").SelectionPluginOptions | undefined;
161
+ actions: import("@atlaskit/editor-plugin-selection").EditorSelectionAPI;
162
+ commands: {
163
+ displayGapCursor: (toggle: boolean) => import("@atlaskit/editor-common/types").EditorCommand;
164
+ };
165
+ sharedState: import("@atlaskit/editor-common/selection").SelectionSharedState;
166
+ }, import("@atlaskit/editor-plugin-selection").SelectionPluginOptions | undefined>,
167
+ import("@atlaskit/editor-common/types").OptionalPlugin<import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"guideline", {
160
168
  dependencies: [
161
169
  import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"width", {
162
170
  sharedState: import("@atlaskit/editor-common/types").EditorContainerWidth | undefined;
@@ -166,15 +174,7 @@ export declare const DragCornerControlsWithSelection: React.FC<import("react-int
166
174
  actions: {
167
175
  displayGuideline: import("@atlaskit/editor-common/guideline").DisplayGuideline;
168
176
  };
169
- }, undefined>,
170
- import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"selection", {
171
- pluginConfiguration: import("@atlaskit/editor-plugin-selection").SelectionPluginOptions | undefined;
172
- actions: import("@atlaskit/editor-plugin-selection").EditorSelectionAPI;
173
- commands: {
174
- displayGapCursor: (toggle: boolean) => import("@atlaskit/editor-common/types").EditorCommand;
175
- };
176
- sharedState: import("@atlaskit/editor-common/selection").SelectionSharedState;
177
- }, import("@atlaskit/editor-plugin-selection").SelectionPluginOptions | undefined>,
177
+ }, undefined>>,
178
178
  import("@atlaskit/editor-common/types").OptionalPlugin<import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"batchAttributeUpdates", {
179
179
  actions: {
180
180
  batchSteps: import("@atlaskit/editor-plugin-batch-attribute-updates").BatchStepsAction;
@@ -78,7 +78,15 @@ export declare const TableFloatingControls: ({ editorView, tableRef, tableNode,
78
78
  import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"width", {
79
79
  sharedState: import("@atlaskit/editor-common/types").EditorContainerWidth | undefined;
80
80
  }, undefined>,
81
- import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"guideline", {
81
+ import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"selection", {
82
+ pluginConfiguration: import("@atlaskit/editor-plugin-selection").SelectionPluginOptions | undefined;
83
+ actions: import("@atlaskit/editor-plugin-selection").EditorSelectionAPI;
84
+ commands: {
85
+ displayGapCursor: (toggle: boolean) => import("@atlaskit/editor-common/types").EditorCommand;
86
+ };
87
+ sharedState: import("@atlaskit/editor-common/selection").SelectionSharedState;
88
+ }, import("@atlaskit/editor-plugin-selection").SelectionPluginOptions | undefined>,
89
+ import("@atlaskit/editor-common/types").OptionalPlugin<import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"guideline", {
82
90
  dependencies: [
83
91
  import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"width", {
84
92
  sharedState: import("@atlaskit/editor-common/types").EditorContainerWidth | undefined;
@@ -88,15 +96,7 @@ export declare const TableFloatingControls: ({ editorView, tableRef, tableNode,
88
96
  actions: {
89
97
  displayGuideline: import("@atlaskit/editor-common/guideline").DisplayGuideline;
90
98
  };
91
- }, undefined>,
92
- import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"selection", {
93
- pluginConfiguration: import("@atlaskit/editor-plugin-selection").SelectionPluginOptions | undefined;
94
- actions: import("@atlaskit/editor-plugin-selection").EditorSelectionAPI;
95
- commands: {
96
- displayGapCursor: (toggle: boolean) => import("@atlaskit/editor-common/types").EditorCommand;
97
- };
98
- sharedState: import("@atlaskit/editor-common/selection").SelectionSharedState;
99
- }, import("@atlaskit/editor-plugin-selection").SelectionPluginOptions | undefined>,
99
+ }, undefined>>,
100
100
  import("@atlaskit/editor-common/types").OptionalPlugin<import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"batchAttributeUpdates", {
101
101
  actions: {
102
102
  batchSteps: import("@atlaskit/editor-plugin-batch-attribute-updates").BatchStepsAction;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-table",
3
- "version": "8.4.9",
3
+ "version": "8.4.11",
4
4
  "description": "Table plugin for the @atlaskit/editor",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/"
@@ -30,7 +30,7 @@
30
30
  "@atlaskit/adf-schema": "^46.1.0",
31
31
  "@atlaskit/button": "^20.3.0",
32
32
  "@atlaskit/custom-steps": "^0.9.0",
33
- "@atlaskit/editor-common": "^96.5.0",
33
+ "@atlaskit/editor-common": "^96.7.0",
34
34
  "@atlaskit/editor-palette": "1.6.3",
35
35
  "@atlaskit/editor-plugin-accessibility-utils": "^1.2.0",
36
36
  "@atlaskit/editor-plugin-analytics": "^1.10.0",
@@ -51,7 +51,7 @@
51
51
  "@atlaskit/pragmatic-drag-and-drop-hitbox": "^1.0.0",
52
52
  "@atlaskit/primitives": "^13.3.0",
53
53
  "@atlaskit/theme": "^14.0.0",
54
- "@atlaskit/tmp-editor-statsig": "^2.27.0",
54
+ "@atlaskit/tmp-editor-statsig": "^2.29.0",
55
55
  "@atlaskit/toggle": "^14.0.0",
56
56
  "@atlaskit/tokens": "^2.5.0",
57
57
  "@atlaskit/tooltip": "^19.0.0",
@@ -25,6 +25,7 @@ import { findParentDomRefOfType, findParentNodeOfType } from '@atlaskit/editor-p
25
25
  import type { EditorView } from '@atlaskit/editor-prosemirror/view';
26
26
  import { TableMap } from '@atlaskit/editor-tables';
27
27
  import { findTable } from '@atlaskit/editor-tables/utils';
28
+ import { fg } from '@atlaskit/platform-feature-flags';
28
29
 
29
30
  import {
30
31
  lazyTableCellView,
@@ -73,7 +74,11 @@ import {
73
74
  transformSliceToFixHardBreakProblemOnCopyFromCell,
74
75
  transformSliceToRemoveOpenTable,
75
76
  } from './utils';
76
- import { isHeaderRowRequired, transformSliceTableLayoutDefaultToCenter } from './utils/paste';
77
+ import {
78
+ isHeaderRowRequired,
79
+ transformSliceTableLayoutDefaultToCenter,
80
+ transformSliceToRemoveNestedTables,
81
+ } from './utils/paste';
77
82
 
78
83
  export const createPlugin = (
79
84
  dispatchAnalyticsEvent: DispatchAnalyticsEvent,
@@ -304,6 +309,10 @@ export const createPlugin = (
304
309
 
305
310
  slice = transformSliceToRemoveOpenNestedExpand(slice, schema);
306
311
 
312
+ if (fg('platform_editor_use_nested_table_pm_nodes')) {
313
+ slice = transformSliceToRemoveNestedTables(slice, schema, editorState.selection);
314
+ }
315
+
307
316
  return slice;
308
317
  },
309
318
  handleClick: ({ state, dispatch }, _pos, event: MouseEvent) => {
@@ -1,8 +1,10 @@
1
+ import { getParentOfTypeCount } from '@atlaskit/editor-common/nesting';
1
2
  import { flatmap, mapChildren, mapSlice } from '@atlaskit/editor-common/utils';
2
- import type { Node as PMNode, Schema } from '@atlaskit/editor-prosemirror/model';
3
- import { Fragment, Slice } from '@atlaskit/editor-prosemirror/model';
4
- import type { EditorState } from '@atlaskit/editor-prosemirror/state';
5
- import { flatten } from '@atlaskit/editor-prosemirror/utils';
3
+ import type { Schema } from '@atlaskit/editor-prosemirror/model';
4
+ import { Slice, Fragment, Node as PMNode } from '@atlaskit/editor-prosemirror/model';
5
+ import type { EditorState, Selection } from '@atlaskit/editor-prosemirror/state';
6
+ import { flatten, hasParentNodeOfType } from '@atlaskit/editor-prosemirror/utils';
7
+ import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
6
8
 
7
9
  import { getPluginState } from '../plugin-factory';
8
10
 
@@ -23,6 +25,54 @@ export const unwrapContentFromTable = (maybeTable: PMNode): PMNode | PMNode[] =>
23
25
  return maybeTable;
24
26
  };
25
27
 
28
+ // Flattens nested tables after a given nesting depth
29
+ // If this looks familiar, it's a heavily modified version of `mapFragment` which has been
30
+ // adjusted to support tracking nesting depth. This wasn't possible by using `mapFragment` directly
31
+ const unwrapNestedTables = (
32
+ content: Fragment,
33
+ schema: Schema,
34
+ unwrapNestDepth: number,
35
+ currentNestDepth = 0,
36
+ ): PMNode[] => {
37
+ const flattenNested = (node: PMNode, tableDepth: number) => {
38
+ if (node.type === schema.nodes.table) {
39
+ if (tableDepth >= unwrapNestDepth) {
40
+ return unwrapContentFromTable(node);
41
+ }
42
+ return node;
43
+ }
44
+ return node;
45
+ };
46
+
47
+ const children = [] as PMNode[];
48
+ for (let i = 0, size = content.childCount; i < size; i++) {
49
+ const node = content.child(i);
50
+ const transformed = node.isLeaf
51
+ ? flattenNested(node, currentNestDepth)
52
+ : flattenNested(
53
+ node.copy(
54
+ Fragment.fromArray(
55
+ unwrapNestedTables(
56
+ node.content,
57
+ schema,
58
+ unwrapNestDepth,
59
+ node.type === schema.nodes.table ? currentNestDepth + 1 : currentNestDepth,
60
+ ),
61
+ ),
62
+ ),
63
+ currentNestDepth,
64
+ );
65
+ if (transformed) {
66
+ if (Array.isArray(transformed)) {
67
+ children.push(...transformed);
68
+ } else {
69
+ children.push(transformed);
70
+ }
71
+ }
72
+ }
73
+ return children;
74
+ };
75
+
26
76
  export const removeTableFromFirstChild = (node: PMNode, i: number): PMNode | PMNode[] => {
27
77
  return i === 0 ? unwrapContentFromTable(node) : node;
28
78
  };
@@ -35,6 +85,87 @@ export const removeTableFromLastChild = (
35
85
  return i === fragment.childCount - 1 ? unwrapContentFromTable(node) : node;
36
86
  };
37
87
 
88
+ export const transformSliceToRemoveNestedTables = (
89
+ slice: Slice,
90
+ schema: Schema,
91
+ selection: Selection,
92
+ ): Slice => {
93
+ const isNestingAllowed = editorExperiment('nested-tables-in-tables', true);
94
+ const { table, tableCell, tableHeader } = schema.nodes;
95
+ let openEnd = slice.openEnd;
96
+
97
+ const newFragment = flatmap(slice.content, (node, i, fragment) => {
98
+ // if pasted content is a node that supports nesting a table
99
+ // such as layoutSection or expand allow 1 level by default
100
+ let allowedTableNesting = 1;
101
+
102
+ if (isNestingAllowed) {
103
+ const isPasteInTable = hasParentNodeOfType([table, tableCell, tableHeader])(selection);
104
+ const isPasteInNestedTable = getParentOfTypeCount(schema.nodes.table)(selection.$from) > 1;
105
+ const isCellPaste =
106
+ isPasteInTable &&
107
+ slice.content.childCount === 1 &&
108
+ slice.content.firstChild?.type === table;
109
+
110
+ // if nesting is allowed we bump up the default nesting allowance to 2 to support
111
+ // two levels of nesting in nodes that support table nesting already such as layoutSection and expands
112
+ allowedTableNesting = 2;
113
+
114
+ // however if pasted content is a table, allow just one level
115
+ if (node.type === schema.nodes.table) {
116
+ allowedTableNesting = 1;
117
+
118
+ // if paste is inside a table, allow no further nesting
119
+ if (isPasteInTable) {
120
+ allowedTableNesting = 0;
121
+ }
122
+
123
+ // unless we are pasting inside a nested table, then bounce back to 1 level
124
+ // because editor-plugin-paste will lift the table to the parent table (just below it)
125
+ if (isPasteInNestedTable) {
126
+ allowedTableNesting = 1;
127
+ }
128
+
129
+ // paste of table cells into a table cell - content is spread across multiple cells
130
+ // by editor-tables so needs to be treated a little differently
131
+ if (isCellPaste) {
132
+ allowedTableNesting = 1;
133
+ if (isPasteInNestedTable) {
134
+ allowedTableNesting = 0;
135
+ }
136
+ }
137
+ }
138
+
139
+ // Prevent invalid openEnd after pasting tables with a selection that ends inside a nested table cell.
140
+ // If the slice ends with a selection that ends inside a nested table, and we paste inside a table we
141
+ // need to adjust the openEnd because it is no longer correct. If we don't, Prosemirror fires an exception
142
+ // because it iterates to a non-existent depth and the transform will not be applied
143
+ if (
144
+ slice.openEnd >= 7 && // depth of a nested table cell
145
+ slice.content.childCount > 1 &&
146
+ slice.content.lastChild?.type === table &&
147
+ isPasteInTable
148
+ ) {
149
+ // re-point the slice's openEnd to non-nested table cell depth
150
+ openEnd = 4;
151
+ }
152
+ } else {
153
+ // for layouts and expands, we start with 1 level of nesting as set above
154
+
155
+ // if pasted content is a table, don't allow further nesting
156
+ if (node.type === schema.nodes.table) {
157
+ allowedTableNesting = 0;
158
+ }
159
+ }
160
+
161
+ // after we've worked out what the allowed nesting depth is, unwrap nested tables
162
+ const newChildren = unwrapNestedTables(node.content, schema, allowedTableNesting);
163
+ return node.copy(Fragment.fromArray(newChildren));
164
+ });
165
+
166
+ return new Slice(newFragment, slice.openStart, openEnd);
167
+ };
168
+
38
169
  /**
39
170
  * When we copy from a table cell with a hardBreak at the end,
40
171
  * the slice generated will come with a hardBreak outside of the table.
@@ -67,8 +67,8 @@ export type TablePlugin = NextEditorPlugin<
67
67
  AnalyticsPlugin,
68
68
  ContentInsertionPlugin,
69
69
  WidthPlugin,
70
- GuidelinePlugin,
71
70
  SelectionPlugin,
71
+ OptionalPlugin<GuidelinePlugin>,
72
72
  OptionalPlugin<BatchAttributeUpdatesPlugin>,
73
73
  OptionalPlugin<AccessibilityUtilsPlugin>,
74
74
  OptionalPlugin<MediaPlugin>,