@atlaskit/editor-plugin-table 42.2.9 → 42.3.1
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 +19 -0
- package/dist/cjs/ui/FloatingContextualButton/FixedButton.js +19 -3
- package/dist/cjs/ui/FloatingContextualButton/index.js +5 -0
- package/dist/cjs/ui/FloatingContextualButton/useCellLayoutVersion.js +58 -0
- package/dist/es2019/ui/FloatingContextualButton/FixedButton.js +18 -3
- package/dist/es2019/ui/FloatingContextualButton/index.js +5 -0
- package/dist/es2019/ui/FloatingContextualButton/useCellLayoutVersion.js +44 -0
- package/dist/esm/ui/FloatingContextualButton/FixedButton.js +20 -4
- package/dist/esm/ui/FloatingContextualButton/index.js +5 -0
- package/dist/esm/ui/FloatingContextualButton/useCellLayoutVersion.js +52 -0
- package/dist/types/ui/FloatingContextualButton/FixedButton.d.ts +3 -1
- package/dist/types/ui/FloatingContextualButton/useCellLayoutVersion.d.ts +7 -0
- package/package.json +8 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# @atlaskit/editor-plugin-table
|
|
2
2
|
|
|
3
|
+
## 42.3.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies
|
|
8
|
+
|
|
9
|
+
## 42.3.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- [`e495ce10dcb71`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/e495ce10dcb71) -
|
|
14
|
+
[EDITOR-9904] Keep the table cell options button on its header cell when the editor width or the
|
|
15
|
+
table's column widths change, with the header stuck or not, behind
|
|
16
|
+
platform_editor_sticky_cell_options_position
|
|
17
|
+
|
|
18
|
+
### Patch Changes
|
|
19
|
+
|
|
20
|
+
- Updated dependencies
|
|
21
|
+
|
|
3
22
|
## 42.2.9
|
|
4
23
|
|
|
5
24
|
### Patch Changes
|
|
@@ -28,7 +28,9 @@ var calcObserverTargetMargin = exports.calcObserverTargetMargin = function calcO
|
|
|
28
28
|
return fixedButtonRect.left - tableWrapperRect.left + scrollLeft;
|
|
29
29
|
};
|
|
30
30
|
var FixedButton = exports.FixedButton = function FixedButton(_ref2) {
|
|
31
|
-
var
|
|
31
|
+
var _ref2$cellLayoutVersi = _ref2.cellLayoutVersion,
|
|
32
|
+
cellLayoutVersion = _ref2$cellLayoutVersi === void 0 ? 0 : _ref2$cellLayoutVersi,
|
|
33
|
+
children = _ref2.children,
|
|
32
34
|
isContextualMenuOpen = _ref2.isContextualMenuOpen,
|
|
33
35
|
mountTo = _ref2.mountTo,
|
|
34
36
|
offset = _ref2.offset,
|
|
@@ -92,10 +94,24 @@ var FixedButton = exports.FixedButton = function FixedButton(_ref2) {
|
|
|
92
94
|
}
|
|
93
95
|
}, [fixedButtonRef, observerTargetRef, tableWrapper, targetCellPosition, targetCellRef, isContextualMenuOpen]);
|
|
94
96
|
var fixedButtonTop = 0;
|
|
97
|
+
|
|
98
|
+
// The left position below is read from the cell's current rect, which already includes the
|
|
99
|
+
// table's horizontal scroll, so the scroll translation accumulated so far must start again.
|
|
100
|
+
(0, _react.useLayoutEffect)(function () {
|
|
101
|
+
var fixedButtonRefCurrent = fixedButtonRef.current;
|
|
102
|
+
var observerTargetRefCurrent = observerTargetRef.current;
|
|
103
|
+
if (cellLayoutVersion === 0 || !fixedButtonRefCurrent || !observerTargetRefCurrent) {
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
fixedButtonRefCurrent.style.transform = '';
|
|
107
|
+
scrollDataRef.current = tableWrapper.scrollLeft;
|
|
108
|
+
leftPosDataRef.current = 0;
|
|
109
|
+
observerTargetRefCurrent.style.marginLeft = "".concat(calcObserverTargetMargin(tableWrapper, fixedButtonRefCurrent), "px");
|
|
110
|
+
}, [cellLayoutVersion, tableWrapper]);
|
|
95
111
|
var containerLeft = (0, _react.useMemo)(function () {
|
|
96
112
|
var container = targetCellRef.closest('[data-editor-container="true"]');
|
|
97
113
|
return (container === null || container === void 0 ? void 0 : container.getBoundingClientRect().left) || 0;
|
|
98
|
-
}, [targetCellRef]);
|
|
114
|
+
}, [targetCellRef, cellLayoutVersion]);
|
|
99
115
|
var left = (0, _react.useMemo)(function () {
|
|
100
116
|
var targetCellRect = targetCellRef.getBoundingClientRect();
|
|
101
117
|
var baseLeft = calcLeftPos({
|
|
@@ -105,7 +121,7 @@ var FixedButton = exports.FixedButton = function FixedButton(_ref2) {
|
|
|
105
121
|
offset: offset
|
|
106
122
|
});
|
|
107
123
|
return baseLeft - containerLeft;
|
|
108
|
-
}, [containerLeft, targetCellRef, offset]);
|
|
124
|
+
}, [containerLeft, targetCellRef, offset, cellLayoutVersion]);
|
|
109
125
|
|
|
110
126
|
// Using a portal here to ensure wrapperRef has the tableWrapper as an
|
|
111
127
|
// ancestor. This is required to make the Intersection Observer work.
|
|
@@ -29,6 +29,7 @@ var _types = require("../../types");
|
|
|
29
29
|
var _stickyHeaderZIndex = require("../sticky-header-z-index");
|
|
30
30
|
var _FixedButton = _interopRequireDefault(require("./FixedButton"));
|
|
31
31
|
var _styles = require("./styles");
|
|
32
|
+
var _useCellLayoutVersion = require("./useCellLayoutVersion");
|
|
32
33
|
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
|
|
33
34
|
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
34
35
|
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } /**
|
|
@@ -96,6 +97,9 @@ var FloatingContextualButtonInner = /*#__PURE__*/_react.default.memo(function (p
|
|
|
96
97
|
};
|
|
97
98
|
var domAtPos = editorView.domAtPos.bind(editorView);
|
|
98
99
|
var targetCellRef = (0, _utils.findDomRefAtPos)(targetCellPosition, domAtPos);
|
|
100
|
+
// Re-renders this component when the cell may have moved, so both FixedButton and Popup
|
|
101
|
+
// reposition: Popup recalculates its position whenever it receives new props.
|
|
102
|
+
var cellLayoutVersion = (0, _useCellLayoutVersion.useCellLayoutVersion)(targetCellRef);
|
|
99
103
|
(0, _react.useEffect)(function () {
|
|
100
104
|
if (isCellMenuOpenByKeyboard && !isCellMenuOpen) {
|
|
101
105
|
var state = editorView.state,
|
|
@@ -188,6 +192,7 @@ var FloatingContextualButtonInner = /*#__PURE__*/_react.default.memo(function (p
|
|
|
188
192
|
}
|
|
189
193
|
if (stickyHeader && parentSticky && tableWrapper) {
|
|
190
194
|
return (0, _react2.jsx)(_FixedButton.default, {
|
|
195
|
+
cellLayoutVersion: cellLayoutVersion,
|
|
191
196
|
offset: BUTTON_OFFSET,
|
|
192
197
|
stickyHeader: stickyHeader,
|
|
193
198
|
tableWrapper: tableWrapper,
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.useCellLayoutVersion = void 0;
|
|
8
|
+
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
|
9
|
+
var _react = require("react");
|
|
10
|
+
var _rafSchd = _interopRequireDefault(require("raf-schd"));
|
|
11
|
+
var _fg = require("@atlaskit/platform-feature-flags/fg");
|
|
12
|
+
/**
|
|
13
|
+
* Counts layout changes that can move the target cell without re-rendering the cell options
|
|
14
|
+
* button: the editor container resizing (window resize, side panel, product sidebar) or the table
|
|
15
|
+
* resizing (column scaling). Changing the count re-renders the button so it repositions on its
|
|
16
|
+
* cell. Stays 0 when the gate is off.
|
|
17
|
+
*/
|
|
18
|
+
var useCellLayoutVersion = exports.useCellLayoutVersion = function useCellLayoutVersion(targetCellRef) {
|
|
19
|
+
var _useState = (0, _react.useState)(0),
|
|
20
|
+
_useState2 = (0, _slicedToArray2.default)(_useState, 2),
|
|
21
|
+
layoutVersion = _useState2[0],
|
|
22
|
+
setLayoutVersion = _useState2[1];
|
|
23
|
+
(0, _react.useEffect)(function () {
|
|
24
|
+
if (!(0, _fg.fg)('platform_editor_sticky_cell_options_position')) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
if (!(targetCellRef instanceof HTMLElement)) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
var container = targetCellRef.closest('[data-editor-container="true"]');
|
|
31
|
+
var table = targetCellRef.closest('table');
|
|
32
|
+
var bumpLayoutVersion = (0, _rafSchd.default)(function () {
|
|
33
|
+
return setLayoutVersion(function (version) {
|
|
34
|
+
return version + 1;
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
var hasReceivedInitialEntries = false;
|
|
38
|
+
var observer = new ResizeObserver(function () {
|
|
39
|
+
// ResizeObserver reports every observed element once on observe(); that is not a move.
|
|
40
|
+
if (!hasReceivedInitialEntries) {
|
|
41
|
+
hasReceivedInitialEntries = true;
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
bumpLayoutVersion();
|
|
45
|
+
});
|
|
46
|
+
if (container) {
|
|
47
|
+
observer.observe(container);
|
|
48
|
+
}
|
|
49
|
+
if (table) {
|
|
50
|
+
observer.observe(table);
|
|
51
|
+
}
|
|
52
|
+
return function () {
|
|
53
|
+
observer.disconnect();
|
|
54
|
+
bumpLayoutVersion.cancel();
|
|
55
|
+
};
|
|
56
|
+
}, [targetCellRef]);
|
|
57
|
+
return layoutVersion;
|
|
58
|
+
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useEffect, useMemo, useRef } from 'react';
|
|
1
|
+
import React, { useEffect, useLayoutEffect, useMemo, useRef } from 'react';
|
|
2
2
|
import { createPortal } from 'react-dom';
|
|
3
3
|
import rafSchedule from 'raf-schd';
|
|
4
4
|
import { TableCssClassName as ClassName } from '../../types';
|
|
@@ -20,6 +20,7 @@ export const calcObserverTargetMargin = (tableWrapper, fixedButtonRefCurrent) =>
|
|
|
20
20
|
return fixedButtonRect.left - tableWrapperRect.left + scrollLeft;
|
|
21
21
|
};
|
|
22
22
|
export const FixedButton = ({
|
|
23
|
+
cellLayoutVersion = 0,
|
|
23
24
|
children,
|
|
24
25
|
isContextualMenuOpen,
|
|
25
26
|
mountTo,
|
|
@@ -85,10 +86,24 @@ export const FixedButton = ({
|
|
|
85
86
|
}
|
|
86
87
|
}, [fixedButtonRef, observerTargetRef, tableWrapper, targetCellPosition, targetCellRef, isContextualMenuOpen]);
|
|
87
88
|
const fixedButtonTop = 0;
|
|
89
|
+
|
|
90
|
+
// The left position below is read from the cell's current rect, which already includes the
|
|
91
|
+
// table's horizontal scroll, so the scroll translation accumulated so far must start again.
|
|
92
|
+
useLayoutEffect(() => {
|
|
93
|
+
const fixedButtonRefCurrent = fixedButtonRef.current;
|
|
94
|
+
const observerTargetRefCurrent = observerTargetRef.current;
|
|
95
|
+
if (cellLayoutVersion === 0 || !fixedButtonRefCurrent || !observerTargetRefCurrent) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
fixedButtonRefCurrent.style.transform = '';
|
|
99
|
+
scrollDataRef.current = tableWrapper.scrollLeft;
|
|
100
|
+
leftPosDataRef.current = 0;
|
|
101
|
+
observerTargetRefCurrent.style.marginLeft = `${calcObserverTargetMargin(tableWrapper, fixedButtonRefCurrent)}px`;
|
|
102
|
+
}, [cellLayoutVersion, tableWrapper]);
|
|
88
103
|
const containerLeft = useMemo(() => {
|
|
89
104
|
const container = targetCellRef.closest('[data-editor-container="true"]');
|
|
90
105
|
return (container === null || container === void 0 ? void 0 : container.getBoundingClientRect().left) || 0;
|
|
91
|
-
}, [targetCellRef]);
|
|
106
|
+
}, [targetCellRef, cellLayoutVersion]);
|
|
92
107
|
const left = useMemo(() => {
|
|
93
108
|
const targetCellRect = targetCellRef.getBoundingClientRect();
|
|
94
109
|
const baseLeft = calcLeftPos({
|
|
@@ -98,7 +113,7 @@ export const FixedButton = ({
|
|
|
98
113
|
offset
|
|
99
114
|
});
|
|
100
115
|
return baseLeft - containerLeft;
|
|
101
|
-
}, [containerLeft, targetCellRef, offset]);
|
|
116
|
+
}, [containerLeft, targetCellRef, offset, cellLayoutVersion]);
|
|
102
117
|
|
|
103
118
|
// Using a portal here to ensure wrapperRef has the tableWrapper as an
|
|
104
119
|
// ancestor. This is required to make the Intersection Observer work.
|
|
@@ -27,6 +27,7 @@ import { getTableZIndexes } from '../sticky-header-z-index';
|
|
|
27
27
|
// eslint-disable-next-line import/no-named-as-default
|
|
28
28
|
import FixedButton from './FixedButton';
|
|
29
29
|
import { tableFloatingCellButtonSelectedStyles, tableFloatingCellButtonStyles } from './styles';
|
|
30
|
+
import { useCellLayoutVersion } from './useCellLayoutVersion';
|
|
30
31
|
const BUTTON_OFFSET = 3;
|
|
31
32
|
const CONTEXTUAL_MENU_BUTTON_Z_INDEX = 2;
|
|
32
33
|
const anchorStyles = css({
|
|
@@ -95,6 +96,9 @@ const FloatingContextualButtonInner = /*#__PURE__*/React.memo(props => {
|
|
|
95
96
|
};
|
|
96
97
|
const domAtPos = editorView.domAtPos.bind(editorView);
|
|
97
98
|
const targetCellRef = findDomRefAtPos(targetCellPosition, domAtPos);
|
|
99
|
+
// Re-renders this component when the cell may have moved, so both FixedButton and Popup
|
|
100
|
+
// reposition: Popup recalculates its position whenever it receives new props.
|
|
101
|
+
const cellLayoutVersion = useCellLayoutVersion(targetCellRef);
|
|
98
102
|
useEffect(() => {
|
|
99
103
|
if (isCellMenuOpenByKeyboard && !isCellMenuOpen) {
|
|
100
104
|
const {
|
|
@@ -194,6 +198,7 @@ const FloatingContextualButtonInner = /*#__PURE__*/React.memo(props => {
|
|
|
194
198
|
}
|
|
195
199
|
if (stickyHeader && parentSticky && tableWrapper) {
|
|
196
200
|
return jsx(FixedButton, {
|
|
201
|
+
cellLayoutVersion: cellLayoutVersion,
|
|
197
202
|
offset: BUTTON_OFFSET,
|
|
198
203
|
stickyHeader: stickyHeader,
|
|
199
204
|
tableWrapper: tableWrapper,
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
|
+
import rafSchedule from 'raf-schd';
|
|
3
|
+
import { fg } from '@atlaskit/platform-feature-flags/fg';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Counts layout changes that can move the target cell without re-rendering the cell options
|
|
7
|
+
* button: the editor container resizing (window resize, side panel, product sidebar) or the table
|
|
8
|
+
* resizing (column scaling). Changing the count re-renders the button so it repositions on its
|
|
9
|
+
* cell. Stays 0 when the gate is off.
|
|
10
|
+
*/
|
|
11
|
+
export const useCellLayoutVersion = targetCellRef => {
|
|
12
|
+
const [layoutVersion, setLayoutVersion] = useState(0);
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
if (!fg('platform_editor_sticky_cell_options_position')) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
if (!(targetCellRef instanceof HTMLElement)) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
const container = targetCellRef.closest('[data-editor-container="true"]');
|
|
21
|
+
const table = targetCellRef.closest('table');
|
|
22
|
+
const bumpLayoutVersion = rafSchedule(() => setLayoutVersion(version => version + 1));
|
|
23
|
+
let hasReceivedInitialEntries = false;
|
|
24
|
+
const observer = new ResizeObserver(() => {
|
|
25
|
+
// ResizeObserver reports every observed element once on observe(); that is not a move.
|
|
26
|
+
if (!hasReceivedInitialEntries) {
|
|
27
|
+
hasReceivedInitialEntries = true;
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
bumpLayoutVersion();
|
|
31
|
+
});
|
|
32
|
+
if (container) {
|
|
33
|
+
observer.observe(container);
|
|
34
|
+
}
|
|
35
|
+
if (table) {
|
|
36
|
+
observer.observe(table);
|
|
37
|
+
}
|
|
38
|
+
return () => {
|
|
39
|
+
observer.disconnect();
|
|
40
|
+
bumpLayoutVersion.cancel();
|
|
41
|
+
};
|
|
42
|
+
}, [targetCellRef]);
|
|
43
|
+
return layoutVersion;
|
|
44
|
+
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useEffect, useMemo, useRef } from 'react';
|
|
1
|
+
import React, { useEffect, useLayoutEffect, useMemo, useRef } from 'react';
|
|
2
2
|
import { createPortal } from 'react-dom';
|
|
3
3
|
import rafSchedule from 'raf-schd';
|
|
4
4
|
import { TableCssClassName as ClassName } from '../../types';
|
|
@@ -19,7 +19,9 @@ export var calcObserverTargetMargin = function calcObserverTargetMargin(tableWra
|
|
|
19
19
|
return fixedButtonRect.left - tableWrapperRect.left + scrollLeft;
|
|
20
20
|
};
|
|
21
21
|
export var FixedButton = function FixedButton(_ref2) {
|
|
22
|
-
var
|
|
22
|
+
var _ref2$cellLayoutVersi = _ref2.cellLayoutVersion,
|
|
23
|
+
cellLayoutVersion = _ref2$cellLayoutVersi === void 0 ? 0 : _ref2$cellLayoutVersi,
|
|
24
|
+
children = _ref2.children,
|
|
23
25
|
isContextualMenuOpen = _ref2.isContextualMenuOpen,
|
|
24
26
|
mountTo = _ref2.mountTo,
|
|
25
27
|
offset = _ref2.offset,
|
|
@@ -83,10 +85,24 @@ export var FixedButton = function FixedButton(_ref2) {
|
|
|
83
85
|
}
|
|
84
86
|
}, [fixedButtonRef, observerTargetRef, tableWrapper, targetCellPosition, targetCellRef, isContextualMenuOpen]);
|
|
85
87
|
var fixedButtonTop = 0;
|
|
88
|
+
|
|
89
|
+
// The left position below is read from the cell's current rect, which already includes the
|
|
90
|
+
// table's horizontal scroll, so the scroll translation accumulated so far must start again.
|
|
91
|
+
useLayoutEffect(function () {
|
|
92
|
+
var fixedButtonRefCurrent = fixedButtonRef.current;
|
|
93
|
+
var observerTargetRefCurrent = observerTargetRef.current;
|
|
94
|
+
if (cellLayoutVersion === 0 || !fixedButtonRefCurrent || !observerTargetRefCurrent) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
fixedButtonRefCurrent.style.transform = '';
|
|
98
|
+
scrollDataRef.current = tableWrapper.scrollLeft;
|
|
99
|
+
leftPosDataRef.current = 0;
|
|
100
|
+
observerTargetRefCurrent.style.marginLeft = "".concat(calcObserverTargetMargin(tableWrapper, fixedButtonRefCurrent), "px");
|
|
101
|
+
}, [cellLayoutVersion, tableWrapper]);
|
|
86
102
|
var containerLeft = useMemo(function () {
|
|
87
103
|
var container = targetCellRef.closest('[data-editor-container="true"]');
|
|
88
104
|
return (container === null || container === void 0 ? void 0 : container.getBoundingClientRect().left) || 0;
|
|
89
|
-
}, [targetCellRef]);
|
|
105
|
+
}, [targetCellRef, cellLayoutVersion]);
|
|
90
106
|
var left = useMemo(function () {
|
|
91
107
|
var targetCellRect = targetCellRef.getBoundingClientRect();
|
|
92
108
|
var baseLeft = calcLeftPos({
|
|
@@ -96,7 +112,7 @@ export var FixedButton = function FixedButton(_ref2) {
|
|
|
96
112
|
offset: offset
|
|
97
113
|
});
|
|
98
114
|
return baseLeft - containerLeft;
|
|
99
|
-
}, [containerLeft, targetCellRef, offset]);
|
|
115
|
+
}, [containerLeft, targetCellRef, offset, cellLayoutVersion]);
|
|
100
116
|
|
|
101
117
|
// Using a portal here to ensure wrapperRef has the tableWrapper as an
|
|
102
118
|
// ancestor. This is required to make the Intersection Observer work.
|
|
@@ -30,6 +30,7 @@ import { getTableZIndexes } from '../sticky-header-z-index';
|
|
|
30
30
|
// eslint-disable-next-line import/no-named-as-default
|
|
31
31
|
import FixedButton from './FixedButton';
|
|
32
32
|
import { tableFloatingCellButtonSelectedStyles, tableFloatingCellButtonStyles } from './styles';
|
|
33
|
+
import { useCellLayoutVersion } from './useCellLayoutVersion';
|
|
33
34
|
var BUTTON_OFFSET = 3;
|
|
34
35
|
var CONTEXTUAL_MENU_BUTTON_Z_INDEX = 2;
|
|
35
36
|
var anchorStyles = css({
|
|
@@ -89,6 +90,9 @@ var FloatingContextualButtonInner = /*#__PURE__*/React.memo(function (props) {
|
|
|
89
90
|
};
|
|
90
91
|
var domAtPos = editorView.domAtPos.bind(editorView);
|
|
91
92
|
var targetCellRef = findDomRefAtPos(targetCellPosition, domAtPos);
|
|
93
|
+
// Re-renders this component when the cell may have moved, so both FixedButton and Popup
|
|
94
|
+
// reposition: Popup recalculates its position whenever it receives new props.
|
|
95
|
+
var cellLayoutVersion = useCellLayoutVersion(targetCellRef);
|
|
92
96
|
useEffect(function () {
|
|
93
97
|
if (isCellMenuOpenByKeyboard && !isCellMenuOpen) {
|
|
94
98
|
var state = editorView.state,
|
|
@@ -181,6 +185,7 @@ var FloatingContextualButtonInner = /*#__PURE__*/React.memo(function (props) {
|
|
|
181
185
|
}
|
|
182
186
|
if (stickyHeader && parentSticky && tableWrapper) {
|
|
183
187
|
return jsx(FixedButton, {
|
|
188
|
+
cellLayoutVersion: cellLayoutVersion,
|
|
184
189
|
offset: BUTTON_OFFSET,
|
|
185
190
|
stickyHeader: stickyHeader,
|
|
186
191
|
tableWrapper: tableWrapper,
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
|
2
|
+
import { useEffect, useState } from 'react';
|
|
3
|
+
import rafSchedule from 'raf-schd';
|
|
4
|
+
import { fg } from '@atlaskit/platform-feature-flags/fg';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Counts layout changes that can move the target cell without re-rendering the cell options
|
|
8
|
+
* button: the editor container resizing (window resize, side panel, product sidebar) or the table
|
|
9
|
+
* resizing (column scaling). Changing the count re-renders the button so it repositions on its
|
|
10
|
+
* cell. Stays 0 when the gate is off.
|
|
11
|
+
*/
|
|
12
|
+
export var useCellLayoutVersion = function useCellLayoutVersion(targetCellRef) {
|
|
13
|
+
var _useState = useState(0),
|
|
14
|
+
_useState2 = _slicedToArray(_useState, 2),
|
|
15
|
+
layoutVersion = _useState2[0],
|
|
16
|
+
setLayoutVersion = _useState2[1];
|
|
17
|
+
useEffect(function () {
|
|
18
|
+
if (!fg('platform_editor_sticky_cell_options_position')) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
if (!(targetCellRef instanceof HTMLElement)) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
var container = targetCellRef.closest('[data-editor-container="true"]');
|
|
25
|
+
var table = targetCellRef.closest('table');
|
|
26
|
+
var bumpLayoutVersion = rafSchedule(function () {
|
|
27
|
+
return setLayoutVersion(function (version) {
|
|
28
|
+
return version + 1;
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
var hasReceivedInitialEntries = false;
|
|
32
|
+
var observer = new ResizeObserver(function () {
|
|
33
|
+
// ResizeObserver reports every observed element once on observe(); that is not a move.
|
|
34
|
+
if (!hasReceivedInitialEntries) {
|
|
35
|
+
hasReceivedInitialEntries = true;
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
bumpLayoutVersion();
|
|
39
|
+
});
|
|
40
|
+
if (container) {
|
|
41
|
+
observer.observe(container);
|
|
42
|
+
}
|
|
43
|
+
if (table) {
|
|
44
|
+
observer.observe(table);
|
|
45
|
+
}
|
|
46
|
+
return function () {
|
|
47
|
+
observer.disconnect();
|
|
48
|
+
bumpLayoutVersion.cancel();
|
|
49
|
+
};
|
|
50
|
+
}, [targetCellRef]);
|
|
51
|
+
return layoutVersion;
|
|
52
|
+
};
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { RowStickyState } from '../../pm-plugins/sticky-headers/types';
|
|
3
3
|
interface Props {
|
|
4
|
+
/** Changes when the cell may have moved without a re-render; see `useCellLayoutVersion`. */
|
|
5
|
+
cellLayoutVersion?: number;
|
|
4
6
|
children: React.ReactNode;
|
|
5
7
|
isContextualMenuOpen: boolean | undefined;
|
|
6
8
|
mountTo: HTMLElement;
|
|
@@ -18,5 +20,5 @@ interface CalcLeftPosData {
|
|
|
18
20
|
}
|
|
19
21
|
export declare const calcLeftPos: ({ buttonWidth, cellRectLeft, cellRefWidth, offset, }: CalcLeftPosData) => number;
|
|
20
22
|
export declare const calcObserverTargetMargin: (tableWrapper: HTMLElement, fixedButtonRefCurrent: HTMLElement) => number;
|
|
21
|
-
export declare const FixedButton: ({ children, isContextualMenuOpen, mountTo, offset, stickyHeader, tableWrapper, targetCellPosition, targetCellRef, }: Props) => React.ReactPortal;
|
|
23
|
+
export declare const FixedButton: ({ cellLayoutVersion, children, isContextualMenuOpen, mountTo, offset, stickyHeader, tableWrapper, targetCellPosition, targetCellRef, }: Props) => React.ReactPortal;
|
|
22
24
|
export default FixedButton;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Counts layout changes that can move the target cell without re-rendering the cell options
|
|
3
|
+
* button: the editor container resizing (window resize, side panel, product sidebar) or the table
|
|
4
|
+
* resizing (column scaling). Changing the count re-renders the button so it repositions on its
|
|
5
|
+
* cell. Stays 0 when the gate is off.
|
|
6
|
+
*/
|
|
7
|
+
export declare const useCellLayoutVersion: (targetCellRef: Node | undefined) => number;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/editor-plugin-table",
|
|
3
|
-
"version": "42.
|
|
3
|
+
"version": "42.3.1",
|
|
4
4
|
"description": "Table plugin for the @atlaskit/editor",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"registry": "https://registry.npmjs.org/"
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"@atlaskit/editor-plugin-batch-attribute-updates": "^30.0.0",
|
|
30
30
|
"@atlaskit/editor-plugin-content-insertion": "^30.0.0",
|
|
31
31
|
"@atlaskit/editor-plugin-editor-viewmode": "^32.0.0",
|
|
32
|
-
"@atlaskit/editor-plugin-extension": "33.0.
|
|
32
|
+
"@atlaskit/editor-plugin-extension": "33.0.10",
|
|
33
33
|
"@atlaskit/editor-plugin-guideline": "^30.0.0",
|
|
34
34
|
"@atlaskit/editor-plugin-interaction": "^44.0.0",
|
|
35
35
|
"@atlaskit/editor-plugin-limited-mode": "^27.0.0",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"@atlaskit/pragmatic-drag-and-drop-auto-scroll": "^3.2.0",
|
|
54
54
|
"@atlaskit/pragmatic-drag-and-drop-hitbox": "^3.0.0",
|
|
55
55
|
"@atlaskit/primitives": "^22.6.0",
|
|
56
|
-
"@atlaskit/tmp-editor-statsig": "^
|
|
56
|
+
"@atlaskit/tmp-editor-statsig": "^254.0.0",
|
|
57
57
|
"@atlaskit/toggle": "^17.3.0",
|
|
58
58
|
"@atlaskit/tokens": "^20.9.0",
|
|
59
59
|
"@atlaskit/tooltip": "^24.4.0",
|
|
@@ -68,12 +68,15 @@
|
|
|
68
68
|
"uuid": "^11.1.1"
|
|
69
69
|
},
|
|
70
70
|
"peerDependencies": {
|
|
71
|
-
"@atlaskit/editor-common": "^134.
|
|
71
|
+
"@atlaskit/editor-common": "^134.7.0",
|
|
72
72
|
"react": "^18.2.0 || ^19.2.0",
|
|
73
73
|
"react-dom": "^18.2.0 || ^19.2.0",
|
|
74
74
|
"react-intl": "^5.25.1 || ^6.0.0 || ^7.0.0"
|
|
75
75
|
},
|
|
76
76
|
"platform-feature-flags": {
|
|
77
|
+
"platform_editor_sticky_cell_options_position": {
|
|
78
|
+
"type": "boolean"
|
|
79
|
+
},
|
|
77
80
|
"platform_editor_ai_suggestion_table_scroll_fix": {
|
|
78
81
|
"type": "boolean"
|
|
79
82
|
},
|
|
@@ -107,7 +110,7 @@
|
|
|
107
110
|
}
|
|
108
111
|
},
|
|
109
112
|
"devDependencies": {
|
|
110
|
-
"@atlaskit/editor-common": "^134.
|
|
113
|
+
"@atlaskit/editor-common": "^134.7.0",
|
|
111
114
|
"react": "^19.2.0",
|
|
112
115
|
"react-dom": "^19.2.0",
|
|
113
116
|
"react-intl": "^7.0.0"
|