@atlaskit/editor-plugin-table 24.4.16 → 24.4.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,27 @@
1
1
  # @atlaskit/editor-plugin-table
2
2
 
3
+ ## 24.4.18
4
+
5
+ ### Patch Changes
6
+
7
+ - [`08b7535d56701`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/08b7535d56701) -
8
+ Disable sticky headers for single-row tables and delay sticky corner masks until the native header
9
+ is active behind the table Q4 patch 4 experiment
10
+ - [`b5f13b4e19c45`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/b5f13b4e19c45) -
11
+ HOT-304844 Fixed table flicker issue when table is inside layout and selection moves in/out of
12
+ table.
13
+ - Updated dependencies
14
+
15
+ ## 24.4.17
16
+
17
+ ### Patch Changes
18
+
19
+ - [`161922d5b8cee`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/161922d5b8cee) -
20
+ Fix editor tooltips affected by inline top-layer rendering. Table cell menu tooltips are no longer
21
+ constrained by the button background selector, and layout column drag handles now own their
22
+ wrapper layout without flattening the tooltip's visual surface.
23
+ - Updated dependencies
24
+
3
25
  ## 24.4.16
4
26
 
5
27
  ### Patch Changes
@@ -600,15 +600,29 @@ var TableRow = exports.default = /*#__PURE__*/function (_TableNodeView) {
600
600
  if (isCurrentTableSelected) {
601
601
  this.colControlsOffset = _consts.tableControlsSpacing;
602
602
 
603
- // move table a little out of the way
604
- // to provide spacing for table controls
605
- if (isTableInsideLayout) {
606
- tableContentWrapper.style.paddingLeft = '11px';
603
+ /**
604
+ * Adding padding left causes flicker when table is inside layout column
605
+ * and selection moves in/out of table.
606
+ */
607
+ if (!(0, _platformFeatureFlags.fg)('platform_editor_table_flicker_issue')) {
608
+ // move table a little out of the way
609
+ // to provide spacing for table controls
610
+ if (isTableInsideLayout) {
611
+ tableContentWrapper.style.paddingLeft = '11px';
612
+ tableContentWrapper.style.marginLeft = '-11px';
613
+ }
607
614
  }
608
615
  } else {
609
616
  this.colControlsOffset = 0;
610
- if (isTableInsideLayout) {
611
- tableContentWrapper.style.removeProperty('padding-left');
617
+ /**
618
+ * Adding padding left causes flicker when table is inside layout column
619
+ * and selection moves in/out of table.
620
+ */
621
+ if (!(0, _platformFeatureFlags.fg)('platform_editor_table_flicker_issue')) {
622
+ if (isTableInsideLayout) {
623
+ tableContentWrapper.style.removeProperty('padding-left');
624
+ tableContentWrapper.style.removeProperty('margin-left');
625
+ }
612
626
  }
613
627
  }
614
628
  }
@@ -82,6 +82,7 @@ var TableRowNativeStickyWithFallback = exports.default = /*#__PURE__*/function (
82
82
  (0, _defineProperty2.default)(_this, "top", 0);
83
83
  (0, _defineProperty2.default)(_this, "hasScrolledSinceLoad", false);
84
84
  (0, _defineProperty2.default)(_this, "disableNativeSticky", false);
85
+ (0, _defineProperty2.default)(_this, "isSingleRowTable", false);
85
86
  /**
86
87
  * Methods
87
88
  */
@@ -109,6 +110,9 @@ var TableRowNativeStickyWithFallback = exports.default = /*#__PURE__*/function (
109
110
  }
110
111
  });
111
112
  _this.isHeaderRow = (0, _nodes.supportedHeaderRow)(node);
113
+ if (_this.isHeaderRow && (0, _expValEquals.expValEquals)('platform_editor_table_q4_patch_4', 'isEnabled', true)) {
114
+ _this.isSingleRowTable = _this.checkIsSingleRowTable();
115
+ }
112
116
  _this.isLegacySticky = false;
113
117
  var _getPluginState = (0, _pluginFactory.getPluginState)(view.state),
114
118
  pluginConfig = _getPluginState.pluginConfig;
@@ -187,6 +191,10 @@ var TableRowNativeStickyWithFallback = exports.default = /*#__PURE__*/function (
187
191
  // Ignored via go/ees005
188
192
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
189
193
  function update(node) {
194
+ if (this.isHeaderRow && (0, _expValEquals.expValEquals)('platform_editor_table_q4_patch_4', 'isEnabled', true)) {
195
+ this.updateSingleRowTableStickyHeaderState();
196
+ }
197
+
190
198
  // do nothing if nodes were identical
191
199
  if (node === this.node) {
192
200
  return true;
@@ -297,6 +305,9 @@ var TableRowNativeStickyWithFallback = exports.default = /*#__PURE__*/function (
297
305
  * be cleaned up.
298
306
  */
299
307
  entries.forEach(function (entry) {
308
+ if ((0, _expValEquals.expValEquals)('platform_editor_table_q4_patch_4', 'isEnabled', true) && _this3.updateSingleRowTableStickyHeaderState()) {
309
+ return;
310
+ }
300
311
  var tableWrapper = _this3.dom.closest(".".concat(_types.TableCssClassName.TABLE_NODE_WRAPPER));
301
312
  if (tableWrapper && tableWrapper instanceof HTMLElement && !(0, _dom2.areAllRectsZero)(entry)) {
302
313
  if (entry.isIntersecting) {
@@ -391,6 +402,9 @@ var TableRowNativeStickyWithFallback = exports.default = /*#__PURE__*/function (
391
402
  if (!(observer.root instanceof HTMLElement)) {
392
403
  return;
393
404
  }
405
+ if ((0, _expValEquals.expValEquals)('platform_editor_table_q4_patch_4', 'isEnabled', true) && _this4.updateSingleRowTableStickyHeaderState()) {
406
+ return;
407
+ }
394
408
  // Only apply classes if page has scrolled since load
395
409
  if (!_this4.hasScrolledSinceLoad) {
396
410
  _this4.overflowObserverEntries = entries;
@@ -441,6 +455,9 @@ var TableRowNativeStickyWithFallback = exports.default = /*#__PURE__*/function (
441
455
  this.stickyStateObserver = new IntersectionObserver(function (entries) {
442
456
  entries.forEach(function (entry) {
443
457
  var _entry$rootBounds;
458
+ if ((0, _expValEquals.expValEquals)('platform_editor_table_q4_patch_4', 'isEnabled', true) && _this5.updateSingleRowTableStickyHeaderState()) {
459
+ return;
460
+ }
444
461
  var tableContainer = _this5.dom.closest(".".concat(_types.TableCssClassName.TABLE_CONTAINER));
445
462
  if (entry.intersectionRect.top === ((_entry$rootBounds = entry.rootBounds) === null || _entry$rootBounds === void 0 ? void 0 : _entry$rootBounds.top) && !_this5.disableNativeSticky) {
446
463
  _this5.dom.classList.add(_types.TableCssClassName.NATIVE_STICKY_ACTIVE);
@@ -579,6 +596,9 @@ var TableRowNativeStickyWithFallback = exports.default = /*#__PURE__*/function (
579
596
  var _this7 = this;
580
597
  this.nodeVisibilityObserver = new IntersectionObserver(function (entries) {
581
598
  entries.forEach(function (entry) {
599
+ if ((0, _expValEquals.expValEquals)('platform_editor_table_q4_patch_4', 'isEnabled', true) && _this7.updateSingleRowTableStickyHeaderState()) {
600
+ return;
601
+ }
582
602
  if (!_this7.isNativeSticky) {
583
603
  return;
584
604
  }
@@ -671,6 +691,9 @@ var TableRowNativeStickyWithFallback = exports.default = /*#__PURE__*/function (
671
691
  }, {
672
692
  key: "refreshLegacyStickyState",
673
693
  value: function refreshLegacyStickyState() {
694
+ if ((0, _expValEquals.expValEquals)('platform_editor_table_q4_patch_4', 'isEnabled', true) && this.updateSingleRowTableStickyHeaderState()) {
695
+ return;
696
+ }
674
697
  var tree = (0, _dom2.getTree)(this.dom);
675
698
  if (!tree) {
676
699
  return;
@@ -822,15 +845,27 @@ var TableRowNativeStickyWithFallback = exports.default = /*#__PURE__*/function (
822
845
  if (isCurrentTableSelected) {
823
846
  this.colControlsOffset = _consts.tableControlsSpacing;
824
847
 
825
- // move table a little out of the way
826
- // to provide spacing for table controls
827
- if (isTableInsideLayout) {
828
- tableContentWrapper.style.paddingLeft = '11px';
848
+ /**
849
+ * Adding padding left causes flicker when table is inside layout column
850
+ * and selection moves in/out of table.
851
+ */
852
+ if (!(0, _platformFeatureFlags.fg)('platform_editor_table_flicker_issue')) {
853
+ // move table a little out of the way
854
+ // to provide spacing for table controls
855
+ if (isTableInsideLayout) {
856
+ tableContentWrapper.style.paddingLeft = '11px';
857
+ }
829
858
  }
830
859
  } else {
831
860
  this.colControlsOffset = 0;
832
- if (isTableInsideLayout) {
833
- tableContentWrapper.style.removeProperty('padding-left');
861
+ /**
862
+ * Adding padding left causes flicker when table is inside layout column
863
+ * and selection moves in/out of table.
864
+ */
865
+ if (!(0, _platformFeatureFlags.fg)('platform_editor_table_flicker_issue')) {
866
+ if (isTableInsideLayout) {
867
+ tableContentWrapper.style.removeProperty('padding-left');
868
+ }
834
869
  }
835
870
  }
836
871
  }
@@ -868,11 +903,75 @@ var TableRowNativeStickyWithFallback = exports.default = /*#__PURE__*/function (
868
903
  });
869
904
  }
870
905
  }
906
+ }, {
907
+ key: "checkIsSingleRowTable",
908
+ value: function checkIsSingleRowTable() {
909
+ var _this1 = this;
910
+ var pos = this.getPos();
911
+ if (typeof pos !== 'number') {
912
+ return false;
913
+ }
914
+ try {
915
+ var _findParentNodeCloses3;
916
+ var $tableRowPos = this.view.state.doc.resolve(pos);
917
+ var tableNode = (_findParentNodeCloses3 = (0, _utils.findParentNodeClosestToPos)($tableRowPos, function (node) {
918
+ return node.type === _this1.view.state.schema.nodes.table;
919
+ })) === null || _findParentNodeCloses3 === void 0 ? void 0 : _findParentNodeCloses3.node;
920
+ return (tableNode === null || tableNode === void 0 ? void 0 : tableNode.childCount) === 1;
921
+ } catch (_unused3) {
922
+ // getPos can return stale positions during AI streaming. Preserve the original sticky
923
+ // header behaviour when the containing table cannot be determined.
924
+ return false;
925
+ }
926
+ }
927
+ }, {
928
+ key: "updateSingleRowTableStickyHeaderState",
929
+ value: function updateSingleRowTableStickyHeaderState() {
930
+ var wasSingleRowTable = this.isSingleRowTable;
931
+ this.isSingleRowTable = this.checkIsSingleRowTable();
932
+ if (this.isSingleRowTable) {
933
+ this.removeSingleRowTableStickyHeaderState();
934
+ } else if (wasSingleRowTable) {
935
+ this.refireNativeStickyObservers();
936
+ }
937
+ return this.isSingleRowTable;
938
+ }
939
+ }, {
940
+ key: "removeSingleRowTableStickyHeaderState",
941
+ value: function removeSingleRowTableStickyHeaderState() {
942
+ this.dom.classList.remove(_types.TableCssClassName.NATIVE_STICKY, _types.TableCssClassName.NATIVE_STICKY_ACTIVE);
943
+ this.isNativeSticky = false;
944
+ var tableWrapper = this.dom.closest(".".concat(_types.TableCssClassName.TABLE_NODE_WRAPPER));
945
+ tableWrapper === null || tableWrapper === void 0 || tableWrapper.classList.remove(_types.TableCssClassName.TABLE_NODE_WRAPPER_NO_OVERFLOW);
946
+ var tableContainer = this.dom.closest(".".concat(_types.TableCssClassName.TABLE_CONTAINER));
947
+ if (tableContainer instanceof HTMLElement) {
948
+ delete tableContainer.dataset.tableHeaderIsStuck;
949
+ }
950
+ var tree = (0, _dom2.getTree)(this.dom);
951
+ if (tree) {
952
+ this.makeRowHeaderNotLegacySticky(tree.table);
953
+ }
954
+ }
955
+ }, {
956
+ key: "refireNativeStickyObservers",
957
+ value: function refireNativeStickyObservers() {
958
+ var _this$stickyStateObse2, _this$stickyStateObse3;
959
+ var table = this.dom.closest('table');
960
+ if (table) {
961
+ var _this$overflowObserve2, _this$overflowObserve3, _this$nodeVisibilityO3, _this$nodeVisibilityO4;
962
+ (_this$overflowObserve2 = this.overflowObserver) === null || _this$overflowObserve2 === void 0 || _this$overflowObserve2.unobserve(table);
963
+ (_this$overflowObserve3 = this.overflowObserver) === null || _this$overflowObserve3 === void 0 || _this$overflowObserve3.observe(table);
964
+ (_this$nodeVisibilityO3 = this.nodeVisibilityObserver) === null || _this$nodeVisibilityO3 === void 0 || _this$nodeVisibilityO3.unobserve(table);
965
+ (_this$nodeVisibilityO4 = this.nodeVisibilityObserver) === null || _this$nodeVisibilityO4 === void 0 || _this$nodeVisibilityO4.observe(table);
966
+ }
967
+ (_this$stickyStateObse2 = this.stickyStateObserver) === null || _this$stickyStateObse2 === void 0 || _this$stickyStateObse2.unobserve(this.dom);
968
+ (_this$stickyStateObse3 = this.stickyStateObserver) === null || _this$stickyStateObse3 === void 0 || _this$stickyStateObse3.observe(this.dom);
969
+ }
871
970
  }, {
872
971
  key: "makeHeaderRowLegacySticky",
873
972
  value: function makeHeaderRowLegacySticky(tree, scrollTop) {
874
973
  var _tbody$firstChild,
875
- _this1 = this;
974
+ _this10 = this;
876
975
  // If header row height is more than 50% of viewport height don't do this
877
976
  if (this.isLegacySticky || this.stickyRowHeight && this.stickyRowHeight > window.innerHeight / 2 || this.isInNestedTable) {
878
977
  return;
@@ -911,7 +1010,7 @@ var TableRowNativeStickyWithFallback = exports.default = /*#__PURE__*/function (
911
1010
  });
912
1011
  var fastScrollThresholdMs = 500;
913
1012
  setTimeout(function () {
914
- _this1.refireIntersectionObservers();
1013
+ _this10.refireIntersectionObservers();
915
1014
  }, fastScrollThresholdMs);
916
1015
  }
917
1016
  this.dom.style.top = "0px";
@@ -5,11 +5,57 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.tableFloatingCellButtonStyles = exports.tableFloatingCellButtonSelectedStyles = void 0;
7
7
  var _react = require("@emotion/react");
8
+ var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
8
9
  var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
9
10
  var _consts = require("../consts");
10
11
  // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
11
12
 
12
- var tableFloatingCellButtonStyles = exports.tableFloatingCellButtonStyles = function tableFloatingCellButtonStyles() {
13
+ // Excludes the inlined top-layer tooltip popover from the background box selector so it isn't squished.
14
+ var topLayerTooltipCellButtonStyles = function topLayerTooltipCellButtonStyles() {
15
+ return (0, _react.css)({
16
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors -- Ignored via go/DSP-18766
17
+ '> div:not([popover])': {
18
+ // Sits behind button to provide surface-color background
19
+ background: "var(--ds-surface, #FFFFFF)",
20
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values, @atlaskit/ui-styling-standard/no-unsafe-values
21
+ borderRadius: (0, _expValEquals.expValEquals)('platform_editor_table_q4_loveability', 'isEnabled', true) ? "var(--ds-radius-small, 4px)" : "var(--ds-radius-small, 3px)",
22
+ display: 'flex',
23
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values, @atlaskit/ui-styling-standard/no-unsafe-values -- Ignored via go/DSP-18766
24
+ height: "".concat(_consts.contextualMenuTriggerSize + 2, "px"),
25
+ width: "var(--ds-space-250, 20px)",
26
+ flexDirection: 'column'
27
+ },
28
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors -- Ignored via go/DSP-18766
29
+ '&& button': {
30
+ background: "var(--ds-background-neutral, #0515240F)",
31
+ flexDirection: 'column',
32
+ margin: "var(--ds-space-025, 2px)",
33
+ outline: "2px solid ".concat("var(--ds-surface, #FFFFFF)"),
34
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values, @atlaskit/ui-styling-standard/no-unsafe-values
35
+ borderRadius: (0, _expValEquals.expValEquals)('platform_editor_table_q4_loveability', 'isEnabled', true) ? "var(--ds-radius-xsmall, 2px)" : '1px',
36
+ padding: 0,
37
+ height: 'calc(100% - 4px)',
38
+ display: 'flex'
39
+ },
40
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors -- Ignored via go/DSP-18766
41
+ '&& button:hover': {
42
+ background: "var(--ds-background-neutral-hovered, #0B120E24)"
43
+ },
44
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors -- Ignored via go/DSP-18766
45
+ '&& button:active': {
46
+ background: "var(--ds-background-neutral-pressed, #080F214A)"
47
+ },
48
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors -- Ignored via go/DSP-18766
49
+ '&& button > span': {
50
+ margin: "0px ".concat("var(--ds-space-negative-050, -4px)")
51
+ },
52
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors -- Ignored via go/DSP-18766
53
+ '&& span': {
54
+ pointerEvents: 'none'
55
+ }
56
+ });
57
+ };
58
+ var legacyCellButtonStyles = function legacyCellButtonStyles() {
13
59
  return (0, _react.css)({
14
60
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors -- Ignored via go/DSP-18766
15
61
  '> div': {
@@ -53,6 +99,9 @@ var tableFloatingCellButtonStyles = exports.tableFloatingCellButtonStyles = func
53
99
  }
54
100
  });
55
101
  };
102
+ var tableFloatingCellButtonStyles = exports.tableFloatingCellButtonStyles = function tableFloatingCellButtonStyles() {
103
+ return (0, _platformFeatureFlags.fg)('platform-dst-top-layer-tooltip') ? topLayerTooltipCellButtonStyles() : legacyCellButtonStyles();
104
+ };
56
105
  var tableFloatingCellButtonSelectedStyles = exports.tableFloatingCellButtonSelectedStyles = function tableFloatingCellButtonSelectedStyles() {
57
106
  return (0, _react.css)({
58
107
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors -- Ignored via go/DSP-18766
@@ -10,6 +10,7 @@ var _react = require("@emotion/react");
10
10
  var _styles = require("@atlaskit/editor-common/styles");
11
11
  var _editorSharedStyles = require("@atlaskit/editor-shared-styles");
12
12
  var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
13
+ var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
13
14
  var _types = require("../types");
14
15
  var _consts = require("./consts");
15
16
  var _templateObject, _templateObject2, _templateObject3, _templateObject4, _templateObject5, _templateObject6, _templateObject7, _templateObject8, _templateObject9, _templateObject0, _templateObject1, _templateObject10, _templateObject11;
@@ -49,7 +50,7 @@ var roundedTableStickyHeaderNumberColumnStyles = function roundedTableStickyHead
49
50
  return (0, _react.css)(_templateObject7 || (_templateObject7 = (0, _taggedTemplateLiteral2.default)(["\n\t.", "[data-number-column='true'] .", " tr th[data-reaches-top][data-reaches-left]::before,\n\t.", "[data-number-column='true'] .", " tr.", " th[data-reaches-left]::before,\n\t.", "[data-number-column='true'] .", " .", " th[data-reaches-left]::before {\n\t\tborder-top-left-radius: ", ";\n\t\tborder-bottom: none;\n\t}\n"])), _types.TableCssClassName.TABLE_CONTAINER, _types.TableCssClassName.TABLE_NODE_WRAPPER_NO_OVERFLOW, _types.TableCssClassName.TABLE_CONTAINER, _types.TableCssClassName.TABLE_NODE_WRAPPER_NO_OVERFLOW, _types.TableCssClassName.NATIVE_STICKY, _types.TableCssClassName.TABLE_CONTAINER, _types.TableCssClassName.TABLE_NODE_WRAPPER_NO_OVERFLOW, _types.TableCssClassName.NATIVE_STICKY_ACTIVE, "var(--ds-radius-xlarge, 12px)");
50
51
  };
51
52
  var roundedTableStickyHeaderCornerMaskStyles = function roundedTableStickyHeaderCornerMaskStyles() {
52
- return (0, _react.css)(_templateObject8 || (_templateObject8 = (0, _taggedTemplateLiteral2.default)(["\n\t/* Same z-index as the sticky row; DOM order keeps the row above this mask and the table border below it. */\n\t.", " {\n\t\tdisplay: none;\n\t\tposition: sticky;\n\t\ttop: calc(", "px - 1px);\n\t\twidth: 12px;\n\t\theight: 12px;\n\t\tmargin-bottom: -12px;\n\t\tbackground: ", ";\n\t\tpointer-events: none;\n\t\tz-index: ", ";\n\t}\n\n\t.", "[data-number-column='true']\n\t\t.", "[data-corner='left'] {\n\t\tmargin-left: -", "px;\n\t}\n\n\t.", "[data-corner='right'] {\n\t\tleft: calc(100% - 11px);\n\t}\n\n\t/*\n\t\tScope the :has() selectors to a DIRECT child table so a nested table that\n\t\thas its own sticky row does not pull the OUTER wrapper's masks into the\n\t\tsticky / fallback layout. The masks belong to the wrapper of the table\n\t\tthat owns the sticky row, never to an ancestor wrapper.\n\t*/\n\t.", ":has(> table > tbody > tr.", ")\n\t\t> .", ",\n\t\t.", ":has(> table.", " > tbody > tr.sticky)\n\t\t> .", " {\n\t\tdisplay: block;\n\t}\n\n\t/*\n\t\tWhen the table overflows horizontally, sticky headers fall back from native\n\t\tposition: sticky to a fixed-position header row. Match that positioning so\n\t\tthe corner masks continue to cover the rounded corners in the fallback path.\n\n\t\tThe direct-child combinator inside :has() is critical: without it a nested\n\t\ttable entering the legacy fallback would incorrectly trigger this rule on\n\t\tthe OUTER wrapper, detaching the outer table's masks from its corners.\n\t*/\n\t.", ":has(> table.", " > tbody > tr.sticky)\n\t\t> .", " {\n\t\tposition: fixed;\n\t\ttop: 30px;\n\t\tz-index: 1;\n\t}\n"])), _types.TableCssClassName.TABLE_CORNER_MASK, _styles.tableMarginTop, "var(--ds-surface, #FFFFFF)", _consts.nativeStickyHeaderZIndex, _types.TableCssClassName.TABLE_CONTAINER, _types.TableCssClassName.TABLE_CORNER_MASK, _editorSharedStyles.akEditorTableNumberColumnWidth, _types.TableCssClassName.TABLE_CORNER_MASK, _types.TableCssClassName.TABLE_NODE_WRAPPER, _types.TableCssClassName.NATIVE_STICKY_ACTIVE, _types.TableCssClassName.TABLE_CORNER_MASK, _types.TableCssClassName.TABLE_NODE_WRAPPER, _types.TableCssClassName.TABLE_STICKY, _types.TableCssClassName.TABLE_CORNER_MASK, _types.TableCssClassName.TABLE_NODE_WRAPPER, _types.TableCssClassName.TABLE_STICKY, _types.TableCssClassName.TABLE_CORNER_MASK);
53
+ return (0, _react.css)(_templateObject8 || (_templateObject8 = (0, _taggedTemplateLiteral2.default)(["\n\t/* Same z-index as the sticky row; DOM order keeps the row above this mask and the table border below it. */\n\t.", " {\n\t\tdisplay: none;\n\t\tposition: sticky;\n\t\ttop: calc(", "px - 1px);\n\t\twidth: 12px;\n\t\theight: 12px;\n\t\tmargin-bottom: -12px;\n\t\tbackground: ", ";\n\t\tpointer-events: none;\n\t\tz-index: ", ";\n\t}\n\n\t.", "[data-number-column='true']\n\t\t.", "[data-corner='left'] {\n\t\tmargin-left: -", "px;\n\t}\n\n\t.", "[data-corner='right'] {\n\t\tleft: calc(100% - 11px);\n\t}\n\n\t/*\n\t\tScope the :has() selectors to a DIRECT child table so a nested table that\n\t\thas its own sticky row does not pull the OUTER wrapper's masks into the\n\t\tsticky / fallback layout. The masks belong to the wrapper of the table\n\t\tthat owns the sticky row, never to an ancestor wrapper.\n\t*/\n\t.", ":has(> table > tbody > tr.", ")\n\t\t> .", ",\n\t\t.", ":has(> table.", " > tbody > tr.sticky)\n\t\t> .", " {\n\t\tdisplay: block;\n\t}\n\n\t/*\n\t\tWhen the table overflows horizontally, sticky headers fall back from native\n\t\tposition: sticky to a fixed-position header row. Match that positioning so\n\t\tthe corner masks continue to cover the rounded corners in the fallback path.\n\n\t\tThe direct-child combinator inside :has() is critical: without it a nested\n\t\ttable entering the legacy fallback would incorrectly trigger this rule on\n\t\tthe OUTER wrapper, detaching the outer table's masks from its corners.\n\t*/\n\t.", ":has(> table.", " > tbody > tr.sticky)\n\t\t> .", " {\n\t\tposition: fixed;\n\t\ttop: 30px;\n\t\tz-index: 1;\n\t}\n"])), _types.TableCssClassName.TABLE_CORNER_MASK, _styles.tableMarginTop, "var(--ds-surface, #FFFFFF)", _consts.nativeStickyHeaderZIndex, _types.TableCssClassName.TABLE_CONTAINER, _types.TableCssClassName.TABLE_CORNER_MASK, _editorSharedStyles.akEditorTableNumberColumnWidth, _types.TableCssClassName.TABLE_CORNER_MASK, _types.TableCssClassName.TABLE_NODE_WRAPPER, (0, _expValEquals.expValEquals)('platform_editor_table_q4_patch_4', 'isEnabled', true) ? "".concat(_types.TableCssClassName.NATIVE_STICKY, ".").concat(_types.TableCssClassName.NATIVE_STICKY_ACTIVE) : _types.TableCssClassName.NATIVE_STICKY_ACTIVE, _types.TableCssClassName.TABLE_CORNER_MASK, _types.TableCssClassName.TABLE_NODE_WRAPPER, _types.TableCssClassName.TABLE_STICKY, _types.TableCssClassName.TABLE_CORNER_MASK, _types.TableCssClassName.TABLE_NODE_WRAPPER, _types.TableCssClassName.TABLE_STICKY, _types.TableCssClassName.TABLE_CORNER_MASK);
53
54
  };
54
55
  var roundedTableStickyHeaderOverlayStyles = function roundedTableStickyHeaderOverlayStyles() {
55
56
  return (0, _react.css)(_templateObject9 || (_templateObject9 = (0, _taggedTemplateLiteral2.default)(["\n\t/*\n\t\tPaint the pinned sticky row's rounded top edge via each cell's ::after.\n\t\ttop: -1px places it in the reserved transparent border slot, aligned with\n\t\tthe row's inset-shadow bottom border. Longhand border-top-* lets\n\t\tinteraction-state rules override only the colour.\n\t*/\n\t.", "\n\t\t> table\n\t\t> tbody\n\t\t> tr.", ".", "\n\t\t> th.", "[data-reaches-top]::after,\n\t\t.", "\n\t\t> table\n\t\t> tbody\n\t\t> tr.", ".", "\n\t\t> td.", "[data-reaches-top]::after {\n\t\tcontent: '';\n\t\tposition: absolute;\n\t\tleft: -1px;\n\t\tright: -1px;\n\t\ttop: -1px;\n\t\tbottom: -1px;\n\t\twidth: auto;\n\t\theight: auto;\n\t\tpointer-events: none;\n\t\tborder-top-width: 1px;\n\t\tborder-top-style: solid;\n\t\tborder-top-color: ", ";\n\t}\n\n\t/* Selection / hover / active-cursor colour for the painted top edge. */\n\t.", "\n\t\t> table\n\t\t> tbody\n\t\t> tr.", ".", "\n\t\t> th.", "[data-reaches-top]:is(\n\t\t\t.", ",\n\t\t\t.", ",\n\t\t\t.", "\n\t\t)::after,\n\t.", "\n\t\t> table\n\t\t> tbody\n\t\t> tr.", ".", "\n\t\t> td.", "[data-reaches-top]:is(\n\t\t\t.", ",\n\t\t\t.", ",\n\t\t\t.", "\n\t\t)::after {\n\t\tborder-top-color: ", ";\n\t}\n\n\t/* Danger colour for the painted top edge. */\n\t.", "\n\t\t> table\n\t\t> tbody\n\t\t> tr.", ".", "\n\t\t> th.", "[data-reaches-top].", "::after,\n\t\t.", "\n\t\t> table\n\t\t> tbody\n\t\t> tr.", ".", "\n\t\t> td.", "[data-reaches-top].", "::after {\n\t\tborder-top-color: ", ";\n\t}\n\n\t:where(.", " > table > tbody > tr.", ")\n\t\t> th.", "[data-reaches-left]::after {\n\t\tborder-left-color: transparent;\n\t}\n\n\t", "\n"])), _types.TableCssClassName.TABLE_NODE_WRAPPER, _types.TableCssClassName.NATIVE_STICKY, _types.TableCssClassName.NATIVE_STICKY_ACTIVE, _types.TableCssClassName.TABLE_HEADER_CELL, _types.TableCssClassName.TABLE_NODE_WRAPPER, _types.TableCssClassName.NATIVE_STICKY, _types.TableCssClassName.NATIVE_STICKY_ACTIVE, _types.TableCssClassName.TABLE_CELL, _consts.tableBorderColor, _types.TableCssClassName.TABLE_NODE_WRAPPER, _types.TableCssClassName.NATIVE_STICKY, _types.TableCssClassName.NATIVE_STICKY_ACTIVE, _types.TableCssClassName.TABLE_HEADER_CELL, _types.TableCssClassName.SELECTED_CELL, _types.TableCssClassName.HOVERED_CELL, _types.TableCssClassName.ACTIVE_CURSOR_CELL, _types.TableCssClassName.TABLE_NODE_WRAPPER, _types.TableCssClassName.NATIVE_STICKY, _types.TableCssClassName.NATIVE_STICKY_ACTIVE, _types.TableCssClassName.TABLE_CELL, _types.TableCssClassName.SELECTED_CELL, _types.TableCssClassName.HOVERED_CELL, _types.TableCssClassName.ACTIVE_CURSOR_CELL, _consts.tableBorderSelectedColor, _types.TableCssClassName.TABLE_NODE_WRAPPER, _types.TableCssClassName.NATIVE_STICKY, _types.TableCssClassName.NATIVE_STICKY_ACTIVE, _types.TableCssClassName.TABLE_HEADER_CELL, _types.TableCssClassName.HOVERED_CELL_IN_DANGER, _types.TableCssClassName.TABLE_NODE_WRAPPER, _types.TableCssClassName.NATIVE_STICKY, _types.TableCssClassName.NATIVE_STICKY_ACTIVE, _types.TableCssClassName.TABLE_CELL, _types.TableCssClassName.HOVERED_CELL_IN_DANGER, _consts.tableBorderDeleteColor, _types.TableCssClassName.TABLE_NODE_WRAPPER, _types.TableCssClassName.NATIVE_STICKY, _types.TableCssClassName.TABLE_HEADER_CELL, (0, _platformFeatureFlags.fg)('platform_editor_table_q4_patch_1') ? (0, _react.css)(_templateObject0 || (_templateObject0 = (0, _taggedTemplateLiteral2.default)(["\n\t\t\t\t/* Node-selected (ak-editor-selected-node) sticky header: the pinned row leaves the table's\n\t\t\t\t\t rounded overlay behind, so recolour its painted top edge to the selected colour too. */\n\t\t\t\t.", ".", "\n\t\t\t\t\t.", "\n\t\t\t\t\t> table\n\t\t\t\t\t> tbody\n\t\t\t\t\t> tr.", ".", "\n\t\t\t\t\t> th.", "[data-reaches-top]::after,\n\t\t\t\t\t.", ".", "\n\t\t\t\t\t.", "\n\t\t\t\t\t> table\n\t\t\t\t\t> tbody\n\t\t\t\t\t> tr.", ".", "\n\t\t\t\t\t> td.", "[data-reaches-top]::after {\n\t\t\t\t\tborder-top-color: ", ";\n\t\t\t\t}\n\t\t\t"])), _types.TableCssClassName.NODEVIEW_WRAPPER, _editorSharedStyles.akEditorSelectedNodeClassName, _types.TableCssClassName.TABLE_NODE_WRAPPER, _types.TableCssClassName.NATIVE_STICKY, _types.TableCssClassName.NATIVE_STICKY_ACTIVE, _types.TableCssClassName.TABLE_HEADER_CELL, _types.TableCssClassName.NODEVIEW_WRAPPER, _editorSharedStyles.akEditorSelectedNodeClassName, _types.TableCssClassName.TABLE_NODE_WRAPPER, _types.TableCssClassName.NATIVE_STICKY, _types.TableCssClassName.NATIVE_STICKY_ACTIVE, _types.TableCssClassName.TABLE_CELL, _consts.tableBorderSelectedColor) : '');
@@ -561,15 +561,29 @@ export default class TableRow extends TableNodeView {
561
561
  if (isCurrentTableSelected) {
562
562
  this.colControlsOffset = tableControlsSpacing;
563
563
 
564
- // move table a little out of the way
565
- // to provide spacing for table controls
566
- if (isTableInsideLayout) {
567
- tableContentWrapper.style.paddingLeft = '11px';
564
+ /**
565
+ * Adding padding left causes flicker when table is inside layout column
566
+ * and selection moves in/out of table.
567
+ */
568
+ if (!fg('platform_editor_table_flicker_issue')) {
569
+ // move table a little out of the way
570
+ // to provide spacing for table controls
571
+ if (isTableInsideLayout) {
572
+ tableContentWrapper.style.paddingLeft = '11px';
573
+ tableContentWrapper.style.marginLeft = '-11px';
574
+ }
568
575
  }
569
576
  } else {
570
577
  this.colControlsOffset = 0;
571
- if (isTableInsideLayout) {
572
- tableContentWrapper.style.removeProperty('padding-left');
578
+ /**
579
+ * Adding padding left causes flicker when table is inside layout column
580
+ * and selection moves in/out of table.
581
+ */
582
+ if (!fg('platform_editor_table_flicker_issue')) {
583
+ if (isTableInsideLayout) {
584
+ tableContentWrapper.style.removeProperty('padding-left');
585
+ tableContentWrapper.style.removeProperty('margin-left');
586
+ }
573
587
  }
574
588
  }
575
589
  }
@@ -66,6 +66,7 @@ export default class TableRowNativeStickyWithFallback extends TableNodeView {
66
66
  _defineProperty(this, "top", 0);
67
67
  _defineProperty(this, "hasScrolledSinceLoad", false);
68
68
  _defineProperty(this, "disableNativeSticky", false);
69
+ _defineProperty(this, "isSingleRowTable", false);
69
70
  /**
70
71
  * Methods
71
72
  */
@@ -93,6 +94,9 @@ export default class TableRowNativeStickyWithFallback extends TableNodeView {
93
94
  }
94
95
  });
95
96
  this.isHeaderRow = supportedHeaderRow(node);
97
+ if (this.isHeaderRow && expValEquals('platform_editor_table_q4_patch_4', 'isEnabled', true)) {
98
+ this.isSingleRowTable = this.checkIsSingleRowTable();
99
+ }
96
100
  this.isLegacySticky = false;
97
101
  const {
98
102
  pluginConfig
@@ -168,6 +172,10 @@ export default class TableRowNativeStickyWithFallback extends TableNodeView {
168
172
  // Ignored via go/ees005
169
173
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
170
174
  update(node, ..._args) {
175
+ if (this.isHeaderRow && expValEquals('platform_editor_table_q4_patch_4', 'isEnabled', true)) {
176
+ this.updateSingleRowTableStickyHeaderState();
177
+ }
178
+
171
179
  // do nothing if nodes were identical
172
180
  if (node === this.node) {
173
181
  return true;
@@ -271,6 +279,9 @@ export default class TableRowNativeStickyWithFallback extends TableNodeView {
271
279
  * be cleaned up.
272
280
  */
273
281
  entries.forEach(entry => {
282
+ if (expValEquals('platform_editor_table_q4_patch_4', 'isEnabled', true) && this.updateSingleRowTableStickyHeaderState()) {
283
+ return;
284
+ }
274
285
  const tableWrapper = this.dom.closest(`.${ClassName.TABLE_NODE_WRAPPER}`);
275
286
  if (tableWrapper && tableWrapper instanceof HTMLElement && !areAllRectsZero(entry)) {
276
287
  if (entry.isIntersecting) {
@@ -360,6 +371,9 @@ export default class TableRowNativeStickyWithFallback extends TableNodeView {
360
371
  if (!(observer.root instanceof HTMLElement)) {
361
372
  return;
362
373
  }
374
+ if (expValEquals('platform_editor_table_q4_patch_4', 'isEnabled', true) && this.updateSingleRowTableStickyHeaderState()) {
375
+ return;
376
+ }
363
377
  // Only apply classes if page has scrolled since load
364
378
  if (!this.hasScrolledSinceLoad) {
365
379
  this.overflowObserverEntries = entries;
@@ -407,6 +421,9 @@ export default class TableRowNativeStickyWithFallback extends TableNodeView {
407
421
  this.stickyStateObserver = new IntersectionObserver(entries => {
408
422
  entries.forEach(entry => {
409
423
  var _entry$rootBounds;
424
+ if (expValEquals('platform_editor_table_q4_patch_4', 'isEnabled', true) && this.updateSingleRowTableStickyHeaderState()) {
425
+ return;
426
+ }
410
427
  const tableContainer = this.dom.closest(`.${ClassName.TABLE_CONTAINER}`);
411
428
  if (entry.intersectionRect.top === ((_entry$rootBounds = entry.rootBounds) === null || _entry$rootBounds === void 0 ? void 0 : _entry$rootBounds.top) && !this.disableNativeSticky) {
412
429
  this.dom.classList.add(ClassName.NATIVE_STICKY_ACTIVE);
@@ -535,6 +552,9 @@ export default class TableRowNativeStickyWithFallback extends TableNodeView {
535
552
  initNodeVisibilityObserver() {
536
553
  this.nodeVisibilityObserver = new IntersectionObserver(entries => {
537
554
  entries.forEach(entry => {
555
+ if (expValEquals('platform_editor_table_q4_patch_4', 'isEnabled', true) && this.updateSingleRowTableStickyHeaderState()) {
556
+ return;
557
+ }
538
558
  if (!this.isNativeSticky) {
539
559
  return;
540
560
  }
@@ -623,6 +643,9 @@ export default class TableRowNativeStickyWithFallback extends TableNodeView {
623
643
  });
624
644
  }
625
645
  refreshLegacyStickyState() {
646
+ if (expValEquals('platform_editor_table_q4_patch_4', 'isEnabled', true) && this.updateSingleRowTableStickyHeaderState()) {
647
+ return;
648
+ }
626
649
  const tree = getTree(this.dom);
627
650
  if (!tree) {
628
651
  return;
@@ -774,15 +797,27 @@ export default class TableRowNativeStickyWithFallback extends TableNodeView {
774
797
  if (isCurrentTableSelected) {
775
798
  this.colControlsOffset = tableControlsSpacing;
776
799
 
777
- // move table a little out of the way
778
- // to provide spacing for table controls
779
- if (isTableInsideLayout) {
780
- tableContentWrapper.style.paddingLeft = '11px';
800
+ /**
801
+ * Adding padding left causes flicker when table is inside layout column
802
+ * and selection moves in/out of table.
803
+ */
804
+ if (!fg('platform_editor_table_flicker_issue')) {
805
+ // move table a little out of the way
806
+ // to provide spacing for table controls
807
+ if (isTableInsideLayout) {
808
+ tableContentWrapper.style.paddingLeft = '11px';
809
+ }
781
810
  }
782
811
  } else {
783
812
  this.colControlsOffset = 0;
784
- if (isTableInsideLayout) {
785
- tableContentWrapper.style.removeProperty('padding-left');
813
+ /**
814
+ * Adding padding left causes flicker when table is inside layout column
815
+ * and selection moves in/out of table.
816
+ */
817
+ if (!fg('platform_editor_table_flicker_issue')) {
818
+ if (isTableInsideLayout) {
819
+ tableContentWrapper.style.removeProperty('padding-left');
820
+ }
786
821
  }
787
822
  }
788
823
  }
@@ -815,6 +850,59 @@ export default class TableRowNativeStickyWithFallback extends TableNodeView {
815
850
  });
816
851
  }
817
852
  }
853
+ checkIsSingleRowTable() {
854
+ const pos = this.getPos();
855
+ if (typeof pos !== 'number') {
856
+ return false;
857
+ }
858
+ try {
859
+ var _findParentNodeCloses3;
860
+ const $tableRowPos = this.view.state.doc.resolve(pos);
861
+ const tableNode = (_findParentNodeCloses3 = findParentNodeClosestToPos($tableRowPos, node => node.type === this.view.state.schema.nodes.table)) === null || _findParentNodeCloses3 === void 0 ? void 0 : _findParentNodeCloses3.node;
862
+ return (tableNode === null || tableNode === void 0 ? void 0 : tableNode.childCount) === 1;
863
+ } catch {
864
+ // getPos can return stale positions during AI streaming. Preserve the original sticky
865
+ // header behaviour when the containing table cannot be determined.
866
+ return false;
867
+ }
868
+ }
869
+ updateSingleRowTableStickyHeaderState() {
870
+ const wasSingleRowTable = this.isSingleRowTable;
871
+ this.isSingleRowTable = this.checkIsSingleRowTable();
872
+ if (this.isSingleRowTable) {
873
+ this.removeSingleRowTableStickyHeaderState();
874
+ } else if (wasSingleRowTable) {
875
+ this.refireNativeStickyObservers();
876
+ }
877
+ return this.isSingleRowTable;
878
+ }
879
+ removeSingleRowTableStickyHeaderState() {
880
+ this.dom.classList.remove(ClassName.NATIVE_STICKY, ClassName.NATIVE_STICKY_ACTIVE);
881
+ this.isNativeSticky = false;
882
+ const tableWrapper = this.dom.closest(`.${ClassName.TABLE_NODE_WRAPPER}`);
883
+ tableWrapper === null || tableWrapper === void 0 ? void 0 : tableWrapper.classList.remove(ClassName.TABLE_NODE_WRAPPER_NO_OVERFLOW);
884
+ const tableContainer = this.dom.closest(`.${ClassName.TABLE_CONTAINER}`);
885
+ if (tableContainer instanceof HTMLElement) {
886
+ delete tableContainer.dataset.tableHeaderIsStuck;
887
+ }
888
+ const tree = getTree(this.dom);
889
+ if (tree) {
890
+ this.makeRowHeaderNotLegacySticky(tree.table);
891
+ }
892
+ }
893
+ refireNativeStickyObservers() {
894
+ var _this$stickyStateObse2, _this$stickyStateObse3;
895
+ const table = this.dom.closest('table');
896
+ if (table) {
897
+ var _this$overflowObserve3, _this$overflowObserve4, _this$nodeVisibilityO3, _this$nodeVisibilityO4;
898
+ (_this$overflowObserve3 = this.overflowObserver) === null || _this$overflowObserve3 === void 0 ? void 0 : _this$overflowObserve3.unobserve(table);
899
+ (_this$overflowObserve4 = this.overflowObserver) === null || _this$overflowObserve4 === void 0 ? void 0 : _this$overflowObserve4.observe(table);
900
+ (_this$nodeVisibilityO3 = this.nodeVisibilityObserver) === null || _this$nodeVisibilityO3 === void 0 ? void 0 : _this$nodeVisibilityO3.unobserve(table);
901
+ (_this$nodeVisibilityO4 = this.nodeVisibilityObserver) === null || _this$nodeVisibilityO4 === void 0 ? void 0 : _this$nodeVisibilityO4.observe(table);
902
+ }
903
+ (_this$stickyStateObse2 = this.stickyStateObserver) === null || _this$stickyStateObse2 === void 0 ? void 0 : _this$stickyStateObse2.unobserve(this.dom);
904
+ (_this$stickyStateObse3 = this.stickyStateObserver) === null || _this$stickyStateObse3 === void 0 ? void 0 : _this$stickyStateObse3.observe(this.dom);
905
+ }
818
906
  makeHeaderRowLegacySticky(tree, scrollTop) {
819
907
  var _tbody$firstChild;
820
908
  // If header row height is more than 50% of viewport height don't do this
@@ -1,8 +1,53 @@
1
1
  // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
2
2
  import { css } from '@emotion/react';
3
+ import { fg } from '@atlaskit/platform-feature-flags';
3
4
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
4
5
  import { contextualMenuTriggerSize } from '../consts';
5
- export const tableFloatingCellButtonStyles = () => css({
6
+
7
+ // Excludes the inlined top-layer tooltip popover from the background box selector so it isn't squished.
8
+ const topLayerTooltipCellButtonStyles = () => css({
9
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors -- Ignored via go/DSP-18766
10
+ '> div:not([popover])': {
11
+ // Sits behind button to provide surface-color background
12
+ background: "var(--ds-surface, #FFFFFF)",
13
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values, @atlaskit/ui-styling-standard/no-unsafe-values
14
+ borderRadius: expValEquals('platform_editor_table_q4_loveability', 'isEnabled', true) ? "var(--ds-radius-small, 4px)" : "var(--ds-radius-small, 3px)",
15
+ display: 'flex',
16
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values, @atlaskit/ui-styling-standard/no-unsafe-values -- Ignored via go/DSP-18766
17
+ height: `${contextualMenuTriggerSize + 2}px`,
18
+ width: "var(--ds-space-250, 20px)",
19
+ flexDirection: 'column'
20
+ },
21
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors -- Ignored via go/DSP-18766
22
+ '&& button': {
23
+ background: "var(--ds-background-neutral, #0515240F)",
24
+ flexDirection: 'column',
25
+ margin: "var(--ds-space-025, 2px)",
26
+ outline: `2px solid ${"var(--ds-surface, #FFFFFF)"}`,
27
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values, @atlaskit/ui-styling-standard/no-unsafe-values
28
+ borderRadius: expValEquals('platform_editor_table_q4_loveability', 'isEnabled', true) ? "var(--ds-radius-xsmall, 2px)" : '1px',
29
+ padding: 0,
30
+ height: 'calc(100% - 4px)',
31
+ display: 'flex'
32
+ },
33
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors -- Ignored via go/DSP-18766
34
+ '&& button:hover': {
35
+ background: "var(--ds-background-neutral-hovered, #0B120E24)"
36
+ },
37
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors -- Ignored via go/DSP-18766
38
+ '&& button:active': {
39
+ background: "var(--ds-background-neutral-pressed, #080F214A)"
40
+ },
41
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors -- Ignored via go/DSP-18766
42
+ '&& button > span': {
43
+ margin: `0px ${"var(--ds-space-negative-050, -4px)"}`
44
+ },
45
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors -- Ignored via go/DSP-18766
46
+ '&& span': {
47
+ pointerEvents: 'none'
48
+ }
49
+ });
50
+ const legacyCellButtonStyles = () => css({
6
51
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors -- Ignored via go/DSP-18766
7
52
  '> div': {
8
53
  // Sits behind button to provide surface-color background
@@ -44,6 +89,7 @@ export const tableFloatingCellButtonStyles = () => css({
44
89
  pointerEvents: 'none'
45
90
  }
46
91
  });
92
+ export const tableFloatingCellButtonStyles = () => fg('platform-dst-top-layer-tooltip') ? topLayerTooltipCellButtonStyles() : legacyCellButtonStyles();
47
93
  export const tableFloatingCellButtonSelectedStyles = () => css({
48
94
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors -- Ignored via go/DSP-18766
49
95
  '&& button': {
@@ -5,6 +5,7 @@ import { css } from '@emotion/react';
5
5
  import { tableMarginTop } from '@atlaskit/editor-common/styles';
6
6
  import { akEditorSelectedNodeClassName, akEditorSmallZIndex, akEditorTableNumberColumnWidth, akEditorUnitZIndex } from '@atlaskit/editor-shared-styles';
7
7
  import { fg } from '@atlaskit/platform-feature-flags';
8
+ import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
8
9
  import { TableCssClassName as ClassName } from '../types';
9
10
  import { nativeStickyHeaderZIndex, tableBorderColor, tableBorderDeleteColor, tableBorderSelectedColor, tableCellSelectedColor } from './consts';
10
11
  const roundedTableCellCornerStyles = () => css`
@@ -481,7 +482,7 @@ const roundedTableStickyHeaderCornerMaskStyles = () => css`
481
482
  sticky / fallback layout. The masks belong to the wrapper of the table
482
483
  that owns the sticky row, never to an ancestor wrapper.
483
484
  */
484
- .${ClassName.TABLE_NODE_WRAPPER}:has(> table > tbody > tr.${ClassName.NATIVE_STICKY_ACTIVE})
485
+ .${ClassName.TABLE_NODE_WRAPPER}:has(> table > tbody > tr.${expValEquals('platform_editor_table_q4_patch_4', 'isEnabled', true) ? `${ClassName.NATIVE_STICKY}.${ClassName.NATIVE_STICKY_ACTIVE}` : ClassName.NATIVE_STICKY_ACTIVE})
485
486
  > .${ClassName.TABLE_CORNER_MASK},
486
487
  .${ClassName.TABLE_NODE_WRAPPER}:has(> table.${ClassName.TABLE_STICKY} > tbody > tr.sticky)
487
488
  > .${ClassName.TABLE_CORNER_MASK} {
@@ -593,15 +593,29 @@ var TableRow = /*#__PURE__*/function (_TableNodeView) {
593
593
  if (isCurrentTableSelected) {
594
594
  this.colControlsOffset = tableControlsSpacing;
595
595
 
596
- // move table a little out of the way
597
- // to provide spacing for table controls
598
- if (isTableInsideLayout) {
599
- tableContentWrapper.style.paddingLeft = '11px';
596
+ /**
597
+ * Adding padding left causes flicker when table is inside layout column
598
+ * and selection moves in/out of table.
599
+ */
600
+ if (!fg('platform_editor_table_flicker_issue')) {
601
+ // move table a little out of the way
602
+ // to provide spacing for table controls
603
+ if (isTableInsideLayout) {
604
+ tableContentWrapper.style.paddingLeft = '11px';
605
+ tableContentWrapper.style.marginLeft = '-11px';
606
+ }
600
607
  }
601
608
  } else {
602
609
  this.colControlsOffset = 0;
603
- if (isTableInsideLayout) {
604
- tableContentWrapper.style.removeProperty('padding-left');
610
+ /**
611
+ * Adding padding left causes flicker when table is inside layout column
612
+ * and selection moves in/out of table.
613
+ */
614
+ if (!fg('platform_editor_table_flicker_issue')) {
615
+ if (isTableInsideLayout) {
616
+ tableContentWrapper.style.removeProperty('padding-left');
617
+ tableContentWrapper.style.removeProperty('margin-left');
618
+ }
605
619
  }
606
620
  }
607
621
  }
@@ -75,6 +75,7 @@ var TableRowNativeStickyWithFallback = /*#__PURE__*/function (_TableNodeView) {
75
75
  _defineProperty(_this, "top", 0);
76
76
  _defineProperty(_this, "hasScrolledSinceLoad", false);
77
77
  _defineProperty(_this, "disableNativeSticky", false);
78
+ _defineProperty(_this, "isSingleRowTable", false);
78
79
  /**
79
80
  * Methods
80
81
  */
@@ -102,6 +103,9 @@ var TableRowNativeStickyWithFallback = /*#__PURE__*/function (_TableNodeView) {
102
103
  }
103
104
  });
104
105
  _this.isHeaderRow = supportedHeaderRow(node);
106
+ if (_this.isHeaderRow && expValEquals('platform_editor_table_q4_patch_4', 'isEnabled', true)) {
107
+ _this.isSingleRowTable = _this.checkIsSingleRowTable();
108
+ }
105
109
  _this.isLegacySticky = false;
106
110
  var _getPluginState = getPluginState(view.state),
107
111
  pluginConfig = _getPluginState.pluginConfig;
@@ -180,6 +184,10 @@ var TableRowNativeStickyWithFallback = /*#__PURE__*/function (_TableNodeView) {
180
184
  // Ignored via go/ees005
181
185
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
182
186
  function update(node) {
187
+ if (this.isHeaderRow && expValEquals('platform_editor_table_q4_patch_4', 'isEnabled', true)) {
188
+ this.updateSingleRowTableStickyHeaderState();
189
+ }
190
+
183
191
  // do nothing if nodes were identical
184
192
  if (node === this.node) {
185
193
  return true;
@@ -290,6 +298,9 @@ var TableRowNativeStickyWithFallback = /*#__PURE__*/function (_TableNodeView) {
290
298
  * be cleaned up.
291
299
  */
292
300
  entries.forEach(function (entry) {
301
+ if (expValEquals('platform_editor_table_q4_patch_4', 'isEnabled', true) && _this3.updateSingleRowTableStickyHeaderState()) {
302
+ return;
303
+ }
293
304
  var tableWrapper = _this3.dom.closest(".".concat(ClassName.TABLE_NODE_WRAPPER));
294
305
  if (tableWrapper && tableWrapper instanceof HTMLElement && !areAllRectsZero(entry)) {
295
306
  if (entry.isIntersecting) {
@@ -384,6 +395,9 @@ var TableRowNativeStickyWithFallback = /*#__PURE__*/function (_TableNodeView) {
384
395
  if (!(observer.root instanceof HTMLElement)) {
385
396
  return;
386
397
  }
398
+ if (expValEquals('platform_editor_table_q4_patch_4', 'isEnabled', true) && _this4.updateSingleRowTableStickyHeaderState()) {
399
+ return;
400
+ }
387
401
  // Only apply classes if page has scrolled since load
388
402
  if (!_this4.hasScrolledSinceLoad) {
389
403
  _this4.overflowObserverEntries = entries;
@@ -434,6 +448,9 @@ var TableRowNativeStickyWithFallback = /*#__PURE__*/function (_TableNodeView) {
434
448
  this.stickyStateObserver = new IntersectionObserver(function (entries) {
435
449
  entries.forEach(function (entry) {
436
450
  var _entry$rootBounds;
451
+ if (expValEquals('platform_editor_table_q4_patch_4', 'isEnabled', true) && _this5.updateSingleRowTableStickyHeaderState()) {
452
+ return;
453
+ }
437
454
  var tableContainer = _this5.dom.closest(".".concat(ClassName.TABLE_CONTAINER));
438
455
  if (entry.intersectionRect.top === ((_entry$rootBounds = entry.rootBounds) === null || _entry$rootBounds === void 0 ? void 0 : _entry$rootBounds.top) && !_this5.disableNativeSticky) {
439
456
  _this5.dom.classList.add(ClassName.NATIVE_STICKY_ACTIVE);
@@ -572,6 +589,9 @@ var TableRowNativeStickyWithFallback = /*#__PURE__*/function (_TableNodeView) {
572
589
  var _this7 = this;
573
590
  this.nodeVisibilityObserver = new IntersectionObserver(function (entries) {
574
591
  entries.forEach(function (entry) {
592
+ if (expValEquals('platform_editor_table_q4_patch_4', 'isEnabled', true) && _this7.updateSingleRowTableStickyHeaderState()) {
593
+ return;
594
+ }
575
595
  if (!_this7.isNativeSticky) {
576
596
  return;
577
597
  }
@@ -664,6 +684,9 @@ var TableRowNativeStickyWithFallback = /*#__PURE__*/function (_TableNodeView) {
664
684
  }, {
665
685
  key: "refreshLegacyStickyState",
666
686
  value: function refreshLegacyStickyState() {
687
+ if (expValEquals('platform_editor_table_q4_patch_4', 'isEnabled', true) && this.updateSingleRowTableStickyHeaderState()) {
688
+ return;
689
+ }
667
690
  var tree = getTree(this.dom);
668
691
  if (!tree) {
669
692
  return;
@@ -815,15 +838,27 @@ var TableRowNativeStickyWithFallback = /*#__PURE__*/function (_TableNodeView) {
815
838
  if (isCurrentTableSelected) {
816
839
  this.colControlsOffset = tableControlsSpacing;
817
840
 
818
- // move table a little out of the way
819
- // to provide spacing for table controls
820
- if (isTableInsideLayout) {
821
- tableContentWrapper.style.paddingLeft = '11px';
841
+ /**
842
+ * Adding padding left causes flicker when table is inside layout column
843
+ * and selection moves in/out of table.
844
+ */
845
+ if (!fg('platform_editor_table_flicker_issue')) {
846
+ // move table a little out of the way
847
+ // to provide spacing for table controls
848
+ if (isTableInsideLayout) {
849
+ tableContentWrapper.style.paddingLeft = '11px';
850
+ }
822
851
  }
823
852
  } else {
824
853
  this.colControlsOffset = 0;
825
- if (isTableInsideLayout) {
826
- tableContentWrapper.style.removeProperty('padding-left');
854
+ /**
855
+ * Adding padding left causes flicker when table is inside layout column
856
+ * and selection moves in/out of table.
857
+ */
858
+ if (!fg('platform_editor_table_flicker_issue')) {
859
+ if (isTableInsideLayout) {
860
+ tableContentWrapper.style.removeProperty('padding-left');
861
+ }
827
862
  }
828
863
  }
829
864
  }
@@ -861,11 +896,75 @@ var TableRowNativeStickyWithFallback = /*#__PURE__*/function (_TableNodeView) {
861
896
  });
862
897
  }
863
898
  }
899
+ }, {
900
+ key: "checkIsSingleRowTable",
901
+ value: function checkIsSingleRowTable() {
902
+ var _this1 = this;
903
+ var pos = this.getPos();
904
+ if (typeof pos !== 'number') {
905
+ return false;
906
+ }
907
+ try {
908
+ var _findParentNodeCloses3;
909
+ var $tableRowPos = this.view.state.doc.resolve(pos);
910
+ var tableNode = (_findParentNodeCloses3 = findParentNodeClosestToPos($tableRowPos, function (node) {
911
+ return node.type === _this1.view.state.schema.nodes.table;
912
+ })) === null || _findParentNodeCloses3 === void 0 ? void 0 : _findParentNodeCloses3.node;
913
+ return (tableNode === null || tableNode === void 0 ? void 0 : tableNode.childCount) === 1;
914
+ } catch (_unused3) {
915
+ // getPos can return stale positions during AI streaming. Preserve the original sticky
916
+ // header behaviour when the containing table cannot be determined.
917
+ return false;
918
+ }
919
+ }
920
+ }, {
921
+ key: "updateSingleRowTableStickyHeaderState",
922
+ value: function updateSingleRowTableStickyHeaderState() {
923
+ var wasSingleRowTable = this.isSingleRowTable;
924
+ this.isSingleRowTable = this.checkIsSingleRowTable();
925
+ if (this.isSingleRowTable) {
926
+ this.removeSingleRowTableStickyHeaderState();
927
+ } else if (wasSingleRowTable) {
928
+ this.refireNativeStickyObservers();
929
+ }
930
+ return this.isSingleRowTable;
931
+ }
932
+ }, {
933
+ key: "removeSingleRowTableStickyHeaderState",
934
+ value: function removeSingleRowTableStickyHeaderState() {
935
+ this.dom.classList.remove(ClassName.NATIVE_STICKY, ClassName.NATIVE_STICKY_ACTIVE);
936
+ this.isNativeSticky = false;
937
+ var tableWrapper = this.dom.closest(".".concat(ClassName.TABLE_NODE_WRAPPER));
938
+ tableWrapper === null || tableWrapper === void 0 || tableWrapper.classList.remove(ClassName.TABLE_NODE_WRAPPER_NO_OVERFLOW);
939
+ var tableContainer = this.dom.closest(".".concat(ClassName.TABLE_CONTAINER));
940
+ if (tableContainer instanceof HTMLElement) {
941
+ delete tableContainer.dataset.tableHeaderIsStuck;
942
+ }
943
+ var tree = getTree(this.dom);
944
+ if (tree) {
945
+ this.makeRowHeaderNotLegacySticky(tree.table);
946
+ }
947
+ }
948
+ }, {
949
+ key: "refireNativeStickyObservers",
950
+ value: function refireNativeStickyObservers() {
951
+ var _this$stickyStateObse2, _this$stickyStateObse3;
952
+ var table = this.dom.closest('table');
953
+ if (table) {
954
+ var _this$overflowObserve2, _this$overflowObserve3, _this$nodeVisibilityO3, _this$nodeVisibilityO4;
955
+ (_this$overflowObserve2 = this.overflowObserver) === null || _this$overflowObserve2 === void 0 || _this$overflowObserve2.unobserve(table);
956
+ (_this$overflowObserve3 = this.overflowObserver) === null || _this$overflowObserve3 === void 0 || _this$overflowObserve3.observe(table);
957
+ (_this$nodeVisibilityO3 = this.nodeVisibilityObserver) === null || _this$nodeVisibilityO3 === void 0 || _this$nodeVisibilityO3.unobserve(table);
958
+ (_this$nodeVisibilityO4 = this.nodeVisibilityObserver) === null || _this$nodeVisibilityO4 === void 0 || _this$nodeVisibilityO4.observe(table);
959
+ }
960
+ (_this$stickyStateObse2 = this.stickyStateObserver) === null || _this$stickyStateObse2 === void 0 || _this$stickyStateObse2.unobserve(this.dom);
961
+ (_this$stickyStateObse3 = this.stickyStateObserver) === null || _this$stickyStateObse3 === void 0 || _this$stickyStateObse3.observe(this.dom);
962
+ }
864
963
  }, {
865
964
  key: "makeHeaderRowLegacySticky",
866
965
  value: function makeHeaderRowLegacySticky(tree, scrollTop) {
867
966
  var _tbody$firstChild,
868
- _this1 = this;
967
+ _this10 = this;
869
968
  // If header row height is more than 50% of viewport height don't do this
870
969
  if (this.isLegacySticky || this.stickyRowHeight && this.stickyRowHeight > window.innerHeight / 2 || this.isInNestedTable) {
871
970
  return;
@@ -904,7 +1003,7 @@ var TableRowNativeStickyWithFallback = /*#__PURE__*/function (_TableNodeView) {
904
1003
  });
905
1004
  var fastScrollThresholdMs = 500;
906
1005
  setTimeout(function () {
907
- _this1.refireIntersectionObservers();
1006
+ _this10.refireIntersectionObservers();
908
1007
  }, fastScrollThresholdMs);
909
1008
  }
910
1009
  this.dom.style.top = "0px";
@@ -1,8 +1,55 @@
1
1
  // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
2
2
  import { css } from '@emotion/react';
3
+ import { fg } from '@atlaskit/platform-feature-flags';
3
4
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
4
5
  import { contextualMenuTriggerSize } from '../consts';
5
- export var tableFloatingCellButtonStyles = function tableFloatingCellButtonStyles() {
6
+
7
+ // Excludes the inlined top-layer tooltip popover from the background box selector so it isn't squished.
8
+ var topLayerTooltipCellButtonStyles = function topLayerTooltipCellButtonStyles() {
9
+ return css({
10
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors -- Ignored via go/DSP-18766
11
+ '> div:not([popover])': {
12
+ // Sits behind button to provide surface-color background
13
+ background: "var(--ds-surface, #FFFFFF)",
14
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values, @atlaskit/ui-styling-standard/no-unsafe-values
15
+ borderRadius: expValEquals('platform_editor_table_q4_loveability', 'isEnabled', true) ? "var(--ds-radius-small, 4px)" : "var(--ds-radius-small, 3px)",
16
+ display: 'flex',
17
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values, @atlaskit/ui-styling-standard/no-unsafe-values -- Ignored via go/DSP-18766
18
+ height: "".concat(contextualMenuTriggerSize + 2, "px"),
19
+ width: "var(--ds-space-250, 20px)",
20
+ flexDirection: 'column'
21
+ },
22
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors -- Ignored via go/DSP-18766
23
+ '&& button': {
24
+ background: "var(--ds-background-neutral, #0515240F)",
25
+ flexDirection: 'column',
26
+ margin: "var(--ds-space-025, 2px)",
27
+ outline: "2px solid ".concat("var(--ds-surface, #FFFFFF)"),
28
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values, @atlaskit/ui-styling-standard/no-unsafe-values
29
+ borderRadius: expValEquals('platform_editor_table_q4_loveability', 'isEnabled', true) ? "var(--ds-radius-xsmall, 2px)" : '1px',
30
+ padding: 0,
31
+ height: 'calc(100% - 4px)',
32
+ display: 'flex'
33
+ },
34
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors -- Ignored via go/DSP-18766
35
+ '&& button:hover': {
36
+ background: "var(--ds-background-neutral-hovered, #0B120E24)"
37
+ },
38
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors -- Ignored via go/DSP-18766
39
+ '&& button:active': {
40
+ background: "var(--ds-background-neutral-pressed, #080F214A)"
41
+ },
42
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors -- Ignored via go/DSP-18766
43
+ '&& button > span': {
44
+ margin: "0px ".concat("var(--ds-space-negative-050, -4px)")
45
+ },
46
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors -- Ignored via go/DSP-18766
47
+ '&& span': {
48
+ pointerEvents: 'none'
49
+ }
50
+ });
51
+ };
52
+ var legacyCellButtonStyles = function legacyCellButtonStyles() {
6
53
  return css({
7
54
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors -- Ignored via go/DSP-18766
8
55
  '> div': {
@@ -46,6 +93,9 @@ export var tableFloatingCellButtonStyles = function tableFloatingCellButtonStyle
46
93
  }
47
94
  });
48
95
  };
96
+ export var tableFloatingCellButtonStyles = function tableFloatingCellButtonStyles() {
97
+ return fg('platform-dst-top-layer-tooltip') ? topLayerTooltipCellButtonStyles() : legacyCellButtonStyles();
98
+ };
49
99
  export var tableFloatingCellButtonSelectedStyles = function tableFloatingCellButtonSelectedStyles() {
50
100
  return css({
51
101
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors -- Ignored via go/DSP-18766
@@ -7,6 +7,7 @@ import { css } from '@emotion/react';
7
7
  import { tableMarginTop } from '@atlaskit/editor-common/styles';
8
8
  import { akEditorSelectedNodeClassName, akEditorSmallZIndex, akEditorTableNumberColumnWidth, akEditorUnitZIndex } from '@atlaskit/editor-shared-styles';
9
9
  import { fg } from '@atlaskit/platform-feature-flags';
10
+ import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
10
11
  import { TableCssClassName as ClassName } from '../types';
11
12
  import { nativeStickyHeaderZIndex, tableBorderColor, tableBorderDeleteColor, tableBorderSelectedColor, tableCellSelectedColor } from './consts';
12
13
  var roundedTableCellCornerStyles = function roundedTableCellCornerStyles() {
@@ -43,7 +44,7 @@ var roundedTableStickyHeaderNumberColumnStyles = function roundedTableStickyHead
43
44
  return css(_templateObject7 || (_templateObject7 = _taggedTemplateLiteral(["\n\t.", "[data-number-column='true'] .", " tr th[data-reaches-top][data-reaches-left]::before,\n\t.", "[data-number-column='true'] .", " tr.", " th[data-reaches-left]::before,\n\t.", "[data-number-column='true'] .", " .", " th[data-reaches-left]::before {\n\t\tborder-top-left-radius: ", ";\n\t\tborder-bottom: none;\n\t}\n"])), ClassName.TABLE_CONTAINER, ClassName.TABLE_NODE_WRAPPER_NO_OVERFLOW, ClassName.TABLE_CONTAINER, ClassName.TABLE_NODE_WRAPPER_NO_OVERFLOW, ClassName.NATIVE_STICKY, ClassName.TABLE_CONTAINER, ClassName.TABLE_NODE_WRAPPER_NO_OVERFLOW, ClassName.NATIVE_STICKY_ACTIVE, "var(--ds-radius-xlarge, 12px)");
44
45
  };
45
46
  var roundedTableStickyHeaderCornerMaskStyles = function roundedTableStickyHeaderCornerMaskStyles() {
46
- return css(_templateObject8 || (_templateObject8 = _taggedTemplateLiteral(["\n\t/* Same z-index as the sticky row; DOM order keeps the row above this mask and the table border below it. */\n\t.", " {\n\t\tdisplay: none;\n\t\tposition: sticky;\n\t\ttop: calc(", "px - 1px);\n\t\twidth: 12px;\n\t\theight: 12px;\n\t\tmargin-bottom: -12px;\n\t\tbackground: ", ";\n\t\tpointer-events: none;\n\t\tz-index: ", ";\n\t}\n\n\t.", "[data-number-column='true']\n\t\t.", "[data-corner='left'] {\n\t\tmargin-left: -", "px;\n\t}\n\n\t.", "[data-corner='right'] {\n\t\tleft: calc(100% - 11px);\n\t}\n\n\t/*\n\t\tScope the :has() selectors to a DIRECT child table so a nested table that\n\t\thas its own sticky row does not pull the OUTER wrapper's masks into the\n\t\tsticky / fallback layout. The masks belong to the wrapper of the table\n\t\tthat owns the sticky row, never to an ancestor wrapper.\n\t*/\n\t.", ":has(> table > tbody > tr.", ")\n\t\t> .", ",\n\t\t.", ":has(> table.", " > tbody > tr.sticky)\n\t\t> .", " {\n\t\tdisplay: block;\n\t}\n\n\t/*\n\t\tWhen the table overflows horizontally, sticky headers fall back from native\n\t\tposition: sticky to a fixed-position header row. Match that positioning so\n\t\tthe corner masks continue to cover the rounded corners in the fallback path.\n\n\t\tThe direct-child combinator inside :has() is critical: without it a nested\n\t\ttable entering the legacy fallback would incorrectly trigger this rule on\n\t\tthe OUTER wrapper, detaching the outer table's masks from its corners.\n\t*/\n\t.", ":has(> table.", " > tbody > tr.sticky)\n\t\t> .", " {\n\t\tposition: fixed;\n\t\ttop: 30px;\n\t\tz-index: 1;\n\t}\n"])), ClassName.TABLE_CORNER_MASK, tableMarginTop, "var(--ds-surface, #FFFFFF)", nativeStickyHeaderZIndex, ClassName.TABLE_CONTAINER, ClassName.TABLE_CORNER_MASK, akEditorTableNumberColumnWidth, ClassName.TABLE_CORNER_MASK, ClassName.TABLE_NODE_WRAPPER, ClassName.NATIVE_STICKY_ACTIVE, ClassName.TABLE_CORNER_MASK, ClassName.TABLE_NODE_WRAPPER, ClassName.TABLE_STICKY, ClassName.TABLE_CORNER_MASK, ClassName.TABLE_NODE_WRAPPER, ClassName.TABLE_STICKY, ClassName.TABLE_CORNER_MASK);
47
+ return css(_templateObject8 || (_templateObject8 = _taggedTemplateLiteral(["\n\t/* Same z-index as the sticky row; DOM order keeps the row above this mask and the table border below it. */\n\t.", " {\n\t\tdisplay: none;\n\t\tposition: sticky;\n\t\ttop: calc(", "px - 1px);\n\t\twidth: 12px;\n\t\theight: 12px;\n\t\tmargin-bottom: -12px;\n\t\tbackground: ", ";\n\t\tpointer-events: none;\n\t\tz-index: ", ";\n\t}\n\n\t.", "[data-number-column='true']\n\t\t.", "[data-corner='left'] {\n\t\tmargin-left: -", "px;\n\t}\n\n\t.", "[data-corner='right'] {\n\t\tleft: calc(100% - 11px);\n\t}\n\n\t/*\n\t\tScope the :has() selectors to a DIRECT child table so a nested table that\n\t\thas its own sticky row does not pull the OUTER wrapper's masks into the\n\t\tsticky / fallback layout. The masks belong to the wrapper of the table\n\t\tthat owns the sticky row, never to an ancestor wrapper.\n\t*/\n\t.", ":has(> table > tbody > tr.", ")\n\t\t> .", ",\n\t\t.", ":has(> table.", " > tbody > tr.sticky)\n\t\t> .", " {\n\t\tdisplay: block;\n\t}\n\n\t/*\n\t\tWhen the table overflows horizontally, sticky headers fall back from native\n\t\tposition: sticky to a fixed-position header row. Match that positioning so\n\t\tthe corner masks continue to cover the rounded corners in the fallback path.\n\n\t\tThe direct-child combinator inside :has() is critical: without it a nested\n\t\ttable entering the legacy fallback would incorrectly trigger this rule on\n\t\tthe OUTER wrapper, detaching the outer table's masks from its corners.\n\t*/\n\t.", ":has(> table.", " > tbody > tr.sticky)\n\t\t> .", " {\n\t\tposition: fixed;\n\t\ttop: 30px;\n\t\tz-index: 1;\n\t}\n"])), ClassName.TABLE_CORNER_MASK, tableMarginTop, "var(--ds-surface, #FFFFFF)", nativeStickyHeaderZIndex, ClassName.TABLE_CONTAINER, ClassName.TABLE_CORNER_MASK, akEditorTableNumberColumnWidth, ClassName.TABLE_CORNER_MASK, ClassName.TABLE_NODE_WRAPPER, expValEquals('platform_editor_table_q4_patch_4', 'isEnabled', true) ? "".concat(ClassName.NATIVE_STICKY, ".").concat(ClassName.NATIVE_STICKY_ACTIVE) : ClassName.NATIVE_STICKY_ACTIVE, ClassName.TABLE_CORNER_MASK, ClassName.TABLE_NODE_WRAPPER, ClassName.TABLE_STICKY, ClassName.TABLE_CORNER_MASK, ClassName.TABLE_NODE_WRAPPER, ClassName.TABLE_STICKY, ClassName.TABLE_CORNER_MASK);
47
48
  };
48
49
  var roundedTableStickyHeaderOverlayStyles = function roundedTableStickyHeaderOverlayStyles() {
49
50
  return css(_templateObject9 || (_templateObject9 = _taggedTemplateLiteral(["\n\t/*\n\t\tPaint the pinned sticky row's rounded top edge via each cell's ::after.\n\t\ttop: -1px places it in the reserved transparent border slot, aligned with\n\t\tthe row's inset-shadow bottom border. Longhand border-top-* lets\n\t\tinteraction-state rules override only the colour.\n\t*/\n\t.", "\n\t\t> table\n\t\t> tbody\n\t\t> tr.", ".", "\n\t\t> th.", "[data-reaches-top]::after,\n\t\t.", "\n\t\t> table\n\t\t> tbody\n\t\t> tr.", ".", "\n\t\t> td.", "[data-reaches-top]::after {\n\t\tcontent: '';\n\t\tposition: absolute;\n\t\tleft: -1px;\n\t\tright: -1px;\n\t\ttop: -1px;\n\t\tbottom: -1px;\n\t\twidth: auto;\n\t\theight: auto;\n\t\tpointer-events: none;\n\t\tborder-top-width: 1px;\n\t\tborder-top-style: solid;\n\t\tborder-top-color: ", ";\n\t}\n\n\t/* Selection / hover / active-cursor colour for the painted top edge. */\n\t.", "\n\t\t> table\n\t\t> tbody\n\t\t> tr.", ".", "\n\t\t> th.", "[data-reaches-top]:is(\n\t\t\t.", ",\n\t\t\t.", ",\n\t\t\t.", "\n\t\t)::after,\n\t.", "\n\t\t> table\n\t\t> tbody\n\t\t> tr.", ".", "\n\t\t> td.", "[data-reaches-top]:is(\n\t\t\t.", ",\n\t\t\t.", ",\n\t\t\t.", "\n\t\t)::after {\n\t\tborder-top-color: ", ";\n\t}\n\n\t/* Danger colour for the painted top edge. */\n\t.", "\n\t\t> table\n\t\t> tbody\n\t\t> tr.", ".", "\n\t\t> th.", "[data-reaches-top].", "::after,\n\t\t.", "\n\t\t> table\n\t\t> tbody\n\t\t> tr.", ".", "\n\t\t> td.", "[data-reaches-top].", "::after {\n\t\tborder-top-color: ", ";\n\t}\n\n\t:where(.", " > table > tbody > tr.", ")\n\t\t> th.", "[data-reaches-left]::after {\n\t\tborder-left-color: transparent;\n\t}\n\n\t", "\n"])), ClassName.TABLE_NODE_WRAPPER, ClassName.NATIVE_STICKY, ClassName.NATIVE_STICKY_ACTIVE, ClassName.TABLE_HEADER_CELL, ClassName.TABLE_NODE_WRAPPER, ClassName.NATIVE_STICKY, ClassName.NATIVE_STICKY_ACTIVE, ClassName.TABLE_CELL, tableBorderColor, ClassName.TABLE_NODE_WRAPPER, ClassName.NATIVE_STICKY, ClassName.NATIVE_STICKY_ACTIVE, ClassName.TABLE_HEADER_CELL, ClassName.SELECTED_CELL, ClassName.HOVERED_CELL, ClassName.ACTIVE_CURSOR_CELL, ClassName.TABLE_NODE_WRAPPER, ClassName.NATIVE_STICKY, ClassName.NATIVE_STICKY_ACTIVE, ClassName.TABLE_CELL, ClassName.SELECTED_CELL, ClassName.HOVERED_CELL, ClassName.ACTIVE_CURSOR_CELL, tableBorderSelectedColor, ClassName.TABLE_NODE_WRAPPER, ClassName.NATIVE_STICKY, ClassName.NATIVE_STICKY_ACTIVE, ClassName.TABLE_HEADER_CELL, ClassName.HOVERED_CELL_IN_DANGER, ClassName.TABLE_NODE_WRAPPER, ClassName.NATIVE_STICKY, ClassName.NATIVE_STICKY_ACTIVE, ClassName.TABLE_CELL, ClassName.HOVERED_CELL_IN_DANGER, tableBorderDeleteColor, ClassName.TABLE_NODE_WRAPPER, ClassName.NATIVE_STICKY, ClassName.TABLE_HEADER_CELL, fg('platform_editor_table_q4_patch_1') ? css(_templateObject0 || (_templateObject0 = _taggedTemplateLiteral(["\n\t\t\t\t/* Node-selected (ak-editor-selected-node) sticky header: the pinned row leaves the table's\n\t\t\t\t\t rounded overlay behind, so recolour its painted top edge to the selected colour too. */\n\t\t\t\t.", ".", "\n\t\t\t\t\t.", "\n\t\t\t\t\t> table\n\t\t\t\t\t> tbody\n\t\t\t\t\t> tr.", ".", "\n\t\t\t\t\t> th.", "[data-reaches-top]::after,\n\t\t\t\t\t.", ".", "\n\t\t\t\t\t.", "\n\t\t\t\t\t> table\n\t\t\t\t\t> tbody\n\t\t\t\t\t> tr.", ".", "\n\t\t\t\t\t> td.", "[data-reaches-top]::after {\n\t\t\t\t\tborder-top-color: ", ";\n\t\t\t\t}\n\t\t\t"])), ClassName.NODEVIEW_WRAPPER, akEditorSelectedNodeClassName, ClassName.TABLE_NODE_WRAPPER, ClassName.NATIVE_STICKY, ClassName.NATIVE_STICKY_ACTIVE, ClassName.TABLE_HEADER_CELL, ClassName.NODEVIEW_WRAPPER, akEditorSelectedNodeClassName, ClassName.TABLE_NODE_WRAPPER, ClassName.NATIVE_STICKY, ClassName.NATIVE_STICKY_ACTIVE, ClassName.TABLE_CELL, tableBorderSelectedColor) : '');
@@ -40,6 +40,7 @@ export default class TableRowNativeStickyWithFallback extends TableNodeView<HTML
40
40
  private onEditorContentAreaHeightChange?;
41
41
  private editorContentAreaHeight?;
42
42
  private nodeVisibilityObserver?;
43
+ private isSingleRowTable;
43
44
  /**
44
45
  * Methods: Nodeview Lifecycle
45
46
  */
@@ -77,6 +78,10 @@ export default class TableRowNativeStickyWithFallback extends TableNodeView<HTML
77
78
  * Useful when the header may have detached from the table.
78
79
  */
79
80
  private refireIntersectionObservers;
81
+ private checkIsSingleRowTable;
82
+ private updateSingleRowTableStickyHeaderState;
83
+ private removeSingleRowTableStickyHeaderState;
84
+ private refireNativeStickyObservers;
80
85
  private toggleDisableNativeSticky;
81
86
  private makeHeaderRowLegacySticky;
82
87
  private makeRowHeaderNotLegacySticky;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-table",
3
- "version": "24.4.16",
3
+ "version": "24.4.18",
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": "^12.0.0",
30
30
  "@atlaskit/editor-plugin-content-insertion": "^12.0.0",
31
31
  "@atlaskit/editor-plugin-editor-viewmode": "^14.0.0",
32
- "@atlaskit/editor-plugin-extension": "15.0.35",
32
+ "@atlaskit/editor-plugin-extension": "15.0.36",
33
33
  "@atlaskit/editor-plugin-guideline": "^12.0.0",
34
34
  "@atlaskit/editor-plugin-interaction": "^23.0.0",
35
35
  "@atlaskit/editor-plugin-limited-mode": "^9.0.0",
@@ -52,7 +52,7 @@
52
52
  "@atlaskit/pragmatic-drag-and-drop-auto-scroll": "^3.0.0",
53
53
  "@atlaskit/pragmatic-drag-and-drop-hitbox": "^2.0.0",
54
54
  "@atlaskit/primitives": "^22.1.0",
55
- "@atlaskit/tmp-editor-statsig": "^131.0.0",
55
+ "@atlaskit/tmp-editor-statsig": "^132.1.0",
56
56
  "@atlaskit/toggle": "^17.1.0",
57
57
  "@atlaskit/tokens": "^16.2.0",
58
58
  "@atlaskit/tooltip": "^23.1.0",
@@ -159,6 +159,12 @@
159
159
  },
160
160
  "platform_editor_table_cell_menu_update": {
161
161
  "type": "boolean"
162
+ },
163
+ "platform-dst-top-layer-tooltip": {
164
+ "type": "boolean"
165
+ },
166
+ "platform_editor_table_flicker_issue": {
167
+ "type": "boolean"
162
168
  }
163
169
  },
164
170
  "devDependencies": {