@atlaskit/editor-plugin-table 10.6.8 → 10.6.10
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 +21 -0
- package/dist/cjs/nodeviews/table.js +99 -7
- package/dist/cjs/tablePlugin.js +1 -1
- package/dist/cjs/ui/toolbar.js +39 -11
- package/dist/es2019/nodeviews/table.js +90 -3
- package/dist/es2019/tablePlugin.js +1 -1
- package/dist/es2019/ui/toolbar.js +30 -3
- package/dist/esm/nodeviews/table.js +99 -7
- package/dist/esm/tablePlugin.js +1 -1
- package/dist/esm/ui/toolbar.js +33 -5
- package/dist/types/nodeviews/table.d.ts +9 -0
- package/dist/types/nodeviews/toDOM.d.ts +4 -2
- package/dist/types/ui/toolbar.d.ts +2 -2
- package/dist/types-ts4.5/nodeviews/table.d.ts +9 -0
- package/dist/types-ts4.5/nodeviews/toDOM.d.ts +4 -2
- package/dist/types-ts4.5/ui/toolbar.d.ts +2 -2
- package/package.json +8 -2
- package/src/nodeviews/TableComponent.tsx +1 -0
- package/src/nodeviews/table.tsx +94 -9
- package/src/nodeviews/toDOM.ts +3 -1
- package/src/tablePlugin.tsx +0 -1
- package/src/ui/toolbar.tsx +36 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# @atlaskit/editor-plugin-table
|
|
2
2
|
|
|
3
|
+
## 10.6.10
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#134965](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/pull-requests/134965)
|
|
8
|
+
[`6c2982045451c`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/6c2982045451c) -
|
|
9
|
+
ED-26568: Remove custom toDOM implementation as it was causing flickering of an unstyled table
|
|
10
|
+
node when loading the table with React18 concurrent mode. Add logic to temporarily ignore all
|
|
11
|
+
non-selection DOM mutations during table initialisation in order to prevent unstyled table
|
|
12
|
+
flashing. Restore mutation handler after react has finished applying the style and structure.
|
|
13
|
+
|
|
14
|
+
## 10.6.9
|
|
15
|
+
|
|
16
|
+
### Patch Changes
|
|
17
|
+
|
|
18
|
+
- [#139053](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/pull-requests/139053)
|
|
19
|
+
[`c1c6278a78c4a`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/c1c6278a78c4a) -
|
|
20
|
+
[ux] Adds a new temporary floating toolbar's config option to hide any toolbars when any table's
|
|
21
|
+
menu is opend.
|
|
22
|
+
- Updated dependencies
|
|
23
|
+
|
|
3
24
|
## 10.6.8
|
|
4
25
|
|
|
5
26
|
### Patch Changes
|
|
@@ -32,6 +32,7 @@ var _tableWidth = require("../pm-plugins/table-width");
|
|
|
32
32
|
var _nodes = require("../pm-plugins/utils/nodes");
|
|
33
33
|
var _TableComponent = _interopRequireDefault(require("./TableComponent"));
|
|
34
34
|
var _TableComponentWithSharedState = require("./TableComponentWithSharedState");
|
|
35
|
+
var _toDOM = require("./toDOM");
|
|
35
36
|
function _callSuper(t, o, e) { return o = (0, _getPrototypeOf2.default)(o), (0, _possibleConstructorReturn2.default)(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], (0, _getPrototypeOf2.default)(t).constructor) : o.apply(t, e)); }
|
|
36
37
|
function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
|
|
37
38
|
function _superPropGet(t, o, e, r) { var p = (0, _get2.default)((0, _getPrototypeOf2.default)(1 & r ? t.prototype : t), o, e); return 2 & r && "function" == typeof p ? function (t) { return p.apply(e, t); } : p; }
|
|
@@ -66,6 +67,8 @@ var handleInlineTableWidth = function handleInlineTableWidth(table, width) {
|
|
|
66
67
|
}
|
|
67
68
|
table.style.setProperty('width', "".concat(width, "px"));
|
|
68
69
|
};
|
|
70
|
+
|
|
71
|
+
// Leave as a fallback incase the table's NodeSpec.toDOM is not defined.
|
|
69
72
|
var toDOM = function toDOM(node, props) {
|
|
70
73
|
var colgroup = '';
|
|
71
74
|
if (props.allowColumnResizing) {
|
|
@@ -86,16 +89,37 @@ var TableView = exports.default = /*#__PURE__*/function (_ReactNodeView) {
|
|
|
86
89
|
_this.eventDispatcher = props.eventDispatcher;
|
|
87
90
|
_this.options = props.options;
|
|
88
91
|
_this.getEditorFeatureFlags = props.getEditorFeatureFlags;
|
|
92
|
+
if ((0, _platformFeatureFlags.fg)('platform_editor_table_initial_load_fix')) {
|
|
93
|
+
_this.handleRef = function (node) {
|
|
94
|
+
return _this._handleTableRef(node);
|
|
95
|
+
};
|
|
96
|
+
}
|
|
89
97
|
return _this;
|
|
90
98
|
}
|
|
91
99
|
(0, _inherits2.default)(TableView, _ReactNodeView);
|
|
92
100
|
return (0, _createClass2.default)(TableView, [{
|
|
93
101
|
key: "getContentDOM",
|
|
94
102
|
value: function getContentDOM() {
|
|
95
|
-
var
|
|
103
|
+
var tableDOMStructure;
|
|
104
|
+
if ((0, _platformFeatureFlags.fg)('platform_editor_table_initial_load_fix')) {
|
|
105
|
+
tableDOMStructure = (0, _toDOM.tableNodeSpecWithFixedToDOM)({
|
|
106
|
+
allowColumnResizing: !!this.reactComponentProps.allowColumnResizing,
|
|
107
|
+
tableResizingEnabled: !!this.reactComponentProps.allowTableResizing,
|
|
108
|
+
getEditorContainerWidth: this.reactComponentProps.getEditorContainerWidth
|
|
109
|
+
}).toDOM(this.node);
|
|
110
|
+
} else {
|
|
111
|
+
tableDOMStructure = toDOM(this.node, this.reactComponentProps);
|
|
112
|
+
}
|
|
113
|
+
var rendered = _model.DOMSerializer.renderSpec(document, tableDOMStructure);
|
|
96
114
|
if (rendered.dom) {
|
|
97
115
|
var _this$options, _this$options2, _this$getEditorFeatur;
|
|
98
|
-
|
|
116
|
+
if ((0, _platformFeatureFlags.fg)('platform_editor_table_initial_load_fix')) {
|
|
117
|
+
var tableElement = rendered.dom.querySelector('table');
|
|
118
|
+
this.table = tableElement ? tableElement : rendered.dom;
|
|
119
|
+
this.renderedDOM = rendered.dom;
|
|
120
|
+
} else {
|
|
121
|
+
this.table = rendered.dom;
|
|
122
|
+
}
|
|
99
123
|
if (!((_this$options = this.options) !== null && _this$options !== void 0 && _this$options.isTableScalingEnabled) || (_this$options2 = this.options) !== null && _this$options2 !== void 0 && _this$options2.isTableScalingEnabled && (_this$getEditorFeatur = this.getEditorFeatureFlags) !== null && _this$getEditorFeatur !== void 0 && _this$getEditorFeatur.call(this).tableWithFixedColumnWidthsOption && this.node.attrs.displayMode === 'fixed') {
|
|
100
124
|
var tableInlineWidth = getInlineWidth(this.node, this.reactComponentProps.options, this.reactComponentProps.view.state, this.reactComponentProps.getPos(), this.reactComponentProps.allowTableResizing);
|
|
101
125
|
if (tableInlineWidth) {
|
|
@@ -105,10 +129,79 @@ var TableView = exports.default = /*#__PURE__*/function (_ReactNodeView) {
|
|
|
105
129
|
}
|
|
106
130
|
return rendered;
|
|
107
131
|
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Handles moving the table from ProseMirror's DOM structure into a React-rendered table node.
|
|
135
|
+
* Temporarily disables mutation observers (except for selection changes) during the move,
|
|
136
|
+
* preserves selection state, and restores it afterwards if mutations occurred and cursor
|
|
137
|
+
* wasn't at start of node. This prevents duplicate tables and maintains editor state during
|
|
138
|
+
* the DOM manipulation.
|
|
139
|
+
*/
|
|
140
|
+
}, {
|
|
141
|
+
key: "_handleTableRef",
|
|
142
|
+
value: function _handleTableRef(node) {
|
|
143
|
+
var _this2 = this;
|
|
144
|
+
var oldIgnoreMutation;
|
|
145
|
+
var selectionBookmark;
|
|
146
|
+
var parentOffset = 0;
|
|
147
|
+
var mutationsIgnored = false;
|
|
148
|
+
|
|
149
|
+
// Only proceed if we have both a node and table, and the table isn't already inside the node
|
|
150
|
+
if (node && this.table && !node.contains(this.table)) {
|
|
151
|
+
var _this$view$state$sele;
|
|
152
|
+
// Store the current ignoreMutation handler so we can restore it later
|
|
153
|
+
oldIgnoreMutation = this.ignoreMutation;
|
|
154
|
+
|
|
155
|
+
// Set up a temporary mutation handler that:
|
|
156
|
+
// - Ignores all DOM mutations except selection changes
|
|
157
|
+
// - Tracks when mutations have been ignored via mutationsIgnored flag
|
|
158
|
+
this.ignoreMutation = function (m) {
|
|
159
|
+
var isSelectionMutation = m.target instanceof Selection;
|
|
160
|
+
if (!isSelectionMutation) {
|
|
161
|
+
mutationsIgnored = true;
|
|
162
|
+
}
|
|
163
|
+
return !isSelectionMutation;
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
// Store the current selection state if there is a visible selection
|
|
167
|
+
// This lets us restore it after DOM changes
|
|
168
|
+
if (this.view.state.selection.visible) {
|
|
169
|
+
selectionBookmark = this.view.state.selection.getBookmark();
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Store the current cursor position within the parent node
|
|
173
|
+
// Used to determine if we need to restore selection later
|
|
174
|
+
if (((_this$view$state$sele = this.view.state.selection) === null || _this$view$state$sele === void 0 ? void 0 : _this$view$state$sele.ranges.length) > 0) {
|
|
175
|
+
var _this$view$state$sele2, _this$view$state$sele3;
|
|
176
|
+
parentOffset = (_this$view$state$sele2 = (_this$view$state$sele3 = this.view.state.selection) === null || _this$view$state$sele3 === void 0 || (_this$view$state$sele3 = _this$view$state$sele3.ranges[0].$from) === null || _this$view$state$sele3 === void 0 ? void 0 : _this$view$state$sele3.parentOffset) !== null && _this$view$state$sele2 !== void 0 ? _this$view$state$sele2 : 0;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Remove the ProseMirror table DOM structure to avoid duplication, as it's replaced with the React table node.
|
|
180
|
+
if (this.renderedDOM) {
|
|
181
|
+
this.dom.removeChild(this.renderedDOM);
|
|
182
|
+
}
|
|
183
|
+
// Move the table from the ProseMirror table structure into the React rendered table node.
|
|
184
|
+
node.appendChild(this.table);
|
|
185
|
+
|
|
186
|
+
// After the next frame:
|
|
187
|
+
requestAnimationFrame(function () {
|
|
188
|
+
// Restore the original mutation handler
|
|
189
|
+
_this2.ignoreMutation = oldIgnoreMutation;
|
|
190
|
+
|
|
191
|
+
// Restore the selection only if:
|
|
192
|
+
// - We have a selection bookmark
|
|
193
|
+
// - Mutations were ignored during the table move
|
|
194
|
+
// - The cursor wasn't at the start of the node
|
|
195
|
+
if (selectionBookmark && mutationsIgnored && parentOffset > 0) {
|
|
196
|
+
_this2.view.dispatch(_this2.view.state.tr.setSelection(selectionBookmark.resolve(_this2.view.state.tr.doc)));
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
}
|
|
108
201
|
}, {
|
|
109
202
|
key: "setDomAttrs",
|
|
110
203
|
value: function setDomAttrs(node) {
|
|
111
|
-
var
|
|
204
|
+
var _this3 = this,
|
|
112
205
|
_this$options3,
|
|
113
206
|
_this$options4,
|
|
114
207
|
_this$getEditorFeatur2;
|
|
@@ -119,7 +212,7 @@ var TableView = exports.default = /*#__PURE__*/function (_ReactNodeView) {
|
|
|
119
212
|
Object.keys(attrs).forEach(function (attr) {
|
|
120
213
|
// Ignored via go/ees005
|
|
121
214
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
122
|
-
|
|
215
|
+
_this3.table.setAttribute(attr, attrs[attr]);
|
|
123
216
|
});
|
|
124
217
|
|
|
125
218
|
// Preserve Table Width cannot have inline width set on the table
|
|
@@ -136,7 +229,7 @@ var TableView = exports.default = /*#__PURE__*/function (_ReactNodeView) {
|
|
|
136
229
|
}, {
|
|
137
230
|
key: "render",
|
|
138
231
|
value: function render(props, forwardRef) {
|
|
139
|
-
var
|
|
232
|
+
var _this4 = this;
|
|
140
233
|
if ((0, _platformFeatureFlags.fg)('platform_editor_table_use_shared_state_hook_fg')) {
|
|
141
234
|
return /*#__PURE__*/_react.default.createElement(_TableComponentWithSharedState.TableComponentWithSharedState, {
|
|
142
235
|
forwardRef: forwardRef,
|
|
@@ -154,7 +247,6 @@ var TableView = exports.default = /*#__PURE__*/function (_ReactNodeView) {
|
|
|
154
247
|
dispatchAnalyticsEvent: props.dispatchAnalyticsEvent
|
|
155
248
|
});
|
|
156
249
|
}
|
|
157
|
-
|
|
158
250
|
// Please, do not copy or use this kind of code below
|
|
159
251
|
// @ts-ignore
|
|
160
252
|
var fakePluginKey = {
|
|
@@ -246,7 +338,7 @@ var TableView = exports.default = /*#__PURE__*/function (_ReactNodeView) {
|
|
|
246
338
|
,
|
|
247
339
|
ordering: pluginState.ordering,
|
|
248
340
|
isResizing: isResizing,
|
|
249
|
-
getNode:
|
|
341
|
+
getNode: _this4.getNode
|
|
250
342
|
// Ignored via go/ees005
|
|
251
343
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
252
344
|
,
|
package/dist/cjs/tablePlugin.js
CHANGED
|
@@ -610,7 +610,7 @@ var tablesPlugin = function tablesPlugin(_ref) {
|
|
|
610
610
|
}
|
|
611
611
|
}];
|
|
612
612
|
},
|
|
613
|
-
floatingToolbar: (0, _toolbar.getToolbarConfig)(defaultGetEditorContainerWidth, api, editorAnalyticsAPI,
|
|
613
|
+
floatingToolbar: (0, _toolbar.getToolbarConfig)(defaultGetEditorContainerWidth, api, editorAnalyticsAPI, function () {
|
|
614
614
|
return editorViewRef.current;
|
|
615
615
|
}, options, isTableFixedColumnWidthsOptionEnabled, shouldUseIncreasedScalingPercent)((0, _createPluginConfig.pluginConfig)(options === null || options === void 0 ? void 0 : options.tableOptions))
|
|
616
616
|
},
|
package/dist/cjs/ui/toolbar.js
CHANGED
|
@@ -37,7 +37,8 @@ var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
|
|
|
37
37
|
var _experiments = require("@atlaskit/tmp-editor-statsig/experiments");
|
|
38
38
|
var _commands = require("../pm-plugins/commands");
|
|
39
39
|
var _commandsWithAnalytics = require("../pm-plugins/commands/commands-with-analytics");
|
|
40
|
-
var _pluginFactory = require("../pm-plugins/plugin-factory");
|
|
40
|
+
var _pluginFactory = require("../pm-plugins/drag-and-drop/plugin-factory");
|
|
41
|
+
var _pluginFactory2 = require("../pm-plugins/plugin-factory");
|
|
41
42
|
var _pluginKey = require("../pm-plugins/table-resizing/plugin-key");
|
|
42
43
|
var _misc = require("../pm-plugins/table-resizing/utils/misc");
|
|
43
44
|
var _resizeState = require("../pm-plugins/table-resizing/utils/resize-state");
|
|
@@ -155,7 +156,7 @@ var getToolbarCellOptionsConfig = exports.getToolbarCellOptionsConfig = function
|
|
|
155
156
|
left = initialSelectionRect.left;
|
|
156
157
|
var numberOfColumns = right - left;
|
|
157
158
|
var numberOfRows = bottom - top;
|
|
158
|
-
var pluginState = (0,
|
|
159
|
+
var pluginState = (0, _pluginFactory2.getPluginState)(editorState);
|
|
159
160
|
var options = [{
|
|
160
161
|
id: 'editor.table.insertColumn',
|
|
161
162
|
title: formatMessage(_messages.tableMessages.insertColumn),
|
|
@@ -318,7 +319,7 @@ var getToolbarCellOptionsConfig = exports.getToolbarCellOptionsConfig = function
|
|
|
318
319
|
0: Math.max(numberOfColumns, numberOfRows)
|
|
319
320
|
}),
|
|
320
321
|
onClick: function onClick(state, dispatch) {
|
|
321
|
-
var _getPluginState = (0,
|
|
322
|
+
var _getPluginState = (0, _pluginFactory2.getPluginState)(state),
|
|
322
323
|
targetCellPosition = _getPluginState.targetCellPosition;
|
|
323
324
|
(0, _commandsWithAnalytics.emptyMultipleCellsWithAnalytics)(editorAnalyticsAPI)(_analytics.INPUT_METHOD.FLOATING_TB, targetCellPosition)(state, dispatch);
|
|
324
325
|
return true;
|
|
@@ -361,21 +362,48 @@ var getClosestSelectionOrTableRect = function getClosestSelectionOrTableRect(sta
|
|
|
361
362
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
362
363
|
return (0, _utils3.isSelectionType)(selection, 'cell') ? (0, _utils3.getSelectionRect)(selection) : tableRect;
|
|
363
364
|
};
|
|
364
|
-
var getToolbarConfig = exports.getToolbarConfig = function getToolbarConfig(getEditorContainerWidth, api, editorAnalyticsAPI,
|
|
365
|
-
var isTableFixedColumnWidthsOptionEnabled = arguments.length >
|
|
366
|
-
var shouldUseIncreasedScalingPercent = arguments.length >
|
|
365
|
+
var getToolbarConfig = exports.getToolbarConfig = function getToolbarConfig(getEditorContainerWidth, api, editorAnalyticsAPI, getEditorView, options) {
|
|
366
|
+
var isTableFixedColumnWidthsOptionEnabled = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : false;
|
|
367
|
+
var shouldUseIncreasedScalingPercent = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : false;
|
|
367
368
|
return function (config) {
|
|
368
369
|
return function (state, intl) {
|
|
369
370
|
var tableObject = (0, _utils3.findTable)(state.selection);
|
|
370
|
-
var pluginState = (0,
|
|
371
|
+
var pluginState = (0, _pluginFactory2.getPluginState)(state);
|
|
371
372
|
var resizeState = _pluginKey.pluginKey.getState(state);
|
|
372
373
|
var tableWidthState = _tableWidth.pluginKey.getState(state);
|
|
373
374
|
var isTableScalingEnabled = (options === null || options === void 0 ? void 0 : options.isTableScalingEnabled) || false;
|
|
375
|
+
var nodeType = state.schema.nodes.table;
|
|
376
|
+
var toolbarTitle = 'Table floating controls';
|
|
377
|
+
if ((0, _experiments.editorExperiment)('platform_editor_controls', 'variant1') && (0, _platformFeatureFlags.fg)('platform_editor_controls_patch_4')) {
|
|
378
|
+
var _api$editorViewMode;
|
|
379
|
+
var isDragHandleMenuOpened = false;
|
|
380
|
+
var isTableRowOrColumnDragged = false;
|
|
381
|
+
if (options !== null && options !== void 0 && options.dragAndDropEnabled) {
|
|
382
|
+
var _getDragDropPluginSta = (0, _pluginFactory.getPluginState)(state),
|
|
383
|
+
_getDragDropPluginSta2 = _getDragDropPluginSta.isDragMenuOpen,
|
|
384
|
+
isDragMenuOpen = _getDragDropPluginSta2 === void 0 ? false : _getDragDropPluginSta2,
|
|
385
|
+
_getDragDropPluginSta3 = _getDragDropPluginSta.isDragging,
|
|
386
|
+
isDragging = _getDragDropPluginSta3 === void 0 ? false : _getDragDropPluginSta3;
|
|
387
|
+
isDragHandleMenuOpened = isDragMenuOpen;
|
|
388
|
+
isTableRowOrColumnDragged = isDragging;
|
|
389
|
+
}
|
|
390
|
+
var isTableOrColumnResizing = !!(resizeState !== null && resizeState !== void 0 && resizeState.dragging || tableWidthState !== null && tableWidthState !== void 0 && tableWidthState.resizing);
|
|
391
|
+
var isTableMenuOpened = pluginState.isContextualMenuOpen || isDragHandleMenuOpened;
|
|
392
|
+
var isViewMode = (api === null || api === void 0 || (_api$editorViewMode = api.editorViewMode) === null || _api$editorViewMode === void 0 || (_api$editorViewMode = _api$editorViewMode.sharedState.currentState()) === null || _api$editorViewMode === void 0 ? void 0 : _api$editorViewMode.mode) === 'view';
|
|
393
|
+
var shouldSuppressAllToolbars = !pluginState.editorHasFocus && !isViewMode || isTableMenuOpened || isTableOrColumnResizing || isTableRowOrColumnDragged;
|
|
394
|
+
if (shouldSuppressAllToolbars) {
|
|
395
|
+
return {
|
|
396
|
+
title: toolbarTitle,
|
|
397
|
+
items: [],
|
|
398
|
+
nodeType: nodeType,
|
|
399
|
+
__suppressAllToolbars: true
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
}
|
|
374
403
|
|
|
375
404
|
// We don't want to show floating toolbar while resizing the table
|
|
376
405
|
var isWidthResizing = tableWidthState === null || tableWidthState === void 0 ? void 0 : tableWidthState.resizing;
|
|
377
406
|
if (tableObject && pluginState.editorHasFocus && !isWidthResizing) {
|
|
378
|
-
var nodeType = state.schema.nodes.table;
|
|
379
407
|
var isNested = pluginState.tablePos && (0, _nodes.isTableNested)(state, pluginState.tablePos);
|
|
380
408
|
var isTableScalingWithFixedColumnWidthsOptionShown = isTableScalingEnabled && isTableFixedColumnWidthsOptionEnabled && !isNested;
|
|
381
409
|
var areTableColumWidthsFixed = tableObject.node.attrs.displayMode === 'fixed';
|
|
@@ -463,7 +491,7 @@ var getToolbarConfig = exports.getToolbarConfig = function getToolbarConfig(getE
|
|
|
463
491
|
} : undefined;
|
|
464
492
|
};
|
|
465
493
|
return {
|
|
466
|
-
title:
|
|
494
|
+
title: toolbarTitle,
|
|
467
495
|
getDomRef: getDomRef,
|
|
468
496
|
nodeType: nodeType,
|
|
469
497
|
offset: [0, 18],
|
|
@@ -581,7 +609,7 @@ var getColumnSettingItems = function getColumnSettingItems(editorState, editorVi
|
|
|
581
609
|
var isTableScalingEnabled = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : false;
|
|
582
610
|
var isTableFixedColumnWidthsOptionEnabled = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : false;
|
|
583
611
|
var isCommentEditor = arguments.length > 8 && arguments[8] !== undefined ? arguments[8] : false;
|
|
584
|
-
var pluginState = (0,
|
|
612
|
+
var pluginState = (0, _pluginFactory2.getPluginState)(editorState);
|
|
585
613
|
var selectionOrTableRect = getClosestSelectionOrTableRect(editorState);
|
|
586
614
|
if (!selectionOrTableRect || !editorView) {
|
|
587
615
|
return [];
|
|
@@ -617,7 +645,7 @@ var getColumnSettingItems = function getColumnSettingItems(editorState, editorVi
|
|
|
617
645
|
var getColorPicker = function getColorPicker(state, menu, _ref5, editorAnalyticsAPI, getEditorView) {
|
|
618
646
|
var _node$attrs;
|
|
619
647
|
var formatMessage = _ref5.formatMessage;
|
|
620
|
-
var _getPluginState2 = (0,
|
|
648
|
+
var _getPluginState2 = (0, _pluginFactory2.getPluginState)(state),
|
|
621
649
|
targetCellPosition = _getPluginState2.targetCellPosition,
|
|
622
650
|
pluginConfig = _getPluginState2.pluginConfig;
|
|
623
651
|
if (!pluginConfig.allowBackgroundColor) {
|
|
@@ -17,6 +17,7 @@ import { pluginKey as tableWidthPluginKey } from '../pm-plugins/table-width';
|
|
|
17
17
|
import { isTableNested } from '../pm-plugins/utils/nodes';
|
|
18
18
|
import TableComponent from './TableComponent';
|
|
19
19
|
import { TableComponentWithSharedState } from './TableComponentWithSharedState';
|
|
20
|
+
import { tableNodeSpecWithFixedToDOM } from './toDOM';
|
|
20
21
|
const tableAttributes = node => {
|
|
21
22
|
return {
|
|
22
23
|
'data-number-column': node.attrs.isNumberColumnEnabled,
|
|
@@ -48,6 +49,8 @@ const handleInlineTableWidth = (table, width) => {
|
|
|
48
49
|
}
|
|
49
50
|
table.style.setProperty('width', `${width}px`);
|
|
50
51
|
};
|
|
52
|
+
|
|
53
|
+
// Leave as a fallback incase the table's NodeSpec.toDOM is not defined.
|
|
51
54
|
const toDOM = (node, props) => {
|
|
52
55
|
let colgroup = '';
|
|
53
56
|
if (props.allowColumnResizing) {
|
|
@@ -66,12 +69,31 @@ export default class TableView extends ReactNodeView {
|
|
|
66
69
|
this.eventDispatcher = props.eventDispatcher;
|
|
67
70
|
this.options = props.options;
|
|
68
71
|
this.getEditorFeatureFlags = props.getEditorFeatureFlags;
|
|
72
|
+
if (fg('platform_editor_table_initial_load_fix')) {
|
|
73
|
+
this.handleRef = node => this._handleTableRef(node);
|
|
74
|
+
}
|
|
69
75
|
}
|
|
70
76
|
getContentDOM() {
|
|
71
|
-
|
|
77
|
+
let tableDOMStructure;
|
|
78
|
+
if (fg('platform_editor_table_initial_load_fix')) {
|
|
79
|
+
tableDOMStructure = tableNodeSpecWithFixedToDOM({
|
|
80
|
+
allowColumnResizing: !!this.reactComponentProps.allowColumnResizing,
|
|
81
|
+
tableResizingEnabled: !!this.reactComponentProps.allowTableResizing,
|
|
82
|
+
getEditorContainerWidth: this.reactComponentProps.getEditorContainerWidth
|
|
83
|
+
}).toDOM(this.node);
|
|
84
|
+
} else {
|
|
85
|
+
tableDOMStructure = toDOM(this.node, this.reactComponentProps);
|
|
86
|
+
}
|
|
87
|
+
const rendered = DOMSerializer.renderSpec(document, tableDOMStructure);
|
|
72
88
|
if (rendered.dom) {
|
|
73
89
|
var _this$options, _this$options2, _this$getEditorFeatur;
|
|
74
|
-
|
|
90
|
+
if (fg('platform_editor_table_initial_load_fix')) {
|
|
91
|
+
const tableElement = rendered.dom.querySelector('table');
|
|
92
|
+
this.table = tableElement ? tableElement : rendered.dom;
|
|
93
|
+
this.renderedDOM = rendered.dom;
|
|
94
|
+
} else {
|
|
95
|
+
this.table = rendered.dom;
|
|
96
|
+
}
|
|
75
97
|
if (!((_this$options = this.options) !== null && _this$options !== void 0 && _this$options.isTableScalingEnabled) || (_this$options2 = this.options) !== null && _this$options2 !== void 0 && _this$options2.isTableScalingEnabled && (_this$getEditorFeatur = this.getEditorFeatureFlags) !== null && _this$getEditorFeatur !== void 0 && _this$getEditorFeatur.call(this).tableWithFixedColumnWidthsOption && this.node.attrs.displayMode === 'fixed') {
|
|
76
98
|
const tableInlineWidth = getInlineWidth(this.node, this.reactComponentProps.options, this.reactComponentProps.view.state, this.reactComponentProps.getPos(), this.reactComponentProps.allowTableResizing);
|
|
77
99
|
if (tableInlineWidth) {
|
|
@@ -81,6 +103,72 @@ export default class TableView extends ReactNodeView {
|
|
|
81
103
|
}
|
|
82
104
|
return rendered;
|
|
83
105
|
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Handles moving the table from ProseMirror's DOM structure into a React-rendered table node.
|
|
109
|
+
* Temporarily disables mutation observers (except for selection changes) during the move,
|
|
110
|
+
* preserves selection state, and restores it afterwards if mutations occurred and cursor
|
|
111
|
+
* wasn't at start of node. This prevents duplicate tables and maintains editor state during
|
|
112
|
+
* the DOM manipulation.
|
|
113
|
+
*/
|
|
114
|
+
_handleTableRef(node) {
|
|
115
|
+
let oldIgnoreMutation;
|
|
116
|
+
let selectionBookmark;
|
|
117
|
+
let parentOffset = 0;
|
|
118
|
+
let mutationsIgnored = false;
|
|
119
|
+
|
|
120
|
+
// Only proceed if we have both a node and table, and the table isn't already inside the node
|
|
121
|
+
if (node && this.table && !node.contains(this.table)) {
|
|
122
|
+
var _this$view$state$sele;
|
|
123
|
+
// Store the current ignoreMutation handler so we can restore it later
|
|
124
|
+
oldIgnoreMutation = this.ignoreMutation;
|
|
125
|
+
|
|
126
|
+
// Set up a temporary mutation handler that:
|
|
127
|
+
// - Ignores all DOM mutations except selection changes
|
|
128
|
+
// - Tracks when mutations have been ignored via mutationsIgnored flag
|
|
129
|
+
this.ignoreMutation = m => {
|
|
130
|
+
const isSelectionMutation = m.target instanceof Selection;
|
|
131
|
+
if (!isSelectionMutation) {
|
|
132
|
+
mutationsIgnored = true;
|
|
133
|
+
}
|
|
134
|
+
return !isSelectionMutation;
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
// Store the current selection state if there is a visible selection
|
|
138
|
+
// This lets us restore it after DOM changes
|
|
139
|
+
if (this.view.state.selection.visible) {
|
|
140
|
+
selectionBookmark = this.view.state.selection.getBookmark();
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Store the current cursor position within the parent node
|
|
144
|
+
// Used to determine if we need to restore selection later
|
|
145
|
+
if (((_this$view$state$sele = this.view.state.selection) === null || _this$view$state$sele === void 0 ? void 0 : _this$view$state$sele.ranges.length) > 0) {
|
|
146
|
+
var _this$view$state$sele2, _this$view$state$sele3, _this$view$state$sele4;
|
|
147
|
+
parentOffset = (_this$view$state$sele2 = (_this$view$state$sele3 = this.view.state.selection) === null || _this$view$state$sele3 === void 0 ? void 0 : (_this$view$state$sele4 = _this$view$state$sele3.ranges[0].$from) === null || _this$view$state$sele4 === void 0 ? void 0 : _this$view$state$sele4.parentOffset) !== null && _this$view$state$sele2 !== void 0 ? _this$view$state$sele2 : 0;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Remove the ProseMirror table DOM structure to avoid duplication, as it's replaced with the React table node.
|
|
151
|
+
if (this.renderedDOM) {
|
|
152
|
+
this.dom.removeChild(this.renderedDOM);
|
|
153
|
+
}
|
|
154
|
+
// Move the table from the ProseMirror table structure into the React rendered table node.
|
|
155
|
+
node.appendChild(this.table);
|
|
156
|
+
|
|
157
|
+
// After the next frame:
|
|
158
|
+
requestAnimationFrame(() => {
|
|
159
|
+
// Restore the original mutation handler
|
|
160
|
+
this.ignoreMutation = oldIgnoreMutation;
|
|
161
|
+
|
|
162
|
+
// Restore the selection only if:
|
|
163
|
+
// - We have a selection bookmark
|
|
164
|
+
// - Mutations were ignored during the table move
|
|
165
|
+
// - The cursor wasn't at the start of the node
|
|
166
|
+
if (selectionBookmark && mutationsIgnored && parentOffset > 0) {
|
|
167
|
+
this.view.dispatch(this.view.state.tr.setSelection(selectionBookmark.resolve(this.view.state.tr.doc)));
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
}
|
|
84
172
|
setDomAttrs(node) {
|
|
85
173
|
var _this$options3, _this$options4, _this$getEditorFeatur2;
|
|
86
174
|
if (!this.table) {
|
|
@@ -122,7 +210,6 @@ export default class TableView extends ReactNodeView {
|
|
|
122
210
|
dispatchAnalyticsEvent: props.dispatchAnalyticsEvent
|
|
123
211
|
});
|
|
124
212
|
}
|
|
125
|
-
|
|
126
213
|
// Please, do not copy or use this kind of code below
|
|
127
214
|
// @ts-ignore
|
|
128
215
|
const fakePluginKey = {
|
|
@@ -605,7 +605,7 @@ const tablesPlugin = ({
|
|
|
605
605
|
return tr;
|
|
606
606
|
}
|
|
607
607
|
}],
|
|
608
|
-
floatingToolbar: getToolbarConfig(defaultGetEditorContainerWidth, api, editorAnalyticsAPI, (
|
|
608
|
+
floatingToolbar: getToolbarConfig(defaultGetEditorContainerWidth, api, editorAnalyticsAPI, () => editorViewRef.current, options, isTableFixedColumnWidthsOptionEnabled, shouldUseIncreasedScalingPercent)(pluginConfig(options === null || options === void 0 ? void 0 : options.tableOptions))
|
|
609
609
|
},
|
|
610
610
|
usePluginHook({
|
|
611
611
|
editorView
|
|
@@ -32,6 +32,7 @@ import { fg } from '@atlaskit/platform-feature-flags';
|
|
|
32
32
|
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
|
|
33
33
|
import { clearHoverSelection, hoverColumns, hoverMergedCells, hoverRows, hoverTable, removeDescendantNodes } from '../pm-plugins/commands';
|
|
34
34
|
import { deleteColumnsWithAnalytics, deleteRowsWithAnalytics, deleteTableWithAnalytics, distributeColumnsWidthsWithAnalytics, emptyMultipleCellsWithAnalytics, insertColumnWithAnalytics, insertRowWithAnalytics, mergeCellsWithAnalytics, setColorWithAnalytics, setTableAlignmentWithAnalytics, sortColumnWithAnalytics, splitCellWithAnalytics, toggleFixedColumnWidthsOptionAnalytics, toggleHeaderColumnWithAnalytics, toggleHeaderRowWithAnalytics, toggleNumberColumnWithAnalytics, wrapTableInExpandWithAnalytics } from '../pm-plugins/commands/commands-with-analytics';
|
|
35
|
+
import { getPluginState as getDragDropPluginState } from '../pm-plugins/drag-and-drop/plugin-factory';
|
|
35
36
|
import { getPluginState } from '../pm-plugins/plugin-factory';
|
|
36
37
|
import { pluginKey as tableResizingPluginKey } from '../pm-plugins/table-resizing/plugin-key';
|
|
37
38
|
import { getStaticTableScalingPercent } from '../pm-plugins/table-resizing/utils/misc';
|
|
@@ -344,17 +345,43 @@ const getClosestSelectionOrTableRect = state => {
|
|
|
344
345
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
345
346
|
return isSelectionType(selection, 'cell') ? getSelectionRect(selection) : tableRect;
|
|
346
347
|
};
|
|
347
|
-
export const getToolbarConfig = (getEditorContainerWidth, api, editorAnalyticsAPI,
|
|
348
|
+
export const getToolbarConfig = (getEditorContainerWidth, api, editorAnalyticsAPI, getEditorView, options, isTableFixedColumnWidthsOptionEnabled = false, shouldUseIncreasedScalingPercent = false) => config => (state, intl) => {
|
|
348
349
|
const tableObject = findTable(state.selection);
|
|
349
350
|
const pluginState = getPluginState(state);
|
|
350
351
|
const resizeState = tableResizingPluginKey.getState(state);
|
|
351
352
|
const tableWidthState = tableWidthPluginKey.getState(state);
|
|
352
353
|
const isTableScalingEnabled = (options === null || options === void 0 ? void 0 : options.isTableScalingEnabled) || false;
|
|
354
|
+
const nodeType = state.schema.nodes.table;
|
|
355
|
+
const toolbarTitle = 'Table floating controls';
|
|
356
|
+
if (editorExperiment('platform_editor_controls', 'variant1') && fg('platform_editor_controls_patch_4')) {
|
|
357
|
+
var _api$editorViewMode, _api$editorViewMode$s;
|
|
358
|
+
let isDragHandleMenuOpened = false;
|
|
359
|
+
let isTableRowOrColumnDragged = false;
|
|
360
|
+
if (options !== null && options !== void 0 && options.dragAndDropEnabled) {
|
|
361
|
+
const {
|
|
362
|
+
isDragMenuOpen = false,
|
|
363
|
+
isDragging = false
|
|
364
|
+
} = getDragDropPluginState(state);
|
|
365
|
+
isDragHandleMenuOpened = isDragMenuOpen;
|
|
366
|
+
isTableRowOrColumnDragged = isDragging;
|
|
367
|
+
}
|
|
368
|
+
const isTableOrColumnResizing = !!(resizeState !== null && resizeState !== void 0 && resizeState.dragging || tableWidthState !== null && tableWidthState !== void 0 && tableWidthState.resizing);
|
|
369
|
+
const isTableMenuOpened = pluginState.isContextualMenuOpen || isDragHandleMenuOpened;
|
|
370
|
+
const isViewMode = (api === null || api === void 0 ? void 0 : (_api$editorViewMode = api.editorViewMode) === null || _api$editorViewMode === void 0 ? void 0 : (_api$editorViewMode$s = _api$editorViewMode.sharedState.currentState()) === null || _api$editorViewMode$s === void 0 ? void 0 : _api$editorViewMode$s.mode) === 'view';
|
|
371
|
+
const shouldSuppressAllToolbars = !pluginState.editorHasFocus && !isViewMode || isTableMenuOpened || isTableOrColumnResizing || isTableRowOrColumnDragged;
|
|
372
|
+
if (shouldSuppressAllToolbars) {
|
|
373
|
+
return {
|
|
374
|
+
title: toolbarTitle,
|
|
375
|
+
items: [],
|
|
376
|
+
nodeType,
|
|
377
|
+
__suppressAllToolbars: true
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
}
|
|
353
381
|
|
|
354
382
|
// We don't want to show floating toolbar while resizing the table
|
|
355
383
|
const isWidthResizing = tableWidthState === null || tableWidthState === void 0 ? void 0 : tableWidthState.resizing;
|
|
356
384
|
if (tableObject && pluginState.editorHasFocus && !isWidthResizing) {
|
|
357
|
-
const nodeType = state.schema.nodes.table;
|
|
358
385
|
const isNested = pluginState.tablePos && isTableNested(state, pluginState.tablePos);
|
|
359
386
|
const isTableScalingWithFixedColumnWidthsOptionShown = isTableScalingEnabled && isTableFixedColumnWidthsOptionEnabled && !isNested;
|
|
360
387
|
const areTableColumWidthsFixed = tableObject.node.attrs.displayMode === 'fixed';
|
|
@@ -433,7 +460,7 @@ export const getToolbarConfig = (getEditorContainerWidth, api, editorAnalyticsAP
|
|
|
433
460
|
onBlur: clearHoverSelection()
|
|
434
461
|
} : undefined;
|
|
435
462
|
return {
|
|
436
|
-
title:
|
|
463
|
+
title: toolbarTitle,
|
|
437
464
|
getDomRef,
|
|
438
465
|
nodeType,
|
|
439
466
|
offset: [0, 18],
|
|
@@ -28,6 +28,7 @@ import { pluginKey as tableWidthPluginKey } from '../pm-plugins/table-width';
|
|
|
28
28
|
import { isTableNested } from '../pm-plugins/utils/nodes';
|
|
29
29
|
import TableComponent from './TableComponent';
|
|
30
30
|
import { TableComponentWithSharedState } from './TableComponentWithSharedState';
|
|
31
|
+
import { tableNodeSpecWithFixedToDOM } from './toDOM';
|
|
31
32
|
var tableAttributes = function tableAttributes(node) {
|
|
32
33
|
return {
|
|
33
34
|
'data-number-column': node.attrs.isNumberColumnEnabled,
|
|
@@ -59,6 +60,8 @@ var handleInlineTableWidth = function handleInlineTableWidth(table, width) {
|
|
|
59
60
|
}
|
|
60
61
|
table.style.setProperty('width', "".concat(width, "px"));
|
|
61
62
|
};
|
|
63
|
+
|
|
64
|
+
// Leave as a fallback incase the table's NodeSpec.toDOM is not defined.
|
|
62
65
|
var toDOM = function toDOM(node, props) {
|
|
63
66
|
var colgroup = '';
|
|
64
67
|
if (props.allowColumnResizing) {
|
|
@@ -79,16 +82,37 @@ var TableView = /*#__PURE__*/function (_ReactNodeView) {
|
|
|
79
82
|
_this.eventDispatcher = props.eventDispatcher;
|
|
80
83
|
_this.options = props.options;
|
|
81
84
|
_this.getEditorFeatureFlags = props.getEditorFeatureFlags;
|
|
85
|
+
if (fg('platform_editor_table_initial_load_fix')) {
|
|
86
|
+
_this.handleRef = function (node) {
|
|
87
|
+
return _this._handleTableRef(node);
|
|
88
|
+
};
|
|
89
|
+
}
|
|
82
90
|
return _this;
|
|
83
91
|
}
|
|
84
92
|
_inherits(TableView, _ReactNodeView);
|
|
85
93
|
return _createClass(TableView, [{
|
|
86
94
|
key: "getContentDOM",
|
|
87
95
|
value: function getContentDOM() {
|
|
88
|
-
var
|
|
96
|
+
var tableDOMStructure;
|
|
97
|
+
if (fg('platform_editor_table_initial_load_fix')) {
|
|
98
|
+
tableDOMStructure = tableNodeSpecWithFixedToDOM({
|
|
99
|
+
allowColumnResizing: !!this.reactComponentProps.allowColumnResizing,
|
|
100
|
+
tableResizingEnabled: !!this.reactComponentProps.allowTableResizing,
|
|
101
|
+
getEditorContainerWidth: this.reactComponentProps.getEditorContainerWidth
|
|
102
|
+
}).toDOM(this.node);
|
|
103
|
+
} else {
|
|
104
|
+
tableDOMStructure = toDOM(this.node, this.reactComponentProps);
|
|
105
|
+
}
|
|
106
|
+
var rendered = DOMSerializer.renderSpec(document, tableDOMStructure);
|
|
89
107
|
if (rendered.dom) {
|
|
90
108
|
var _this$options, _this$options2, _this$getEditorFeatur;
|
|
91
|
-
|
|
109
|
+
if (fg('platform_editor_table_initial_load_fix')) {
|
|
110
|
+
var tableElement = rendered.dom.querySelector('table');
|
|
111
|
+
this.table = tableElement ? tableElement : rendered.dom;
|
|
112
|
+
this.renderedDOM = rendered.dom;
|
|
113
|
+
} else {
|
|
114
|
+
this.table = rendered.dom;
|
|
115
|
+
}
|
|
92
116
|
if (!((_this$options = this.options) !== null && _this$options !== void 0 && _this$options.isTableScalingEnabled) || (_this$options2 = this.options) !== null && _this$options2 !== void 0 && _this$options2.isTableScalingEnabled && (_this$getEditorFeatur = this.getEditorFeatureFlags) !== null && _this$getEditorFeatur !== void 0 && _this$getEditorFeatur.call(this).tableWithFixedColumnWidthsOption && this.node.attrs.displayMode === 'fixed') {
|
|
93
117
|
var tableInlineWidth = getInlineWidth(this.node, this.reactComponentProps.options, this.reactComponentProps.view.state, this.reactComponentProps.getPos(), this.reactComponentProps.allowTableResizing);
|
|
94
118
|
if (tableInlineWidth) {
|
|
@@ -98,10 +122,79 @@ var TableView = /*#__PURE__*/function (_ReactNodeView) {
|
|
|
98
122
|
}
|
|
99
123
|
return rendered;
|
|
100
124
|
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Handles moving the table from ProseMirror's DOM structure into a React-rendered table node.
|
|
128
|
+
* Temporarily disables mutation observers (except for selection changes) during the move,
|
|
129
|
+
* preserves selection state, and restores it afterwards if mutations occurred and cursor
|
|
130
|
+
* wasn't at start of node. This prevents duplicate tables and maintains editor state during
|
|
131
|
+
* the DOM manipulation.
|
|
132
|
+
*/
|
|
133
|
+
}, {
|
|
134
|
+
key: "_handleTableRef",
|
|
135
|
+
value: function _handleTableRef(node) {
|
|
136
|
+
var _this2 = this;
|
|
137
|
+
var oldIgnoreMutation;
|
|
138
|
+
var selectionBookmark;
|
|
139
|
+
var parentOffset = 0;
|
|
140
|
+
var mutationsIgnored = false;
|
|
141
|
+
|
|
142
|
+
// Only proceed if we have both a node and table, and the table isn't already inside the node
|
|
143
|
+
if (node && this.table && !node.contains(this.table)) {
|
|
144
|
+
var _this$view$state$sele;
|
|
145
|
+
// Store the current ignoreMutation handler so we can restore it later
|
|
146
|
+
oldIgnoreMutation = this.ignoreMutation;
|
|
147
|
+
|
|
148
|
+
// Set up a temporary mutation handler that:
|
|
149
|
+
// - Ignores all DOM mutations except selection changes
|
|
150
|
+
// - Tracks when mutations have been ignored via mutationsIgnored flag
|
|
151
|
+
this.ignoreMutation = function (m) {
|
|
152
|
+
var isSelectionMutation = m.target instanceof Selection;
|
|
153
|
+
if (!isSelectionMutation) {
|
|
154
|
+
mutationsIgnored = true;
|
|
155
|
+
}
|
|
156
|
+
return !isSelectionMutation;
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
// Store the current selection state if there is a visible selection
|
|
160
|
+
// This lets us restore it after DOM changes
|
|
161
|
+
if (this.view.state.selection.visible) {
|
|
162
|
+
selectionBookmark = this.view.state.selection.getBookmark();
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Store the current cursor position within the parent node
|
|
166
|
+
// Used to determine if we need to restore selection later
|
|
167
|
+
if (((_this$view$state$sele = this.view.state.selection) === null || _this$view$state$sele === void 0 ? void 0 : _this$view$state$sele.ranges.length) > 0) {
|
|
168
|
+
var _this$view$state$sele2, _this$view$state$sele3;
|
|
169
|
+
parentOffset = (_this$view$state$sele2 = (_this$view$state$sele3 = this.view.state.selection) === null || _this$view$state$sele3 === void 0 || (_this$view$state$sele3 = _this$view$state$sele3.ranges[0].$from) === null || _this$view$state$sele3 === void 0 ? void 0 : _this$view$state$sele3.parentOffset) !== null && _this$view$state$sele2 !== void 0 ? _this$view$state$sele2 : 0;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Remove the ProseMirror table DOM structure to avoid duplication, as it's replaced with the React table node.
|
|
173
|
+
if (this.renderedDOM) {
|
|
174
|
+
this.dom.removeChild(this.renderedDOM);
|
|
175
|
+
}
|
|
176
|
+
// Move the table from the ProseMirror table structure into the React rendered table node.
|
|
177
|
+
node.appendChild(this.table);
|
|
178
|
+
|
|
179
|
+
// After the next frame:
|
|
180
|
+
requestAnimationFrame(function () {
|
|
181
|
+
// Restore the original mutation handler
|
|
182
|
+
_this2.ignoreMutation = oldIgnoreMutation;
|
|
183
|
+
|
|
184
|
+
// Restore the selection only if:
|
|
185
|
+
// - We have a selection bookmark
|
|
186
|
+
// - Mutations were ignored during the table move
|
|
187
|
+
// - The cursor wasn't at the start of the node
|
|
188
|
+
if (selectionBookmark && mutationsIgnored && parentOffset > 0) {
|
|
189
|
+
_this2.view.dispatch(_this2.view.state.tr.setSelection(selectionBookmark.resolve(_this2.view.state.tr.doc)));
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
}
|
|
101
194
|
}, {
|
|
102
195
|
key: "setDomAttrs",
|
|
103
196
|
value: function setDomAttrs(node) {
|
|
104
|
-
var
|
|
197
|
+
var _this3 = this,
|
|
105
198
|
_this$options3,
|
|
106
199
|
_this$options4,
|
|
107
200
|
_this$getEditorFeatur2;
|
|
@@ -112,7 +205,7 @@ var TableView = /*#__PURE__*/function (_ReactNodeView) {
|
|
|
112
205
|
Object.keys(attrs).forEach(function (attr) {
|
|
113
206
|
// Ignored via go/ees005
|
|
114
207
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
115
|
-
|
|
208
|
+
_this3.table.setAttribute(attr, attrs[attr]);
|
|
116
209
|
});
|
|
117
210
|
|
|
118
211
|
// Preserve Table Width cannot have inline width set on the table
|
|
@@ -129,7 +222,7 @@ var TableView = /*#__PURE__*/function (_ReactNodeView) {
|
|
|
129
222
|
}, {
|
|
130
223
|
key: "render",
|
|
131
224
|
value: function render(props, forwardRef) {
|
|
132
|
-
var
|
|
225
|
+
var _this4 = this;
|
|
133
226
|
if (fg('platform_editor_table_use_shared_state_hook_fg')) {
|
|
134
227
|
return /*#__PURE__*/React.createElement(TableComponentWithSharedState, {
|
|
135
228
|
forwardRef: forwardRef,
|
|
@@ -147,7 +240,6 @@ var TableView = /*#__PURE__*/function (_ReactNodeView) {
|
|
|
147
240
|
dispatchAnalyticsEvent: props.dispatchAnalyticsEvent
|
|
148
241
|
});
|
|
149
242
|
}
|
|
150
|
-
|
|
151
243
|
// Please, do not copy or use this kind of code below
|
|
152
244
|
// @ts-ignore
|
|
153
245
|
var fakePluginKey = {
|
|
@@ -239,7 +331,7 @@ var TableView = /*#__PURE__*/function (_ReactNodeView) {
|
|
|
239
331
|
,
|
|
240
332
|
ordering: pluginState.ordering,
|
|
241
333
|
isResizing: isResizing,
|
|
242
|
-
getNode:
|
|
334
|
+
getNode: _this4.getNode
|
|
243
335
|
// Ignored via go/ees005
|
|
244
336
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
245
337
|
,
|
package/dist/esm/tablePlugin.js
CHANGED
|
@@ -601,7 +601,7 @@ var tablesPlugin = function tablesPlugin(_ref) {
|
|
|
601
601
|
}
|
|
602
602
|
}];
|
|
603
603
|
},
|
|
604
|
-
floatingToolbar: getToolbarConfig(defaultGetEditorContainerWidth, api, editorAnalyticsAPI,
|
|
604
|
+
floatingToolbar: getToolbarConfig(defaultGetEditorContainerWidth, api, editorAnalyticsAPI, function () {
|
|
605
605
|
return editorViewRef.current;
|
|
606
606
|
}, options, isTableFixedColumnWidthsOptionEnabled, shouldUseIncreasedScalingPercent)(pluginConfig(options === null || options === void 0 ? void 0 : options.tableOptions))
|
|
607
607
|
},
|
package/dist/esm/ui/toolbar.js
CHANGED
|
@@ -36,6 +36,7 @@ import { fg } from '@atlaskit/platform-feature-flags';
|
|
|
36
36
|
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
|
|
37
37
|
import { clearHoverSelection, hoverColumns, hoverMergedCells, hoverRows, hoverTable, removeDescendantNodes } from '../pm-plugins/commands';
|
|
38
38
|
import { deleteColumnsWithAnalytics, deleteRowsWithAnalytics, deleteTableWithAnalytics, distributeColumnsWidthsWithAnalytics, emptyMultipleCellsWithAnalytics, insertColumnWithAnalytics, insertRowWithAnalytics, mergeCellsWithAnalytics, setColorWithAnalytics, setTableAlignmentWithAnalytics, sortColumnWithAnalytics, splitCellWithAnalytics, toggleFixedColumnWidthsOptionAnalytics, toggleHeaderColumnWithAnalytics, toggleHeaderRowWithAnalytics, toggleNumberColumnWithAnalytics, wrapTableInExpandWithAnalytics } from '../pm-plugins/commands/commands-with-analytics';
|
|
39
|
+
import { getPluginState as getDragDropPluginState } from '../pm-plugins/drag-and-drop/plugin-factory';
|
|
39
40
|
import { getPluginState } from '../pm-plugins/plugin-factory';
|
|
40
41
|
import { pluginKey as tableResizingPluginKey } from '../pm-plugins/table-resizing/plugin-key';
|
|
41
42
|
import { getStaticTableScalingPercent } from '../pm-plugins/table-resizing/utils/misc';
|
|
@@ -353,9 +354,9 @@ var getClosestSelectionOrTableRect = function getClosestSelectionOrTableRect(sta
|
|
|
353
354
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
354
355
|
return isSelectionType(selection, 'cell') ? getSelectionRect(selection) : tableRect;
|
|
355
356
|
};
|
|
356
|
-
export var getToolbarConfig = function getToolbarConfig(getEditorContainerWidth, api, editorAnalyticsAPI,
|
|
357
|
-
var isTableFixedColumnWidthsOptionEnabled = arguments.length >
|
|
358
|
-
var shouldUseIncreasedScalingPercent = arguments.length >
|
|
357
|
+
export var getToolbarConfig = function getToolbarConfig(getEditorContainerWidth, api, editorAnalyticsAPI, getEditorView, options) {
|
|
358
|
+
var isTableFixedColumnWidthsOptionEnabled = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : false;
|
|
359
|
+
var shouldUseIncreasedScalingPercent = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : false;
|
|
359
360
|
return function (config) {
|
|
360
361
|
return function (state, intl) {
|
|
361
362
|
var tableObject = findTable(state.selection);
|
|
@@ -363,11 +364,38 @@ export var getToolbarConfig = function getToolbarConfig(getEditorContainerWidth,
|
|
|
363
364
|
var resizeState = tableResizingPluginKey.getState(state);
|
|
364
365
|
var tableWidthState = tableWidthPluginKey.getState(state);
|
|
365
366
|
var isTableScalingEnabled = (options === null || options === void 0 ? void 0 : options.isTableScalingEnabled) || false;
|
|
367
|
+
var nodeType = state.schema.nodes.table;
|
|
368
|
+
var toolbarTitle = 'Table floating controls';
|
|
369
|
+
if (editorExperiment('platform_editor_controls', 'variant1') && fg('platform_editor_controls_patch_4')) {
|
|
370
|
+
var _api$editorViewMode;
|
|
371
|
+
var isDragHandleMenuOpened = false;
|
|
372
|
+
var isTableRowOrColumnDragged = false;
|
|
373
|
+
if (options !== null && options !== void 0 && options.dragAndDropEnabled) {
|
|
374
|
+
var _getDragDropPluginSta = getDragDropPluginState(state),
|
|
375
|
+
_getDragDropPluginSta2 = _getDragDropPluginSta.isDragMenuOpen,
|
|
376
|
+
isDragMenuOpen = _getDragDropPluginSta2 === void 0 ? false : _getDragDropPluginSta2,
|
|
377
|
+
_getDragDropPluginSta3 = _getDragDropPluginSta.isDragging,
|
|
378
|
+
isDragging = _getDragDropPluginSta3 === void 0 ? false : _getDragDropPluginSta3;
|
|
379
|
+
isDragHandleMenuOpened = isDragMenuOpen;
|
|
380
|
+
isTableRowOrColumnDragged = isDragging;
|
|
381
|
+
}
|
|
382
|
+
var isTableOrColumnResizing = !!(resizeState !== null && resizeState !== void 0 && resizeState.dragging || tableWidthState !== null && tableWidthState !== void 0 && tableWidthState.resizing);
|
|
383
|
+
var isTableMenuOpened = pluginState.isContextualMenuOpen || isDragHandleMenuOpened;
|
|
384
|
+
var isViewMode = (api === null || api === void 0 || (_api$editorViewMode = api.editorViewMode) === null || _api$editorViewMode === void 0 || (_api$editorViewMode = _api$editorViewMode.sharedState.currentState()) === null || _api$editorViewMode === void 0 ? void 0 : _api$editorViewMode.mode) === 'view';
|
|
385
|
+
var shouldSuppressAllToolbars = !pluginState.editorHasFocus && !isViewMode || isTableMenuOpened || isTableOrColumnResizing || isTableRowOrColumnDragged;
|
|
386
|
+
if (shouldSuppressAllToolbars) {
|
|
387
|
+
return {
|
|
388
|
+
title: toolbarTitle,
|
|
389
|
+
items: [],
|
|
390
|
+
nodeType: nodeType,
|
|
391
|
+
__suppressAllToolbars: true
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
}
|
|
366
395
|
|
|
367
396
|
// We don't want to show floating toolbar while resizing the table
|
|
368
397
|
var isWidthResizing = tableWidthState === null || tableWidthState === void 0 ? void 0 : tableWidthState.resizing;
|
|
369
398
|
if (tableObject && pluginState.editorHasFocus && !isWidthResizing) {
|
|
370
|
-
var nodeType = state.schema.nodes.table;
|
|
371
399
|
var isNested = pluginState.tablePos && isTableNested(state, pluginState.tablePos);
|
|
372
400
|
var isTableScalingWithFixedColumnWidthsOptionShown = isTableScalingEnabled && isTableFixedColumnWidthsOptionEnabled && !isNested;
|
|
373
401
|
var areTableColumWidthsFixed = tableObject.node.attrs.displayMode === 'fixed';
|
|
@@ -455,7 +483,7 @@ export var getToolbarConfig = function getToolbarConfig(getEditorContainerWidth,
|
|
|
455
483
|
} : undefined;
|
|
456
484
|
};
|
|
457
485
|
return {
|
|
458
|
-
title:
|
|
486
|
+
title: toolbarTitle,
|
|
459
487
|
getDomRef: getDomRef,
|
|
460
488
|
nodeType: nodeType,
|
|
461
489
|
offset: [0, 18],
|
|
@@ -11,6 +11,7 @@ import type { Props } from './types';
|
|
|
11
11
|
type ForwardRef = (node: HTMLElement | null) => void;
|
|
12
12
|
export default class TableView extends ReactNodeView<Props> {
|
|
13
13
|
private table;
|
|
14
|
+
private renderedDOM?;
|
|
14
15
|
private resizeObserver?;
|
|
15
16
|
eventDispatcher?: EventDispatcher;
|
|
16
17
|
getPos: getPosHandlerNode;
|
|
@@ -21,6 +22,14 @@ export default class TableView extends ReactNodeView<Props> {
|
|
|
21
22
|
dom: HTMLElement;
|
|
22
23
|
contentDOM?: HTMLElement | undefined;
|
|
23
24
|
};
|
|
25
|
+
/**
|
|
26
|
+
* Handles moving the table from ProseMirror's DOM structure into a React-rendered table node.
|
|
27
|
+
* Temporarily disables mutation observers (except for selection changes) during the move,
|
|
28
|
+
* preserves selection state, and restores it afterwards if mutations occurred and cursor
|
|
29
|
+
* wasn't at start of node. This prevents duplicate tables and maintains editor state during
|
|
30
|
+
* the DOM manipulation.
|
|
31
|
+
*/
|
|
32
|
+
private _handleTableRef;
|
|
24
33
|
setDomAttrs(node: PmNode): void;
|
|
25
34
|
getNode: () => PmNode;
|
|
26
35
|
render(props: Props, forwardRef: ForwardRef): React.JSX.Element;
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import type { GetEditorContainerWidth } from '@atlaskit/editor-common/types';
|
|
2
|
-
import type { NodeSpec } from '@atlaskit/editor-prosemirror/model';
|
|
2
|
+
import type { DOMOutputSpec, NodeSpec, Node as PMNode } from '@atlaskit/editor-prosemirror/model';
|
|
3
3
|
type Config = {
|
|
4
4
|
allowColumnResizing: boolean;
|
|
5
5
|
tableResizingEnabled: boolean;
|
|
6
6
|
getEditorContainerWidth: GetEditorContainerWidth;
|
|
7
7
|
isNestingSupported?: boolean;
|
|
8
8
|
};
|
|
9
|
-
export declare const tableNodeSpecWithFixedToDOM: (config: Config) => NodeSpec
|
|
9
|
+
export declare const tableNodeSpecWithFixedToDOM: (config: Config) => NodeSpec & {
|
|
10
|
+
toDOM: (node: PMNode) => DOMOutputSpec;
|
|
11
|
+
};
|
|
10
12
|
export {};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { EditorAnalyticsAPI } from '@atlaskit/editor-common/analytics';
|
|
2
|
-
import type { Command, FloatingToolbarDropdown, FloatingToolbarHandler, FloatingToolbarItem, GetEditorContainerWidth
|
|
2
|
+
import type { Command, FloatingToolbarDropdown, FloatingToolbarHandler, FloatingToolbarItem, GetEditorContainerWidth } from '@atlaskit/editor-common/types';
|
|
3
3
|
import type { EditorState } from '@atlaskit/editor-prosemirror/state';
|
|
4
4
|
import type { EditorView } from '@atlaskit/editor-prosemirror/view';
|
|
5
5
|
import { Rect } from '@atlaskit/editor-tables/table-map';
|
|
@@ -8,4 +8,4 @@ import type { PluginConfig, PluginInjectionAPI, ToolbarMenuConfig, ToolbarMenuCo
|
|
|
8
8
|
export declare const getToolbarMenuConfig: (config: ToolbarMenuConfig, state: ToolbarMenuState, { formatMessage }: ToolbarMenuContext, editorAnalyticsAPI: EditorAnalyticsAPI | undefined | null, isTableScalingWithFixedColumnWidthsOptionShown?: boolean, areTableColumnWidthsFixed?: boolean) => FloatingToolbarItem<Command>;
|
|
9
9
|
export declare const getToolbarCellOptionsConfig: (editorState: EditorState, editorView: EditorView | undefined | null, initialSelectionRect: Rect, { formatMessage }: ToolbarMenuContext, getEditorContainerWidth: GetEditorContainerWidth, api: PluginInjectionAPI | undefined | null, editorAnalyticsAPI: EditorAnalyticsAPI | undefined | null, isTableScalingEnabled?: boolean, isTableFixedColumnWidthsOptionEnabled?: boolean, shouldUseIncreasedScalingPercent?: boolean, isCommentEditor?: boolean) => FloatingToolbarDropdown<Command>;
|
|
10
10
|
export declare const getClosestSelectionRect: (state: EditorState) => Rect | undefined;
|
|
11
|
-
export declare const getToolbarConfig: (getEditorContainerWidth: GetEditorContainerWidth, api: PluginInjectionAPI | undefined | null, editorAnalyticsAPI: EditorAnalyticsAPI | undefined | null,
|
|
11
|
+
export declare const getToolbarConfig: (getEditorContainerWidth: GetEditorContainerWidth, api: PluginInjectionAPI | undefined | null, editorAnalyticsAPI: EditorAnalyticsAPI | undefined | null, getEditorView: () => EditorView | null, options?: TablePluginOptions, isTableFixedColumnWidthsOptionEnabled?: boolean, shouldUseIncreasedScalingPercent?: boolean) => (config: PluginConfig) => FloatingToolbarHandler;
|
|
@@ -11,6 +11,7 @@ import type { Props } from './types';
|
|
|
11
11
|
type ForwardRef = (node: HTMLElement | null) => void;
|
|
12
12
|
export default class TableView extends ReactNodeView<Props> {
|
|
13
13
|
private table;
|
|
14
|
+
private renderedDOM?;
|
|
14
15
|
private resizeObserver?;
|
|
15
16
|
eventDispatcher?: EventDispatcher;
|
|
16
17
|
getPos: getPosHandlerNode;
|
|
@@ -21,6 +22,14 @@ export default class TableView extends ReactNodeView<Props> {
|
|
|
21
22
|
dom: HTMLElement;
|
|
22
23
|
contentDOM?: HTMLElement | undefined;
|
|
23
24
|
};
|
|
25
|
+
/**
|
|
26
|
+
* Handles moving the table from ProseMirror's DOM structure into a React-rendered table node.
|
|
27
|
+
* Temporarily disables mutation observers (except for selection changes) during the move,
|
|
28
|
+
* preserves selection state, and restores it afterwards if mutations occurred and cursor
|
|
29
|
+
* wasn't at start of node. This prevents duplicate tables and maintains editor state during
|
|
30
|
+
* the DOM manipulation.
|
|
31
|
+
*/
|
|
32
|
+
private _handleTableRef;
|
|
24
33
|
setDomAttrs(node: PmNode): void;
|
|
25
34
|
getNode: () => PmNode;
|
|
26
35
|
render(props: Props, forwardRef: ForwardRef): React.JSX.Element;
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import type { GetEditorContainerWidth } from '@atlaskit/editor-common/types';
|
|
2
|
-
import type { NodeSpec } from '@atlaskit/editor-prosemirror/model';
|
|
2
|
+
import type { DOMOutputSpec, NodeSpec, Node as PMNode } from '@atlaskit/editor-prosemirror/model';
|
|
3
3
|
type Config = {
|
|
4
4
|
allowColumnResizing: boolean;
|
|
5
5
|
tableResizingEnabled: boolean;
|
|
6
6
|
getEditorContainerWidth: GetEditorContainerWidth;
|
|
7
7
|
isNestingSupported?: boolean;
|
|
8
8
|
};
|
|
9
|
-
export declare const tableNodeSpecWithFixedToDOM: (config: Config) => NodeSpec
|
|
9
|
+
export declare const tableNodeSpecWithFixedToDOM: (config: Config) => NodeSpec & {
|
|
10
|
+
toDOM: (node: PMNode) => DOMOutputSpec;
|
|
11
|
+
};
|
|
10
12
|
export {};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { EditorAnalyticsAPI } from '@atlaskit/editor-common/analytics';
|
|
2
|
-
import type { Command, FloatingToolbarDropdown, FloatingToolbarHandler, FloatingToolbarItem, GetEditorContainerWidth
|
|
2
|
+
import type { Command, FloatingToolbarDropdown, FloatingToolbarHandler, FloatingToolbarItem, GetEditorContainerWidth } from '@atlaskit/editor-common/types';
|
|
3
3
|
import type { EditorState } from '@atlaskit/editor-prosemirror/state';
|
|
4
4
|
import type { EditorView } from '@atlaskit/editor-prosemirror/view';
|
|
5
5
|
import { Rect } from '@atlaskit/editor-tables/table-map';
|
|
@@ -8,4 +8,4 @@ import type { PluginConfig, PluginInjectionAPI, ToolbarMenuConfig, ToolbarMenuCo
|
|
|
8
8
|
export declare const getToolbarMenuConfig: (config: ToolbarMenuConfig, state: ToolbarMenuState, { formatMessage }: ToolbarMenuContext, editorAnalyticsAPI: EditorAnalyticsAPI | undefined | null, isTableScalingWithFixedColumnWidthsOptionShown?: boolean, areTableColumnWidthsFixed?: boolean) => FloatingToolbarItem<Command>;
|
|
9
9
|
export declare const getToolbarCellOptionsConfig: (editorState: EditorState, editorView: EditorView | undefined | null, initialSelectionRect: Rect, { formatMessage }: ToolbarMenuContext, getEditorContainerWidth: GetEditorContainerWidth, api: PluginInjectionAPI | undefined | null, editorAnalyticsAPI: EditorAnalyticsAPI | undefined | null, isTableScalingEnabled?: boolean, isTableFixedColumnWidthsOptionEnabled?: boolean, shouldUseIncreasedScalingPercent?: boolean, isCommentEditor?: boolean) => FloatingToolbarDropdown<Command>;
|
|
10
10
|
export declare const getClosestSelectionRect: (state: EditorState) => Rect | undefined;
|
|
11
|
-
export declare const getToolbarConfig: (getEditorContainerWidth: GetEditorContainerWidth, api: PluginInjectionAPI | undefined | null, editorAnalyticsAPI: EditorAnalyticsAPI | undefined | null,
|
|
11
|
+
export declare const getToolbarConfig: (getEditorContainerWidth: GetEditorContainerWidth, api: PluginInjectionAPI | undefined | null, editorAnalyticsAPI: EditorAnalyticsAPI | undefined | null, getEditorView: () => EditorView | null, options?: TablePluginOptions, isTableFixedColumnWidthsOptionEnabled?: boolean, shouldUseIncreasedScalingPercent?: boolean) => (config: PluginConfig) => FloatingToolbarHandler;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/editor-plugin-table",
|
|
3
|
-
"version": "10.6.
|
|
3
|
+
"version": "10.6.10",
|
|
4
4
|
"description": "Table plugin for the @atlaskit/editor",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"registry": "https://registry.npmjs.org/"
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"@atlaskit/adf-schema": "^47.6.0",
|
|
33
33
|
"@atlaskit/button": "^23.0.0",
|
|
34
34
|
"@atlaskit/custom-steps": "^0.11.0",
|
|
35
|
-
"@atlaskit/editor-common": "^103.
|
|
35
|
+
"@atlaskit/editor-common": "^103.3.0",
|
|
36
36
|
"@atlaskit/editor-palette": "^2.1.0",
|
|
37
37
|
"@atlaskit/editor-plugin-accessibility-utils": "^2.0.0",
|
|
38
38
|
"@atlaskit/editor-plugin-analytics": "^2.2.0",
|
|
@@ -123,6 +123,9 @@
|
|
|
123
123
|
"type": "boolean",
|
|
124
124
|
"referenceOnly": true
|
|
125
125
|
},
|
|
126
|
+
"platform_editor_table_initial_load_fix": {
|
|
127
|
+
"type": "boolean"
|
|
128
|
+
},
|
|
126
129
|
"platform_editor_table_overflow_in_full_width_fix": {
|
|
127
130
|
"type": "boolean"
|
|
128
131
|
},
|
|
@@ -197,6 +200,9 @@
|
|
|
197
200
|
},
|
|
198
201
|
"platform_editor_controls_patch_2": {
|
|
199
202
|
"type": "boolean"
|
|
203
|
+
},
|
|
204
|
+
"platform_editor_controls_patch_4": {
|
|
205
|
+
"type": "boolean"
|
|
200
206
|
}
|
|
201
207
|
}
|
|
202
208
|
}
|
|
@@ -1033,6 +1033,7 @@ class TableComponent extends React.Component<ComponentProps, TableState> {
|
|
|
1033
1033
|
if (elem) {
|
|
1034
1034
|
this.props.contentDOM(elem);
|
|
1035
1035
|
const tableElement = elem.querySelector('table');
|
|
1036
|
+
|
|
1036
1037
|
if (tableElement !== this.table) {
|
|
1037
1038
|
this.table = tableElement;
|
|
1038
1039
|
this.createShadowSentinels(this.table);
|
package/src/nodeviews/table.tsx
CHANGED
|
@@ -15,7 +15,7 @@ import type {
|
|
|
15
15
|
import { WithPluginState } from '@atlaskit/editor-common/with-plugin-state';
|
|
16
16
|
import type { DOMOutputSpec, Node as PmNode } from '@atlaskit/editor-prosemirror/model';
|
|
17
17
|
import { DOMSerializer } from '@atlaskit/editor-prosemirror/model';
|
|
18
|
-
import type { EditorState, PluginKey } from '@atlaskit/editor-prosemirror/state';
|
|
18
|
+
import type { EditorState, PluginKey, SelectionBookmark } from '@atlaskit/editor-prosemirror/state';
|
|
19
19
|
import type { EditorView, NodeView } from '@atlaskit/editor-prosemirror/view';
|
|
20
20
|
import { akEditorTableNumberColumnWidth } from '@atlaskit/editor-shared-styles';
|
|
21
21
|
import { TableMap } from '@atlaskit/editor-tables/table-map';
|
|
@@ -33,6 +33,7 @@ import type { PluginInjectionAPI } from '../types';
|
|
|
33
33
|
|
|
34
34
|
import TableComponent from './TableComponent';
|
|
35
35
|
import { TableComponentWithSharedState } from './TableComponentWithSharedState';
|
|
36
|
+
import { tableNodeSpecWithFixedToDOM } from './toDOM';
|
|
36
37
|
import type { Props } from './types';
|
|
37
38
|
|
|
38
39
|
type ForwardRef = (node: HTMLElement | null) => void;
|
|
@@ -80,18 +81,18 @@ const handleInlineTableWidth = (table: HTMLElement, width: number | undefined) =
|
|
|
80
81
|
table.style.setProperty('width', `${width}px`);
|
|
81
82
|
};
|
|
82
83
|
|
|
84
|
+
// Leave as a fallback incase the table's NodeSpec.toDOM is not defined.
|
|
83
85
|
const toDOM = (node: PmNode, props: Props) => {
|
|
84
86
|
let colgroup: DOMOutputSpec = '';
|
|
85
|
-
|
|
86
87
|
if (props.allowColumnResizing) {
|
|
87
88
|
colgroup = ['colgroup', {}, ...generateColgroup(node)];
|
|
88
89
|
}
|
|
89
|
-
|
|
90
90
|
return ['table', tableAttributes(node), colgroup, ['tbody', 0]] as DOMOutputSpec;
|
|
91
91
|
};
|
|
92
92
|
|
|
93
93
|
export default class TableView extends ReactNodeView<Props> {
|
|
94
94
|
private table: HTMLElement | undefined;
|
|
95
|
+
private renderedDOM?: HTMLElement;
|
|
95
96
|
private resizeObserver?: ResizeObserver;
|
|
96
97
|
eventDispatcher?: EventDispatcher;
|
|
97
98
|
getPos: getPosHandlerNode;
|
|
@@ -111,19 +112,37 @@ export default class TableView extends ReactNodeView<Props> {
|
|
|
111
112
|
this.eventDispatcher = props.eventDispatcher;
|
|
112
113
|
this.options = props.options;
|
|
113
114
|
this.getEditorFeatureFlags = props.getEditorFeatureFlags;
|
|
115
|
+
|
|
116
|
+
if (fg('platform_editor_table_initial_load_fix')) {
|
|
117
|
+
this.handleRef = (node: HTMLElement | null) => this._handleTableRef(node);
|
|
118
|
+
}
|
|
114
119
|
}
|
|
115
120
|
|
|
116
121
|
getContentDOM() {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
122
|
+
let tableDOMStructure;
|
|
123
|
+
if (fg('platform_editor_table_initial_load_fix')) {
|
|
124
|
+
tableDOMStructure = tableNodeSpecWithFixedToDOM({
|
|
125
|
+
allowColumnResizing: !!this.reactComponentProps.allowColumnResizing,
|
|
126
|
+
tableResizingEnabled: !!this.reactComponentProps.allowTableResizing,
|
|
127
|
+
getEditorContainerWidth: this.reactComponentProps.getEditorContainerWidth,
|
|
128
|
+
}).toDOM(this.node);
|
|
129
|
+
} else {
|
|
130
|
+
tableDOMStructure = toDOM(this.node, this.reactComponentProps as Props);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const rendered = DOMSerializer.renderSpec(document, tableDOMStructure) as {
|
|
121
134
|
dom: HTMLElement;
|
|
122
135
|
contentDOM?: HTMLElement;
|
|
123
136
|
};
|
|
124
137
|
|
|
125
138
|
if (rendered.dom) {
|
|
126
|
-
|
|
139
|
+
if (fg('platform_editor_table_initial_load_fix')) {
|
|
140
|
+
const tableElement = rendered.dom.querySelector('table');
|
|
141
|
+
this.table = tableElement ? tableElement : rendered.dom;
|
|
142
|
+
this.renderedDOM = rendered.dom;
|
|
143
|
+
} else {
|
|
144
|
+
this.table = rendered.dom;
|
|
145
|
+
}
|
|
127
146
|
|
|
128
147
|
if (
|
|
129
148
|
!this.options?.isTableScalingEnabled ||
|
|
@@ -147,6 +166,73 @@ export default class TableView extends ReactNodeView<Props> {
|
|
|
147
166
|
return rendered;
|
|
148
167
|
}
|
|
149
168
|
|
|
169
|
+
/**
|
|
170
|
+
* Handles moving the table from ProseMirror's DOM structure into a React-rendered table node.
|
|
171
|
+
* Temporarily disables mutation observers (except for selection changes) during the move,
|
|
172
|
+
* preserves selection state, and restores it afterwards if mutations occurred and cursor
|
|
173
|
+
* wasn't at start of node. This prevents duplicate tables and maintains editor state during
|
|
174
|
+
* the DOM manipulation.
|
|
175
|
+
*/
|
|
176
|
+
private _handleTableRef(node: HTMLElement | null) {
|
|
177
|
+
let oldIgnoreMutation: (mutation: MutationRecord) => boolean;
|
|
178
|
+
|
|
179
|
+
let selectionBookmark: SelectionBookmark;
|
|
180
|
+
let parentOffset = 0;
|
|
181
|
+
let mutationsIgnored = false;
|
|
182
|
+
|
|
183
|
+
// Only proceed if we have both a node and table, and the table isn't already inside the node
|
|
184
|
+
if (node && this.table && !node.contains(this.table)) {
|
|
185
|
+
// Store the current ignoreMutation handler so we can restore it later
|
|
186
|
+
oldIgnoreMutation = this.ignoreMutation;
|
|
187
|
+
|
|
188
|
+
// Set up a temporary mutation handler that:
|
|
189
|
+
// - Ignores all DOM mutations except selection changes
|
|
190
|
+
// - Tracks when mutations have been ignored via mutationsIgnored flag
|
|
191
|
+
this.ignoreMutation = (m: MutationRecord) => {
|
|
192
|
+
const isSelectionMutation = m.target instanceof Selection;
|
|
193
|
+
if (!isSelectionMutation) {
|
|
194
|
+
mutationsIgnored = true;
|
|
195
|
+
}
|
|
196
|
+
return !isSelectionMutation;
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
// Store the current selection state if there is a visible selection
|
|
200
|
+
// This lets us restore it after DOM changes
|
|
201
|
+
if (this.view.state.selection.visible) {
|
|
202
|
+
selectionBookmark = this.view.state.selection.getBookmark();
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// Store the current cursor position within the parent node
|
|
206
|
+
// Used to determine if we need to restore selection later
|
|
207
|
+
if (this.view.state.selection?.ranges.length > 0) {
|
|
208
|
+
parentOffset = this.view.state.selection?.ranges[0].$from?.parentOffset ?? 0;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Remove the ProseMirror table DOM structure to avoid duplication, as it's replaced with the React table node.
|
|
212
|
+
if (this.renderedDOM) {
|
|
213
|
+
this.dom.removeChild(this.renderedDOM);
|
|
214
|
+
}
|
|
215
|
+
// Move the table from the ProseMirror table structure into the React rendered table node.
|
|
216
|
+
node.appendChild(this.table);
|
|
217
|
+
|
|
218
|
+
// After the next frame:
|
|
219
|
+
requestAnimationFrame(() => {
|
|
220
|
+
// Restore the original mutation handler
|
|
221
|
+
this.ignoreMutation = oldIgnoreMutation;
|
|
222
|
+
|
|
223
|
+
// Restore the selection only if:
|
|
224
|
+
// - We have a selection bookmark
|
|
225
|
+
// - Mutations were ignored during the table move
|
|
226
|
+
// - The cursor wasn't at the start of the node
|
|
227
|
+
if (selectionBookmark && mutationsIgnored && parentOffset > 0) {
|
|
228
|
+
this.view.dispatch(
|
|
229
|
+
this.view.state.tr.setSelection(selectionBookmark.resolve(this.view.state.tr.doc)),
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
150
236
|
setDomAttrs(node: PmNode) {
|
|
151
237
|
if (!this.table) {
|
|
152
238
|
return;
|
|
@@ -206,7 +292,6 @@ export default class TableView extends ReactNodeView<Props> {
|
|
|
206
292
|
/>
|
|
207
293
|
);
|
|
208
294
|
}
|
|
209
|
-
|
|
210
295
|
// Please, do not copy or use this kind of code below
|
|
211
296
|
// @ts-ignore
|
|
212
297
|
const fakePluginKey = {
|
package/src/nodeviews/toDOM.ts
CHANGED
|
@@ -17,7 +17,9 @@ type Config = {
|
|
|
17
17
|
getEditorContainerWidth: GetEditorContainerWidth;
|
|
18
18
|
isNestingSupported?: boolean;
|
|
19
19
|
};
|
|
20
|
-
export const tableNodeSpecWithFixedToDOM = (
|
|
20
|
+
export const tableNodeSpecWithFixedToDOM = (
|
|
21
|
+
config: Config,
|
|
22
|
+
): NodeSpec & { toDOM: (node: PMNode) => DOMOutputSpec } => {
|
|
21
23
|
const tableNode = config.isNestingSupported ? tableWithNestedTable : table;
|
|
22
24
|
|
|
23
25
|
return {
|
package/src/tablePlugin.tsx
CHANGED
|
@@ -768,7 +768,6 @@ const tablesPlugin: TablePlugin = ({ config: options, api }) => {
|
|
|
768
768
|
defaultGetEditorContainerWidth,
|
|
769
769
|
api,
|
|
770
770
|
editorAnalyticsAPI,
|
|
771
|
-
options?.getEditorFeatureFlags || defaultGetEditorFeatureFlags,
|
|
772
771
|
() => editorViewRef.current,
|
|
773
772
|
options,
|
|
774
773
|
isTableFixedColumnWidthsOptionEnabled,
|
package/src/ui/toolbar.tsx
CHANGED
|
@@ -23,7 +23,6 @@ import type {
|
|
|
23
23
|
FloatingToolbarHandler,
|
|
24
24
|
FloatingToolbarItem,
|
|
25
25
|
GetEditorContainerWidth,
|
|
26
|
-
GetEditorFeatureFlags,
|
|
27
26
|
Icon,
|
|
28
27
|
typeOption,
|
|
29
28
|
} from '@atlaskit/editor-common/types';
|
|
@@ -87,6 +86,7 @@ import {
|
|
|
87
86
|
toggleNumberColumnWithAnalytics,
|
|
88
87
|
wrapTableInExpandWithAnalytics,
|
|
89
88
|
} from '../pm-plugins/commands/commands-with-analytics';
|
|
89
|
+
import { getPluginState as getDragDropPluginState } from '../pm-plugins/drag-and-drop/plugin-factory';
|
|
90
90
|
import { getPluginState } from '../pm-plugins/plugin-factory';
|
|
91
91
|
import { pluginKey as tableResizingPluginKey } from '../pm-plugins/table-resizing/plugin-key';
|
|
92
92
|
import { getStaticTableScalingPercent } from '../pm-plugins/table-resizing/utils/misc';
|
|
@@ -479,7 +479,6 @@ export const getToolbarConfig =
|
|
|
479
479
|
getEditorContainerWidth: GetEditorContainerWidth,
|
|
480
480
|
api: PluginInjectionAPI | undefined | null,
|
|
481
481
|
editorAnalyticsAPI: EditorAnalyticsAPI | undefined | null,
|
|
482
|
-
getEditorFeatureFlags: GetEditorFeatureFlags,
|
|
483
482
|
getEditorView: () => EditorView | null,
|
|
484
483
|
options?: TablePluginOptions,
|
|
485
484
|
isTableFixedColumnWidthsOptionEnabled = false,
|
|
@@ -492,12 +491,45 @@ export const getToolbarConfig =
|
|
|
492
491
|
const resizeState = tableResizingPluginKey.getState(state);
|
|
493
492
|
const tableWidthState = tableWidthPluginKey.getState(state);
|
|
494
493
|
const isTableScalingEnabled = options?.isTableScalingEnabled || false;
|
|
494
|
+
const nodeType = state.schema.nodes.table;
|
|
495
|
+
const toolbarTitle = 'Table floating controls';
|
|
496
|
+
|
|
497
|
+
if (
|
|
498
|
+
editorExperiment('platform_editor_controls', 'variant1') &&
|
|
499
|
+
fg('platform_editor_controls_patch_4')
|
|
500
|
+
) {
|
|
501
|
+
let isDragHandleMenuOpened = false;
|
|
502
|
+
let isTableRowOrColumnDragged = false;
|
|
503
|
+
if (options?.dragAndDropEnabled) {
|
|
504
|
+
const { isDragMenuOpen = false, isDragging = false } = getDragDropPluginState(state);
|
|
505
|
+
isDragHandleMenuOpened = isDragMenuOpen;
|
|
506
|
+
isTableRowOrColumnDragged = isDragging;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
const isTableOrColumnResizing = !!(resizeState?.dragging || tableWidthState?.resizing);
|
|
510
|
+
const isTableMenuOpened = pluginState.isContextualMenuOpen || isDragHandleMenuOpened;
|
|
511
|
+
const isViewMode = api?.editorViewMode?.sharedState.currentState()?.mode === 'view';
|
|
512
|
+
|
|
513
|
+
const shouldSuppressAllToolbars =
|
|
514
|
+
(!pluginState.editorHasFocus && !isViewMode) ||
|
|
515
|
+
isTableMenuOpened ||
|
|
516
|
+
isTableOrColumnResizing ||
|
|
517
|
+
isTableRowOrColumnDragged;
|
|
518
|
+
|
|
519
|
+
if (shouldSuppressAllToolbars) {
|
|
520
|
+
return {
|
|
521
|
+
title: toolbarTitle,
|
|
522
|
+
items: [],
|
|
523
|
+
nodeType,
|
|
524
|
+
__suppressAllToolbars: true,
|
|
525
|
+
};
|
|
526
|
+
}
|
|
527
|
+
}
|
|
495
528
|
|
|
496
529
|
// We don't want to show floating toolbar while resizing the table
|
|
497
530
|
const isWidthResizing = tableWidthState?.resizing;
|
|
498
531
|
|
|
499
532
|
if (tableObject && pluginState.editorHasFocus && !isWidthResizing) {
|
|
500
|
-
const nodeType = state.schema.nodes.table;
|
|
501
533
|
const isNested = pluginState.tablePos && isTableNested(state, pluginState.tablePos);
|
|
502
534
|
const isTableScalingWithFixedColumnWidthsOptionShown =
|
|
503
535
|
isTableScalingEnabled && isTableFixedColumnWidthsOptionEnabled && !isNested;
|
|
@@ -645,7 +677,7 @@ export const getToolbarConfig =
|
|
|
645
677
|
: undefined;
|
|
646
678
|
|
|
647
679
|
return {
|
|
648
|
-
title:
|
|
680
|
+
title: toolbarTitle,
|
|
649
681
|
getDomRef,
|
|
650
682
|
nodeType,
|
|
651
683
|
offset: [0, 18],
|