@atlaskit/editor-plugin-table 3.2.0 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -0
- package/dist/cjs/plugins/table/nodeviews/TableResizer.js +18 -17
- package/dist/cjs/plugins/table/pm-plugins/sticky-headers/nodeviews/tableRow.js +37 -4
- package/dist/es2019/plugins/table/nodeviews/TableResizer.js +18 -17
- package/dist/es2019/plugins/table/pm-plugins/sticky-headers/nodeviews/tableRow.js +39 -6
- package/dist/esm/plugins/table/nodeviews/TableResizer.js +18 -17
- package/dist/esm/plugins/table/pm-plugins/sticky-headers/nodeviews/tableRow.js +37 -4
- package/dist/types/plugins/table/pm-plugins/sticky-headers/nodeviews/tableRow.d.ts +5 -0
- package/dist/types-ts4.5/plugins/table/pm-plugins/sticky-headers/nodeviews/tableRow.d.ts +5 -0
- package/package.json +2 -2
- package/src/plugins/table/nodeviews/TableResizer.tsx +23 -23
- package/src/plugins/table/pm-plugins/sticky-headers/nodeviews/tableRow.ts +40 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# @atlaskit/editor-plugin-table
|
|
2
2
|
|
|
3
|
+
## 4.0.0
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- [`151b0d45db4`](https://bitbucket.org/atlassian/atlassian-frontend/commits/151b0d45db4) - Changed Resizer API. Removed handleComponent, innerPadding & handleMarginTop. Also renamed HandleHeightSizeType to HandleSize. The resizer should be opionated and control the handle component itself. innerPadding & handleMarginTop can also be controlled via the handleStyles override property.
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Updated dependencies
|
|
12
|
+
|
|
13
|
+
## 3.2.1
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- [`b1a93f61747`](https://bitbucket.org/atlassian/atlassian-frontend/commits/b1a93f61747) - [ED-20091] add logic to refire intersection observers and prevent detached table sticky headers
|
|
18
|
+
|
|
3
19
|
## 3.2.0
|
|
4
20
|
|
|
5
21
|
### Minor Changes
|
|
@@ -38,15 +38,16 @@ var messages = (0, _reactIntlNext.defineMessages)({
|
|
|
38
38
|
var handles = {
|
|
39
39
|
right: true
|
|
40
40
|
};
|
|
41
|
-
var
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
if (!tableHeight) {
|
|
47
|
-
return handleHeightSize;
|
|
41
|
+
var handleStyles = {
|
|
42
|
+
right: {
|
|
43
|
+
// eslint-disable-next-line
|
|
44
|
+
right: '-14px',
|
|
45
|
+
marginTop: "var(--ds-space-150, 12px)"
|
|
48
46
|
}
|
|
49
|
-
|
|
47
|
+
};
|
|
48
|
+
var getResizerHandleHeight = function getResizerHandleHeight(tableRef) {
|
|
49
|
+
var _tableRef$clientHeigh;
|
|
50
|
+
var tableHeight = (_tableRef$clientHeigh = tableRef === null || tableRef === void 0 ? void 0 : tableRef.clientHeight) !== null && _tableRef$clientHeigh !== void 0 ? _tableRef$clientHeigh : 0;
|
|
50
51
|
/*
|
|
51
52
|
- One row table height (minimum possible table height) ~ 45px
|
|
52
53
|
- Two row table height ~ 90px
|
|
@@ -55,12 +56,13 @@ var getResizerHandleHeight = function getResizerHandleHeight(tableRef) {
|
|
|
55
56
|
- > 46 because the height of the table can be a float number like 45.44.
|
|
56
57
|
- < 96 is the height of large resize handle.
|
|
57
58
|
*/
|
|
58
|
-
if (tableHeight
|
|
59
|
-
|
|
60
|
-
}
|
|
61
|
-
|
|
59
|
+
if (tableHeight >= 96) {
|
|
60
|
+
return 'large';
|
|
61
|
+
}
|
|
62
|
+
if (tableHeight > 46) {
|
|
63
|
+
return 'medium';
|
|
62
64
|
}
|
|
63
|
-
return
|
|
65
|
+
return 'small';
|
|
64
66
|
};
|
|
65
67
|
var getResizerMinWidth = function getResizerMinWidth(node) {
|
|
66
68
|
var currentColumnCount = (0, _utils2.getColgroupChildrenLength)(node);
|
|
@@ -107,7 +109,7 @@ var TableResizer = function TableResizer(_ref) {
|
|
|
107
109
|
var _useIntl = (0, _reactIntlNext.useIntl)(),
|
|
108
110
|
formatMessage = _useIntl.formatMessage;
|
|
109
111
|
var resizerMinWidth = getResizerMinWidth(node);
|
|
110
|
-
var
|
|
112
|
+
var handleSize = getResizerHandleHeight(tableRef);
|
|
111
113
|
var _getPluginState = (0, _pluginFactory.getPluginState)(editorView.state),
|
|
112
114
|
isInDanger = _getPluginState.isInDanger;
|
|
113
115
|
var _useMeasureFramerate = (0, _analytics2.useMeasureFramerate)(),
|
|
@@ -244,8 +246,8 @@ var TableResizer = function TableResizer(_ref) {
|
|
|
244
246
|
enable: handles,
|
|
245
247
|
width: width,
|
|
246
248
|
handleAlignmentMethod: "sticky",
|
|
247
|
-
|
|
248
|
-
|
|
249
|
+
handleSize: handleSize,
|
|
250
|
+
handleStyles: handleStyles,
|
|
249
251
|
handleResizeStart: handleResizeStart,
|
|
250
252
|
handleResize: scheduleResize,
|
|
251
253
|
handleResizeStop: handleResizeStop,
|
|
@@ -255,7 +257,6 @@ var TableResizer = function TableResizer(_ref) {
|
|
|
255
257
|
snapGap: _consts.TABLE_SNAP_GAP,
|
|
256
258
|
snap: guidelineSnaps,
|
|
257
259
|
handlePositioning: "adjacent",
|
|
258
|
-
innerPadding: tableHandlePosition,
|
|
259
260
|
isHandleVisible: isTableSelected,
|
|
260
261
|
appearance: isInDanger && isTableSelected ? 'danger' : undefined,
|
|
261
262
|
handleHighlight: "shadow",
|
|
@@ -149,10 +149,24 @@ var TableRowNodeView = /*#__PURE__*/function () {
|
|
|
149
149
|
// otherwise make it non-sticky
|
|
150
150
|
return false;
|
|
151
151
|
});
|
|
152
|
+
/**
|
|
153
|
+
* Manually refire the intersection observers.
|
|
154
|
+
* Useful when the header may have detached from the table.
|
|
155
|
+
*/
|
|
156
|
+
(0, _defineProperty2.default)(this, "refireIntersectionObservers", function () {
|
|
157
|
+
if (_this.isSticky) {
|
|
158
|
+
[_this.sentinels.top, _this.sentinels.bottom].forEach(function (el) {
|
|
159
|
+
if (el && _this.intersectionObserver) {
|
|
160
|
+
_this.intersectionObserver.unobserve(el);
|
|
161
|
+
_this.intersectionObserver.observe(el);
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
});
|
|
152
166
|
(0, _defineProperty2.default)(this, "makeHeaderRowSticky", function (tree, scrollTop) {
|
|
153
167
|
var _tbody$firstChild;
|
|
154
168
|
// If header row height is more than 50% of viewport height don't do this
|
|
155
|
-
if (_this.stickyRowHeight && _this.stickyRowHeight > window.innerHeight / 2) {
|
|
169
|
+
if (_this.isSticky || _this.stickyRowHeight && _this.stickyRowHeight > window.innerHeight / 2) {
|
|
156
170
|
return;
|
|
157
171
|
}
|
|
158
172
|
var table = tree.table,
|
|
@@ -170,10 +184,25 @@ var TableRowNodeView = /*#__PURE__*/function () {
|
|
|
170
184
|
}
|
|
171
185
|
var domTop = currentTableTop > 0 ? scrollTop : scrollTop + currentTableTop;
|
|
172
186
|
if (!_this.isSticky) {
|
|
187
|
+
var _this$editorScrollabl;
|
|
173
188
|
(0, _dom.syncStickyRowToTable)(table);
|
|
174
189
|
_this.dom.classList.add('sticky');
|
|
175
190
|
table.classList.add(_types.TableCssClassName.TABLE_STICKY);
|
|
176
191
|
_this.isSticky = true;
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* The logic below is not desirable, but acts as a fail safe for scenarios where the sticky header
|
|
195
|
+
* detaches from the table. This typically happens during a fast scroll by the user which causes
|
|
196
|
+
* the intersection observer logic to not fire as expected.
|
|
197
|
+
*/
|
|
198
|
+
(_this$editorScrollabl = _this.editorScrollableElement) === null || _this$editorScrollabl === void 0 ? void 0 : _this$editorScrollabl.addEventListener('scrollend', _this.refireIntersectionObservers, {
|
|
199
|
+
passive: true,
|
|
200
|
+
once: true
|
|
201
|
+
});
|
|
202
|
+
var fastScrollThresholdMs = 500;
|
|
203
|
+
setTimeout(function () {
|
|
204
|
+
_this.refireIntersectionObservers();
|
|
205
|
+
}, fastScrollThresholdMs);
|
|
177
206
|
}
|
|
178
207
|
_this.dom.style.top = "".concat(domTop, "px");
|
|
179
208
|
(0, _dom.updateStickyMargins)(table);
|
|
@@ -270,8 +299,12 @@ var TableRowNodeView = /*#__PURE__*/function () {
|
|
|
270
299
|
this.eventDispatcher.on('widthPlugin', this.updateStickyHeaderWidth);
|
|
271
300
|
this.eventDispatcher.on(_pluginKey.pluginKey.key, this.onTablePluginState);
|
|
272
301
|
this.listening = true;
|
|
273
|
-
this.dom.addEventListener('wheel', this.headerRowMouseScroll.bind(this)
|
|
274
|
-
|
|
302
|
+
this.dom.addEventListener('wheel', this.headerRowMouseScroll.bind(this), {
|
|
303
|
+
passive: true
|
|
304
|
+
});
|
|
305
|
+
this.dom.addEventListener('touchmove', this.headerRowMouseScroll.bind(this), {
|
|
306
|
+
passive: true
|
|
307
|
+
});
|
|
275
308
|
}
|
|
276
309
|
}, {
|
|
277
310
|
key: "unsubscribe",
|
|
@@ -282,7 +315,7 @@ var TableRowNodeView = /*#__PURE__*/function () {
|
|
|
282
315
|
if (this.intersectionObserver) {
|
|
283
316
|
this.intersectionObserver.disconnect();
|
|
284
317
|
// ED-16211 Once intersection observer is disconnected, we need to remove the isObserved from the sentinels
|
|
285
|
-
// Otherwise when
|
|
318
|
+
// Otherwise when newer intersection observer is created it will not observe because it thinks its already being observed
|
|
286
319
|
[this.sentinels.top, this.sentinels.bottom].forEach(function (el) {
|
|
287
320
|
if (el) {
|
|
288
321
|
delete el.dataset.isObserved;
|
|
@@ -24,15 +24,16 @@ const messages = defineMessages({
|
|
|
24
24
|
const handles = {
|
|
25
25
|
right: true
|
|
26
26
|
};
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
if (!tableHeight) {
|
|
33
|
-
return handleHeightSize;
|
|
27
|
+
const handleStyles = {
|
|
28
|
+
right: {
|
|
29
|
+
// eslint-disable-next-line
|
|
30
|
+
right: '-14px',
|
|
31
|
+
marginTop: "var(--ds-space-150, 12px)"
|
|
34
32
|
}
|
|
35
|
-
|
|
33
|
+
};
|
|
34
|
+
const getResizerHandleHeight = tableRef => {
|
|
35
|
+
var _tableRef$clientHeigh;
|
|
36
|
+
const tableHeight = (_tableRef$clientHeigh = tableRef === null || tableRef === void 0 ? void 0 : tableRef.clientHeight) !== null && _tableRef$clientHeigh !== void 0 ? _tableRef$clientHeigh : 0;
|
|
36
37
|
/*
|
|
37
38
|
- One row table height (minimum possible table height) ~ 45px
|
|
38
39
|
- Two row table height ~ 90px
|
|
@@ -41,12 +42,13 @@ const getResizerHandleHeight = tableRef => {
|
|
|
41
42
|
- > 46 because the height of the table can be a float number like 45.44.
|
|
42
43
|
- < 96 is the height of large resize handle.
|
|
43
44
|
*/
|
|
44
|
-
if (tableHeight
|
|
45
|
-
|
|
46
|
-
}
|
|
47
|
-
|
|
45
|
+
if (tableHeight >= 96) {
|
|
46
|
+
return 'large';
|
|
47
|
+
}
|
|
48
|
+
if (tableHeight > 46) {
|
|
49
|
+
return 'medium';
|
|
48
50
|
}
|
|
49
|
-
return
|
|
51
|
+
return 'small';
|
|
50
52
|
};
|
|
51
53
|
const getResizerMinWidth = node => {
|
|
52
54
|
const currentColumnCount = getColgroupChildrenLength(node);
|
|
@@ -92,7 +94,7 @@ export const TableResizer = ({
|
|
|
92
94
|
formatMessage
|
|
93
95
|
} = useIntl();
|
|
94
96
|
const resizerMinWidth = getResizerMinWidth(node);
|
|
95
|
-
const
|
|
97
|
+
const handleSize = getResizerHandleHeight(tableRef);
|
|
96
98
|
const {
|
|
97
99
|
isInDanger
|
|
98
100
|
} = getPluginState(editorView.state);
|
|
@@ -239,8 +241,8 @@ export const TableResizer = ({
|
|
|
239
241
|
enable: handles,
|
|
240
242
|
width: width,
|
|
241
243
|
handleAlignmentMethod: "sticky",
|
|
242
|
-
|
|
243
|
-
|
|
244
|
+
handleSize: handleSize,
|
|
245
|
+
handleStyles: handleStyles,
|
|
244
246
|
handleResizeStart: handleResizeStart,
|
|
245
247
|
handleResize: scheduleResize,
|
|
246
248
|
handleResizeStop: handleResizeStop,
|
|
@@ -250,7 +252,6 @@ export const TableResizer = ({
|
|
|
250
252
|
snapGap: TABLE_SNAP_GAP,
|
|
251
253
|
snap: guidelineSnaps,
|
|
252
254
|
handlePositioning: "adjacent",
|
|
253
|
-
innerPadding: tableHandlePosition,
|
|
254
255
|
isHandleVisible: isTableSelected,
|
|
255
256
|
appearance: isInDanger && isTableSelected ? 'danger' : undefined,
|
|
256
257
|
handleHighlight: "shadow",
|
|
@@ -137,10 +137,24 @@ export class TableRowNodeView {
|
|
|
137
137
|
// otherwise make it non-sticky
|
|
138
138
|
return false;
|
|
139
139
|
});
|
|
140
|
+
/**
|
|
141
|
+
* Manually refire the intersection observers.
|
|
142
|
+
* Useful when the header may have detached from the table.
|
|
143
|
+
*/
|
|
144
|
+
_defineProperty(this, "refireIntersectionObservers", () => {
|
|
145
|
+
if (this.isSticky) {
|
|
146
|
+
[this.sentinels.top, this.sentinels.bottom].forEach(el => {
|
|
147
|
+
if (el && this.intersectionObserver) {
|
|
148
|
+
this.intersectionObserver.unobserve(el);
|
|
149
|
+
this.intersectionObserver.observe(el);
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
});
|
|
140
154
|
_defineProperty(this, "makeHeaderRowSticky", (tree, scrollTop) => {
|
|
141
155
|
var _tbody$firstChild;
|
|
142
156
|
// If header row height is more than 50% of viewport height don't do this
|
|
143
|
-
if (this.stickyRowHeight && this.stickyRowHeight > window.innerHeight / 2) {
|
|
157
|
+
if (this.isSticky || this.stickyRowHeight && this.stickyRowHeight > window.innerHeight / 2) {
|
|
144
158
|
return;
|
|
145
159
|
}
|
|
146
160
|
const {
|
|
@@ -160,10 +174,25 @@ export class TableRowNodeView {
|
|
|
160
174
|
}
|
|
161
175
|
const domTop = currentTableTop > 0 ? scrollTop : scrollTop + currentTableTop;
|
|
162
176
|
if (!this.isSticky) {
|
|
177
|
+
var _this$editorScrollabl;
|
|
163
178
|
syncStickyRowToTable(table);
|
|
164
179
|
this.dom.classList.add('sticky');
|
|
165
180
|
table.classList.add(ClassName.TABLE_STICKY);
|
|
166
181
|
this.isSticky = true;
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* The logic below is not desirable, but acts as a fail safe for scenarios where the sticky header
|
|
185
|
+
* detaches from the table. This typically happens during a fast scroll by the user which causes
|
|
186
|
+
* the intersection observer logic to not fire as expected.
|
|
187
|
+
*/
|
|
188
|
+
(_this$editorScrollabl = this.editorScrollableElement) === null || _this$editorScrollabl === void 0 ? void 0 : _this$editorScrollabl.addEventListener('scrollend', this.refireIntersectionObservers, {
|
|
189
|
+
passive: true,
|
|
190
|
+
once: true
|
|
191
|
+
});
|
|
192
|
+
const fastScrollThresholdMs = 500;
|
|
193
|
+
setTimeout(() => {
|
|
194
|
+
this.refireIntersectionObservers();
|
|
195
|
+
}, fastScrollThresholdMs);
|
|
167
196
|
}
|
|
168
197
|
this.dom.style.top = `${domTop}px`;
|
|
169
198
|
updateTableMargin(table);
|
|
@@ -245,8 +274,12 @@ export class TableRowNodeView {
|
|
|
245
274
|
this.eventDispatcher.on('widthPlugin', this.updateStickyHeaderWidth);
|
|
246
275
|
this.eventDispatcher.on(tablePluginKey.key, this.onTablePluginState);
|
|
247
276
|
this.listening = true;
|
|
248
|
-
this.dom.addEventListener('wheel', this.headerRowMouseScroll.bind(this)
|
|
249
|
-
|
|
277
|
+
this.dom.addEventListener('wheel', this.headerRowMouseScroll.bind(this), {
|
|
278
|
+
passive: true
|
|
279
|
+
});
|
|
280
|
+
this.dom.addEventListener('touchmove', this.headerRowMouseScroll.bind(this), {
|
|
281
|
+
passive: true
|
|
282
|
+
});
|
|
250
283
|
}
|
|
251
284
|
unsubscribe() {
|
|
252
285
|
if (!this.listening) {
|
|
@@ -255,7 +288,7 @@ export class TableRowNodeView {
|
|
|
255
288
|
if (this.intersectionObserver) {
|
|
256
289
|
this.intersectionObserver.disconnect();
|
|
257
290
|
// ED-16211 Once intersection observer is disconnected, we need to remove the isObserved from the sentinels
|
|
258
|
-
// Otherwise when
|
|
291
|
+
// Otherwise when newer intersection observer is created it will not observe because it thinks its already being observed
|
|
259
292
|
[this.sentinels.top, this.sentinels.bottom].forEach(el => {
|
|
260
293
|
if (el) {
|
|
261
294
|
delete el.dataset.isObserved;
|
|
@@ -316,10 +349,10 @@ export class TableRowNodeView {
|
|
|
316
349
|
table
|
|
317
350
|
} = this.tree;
|
|
318
351
|
entries.forEach(entry => {
|
|
319
|
-
var _this$
|
|
352
|
+
var _this$editorScrollabl2;
|
|
320
353
|
// On resize of the parent scroll element we need to adjust the width
|
|
321
354
|
// of the sticky header
|
|
322
|
-
if (entry.target.className === ((_this$
|
|
355
|
+
if (entry.target.className === ((_this$editorScrollabl2 = this.editorScrollableElement) === null || _this$editorScrollabl2 === void 0 ? void 0 : _this$editorScrollabl2.className)) {
|
|
323
356
|
this.updateStickyHeaderWidth();
|
|
324
357
|
} else {
|
|
325
358
|
const newHeight = entry.contentRect ? entry.contentRect.height : entry.target.offsetHeight;
|
|
@@ -28,15 +28,16 @@ var messages = defineMessages({
|
|
|
28
28
|
var handles = {
|
|
29
29
|
right: true
|
|
30
30
|
};
|
|
31
|
-
var
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
if (!tableHeight) {
|
|
37
|
-
return handleHeightSize;
|
|
31
|
+
var handleStyles = {
|
|
32
|
+
right: {
|
|
33
|
+
// eslint-disable-next-line
|
|
34
|
+
right: '-14px',
|
|
35
|
+
marginTop: "var(--ds-space-150, 12px)"
|
|
38
36
|
}
|
|
39
|
-
|
|
37
|
+
};
|
|
38
|
+
var getResizerHandleHeight = function getResizerHandleHeight(tableRef) {
|
|
39
|
+
var _tableRef$clientHeigh;
|
|
40
|
+
var tableHeight = (_tableRef$clientHeigh = tableRef === null || tableRef === void 0 ? void 0 : tableRef.clientHeight) !== null && _tableRef$clientHeigh !== void 0 ? _tableRef$clientHeigh : 0;
|
|
40
41
|
/*
|
|
41
42
|
- One row table height (minimum possible table height) ~ 45px
|
|
42
43
|
- Two row table height ~ 90px
|
|
@@ -45,12 +46,13 @@ var getResizerHandleHeight = function getResizerHandleHeight(tableRef) {
|
|
|
45
46
|
- > 46 because the height of the table can be a float number like 45.44.
|
|
46
47
|
- < 96 is the height of large resize handle.
|
|
47
48
|
*/
|
|
48
|
-
if (tableHeight
|
|
49
|
-
|
|
50
|
-
}
|
|
51
|
-
|
|
49
|
+
if (tableHeight >= 96) {
|
|
50
|
+
return 'large';
|
|
51
|
+
}
|
|
52
|
+
if (tableHeight > 46) {
|
|
53
|
+
return 'medium';
|
|
52
54
|
}
|
|
53
|
-
return
|
|
55
|
+
return 'small';
|
|
54
56
|
};
|
|
55
57
|
var getResizerMinWidth = function getResizerMinWidth(node) {
|
|
56
58
|
var currentColumnCount = getColgroupChildrenLength(node);
|
|
@@ -97,7 +99,7 @@ export var TableResizer = function TableResizer(_ref) {
|
|
|
97
99
|
var _useIntl = useIntl(),
|
|
98
100
|
formatMessage = _useIntl.formatMessage;
|
|
99
101
|
var resizerMinWidth = getResizerMinWidth(node);
|
|
100
|
-
var
|
|
102
|
+
var handleSize = getResizerHandleHeight(tableRef);
|
|
101
103
|
var _getPluginState = getPluginState(editorView.state),
|
|
102
104
|
isInDanger = _getPluginState.isInDanger;
|
|
103
105
|
var _useMeasureFramerate = useMeasureFramerate(),
|
|
@@ -234,8 +236,8 @@ export var TableResizer = function TableResizer(_ref) {
|
|
|
234
236
|
enable: handles,
|
|
235
237
|
width: width,
|
|
236
238
|
handleAlignmentMethod: "sticky",
|
|
237
|
-
|
|
238
|
-
|
|
239
|
+
handleSize: handleSize,
|
|
240
|
+
handleStyles: handleStyles,
|
|
239
241
|
handleResizeStart: handleResizeStart,
|
|
240
242
|
handleResize: scheduleResize,
|
|
241
243
|
handleResizeStop: handleResizeStop,
|
|
@@ -245,7 +247,6 @@ export var TableResizer = function TableResizer(_ref) {
|
|
|
245
247
|
snapGap: TABLE_SNAP_GAP,
|
|
246
248
|
snap: guidelineSnaps,
|
|
247
249
|
handlePositioning: "adjacent",
|
|
248
|
-
innerPadding: tableHandlePosition,
|
|
249
250
|
isHandleVisible: isTableSelected,
|
|
250
251
|
appearance: isInDanger && isTableSelected ? 'danger' : undefined,
|
|
251
252
|
handleHighlight: "shadow",
|
|
@@ -142,10 +142,24 @@ export var TableRowNodeView = /*#__PURE__*/function () {
|
|
|
142
142
|
// otherwise make it non-sticky
|
|
143
143
|
return false;
|
|
144
144
|
});
|
|
145
|
+
/**
|
|
146
|
+
* Manually refire the intersection observers.
|
|
147
|
+
* Useful when the header may have detached from the table.
|
|
148
|
+
*/
|
|
149
|
+
_defineProperty(this, "refireIntersectionObservers", function () {
|
|
150
|
+
if (_this.isSticky) {
|
|
151
|
+
[_this.sentinels.top, _this.sentinels.bottom].forEach(function (el) {
|
|
152
|
+
if (el && _this.intersectionObserver) {
|
|
153
|
+
_this.intersectionObserver.unobserve(el);
|
|
154
|
+
_this.intersectionObserver.observe(el);
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
});
|
|
145
159
|
_defineProperty(this, "makeHeaderRowSticky", function (tree, scrollTop) {
|
|
146
160
|
var _tbody$firstChild;
|
|
147
161
|
// If header row height is more than 50% of viewport height don't do this
|
|
148
|
-
if (_this.stickyRowHeight && _this.stickyRowHeight > window.innerHeight / 2) {
|
|
162
|
+
if (_this.isSticky || _this.stickyRowHeight && _this.stickyRowHeight > window.innerHeight / 2) {
|
|
149
163
|
return;
|
|
150
164
|
}
|
|
151
165
|
var table = tree.table,
|
|
@@ -163,10 +177,25 @@ export var TableRowNodeView = /*#__PURE__*/function () {
|
|
|
163
177
|
}
|
|
164
178
|
var domTop = currentTableTop > 0 ? scrollTop : scrollTop + currentTableTop;
|
|
165
179
|
if (!_this.isSticky) {
|
|
180
|
+
var _this$editorScrollabl;
|
|
166
181
|
syncStickyRowToTable(table);
|
|
167
182
|
_this.dom.classList.add('sticky');
|
|
168
183
|
table.classList.add(ClassName.TABLE_STICKY);
|
|
169
184
|
_this.isSticky = true;
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* The logic below is not desirable, but acts as a fail safe for scenarios where the sticky header
|
|
188
|
+
* detaches from the table. This typically happens during a fast scroll by the user which causes
|
|
189
|
+
* the intersection observer logic to not fire as expected.
|
|
190
|
+
*/
|
|
191
|
+
(_this$editorScrollabl = _this.editorScrollableElement) === null || _this$editorScrollabl === void 0 ? void 0 : _this$editorScrollabl.addEventListener('scrollend', _this.refireIntersectionObservers, {
|
|
192
|
+
passive: true,
|
|
193
|
+
once: true
|
|
194
|
+
});
|
|
195
|
+
var fastScrollThresholdMs = 500;
|
|
196
|
+
setTimeout(function () {
|
|
197
|
+
_this.refireIntersectionObservers();
|
|
198
|
+
}, fastScrollThresholdMs);
|
|
170
199
|
}
|
|
171
200
|
_this.dom.style.top = "".concat(domTop, "px");
|
|
172
201
|
updateTableMargin(table);
|
|
@@ -263,8 +292,12 @@ export var TableRowNodeView = /*#__PURE__*/function () {
|
|
|
263
292
|
this.eventDispatcher.on('widthPlugin', this.updateStickyHeaderWidth);
|
|
264
293
|
this.eventDispatcher.on(tablePluginKey.key, this.onTablePluginState);
|
|
265
294
|
this.listening = true;
|
|
266
|
-
this.dom.addEventListener('wheel', this.headerRowMouseScroll.bind(this)
|
|
267
|
-
|
|
295
|
+
this.dom.addEventListener('wheel', this.headerRowMouseScroll.bind(this), {
|
|
296
|
+
passive: true
|
|
297
|
+
});
|
|
298
|
+
this.dom.addEventListener('touchmove', this.headerRowMouseScroll.bind(this), {
|
|
299
|
+
passive: true
|
|
300
|
+
});
|
|
268
301
|
}
|
|
269
302
|
}, {
|
|
270
303
|
key: "unsubscribe",
|
|
@@ -275,7 +308,7 @@ export var TableRowNodeView = /*#__PURE__*/function () {
|
|
|
275
308
|
if (this.intersectionObserver) {
|
|
276
309
|
this.intersectionObserver.disconnect();
|
|
277
310
|
// ED-16211 Once intersection observer is disconnected, we need to remove the isObserved from the sentinels
|
|
278
|
-
// Otherwise when
|
|
311
|
+
// Otherwise when newer intersection observer is created it will not observe because it thinks its already being observed
|
|
279
312
|
[this.sentinels.top, this.sentinels.bottom].forEach(function (el) {
|
|
280
313
|
if (el) {
|
|
281
314
|
delete el.dataset.isObserved;
|
|
@@ -55,6 +55,11 @@ export declare class TableRowNodeView implements NodeView {
|
|
|
55
55
|
onTablePluginState: (state: TablePluginState) => void;
|
|
56
56
|
updateStickyHeaderWidth: () => void;
|
|
57
57
|
shouldHeaderStick: (tree: TableDOMElements) => boolean;
|
|
58
|
+
/**
|
|
59
|
+
* Manually refire the intersection observers.
|
|
60
|
+
* Useful when the header may have detached from the table.
|
|
61
|
+
*/
|
|
62
|
+
refireIntersectionObservers: () => void;
|
|
58
63
|
makeHeaderRowSticky: (tree: TableDOMElements, scrollTop?: number) => void;
|
|
59
64
|
makeRowHeaderNotSticky: (table: HTMLElement, isEditorDestroyed?: boolean) => void;
|
|
60
65
|
getWrapperoffset: (inverse?: boolean) => number;
|
|
@@ -55,6 +55,11 @@ export declare class TableRowNodeView implements NodeView {
|
|
|
55
55
|
onTablePluginState: (state: TablePluginState) => void;
|
|
56
56
|
updateStickyHeaderWidth: () => void;
|
|
57
57
|
shouldHeaderStick: (tree: TableDOMElements) => boolean;
|
|
58
|
+
/**
|
|
59
|
+
* Manually refire the intersection observers.
|
|
60
|
+
* Useful when the header may have detached from the table.
|
|
61
|
+
*/
|
|
62
|
+
refireIntersectionObservers: () => void;
|
|
58
63
|
makeHeaderRowSticky: (tree: TableDOMElements, scrollTop?: number) => void;
|
|
59
64
|
makeRowHeaderNotSticky: (table: HTMLElement, isEditorDestroyed?: boolean) => void;
|
|
60
65
|
getWrapperoffset: (inverse?: boolean) => number;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/editor-plugin-table",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0",
|
|
4
4
|
"description": "Table plugin for the @atlaskit/editor",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"registry": "https://registry.npmjs.org/"
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@atlaskit/adf-schema": "^29.1.0",
|
|
31
|
-
"@atlaskit/editor-common": "^
|
|
31
|
+
"@atlaskit/editor-common": "^76.0.0",
|
|
32
32
|
"@atlaskit/editor-palette": "1.5.1",
|
|
33
33
|
"@atlaskit/editor-plugin-analytics": "^0.2.0",
|
|
34
34
|
"@atlaskit/editor-plugin-content-insertion": "^0.1.0",
|
|
@@ -14,16 +14,14 @@ import type { TableEventPayload } from '@atlaskit/editor-common/analytics';
|
|
|
14
14
|
import { TABLE_OVERFLOW_CHANGE_TRIGGER } from '@atlaskit/editor-common/analytics';
|
|
15
15
|
import { getGuidelinesWithHighlights } from '@atlaskit/editor-common/guideline';
|
|
16
16
|
import type { GuidelineConfig } from '@atlaskit/editor-common/guideline';
|
|
17
|
-
import type {
|
|
18
|
-
HandleHeightSizeType,
|
|
19
|
-
HandleResize,
|
|
20
|
-
} from '@atlaskit/editor-common/resizer';
|
|
17
|
+
import type { HandleResize, HandleSize } from '@atlaskit/editor-common/resizer';
|
|
21
18
|
import { ResizerNext } from '@atlaskit/editor-common/resizer';
|
|
22
19
|
import type { Node as PMNode } from '@atlaskit/editor-prosemirror/model';
|
|
23
20
|
import type { Transaction } from '@atlaskit/editor-prosemirror/state';
|
|
24
21
|
import type { EditorView } from '@atlaskit/editor-prosemirror/view';
|
|
25
22
|
import { findTable } from '@atlaskit/editor-tables/utils';
|
|
26
23
|
import { getBooleanFF } from '@atlaskit/platform-feature-flags';
|
|
24
|
+
import { token } from '@atlaskit/tokens';
|
|
27
25
|
|
|
28
26
|
import { getPluginState } from '../pm-plugins/plugin-factory';
|
|
29
27
|
import { META_KEYS } from '../pm-plugins/table-analytics';
|
|
@@ -77,17 +75,18 @@ const messages = defineMessages({
|
|
|
77
75
|
});
|
|
78
76
|
|
|
79
77
|
const handles = { right: true };
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
if (!tableHeight) {
|
|
88
|
-
return handleHeightSize;
|
|
89
|
-
}
|
|
78
|
+
const handleStyles = {
|
|
79
|
+
right: {
|
|
80
|
+
// eslint-disable-next-line
|
|
81
|
+
right: '-14px',
|
|
82
|
+
marginTop: token('space.150', '12px'),
|
|
83
|
+
},
|
|
84
|
+
};
|
|
90
85
|
|
|
86
|
+
const getResizerHandleHeight = (
|
|
87
|
+
tableRef: HTMLTableElement | undefined,
|
|
88
|
+
): HandleSize | undefined => {
|
|
89
|
+
const tableHeight = tableRef?.clientHeight ?? 0;
|
|
91
90
|
/*
|
|
92
91
|
- One row table height (minimum possible table height) ~ 45px
|
|
93
92
|
- Two row table height ~ 90px
|
|
@@ -97,13 +96,15 @@ const getResizerHandleHeight = (tableRef: HTMLTableElement | undefined) => {
|
|
|
97
96
|
- > 46 because the height of the table can be a float number like 45.44.
|
|
98
97
|
- < 96 is the height of large resize handle.
|
|
99
98
|
*/
|
|
100
|
-
if (tableHeight
|
|
101
|
-
|
|
102
|
-
}
|
|
103
|
-
|
|
99
|
+
if (tableHeight >= 96) {
|
|
100
|
+
return 'large';
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (tableHeight > 46) {
|
|
104
|
+
return 'medium';
|
|
104
105
|
}
|
|
105
106
|
|
|
106
|
-
return
|
|
107
|
+
return 'small';
|
|
107
108
|
};
|
|
108
109
|
|
|
109
110
|
const getResizerMinWidth = (node: PMNode) => {
|
|
@@ -160,7 +161,7 @@ export const TableResizer = ({
|
|
|
160
161
|
const { formatMessage } = useIntl();
|
|
161
162
|
|
|
162
163
|
const resizerMinWidth = getResizerMinWidth(node);
|
|
163
|
-
const
|
|
164
|
+
const handleSize = getResizerHandleHeight(tableRef);
|
|
164
165
|
const { isInDanger } = getPluginState(editorView.state);
|
|
165
166
|
|
|
166
167
|
const { startMeasure, endMeasure, countFrames } = useMeasureFramerate();
|
|
@@ -389,8 +390,8 @@ export const TableResizer = ({
|
|
|
389
390
|
enable={handles}
|
|
390
391
|
width={width}
|
|
391
392
|
handleAlignmentMethod="sticky"
|
|
392
|
-
|
|
393
|
-
|
|
393
|
+
handleSize={handleSize}
|
|
394
|
+
handleStyles={handleStyles}
|
|
394
395
|
handleResizeStart={handleResizeStart}
|
|
395
396
|
handleResize={scheduleResize}
|
|
396
397
|
handleResizeStop={handleResizeStop}
|
|
@@ -400,7 +401,6 @@ export const TableResizer = ({
|
|
|
400
401
|
snapGap={TABLE_SNAP_GAP}
|
|
401
402
|
snap={guidelineSnaps}
|
|
402
403
|
handlePositioning="adjacent"
|
|
403
|
-
innerPadding={tableHandlePosition}
|
|
404
404
|
isHandleVisible={isTableSelected}
|
|
405
405
|
appearance={isInDanger && isTableSelected ? 'danger' : undefined}
|
|
406
406
|
handleHighlight="shadow"
|
|
@@ -150,10 +150,13 @@ export class TableRowNodeView implements NodeView {
|
|
|
150
150
|
|
|
151
151
|
this.listening = true;
|
|
152
152
|
|
|
153
|
-
this.dom.addEventListener('wheel', this.headerRowMouseScroll.bind(this)
|
|
153
|
+
this.dom.addEventListener('wheel', this.headerRowMouseScroll.bind(this), {
|
|
154
|
+
passive: true,
|
|
155
|
+
});
|
|
154
156
|
this.dom.addEventListener(
|
|
155
157
|
'touchmove',
|
|
156
158
|
this.headerRowMouseScroll.bind(this),
|
|
159
|
+
{ passive: true },
|
|
157
160
|
);
|
|
158
161
|
}
|
|
159
162
|
|
|
@@ -164,7 +167,7 @@ export class TableRowNodeView implements NodeView {
|
|
|
164
167
|
if (this.intersectionObserver) {
|
|
165
168
|
this.intersectionObserver.disconnect();
|
|
166
169
|
// ED-16211 Once intersection observer is disconnected, we need to remove the isObserved from the sentinels
|
|
167
|
-
// Otherwise when
|
|
170
|
+
// Otherwise when newer intersection observer is created it will not observe because it thinks its already being observed
|
|
168
171
|
[this.sentinels.top, this.sentinels.bottom].forEach((el) => {
|
|
169
172
|
if (el) {
|
|
170
173
|
delete el.dataset.isObserved;
|
|
@@ -522,9 +525,27 @@ export class TableRowNodeView implements NodeView {
|
|
|
522
525
|
return false;
|
|
523
526
|
};
|
|
524
527
|
|
|
528
|
+
/**
|
|
529
|
+
* Manually refire the intersection observers.
|
|
530
|
+
* Useful when the header may have detached from the table.
|
|
531
|
+
*/
|
|
532
|
+
refireIntersectionObservers = () => {
|
|
533
|
+
if (this.isSticky) {
|
|
534
|
+
[this.sentinels.top, this.sentinels.bottom].forEach((el) => {
|
|
535
|
+
if (el && this.intersectionObserver) {
|
|
536
|
+
this.intersectionObserver.unobserve(el);
|
|
537
|
+
this.intersectionObserver.observe(el);
|
|
538
|
+
}
|
|
539
|
+
});
|
|
540
|
+
}
|
|
541
|
+
};
|
|
542
|
+
|
|
525
543
|
makeHeaderRowSticky = (tree: TableDOMElements, scrollTop?: number) => {
|
|
526
544
|
// If header row height is more than 50% of viewport height don't do this
|
|
527
|
-
if (
|
|
545
|
+
if (
|
|
546
|
+
this.isSticky ||
|
|
547
|
+
(this.stickyRowHeight && this.stickyRowHeight > window.innerHeight / 2)
|
|
548
|
+
) {
|
|
528
549
|
return;
|
|
529
550
|
}
|
|
530
551
|
|
|
@@ -552,6 +573,22 @@ export class TableRowNodeView implements NodeView {
|
|
|
552
573
|
table.classList.add(ClassName.TABLE_STICKY);
|
|
553
574
|
|
|
554
575
|
this.isSticky = true;
|
|
576
|
+
|
|
577
|
+
/**
|
|
578
|
+
* The logic below is not desirable, but acts as a fail safe for scenarios where the sticky header
|
|
579
|
+
* detaches from the table. This typically happens during a fast scroll by the user which causes
|
|
580
|
+
* the intersection observer logic to not fire as expected.
|
|
581
|
+
*/
|
|
582
|
+
this.editorScrollableElement?.addEventListener(
|
|
583
|
+
'scrollend',
|
|
584
|
+
this.refireIntersectionObservers,
|
|
585
|
+
{ passive: true, once: true },
|
|
586
|
+
);
|
|
587
|
+
|
|
588
|
+
const fastScrollThresholdMs = 500;
|
|
589
|
+
setTimeout(() => {
|
|
590
|
+
this.refireIntersectionObservers();
|
|
591
|
+
}, fastScrollThresholdMs);
|
|
555
592
|
}
|
|
556
593
|
|
|
557
594
|
this.dom.style.top = `${domTop}px`;
|