@atlaskit/editor-plugin-table 10.6.9 → 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 +11 -0
- package/dist/cjs/nodeviews/table.js +99 -7
- package/dist/es2019/nodeviews/table.js +90 -3
- package/dist/esm/nodeviews/table.js +99 -7
- package/dist/types/nodeviews/table.d.ts +9 -0
- package/dist/types/nodeviews/toDOM.d.ts +4 -2
- package/dist/types-ts4.5/nodeviews/table.d.ts +9 -0
- package/dist/types-ts4.5/nodeviews/toDOM.d.ts +4 -2
- package/package.json +5 -2
- package/src/nodeviews/TableComponent.tsx +1 -0
- package/src/nodeviews/table.tsx +94 -9
- package/src/nodeviews/toDOM.ts +3 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
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
|
+
|
|
3
14
|
## 10.6.9
|
|
4
15
|
|
|
5
16
|
### 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
|
,
|
|
@@ -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 = {
|
|
@@ -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
|
,
|
|
@@ -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 {};
|
|
@@ -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 {};
|
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
|
},
|
|
@@ -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 {
|