@atlaskit/renderer 137.1.8 → 137.1.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/dist/cjs/react/index.js +1 -1
  3. package/dist/cjs/react/nodes/table/colgroup.js +1 -2
  4. package/dist/cjs/react/nodes/table/sticky.js +2 -4
  5. package/dist/cjs/react/nodes/table/table.js +1 -12
  6. package/dist/cjs/react/nodes/table.js +471 -203
  7. package/dist/cjs/ui/Expand.js +33 -7
  8. package/dist/cjs/ui/Renderer/breakout-ssr.js +1 -2
  9. package/dist/cjs/ui/Renderer/index.js +3 -3
  10. package/dist/cjs/ui/utils/expand-body.js +218 -0
  11. package/dist/cjs/ui/utils/expand-search-text.js +39 -1
  12. package/dist/es2019/react/index.js +1 -1
  13. package/dist/es2019/react/nodes/table/colgroup.js +1 -2
  14. package/dist/es2019/react/nodes/table/sticky.js +2 -3
  15. package/dist/es2019/react/nodes/table/table.js +1 -12
  16. package/dist/es2019/react/nodes/table.js +457 -190
  17. package/dist/es2019/ui/Expand.js +33 -7
  18. package/dist/es2019/ui/Renderer/breakout-ssr.js +1 -2
  19. package/dist/es2019/ui/Renderer/index.js +3 -3
  20. package/dist/es2019/ui/utils/expand-body.js +198 -0
  21. package/dist/es2019/ui/utils/expand-search-text.js +38 -0
  22. package/dist/esm/react/index.js +1 -1
  23. package/dist/esm/react/nodes/table/colgroup.js +1 -2
  24. package/dist/esm/react/nodes/table/sticky.js +2 -4
  25. package/dist/esm/react/nodes/table/table.js +1 -12
  26. package/dist/esm/react/nodes/table.js +471 -202
  27. package/dist/esm/ui/Expand.js +33 -7
  28. package/dist/esm/ui/Renderer/breakout-ssr.js +1 -2
  29. package/dist/esm/ui/Renderer/index.js +3 -3
  30. package/dist/esm/ui/utils/expand-body.js +210 -0
  31. package/dist/esm/ui/utils/expand-search-text.js +38 -0
  32. package/dist/types/react/nodes/table/sticky.d.ts +1 -2
  33. package/dist/types/react/nodes/table.d.ts +78 -8
  34. package/dist/types/ui/{expand-body.d.ts → utils/expand-body.d.ts} +26 -5
  35. package/dist/types/ui/utils/expand-search-text.d.ts +14 -0
  36. package/package.json +6 -9
  37. package/dist/cjs/react/nodes/tableNew.js +0 -1050
  38. package/dist/cjs/ui/expand-body.js +0 -122
  39. package/dist/es2019/react/nodes/tableNew.js +0 -986
  40. package/dist/es2019/ui/expand-body.js +0 -107
  41. package/dist/esm/react/nodes/tableNew.js +0 -1044
  42. package/dist/esm/ui/expand-body.js +0 -114
  43. package/dist/types/react/nodes/tableNew.d.ts +0 -189
@@ -1,5 +1,5 @@
1
1
  import _extends from "@babel/runtime/helpers/extends";
2
- import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
2
+ import _typeof from "@babel/runtime/helpers/typeof";
3
3
  import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
4
4
  import _createClass from "@babel/runtime/helpers/createClass";
5
5
  import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";
@@ -13,29 +13,45 @@ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r)
13
13
  function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
14
14
  function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }
15
15
  function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
16
+ /* eslint-disable @atlaskit/ui-styling-standard/no-classname-prop, @atlaskit/ui-styling-standard/enforce-style-prop, @repo/internal/react/no-class-components */
16
17
  import React from 'react';
17
- import { useIntl } from 'react-intl';
18
18
  import { TableSharedCssClassName, tableMarginTop } from '@atlaskit/editor-common/styles';
19
- import { tableMessages } from '@atlaskit/editor-common/messages';
20
- import { WidthConsumer, overflowShadow } from '@atlaskit/editor-common/ui';
19
+ import { overflowShadow } from '@atlaskit/editor-common/ui';
20
+ import { getTableContainerWidth } from '@atlaskit/editor-common/node-width';
21
+ import { FullPagePadding } from '../../ui/Renderer/style';
21
22
  import { fg } from '@atlaskit/platform-feature-flags/fg';
23
+ import { RendererCssClassName } from '../../consts';
22
24
  import { createCompareNodes, convertProsemirrorTableNodeToArrayOfRows, hasMergedCell, compose } from '@atlaskit/editor-common/utils';
23
25
  import { SortOrder } from '@atlaskit/editor-common/types';
24
26
  import { akEditorDefaultLayoutWidth, akEditorFullWidthLayoutWidth, akEditorMaxWidthLayoutWidth } from '@atlaskit/editor-shared-styles';
25
- import { getTableContainerWidth } from '@atlaskit/editor-common/node-width';
26
27
  import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
27
- import { FullPagePadding } from '../../ui/Renderer/style';
28
- import { TableHeader } from './tableCell';
28
+ import { TableCell, TableHeader } from './tableCell';
29
29
  import { withSmartCardStorage } from '../../ui/SmartCardStorage';
30
30
  import { StickyTable, tableStickyPadding, OverflowParent } from './table/sticky';
31
31
  import { Table } from './table/table';
32
- import { isCommentAppearance, isFullPageAppearance, isFullWidthAppearance, isFullWidthOrFullPageAppearance, isMaxWidthAppearance } from '../utils/appearance';
32
+ import { isCommentAppearance, isFullWidthOrFullPageAppearance, isFullWidthAppearance, isMaxWidthAppearance, isFullPageAppearance } from '../utils/appearance';
33
33
  import { TableStickyScrollbar } from './TableStickyScrollbar';
34
34
  import { useRendererContext } from '../../renderer-context';
35
- import { TableProcessorWithContainerStyles, RefSyncBlockFakeBorders } from './tableNew';
36
35
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
37
36
  import { isTableInContentMode } from '@atlaskit/editor-common/table';
38
37
  import { isContentModeSupported } from './table/content-mode';
38
+ var stickyContainerBaseStyles = {
39
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766
40
+ height: "var(--ds-space-250, 20px)",
41
+ // MAX_BROWSER_SCROLLBAR_HEIGHT
42
+ // Follow editor to hide by default so it does not show empty gap in SSR
43
+ // https://bitbucket.org/atlassian/atlassian-frontend-monorepo/src/master/platform/packages/editor/editor-plugin-table/src/nodeviews/TableComponent.tsx#957
44
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766
45
+ display: 'block',
46
+ width: '100%'
47
+ };
48
+ var stickyContainerAdditionalStyles = {
49
+ visibility: 'hidden',
50
+ overflowX: 'auto',
51
+ position: 'sticky',
52
+ bottom: "var(--ds-space-0, 0px)",
53
+ zIndex: 1
54
+ };
39
55
  export var isTableResizingEnabled = function isTableResizingEnabled(appearance) {
40
56
  return isFullWidthOrFullPageAppearance(appearance) || isCommentAppearance(appearance);
41
57
  };
@@ -95,7 +111,7 @@ export var shouldHeaderPinBottom = function shouldHeaderPinBottom(scrollTop, tab
95
111
  return tableBottom - rowHeight <= scrollTop && !(tableBottom < scrollTop);
96
112
  };
97
113
  export var addSortableColumn = function addSortableColumn(rows, tableOrderStatus, onSorting
98
- // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-explicit-any
114
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
99
115
  ) {
100
116
  return React.Children.map(rows, function (row, index) {
101
117
  if (index === 0) {
@@ -126,44 +142,53 @@ export var isHeaderRowEnabled = function isHeaderRowEnabled(rows
126
142
  return node.type === TableHeader;
127
143
  });
128
144
  };
129
- /**
130
- * This TableWrapper component was created to make sure that the aria-label can be
131
- * internationalized without needing to add `intl` to the TableContainer.
132
- *
133
- * <TableWrapper wrapperRef={ref} onScroll={handleScroll} stickyHeaders={config}>
134
- * <Table>...</Table>
135
- * </TableWrapper>
136
- */
137
- var TableWrapper = function TableWrapper(_ref2) {
138
- var children = _ref2.children,
139
- wrapperRef = _ref2.wrapperRef,
140
- onScroll = _ref2.onScroll,
141
- stickyHeaders = _ref2.stickyHeaders,
142
- tabIndex = _ref2.tabIndex;
143
- var _useIntl = useIntl(),
144
- formatMessage = _useIntl.formatMessage;
145
- var isScrollableRegion = tabIndex !== undefined;
146
- return /*#__PURE__*/React.createElement("div", {
147
- // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
148
- className: TableSharedCssClassName.TABLE_NODE_WRAPPER,
149
- ref: wrapperRef,
150
- onScroll: stickyHeaders ? onScroll : undefined
151
- // Adding tabIndex here because this is a scrollable container and it needs to be focusable so keyboard users can scroll it.
152
- // eslint-disable-next-line @atlassian/a11y/no-noninteractive-tabindex
153
- ,
154
- tabIndex: tabIndex,
155
- role: isScrollableRegion ? 'region' : undefined,
156
- "aria-label": isScrollableRegion ? formatMessage(tableMessages.tableScrollRegion) : undefined
157
- }, children);
158
- };
159
145
  export var tableCanBeSticky = function tableCanBeSticky(node, children
160
146
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
161
147
  ) {
162
148
  return isHeaderRowEnabled(children) && node && node.firstChild && !hasRowspan(node.firstChild);
163
149
  };
164
150
  /**
165
- *
166
- */
151
+ * Fake left/right borders rendered as direct children of TABLE_CONTAINER
152
+ * (the non-scrolling parent of the horizontally scrolling TABLE_NODE_WRAPPER).
153
+ *
154
+ * The visible styling for these divs lives in `tableFakeBorderStyles`
155
+ * (`renderer/src/ui/Renderer/RendererStyleContainer.tsx`), which is applied
156
+ * when `isInsideSyncBlock` is true.
157
+ */
158
+ var TableFakeBorders = function TableFakeBorders(_ref2) {
159
+ var isNumberColumnEnabled = _ref2.isNumberColumnEnabled;
160
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
161
+ className: TableSharedCssClassName.TABLE_LEFT_BORDER,
162
+ "data-with-numbered-table": isNumberColumnEnabled ? 'true' : undefined,
163
+ "data-testid": "table-left-border"
164
+ }), /*#__PURE__*/React.createElement("div", {
165
+ className: TableSharedCssClassName.TABLE_RIGHT_BORDER,
166
+ "data-with-numbered-table": isNumberColumnEnabled ? 'true' : undefined,
167
+ "data-testid": "table-right-border"
168
+ }));
169
+ };
170
+
171
+ /**
172
+ * Reads `nestedRendererType` from RendererContext and renders the fake left/right
173
+ * borders only when the current renderer is the nested renderer for a reference
174
+ * synced block.
175
+ */
176
+ export var RefSyncBlockFakeBorders = function RefSyncBlockFakeBorders(_ref3) {
177
+ var isNumberColumnEnabled = _ref3.isNumberColumnEnabled;
178
+ var _useRendererContext = useRendererContext(),
179
+ nestedRendererType = _useRendererContext.nestedRendererType;
180
+ var isInsideOfRefSyncBlock = nestedRendererType === 'syncedBlock';
181
+ if (!isInsideOfRefSyncBlock) {
182
+ return null;
183
+ }
184
+ return /*#__PURE__*/React.createElement(TableFakeBorders, {
185
+ isNumberColumnEnabled: isNumberColumnEnabled
186
+ });
187
+ };
188
+
189
+ /**
190
+ * TableContainer renders tables using only CSS-based rules
191
+ */
167
192
  // Ignored via go/ees005
168
193
  // eslint-disable-next-line @repo/internal/react/no-class-components
169
194
  export var TableContainer = /*#__PURE__*/function (_React$Component) {
@@ -186,6 +211,12 @@ export var TableContainer = /*#__PURE__*/function (_React$Component) {
186
211
  _defineProperty(_this, "stickyWrapperRef", /*#__PURE__*/React.createRef());
187
212
  _defineProperty(_this, "wrapperRef", /*#__PURE__*/React.createRef());
188
213
  _defineProperty(_this, "overflowParent", null);
214
+ _defineProperty(_this, "containerRef", null);
215
+ _defineProperty(_this, "_isInsideNestedRenderer", null);
216
+ _defineProperty(_this, "_isInsideTableCell", null);
217
+ // Stores the last computed style values from render() for use by applyNestedRendererTableFix().
218
+ // This avoids reading from the DOM which can be stale when React removes properties between renders.
219
+ _defineProperty(_this, "lastComputedStyle", {});
189
220
  _defineProperty(_this, "resizeObserver", null);
190
221
  _defineProperty(_this, "applyResizerChange", function (entries) {
191
222
  var wrapperWidth = _this.state.wrapperWidth;
@@ -213,6 +244,25 @@ export var TableContainer = /*#__PURE__*/function (_React$Component) {
213
244
  });
214
245
  }
215
246
  });
247
+ /**
248
+ * Callback ref that captures the container DOM element and also forwards
249
+ * to the handleRef prop from the overflow shadow HOC.
250
+ */
251
+ _defineProperty(_this, "setContainerRef", function (el) {
252
+ if (_this.containerRef !== el) {
253
+ _this._isInsideNestedRenderer = null;
254
+ _this._isInsideTableCell = null;
255
+ }
256
+ _this.containerRef = el;
257
+ var handleRef = _this.props.handleRef;
258
+ if (typeof handleRef === 'function') {
259
+ handleRef(el);
260
+ } else if (handleRef && _typeof(handleRef) === 'object') {
261
+ // Ignored via go/ees005
262
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
263
+ handleRef.current = el;
264
+ }
265
+ });
216
266
  _defineProperty(_this, "componentWillUnmount", function () {
217
267
  if (_this.overflowParent) {
218
268
  // Ignored via go/ees005
@@ -288,9 +338,148 @@ export var TableContainer = /*#__PURE__*/function (_React$Component) {
288
338
  }
289
339
  _inherits(TableContainer, _React$Component);
290
340
  return _createClass(TableContainer, [{
341
+ key: "isInsideNestedRenderer",
342
+ value:
343
+ /**
344
+ * Checks if this table is inside a nested renderer (e.g. Include Page macro)
345
+ * by looking for multiple .ak-renderer-document ancestors in the DOM.
346
+ * The result is cached since a table's position in the DOM tree is stable after mount.
347
+ */
348
+ function isInsideNestedRenderer() {
349
+ if (this._isInsideNestedRenderer !== null) {
350
+ return this._isInsideNestedRenderer;
351
+ }
352
+ if (!this.containerRef) {
353
+ return false;
354
+ }
355
+ var docAncestorCount = 0;
356
+ var el = this.containerRef.parentElement;
357
+ while (el) {
358
+ if (el.classList.contains(RendererCssClassName.DOCUMENT)) {
359
+ docAncestorCount++;
360
+ if (docAncestorCount >= 2) {
361
+ this._isInsideNestedRenderer = true;
362
+ return true;
363
+ }
364
+ }
365
+ el = el.parentElement;
366
+ }
367
+ this._isInsideNestedRenderer = false;
368
+ return false;
369
+ }
370
+
371
+ /**
372
+ * Checks if this table is inside a table cell in the DOM. The result is cached
373
+ * since a table's position in the DOM tree is stable after mount.
374
+ */
375
+ }, {
376
+ key: "isInsideTableCell",
377
+ value: function isInsideTableCell() {
378
+ if (this._isInsideTableCell !== null) {
379
+ return this._isInsideTableCell;
380
+ }
381
+ if (!this.containerRef) {
382
+ return false;
383
+ }
384
+ this._isInsideTableCell = Boolean(this.containerRef.closest('td, th'));
385
+ return this._isInsideTableCell;
386
+ }
387
+ }, {
388
+ key: "isInsideTableContext",
389
+ value: function isInsideTableContext() {
390
+ return Boolean(this.props.isInsideOfTable || this.isInsideTableCell());
391
+ }
392
+
393
+ /**
394
+ * For tables inside nested renderers (e.g. Include Page macro), the parent
395
+ * renderer's CSS override forces width:100%!important and left:0!important
396
+ * which overrides the inline styles set by this component. Using
397
+ * style.setProperty with 'important' priority on inline styles beats
398
+ * stylesheet !important rules per the CSS cascade.
399
+ *
400
+ * Tables that are nested inside another table need to remain constrained by
401
+ * their table-cell context. Do not promote their width to inline !important,
402
+ * otherwise nested tables rendered through macros such as Excerpt Include can
403
+ * overflow and overlap adjacent cells.
404
+ *
405
+ * Top-level tables in nested renderers still preserve their saved width, but
406
+ * are capped to their containing block so wide tables do not escape constrained
407
+ * macro bodies such as Excerpt Include panels.
408
+ *
409
+ * Uses lastComputedStyle (populated during render) rather than reading from
410
+ * element.style, because React may remove properties from the DOM when their
411
+ * values transition to undefined between renders.
412
+ *
413
+ * `platform_nested_table_style_override_2` fixes a follow-up regression where a
414
+ * NON-resized table inside an Excerpt macro (not Excerpt Include) on a
415
+ * wide/full-width page shrinks to only show its first columns in the renderer.
416
+ * Inside a nested renderer (a macro body) a non-resized table's computed width
417
+ * is a default layout cap (760px/1800px, or a `cqw` length for full-page
418
+ * appearances) taken from the outer renderer's width context. That value does
419
+ * not match the macro's own box, so promoting it to inline `!important` makes
420
+ * the table collapse. Such tables have no author-chosen size to preserve, so
421
+ * under this gate we re-assert the parent stylesheet's intent (fill the box:
422
+ * `width: 100%; left: 0`) with inline `!important`.
423
+ *
424
+ * Explicitly resized tables (`tableNode.attrs.width` set) are excluded and keep
425
+ * the original PGXT-10226 behavior: their author-chosen width/left is promoted
426
+ * verbatim so the Include Page macro does not stretch or indent them. The
427
+ * table-cell short-circuit (PGXT-10294) above also still applies.
428
+ */
429
+ }, {
430
+ key: "applyNestedRendererTableFix",
431
+ value: function applyNestedRendererTableFix() {
432
+ var _this$props$tableNode;
433
+ if (!this.containerRef || !fg('platform_nested_table_style_override')) {
434
+ return;
435
+ }
436
+ if (!this.isInsideNestedRenderer() || this.isInsideTableContext()) {
437
+ return;
438
+ }
439
+ var _this$lastComputedSty = this.lastComputedStyle,
440
+ width = _this$lastComputedSty.width,
441
+ left = _this$lastComputedSty.left,
442
+ marginLeft = _this$lastComputedSty.marginLeft;
443
+ var style = this.containerRef.style;
444
+
445
+ // A table is "explicitly resized" when the author set a width on the node.
446
+ // Non-resized tables instead take a default layout cap (e.g. 760px/1800px)
447
+ // derived from the outer renderer's appearance.
448
+ var isExplicitlyResized = Boolean((_this$props$tableNode = this.props.tableNode) === null || _this$props$tableNode === void 0 ? void 0 : _this$props$tableNode.attrs.width);
449
+ if (!isExplicitlyResized && fg('platform_nested_table_style_override_2')) {
450
+ // PGXT-10421: For a NON-resized table inside a nested renderer (e.g. an
451
+ // Excerpt macro body), the computed width is a default layout cap
452
+ // (760px/1800px, or a `cqw` length for full-page appearances) taken from
453
+ // the *outer* renderer's width context. That value does not match the
454
+ // macro's own box, so promoting it to inline `!important` makes the table
455
+ // ignore the available space and collapse to its first columns.
456
+ //
457
+ // These tables have no author-chosen size to preserve, so re-assert the
458
+ // parent stylesheet's intent — fill the available box (`width: 100%`) —
459
+ // with inline `!important` priority so it survives React re-renders and
460
+ // wins over the stylesheet rule that leaks into nested renderers.
461
+ style.setProperty('width', '100%', 'important');
462
+ style.setProperty('max-width', '100%', 'important');
463
+ style.setProperty('left', '0', 'important');
464
+ style.setProperty('margin-left', '0', 'important');
465
+ return;
466
+ }
467
+
468
+ // PGXT-10226: An explicitly resized table inside a nested renderer (e.g.
469
+ // Include Page macro) must keep its author-chosen width and position. The
470
+ // parent stylesheet forces `width: 100% !important; left: 0 !important`,
471
+ // which would stretch and indent it, so we promote the component's own
472
+ // computed width/left with inline `!important` to win the cascade.
473
+ style.setProperty('width', width || 'auto', 'important');
474
+ style.setProperty('max-width', '100%', 'important');
475
+ style.setProperty('left', left || 'auto', 'important');
476
+ style.setProperty('margin-left', marginLeft || '0', 'important');
477
+ }
478
+ }, {
291
479
  key: "componentDidMount",
292
480
  value:
293
481
  /**
482
+ * Starts observing table dimensions and wires sticky header/scrollbar behavior after mount.
294
483
  *
295
484
  * @example
296
485
  */
@@ -312,9 +501,11 @@ export var TableContainer = /*#__PURE__*/function (_React$Component) {
312
501
  if (this.wrapperRef.current && isStickyScrollbarEnabled(this.props.rendererAppearance)) {
313
502
  this.stickyScrollbar = new TableStickyScrollbar(this.wrapperRef.current);
314
503
  }
504
+ this.applyNestedRendererTableFix();
315
505
  }
316
506
 
317
507
  /**
508
+ * Updates sticky header wiring and scroll synchronization after prop or state changes.
318
509
  *
319
510
  * @param prevProps
320
511
  * @param prevState
@@ -343,12 +534,16 @@ export var TableContainer = /*#__PURE__*/function (_React$Component) {
343
534
  if (prevState.stickyMode !== this.state.stickyMode) {
344
535
  this.onWrapperScrolled();
345
536
  }
537
+
538
+ // React re-applies the style prop on every render, which overwrites the
539
+ // !important priorities set at mount time. Re-apply after each update.
540
+ this.applyNestedRendererTableFix();
346
541
  }
347
542
  }, {
348
543
  key: "pinTop",
349
544
  get:
350
545
  /**
351
- *
546
+ * Calculates the top offset used when the sticky header is pinned to the table bottom.
352
547
  */
353
548
  function get() {
354
549
  if (!this.tableRef.current || !this.stickyHeaderRef.current) {
@@ -358,7 +553,7 @@ export var TableContainer = /*#__PURE__*/function (_React$Component) {
358
553
  }
359
554
 
360
555
  /**
361
- *
556
+ * Determines whether sticky header positioning should include the default scroll root offset.
362
557
  */
363
558
  }, {
364
559
  key: "shouldAddOverflowParentOffsetTop_DO_NOT_USE",
@@ -371,7 +566,7 @@ export var TableContainer = /*#__PURE__*/function (_React$Component) {
371
566
  }
372
567
 
373
568
  /**
374
- *
569
+ * Resolves the top position for the sticky header based on the current sticky mode.
375
570
  */
376
571
  }, {
377
572
  key: "stickyTop",
@@ -393,6 +588,7 @@ export var TableContainer = /*#__PURE__*/function (_React$Component) {
393
588
  }
394
589
 
395
590
  /**
591
+ * Renders the table container, sticky header, table content, sticky scrollbar, and synced block borders.
396
592
  *
397
593
  * @example
398
594
  */
@@ -403,7 +599,6 @@ export var TableContainer = /*#__PURE__*/function (_React$Component) {
403
599
  var _this$props = this.props,
404
600
  isNumberColumnEnabled = _this$props.isNumberColumnEnabled,
405
601
  layout = _this$props.layout,
406
- renderWidth = _this$props.renderWidth,
407
602
  columnWidths = _this$props.columnWidths,
408
603
  stickyHeaders = _this$props.stickyHeaders,
409
604
  tableNode = _this$props.tableNode,
@@ -418,67 +613,43 @@ export var TableContainer = /*#__PURE__*/function (_React$Component) {
418
613
  allowFixedColumnWidthOption = _this$props.allowFixedColumnWidthOption;
419
614
  var stickyMode = this.state.stickyMode;
420
615
  var lineLengthFixedWidth = akEditorDefaultLayoutWidth;
421
- var left;
422
616
  var updatedLayout;
423
-
424
- // The tableWidth and left offset logic below must stay aligned with the `breakout-ssr.tsx` logic
425
- // Please consider changes below carefully to not negatively impact SSR
426
- // `renderWidth` cannot be depended on during SSR
427
- var isRenderWidthValid = !!renderWidth && renderWidth > 0;
428
617
  var fullPageRendererWidthCSS = editorExperiment('platform_editor_preview_panel_responsiveness', true, {
429
618
  exposure: true
430
619
  }) ? 'calc(100cqw - var(--ak-renderer--full-page-gutter) * 2)' : "100cqw - ".concat(FullPagePadding, "px * 2");
431
620
  var renderWidthCSS = rendererAppearance === 'full-page' ? fullPageRendererWidthCSS : "100cqw";
432
621
  var calcDefaultLayoutWidthByAppearance = function calcDefaultLayoutWidthByAppearance(rendererAppearance, tableNode) {
433
- if (rendererAppearance === 'full-width' && !(tableNode !== null && tableNode !== void 0 && tableNode.attrs.width)) {
434
- return [isRenderWidthValid ? Math.min(akEditorFullWidthLayoutWidth, renderWidth) : akEditorFullWidthLayoutWidth, "min(".concat(akEditorFullWidthLayoutWidth, "px, ").concat(renderWidthCSS, ")")];
435
- } else if (rendererAppearance === 'max' && !(tableNode !== null && tableNode !== void 0 && tableNode.attrs.width)) {
436
- return [isRenderWidthValid ? Math.min(akEditorMaxWidthLayoutWidth, renderWidth) : akEditorMaxWidthLayoutWidth, "min(".concat(akEditorMaxWidthLayoutWidth, "px, ").concat(renderWidthCSS, ")")];
622
+ if (rendererAppearance === 'max' && !(tableNode !== null && tableNode !== void 0 && tableNode.attrs.width) && (expValEquals('editor_tinymce_full_width_mode', 'isEnabled', true) || expValEquals('confluence_max_width_content_appearance', 'isEnabled', true))) {
623
+ return "min(".concat(akEditorMaxWidthLayoutWidth, "px, ").concat(renderWidthCSS, ")");
624
+ } else if (rendererAppearance === 'full-width' && !(tableNode !== null && tableNode !== void 0 && tableNode.attrs.width)) {
625
+ return "min(".concat(akEditorFullWidthLayoutWidth, "px, ").concat(renderWidthCSS, ")");
437
626
  } else if (rendererAppearance === 'comment' && allowTableResizing && !(tableNode !== null && tableNode !== void 0 && tableNode.attrs.width)) {
438
- var tableContainerWidth = getTableContainerWidth(tableNode);
439
- return [isRenderWidthValid ? renderWidth : tableContainerWidth, renderWidthCSS];
627
+ return renderWidthCSS;
440
628
  } else {
441
629
  // custom width, or width mapped to breakpoint
442
- var _tableContainerWidth = getTableContainerWidth(tableNode);
443
- return [isRenderWidthValid ? Math.min(_tableContainerWidth, renderWidth) : _tableContainerWidth, "min(".concat(_tableContainerWidth, "px, ").concat(renderWidthCSS, ")")];
630
+ var tableContainerWidth = getTableContainerWidth(tableNode);
631
+ return "min(".concat(tableContainerWidth, "px, ").concat(renderWidthCSS, ")");
444
632
  }
445
633
  };
446
- var _calcDefaultLayoutWid = calcDefaultLayoutWidthByAppearance(rendererAppearance, tableNode),
447
- _calcDefaultLayoutWid2 = _slicedToArray(_calcDefaultLayoutWid, 2),
448
- tableWidth = _calcDefaultLayoutWid2[0],
449
- tableWidthCSS = _calcDefaultLayoutWid2[1];
634
+ var tableWidthCSS = calcDefaultLayoutWidthByAppearance(rendererAppearance, tableNode);
450
635
 
451
636
  // Logic for table alignment in renderer
452
637
  var isTableAlignStart = tableNode && tableNode.attrs && tableNode.attrs.layout === 'align-start' && allowTableAlignment;
453
- var fullWidthLineLength = isRenderWidthValid ? Math.min(akEditorFullWidthLayoutWidth, renderWidth) : akEditorFullWidthLayoutWidth;
454
638
  var fullWidthLineLengthCSS = "min(".concat(akEditorFullWidthLayoutWidth, "px, ").concat(renderWidthCSS, ")");
455
- var maxWidthLineLength = isRenderWidthValid ? Math.min(akEditorMaxWidthLayoutWidth, renderWidth) : akEditorMaxWidthLayoutWidth;
456
639
  var maxWidthLineLengthCSS = "min(".concat(akEditorMaxWidthLayoutWidth, "px, ").concat(renderWidthCSS, ")");
457
- var commentLineLength = isRenderWidthValid ? renderWidth : lineLengthFixedWidth;
458
640
  var isCommentAppearanceAndTableAlignmentEnabled = isCommentAppearance(rendererAppearance) && allowTableAlignment;
459
- var lineLength = isFullWidthAppearance(rendererAppearance) ? fullWidthLineLength : isMaxWidthAppearance(rendererAppearance) && (expValEquals('editor_tinymce_full_width_mode', 'isEnabled', true) || expValEquals('confluence_max_width_content_appearance', 'isEnabled', true)) ? maxWidthLineLength : isCommentAppearanceAndTableAlignmentEnabled ? commentLineLength : lineLengthFixedWidth;
460
641
  var lineLengthCSS = isFullWidthAppearance(rendererAppearance) ? fullWidthLineLengthCSS : isMaxWidthAppearance(rendererAppearance) && (expValEquals('editor_tinymce_full_width_mode', 'isEnabled', true) || expValEquals('confluence_max_width_content_appearance', 'isEnabled', true)) ? maxWidthLineLengthCSS : isCommentAppearanceAndTableAlignmentEnabled ? renderWidthCSS : "".concat(lineLengthFixedWidth, "px");
461
-
462
- // Setting fixTableSSRResizing to false while FG logic is true in tableNew
463
- var fixTableSSRResizing = false;
464
- var tableWidthNew = fixTableSSRResizing ? getTableContainerWidth(tableNode) : tableWidth;
465
- var shouldCalculateLeftForAlignment = !isInsideOfBlockNode && !isInsideOfTable && isTableAlignStart && (isFullPageAppearance(rendererAppearance) && tableWidthNew <= lineLengthFixedWidth || isFullWidthAppearance(rendererAppearance) || (expValEquals('editor_tinymce_full_width_mode', 'isEnabled', true) || expValEquals('confluence_max_width_content_appearance', 'isEnabled', true)) && isMaxWidthAppearance(rendererAppearance) || isCommentAppearanceAndTableAlignmentEnabled);
642
+ var tableWidthNew = getTableContainerWidth(tableNode);
643
+ var shouldCalculateLeftForAlignment = !isInsideOfBlockNode && !isInsideOfTable && isTableAlignStart && (isFullPageAppearance(rendererAppearance) && tableWidthNew <= lineLengthFixedWidth || isFullWidthAppearance(rendererAppearance) || isMaxWidthAppearance(rendererAppearance) && (expValEquals('editor_tinymce_full_width_mode', 'isEnabled', true) || expValEquals('confluence_max_width_content_appearance', 'isEnabled', true)) || isCommentAppearanceAndTableAlignmentEnabled);
466
644
  var leftCSS;
467
645
  if (shouldCalculateLeftForAlignment) {
468
- left = (tableWidth - lineLength) / 2;
469
646
  leftCSS = "(".concat(tableWidthCSS, " - ").concat(lineLengthCSS, ") / 2");
470
647
  }
471
- if (fixTableSSRResizing) {
472
- if (!shouldCalculateLeftForAlignment && isFullPageAppearance(rendererAppearance)) {
473
- // Note tableWidthCSS here is the renderer width
474
- // When the screen is super wide we want table to break out.
475
- // However if screen is smaller than 760px. We want table align to left.
476
- leftCSS = "min(0px, ".concat(lineLengthCSS, " - ").concat(tableWidthCSS, ") / 2");
477
- }
478
- } else {
479
- if (!shouldCalculateLeftForAlignment && isFullPageAppearance(rendererAppearance) && tableWidthNew > lineLengthFixedWidth) {
480
- left = lineLengthFixedWidth / 2 - tableWidth / 2;
481
- }
648
+ if (!shouldCalculateLeftForAlignment && isFullPageAppearance(rendererAppearance)) {
649
+ // Note tableWidthCSS here is the renderer width
650
+ // When the screen is super wide we want table to break out.
651
+ // However if screen is smaller than 760px. We want table align to left.
652
+ leftCSS = "min(0px, ".concat(lineLengthCSS, " - ").concat(tableWidthCSS, ") / 2");
482
653
  }
483
654
  var children = React.Children.toArray(this.props.children);
484
655
 
@@ -498,7 +669,7 @@ export var TableContainer = /*#__PURE__*/function (_React$Component) {
498
669
  // We can only use CSS to determine the width when we have a known width in container.
499
670
  // When appearance is full-page, full-width or comment we use CSS based width calculation.
500
671
  // Otherwise it's fixed table width (customized width) or inherit.
501
- if ((rendererAppearance === 'full-page' || rendererAppearance === 'full-width' || rendererAppearance === 'max') && fixTableSSRResizing) {
672
+ if (rendererAppearance === 'full-page' || rendererAppearance === 'full-width' || rendererAppearance === 'max' && (expValEquals('editor_tinymce_full_width_mode', 'isEnabled', true) || expValEquals('confluence_max_width_content_appearance', 'isEnabled', true))) {
502
673
  finalTableContainerWidth = allowTableResizing ? "calc(".concat(tableWidthCSS, ")") : 'inherit';
503
674
  }
504
675
  if (rendererAppearance === 'comment' && allowTableResizing && !allowTableAlignment) {
@@ -509,13 +680,13 @@ export var TableContainer = /*#__PURE__*/function (_React$Component) {
509
680
 
510
681
  // !NOTE: it a table resized to 760 is copied from 'full-page' editor and pasted in comment editor
511
682
  // where (allowTableResizing && !allowTableAlignment), the table will loose 760px width.
512
- finalTableContainerWidth = tableNode !== null && tableNode !== void 0 && tableNode.attrs.width && (tableNode === null || tableNode === void 0 ? void 0 : tableNode.attrs.width) !== akEditorDefaultLayoutWidth ? fixTableSSRResizing ? "calc(".concat(tableWidthCSS, ")") : tableWidth : 'inherit';
683
+ finalTableContainerWidth = tableNode !== null && tableNode !== void 0 && tableNode.attrs.width && (tableNode === null || tableNode === void 0 ? void 0 : tableNode.attrs.width) !== akEditorDefaultLayoutWidth ? "calc(".concat(tableWidthCSS, ")") : 'inherit';
513
684
  }
514
685
  if (rendererAppearance === 'comment' && allowTableResizing && allowTableAlignment) {
515
686
  // If table alignment is enabled and layout is not 'align-start' or 'center', we are loading a table that was
516
687
  // created before "Support Table in Comments" FF was enabled. So the table should have the same width as renderer container
517
688
  // instead of 760 that was set on tableNode when the table had been published.
518
- finalTableContainerWidth = ((tableNode === null || tableNode === void 0 ? void 0 : tableNode.attrs.layout) === 'align-start' || (tableNode === null || tableNode === void 0 ? void 0 : tableNode.attrs.layout) === 'center') && tableNode !== null && tableNode !== void 0 && tableNode.attrs.width ? fixTableSSRResizing ? "calc(".concat(tableWidthCSS, ")") : tableWidth : 'inherit';
689
+ finalTableContainerWidth = ((tableNode === null || tableNode === void 0 ? void 0 : tableNode.attrs.layout) === 'align-start' || (tableNode === null || tableNode === void 0 ? void 0 : tableNode.attrs.layout) === 'center') && tableNode !== null && tableNode !== void 0 && tableNode.attrs.width ? "calc(".concat(tableWidthCSS, ")") : 'inherit';
519
690
  }
520
691
  var isContentModeTable = isTableInContentMode({
521
692
  tableNode: tableNode,
@@ -525,41 +696,39 @@ export var TableContainer = /*#__PURE__*/function (_React$Component) {
525
696
  }),
526
697
  isTableNested: isInsideOfBlockNode || isInsideOfNestedRenderer || isInsideOfTable
527
698
  }) && expValEquals('platform_editor_table_fit_to_content_auto_convert', 'isEnabled', true);
528
- var style;
529
- if (fixTableSSRResizing) {
530
- style = _objectSpread(_objectSpread({}, isContentModeTable && {
531
- '--renderer-table-max-width': renderWidthCSS
532
- }), {}, {
533
- width: finalTableContainerWidth,
534
- left: leftCSS ? "calc(".concat(leftCSS, ")") : undefined,
535
- marginLeft: shouldCalculateLeftForAlignment && leftCSS !== undefined ? "calc(-1 * (".concat(leftCSS, "))") : undefined
536
- });
537
- } else {
538
- style = _objectSpread(_objectSpread({}, isContentModeTable && {
539
- '--renderer-table-max-width': "".concat(renderWidth, "px")
540
- }), {}, {
541
- width: finalTableContainerWidth,
542
- left: left,
543
- marginLeft: shouldCalculateLeftForAlignment && left !== undefined ? -left : undefined
544
- });
545
- }
699
+ var style = _objectSpread(_objectSpread({}, isContentModeTable && {
700
+ '--renderer-table-max-width': renderWidthCSS
701
+ }), {}, {
702
+ width: finalTableContainerWidth,
703
+ left: leftCSS ? "calc(".concat(leftCSS, ")") : undefined,
704
+ marginLeft: shouldCalculateLeftForAlignment && leftCSS !== undefined ? "calc(-1 * (".concat(leftCSS, "))") : undefined
705
+ });
706
+
707
+ // Store computed style values for applyNestedRendererTableFix() to use.
708
+ // Reading from props rather than the DOM ensures correctness when React
709
+ // removes properties (transitions from set to undefined) between renders.
710
+ this.lastComputedStyle = {
711
+ width: typeof style.width === 'number' ? "".concat(style.width, "px") : style.width,
712
+ left: style.left,
713
+ marginLeft: style.marginLeft
714
+ };
546
715
  return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
547
716
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
548
717
  className: "".concat(TableSharedCssClassName.TABLE_CONTAINER, " ").concat(this.props.shadowClassNames || ''),
549
718
  "data-layout": updatedLayout,
550
- ref: this.props.handleRef
551
- // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766
552
- ,
719
+ "data-testid": "table-container",
720
+ ref: this.setContainerRef,
553
721
  style: style
722
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766
554
723
  }, isStickyScrollbarEnabled(this.props.rendererAppearance) && /*#__PURE__*/React.createElement("div", {
555
724
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
556
725
  className: TableSharedCssClassName.TABLE_STICKY_SCROLLBAR_SENTINEL_TOP,
557
726
  "data-testid": "sticky-scrollbar-sentinel-top"
558
- }), stickyHeaders && tableCanBeSticky(tableNode, children) && /*#__PURE__*/React.createElement(StickyTable, {
727
+ }), stickyHeaders && tableNode && !isContentModeTable && tableCanBeSticky(tableNode, children) && /*#__PURE__*/React.createElement(StickyTable, {
559
728
  isNumberColumnEnabled: isNumberColumnEnabled,
560
- tableWidth: tableWidth,
729
+ tableWidth: "inherit",
730
+ renderWidth: 0,
561
731
  layout: layout,
562
- renderWidth: renderWidth,
563
732
  handleRef: this.props.handleRef,
564
733
  shadowClassNames: this.props.shadowClassNames,
565
734
  top: this.stickyTop,
@@ -572,17 +741,23 @@ export var TableContainer = /*#__PURE__*/function (_React$Component) {
572
741
  rendererAppearance: rendererAppearance,
573
742
  allowTableResizing: allowTableResizing,
574
743
  allowFixedColumnWidthOption: allowFixedColumnWidthOption
575
- }, [children && children[0]]), /*#__PURE__*/React.createElement(TableWrapper, {
576
- wrapperRef: this.wrapperRef,
577
- onScroll: this.props.stickyHeaders ? this.onWrapperScrolled : undefined,
578
- stickyHeaders: stickyHeaders,
579
- tabIndex: this.props.tabIndex
744
+ }, [children && children[0]]), /*#__PURE__*/React.createElement("div", {
745
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
746
+ className: TableSharedCssClassName.TABLE_NODE_WRAPPER,
747
+ ref: this.wrapperRef,
748
+ "data-number-column": tableNode === null || tableNode === void 0 ? void 0 : tableNode.attrs.isNumberColumnEnabled,
749
+ "data-layout": tableNode === null || tableNode === void 0 ? void 0 : tableNode.attrs.layout,
750
+ "data-autosize": tableNode === null || tableNode === void 0 ? void 0 : tableNode.attrs.__autoSize,
751
+ "data-table-local-id": tableNode === null || tableNode === void 0 ? void 0 : tableNode.attrs.localId,
752
+ "data-table-width": tableNode === null || tableNode === void 0 ? void 0 : tableNode.attrs.width,
753
+ "data-vc": "table-node-wrapper",
754
+ onScroll: this.props.stickyHeaders && this.onWrapperScrolled
580
755
  }, /*#__PURE__*/React.createElement(Table, {
581
756
  innerRef: this.tableRef,
582
757
  columnWidths: columnWidths,
583
758
  layout: layout,
759
+ renderWidth: 0,
584
760
  isNumberColumnEnabled: isNumberColumnEnabled,
585
- renderWidth: renderWidth,
586
761
  tableNode: tableNode,
587
762
  rendererAppearance: rendererAppearance,
588
763
  isInsideOfBlockNode: isInsideOfBlockNode,
@@ -594,22 +769,13 @@ export var TableContainer = /*#__PURE__*/function (_React$Component) {
594
769
  allowFixedColumnWidthOption: allowFixedColumnWidthOption
595
770
  }, this.grabFirstRowRef(children))), isStickyScrollbarEnabled(this.props.rendererAppearance) && /*#__PURE__*/React.createElement("div", {
596
771
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
597
- className: TableSharedCssClassName.TABLE_STICKY_SCROLLBAR_CONTAINER,
772
+ className: "".concat(TableSharedCssClassName.TABLE_STICKY_SCROLLBAR_CONTAINER).concat(fg('confluence_frontend_table_scrollbar_ttvc_fix') ? '-view-page' : ''),
598
773
  ref: this.stickyScrollbarRef,
599
- style: {
600
- // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766
601
- height: "var(--ds-space-250, 20px)",
602
- // MAX_BROWSER_SCROLLBAR_HEIGHT
603
- // Follow editor to hide by default so it does not show empty gap in SSR
604
- // https://bitbucket.org/atlassian/atlassian-frontend-monorepo/src/master/platform/packages/editor/editor-plugin-table/src/nodeviews/TableComponent.tsx#957
605
- // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766
606
- display: fixTableSSRResizing ? 'none' : 'block',
607
- // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop
608
- width: '100%'
609
- }
774
+ "data-vc": "table-sticky-scrollbar-container",
775
+ style: fg('confluence_frontend_table_scrollbar_ttvc_fix') ? _objectSpread(_objectSpread({}, stickyContainerBaseStyles), stickyContainerAdditionalStyles) : stickyContainerBaseStyles
610
776
  }, /*#__PURE__*/React.createElement("div", {
611
777
  style: {
612
- width: (_this$tableRef$curren = this.tableRef.current) === null || _this$tableRef$curren === void 0 ? void 0 : _this$tableRef$curren.clientWidth,
778
+ width: fg('confluence_frontend_table_scrollbar_ttvc_fix') ? '100%' : (_this$tableRef$curren = this.tableRef.current) === null || _this$tableRef$curren === void 0 ? void 0 : _this$tableRef$curren.clientWidth,
613
779
  // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766
614
780
  height: '100%'
615
781
  }
@@ -623,19 +789,117 @@ export var TableContainer = /*#__PURE__*/function (_React$Component) {
623
789
  }
624
790
  }]);
625
791
  }(React.Component);
792
+ var getCellEdgePropsByCellOffset = function getCellEdgePropsByCellOffset(tableNode, isNumberColumnEnabled) {
793
+ var cellEdgePropsByCellOffset = new Map();
794
+ var cellRightByCellOffset = new Map();
795
+ var occupiedGrid = [];
796
+ var tableWidth = 0;
797
+ var cellOffset = 0;
798
+ tableNode.forEach(function (rowNode, _rowOffset, rowIndex) {
799
+ var _occupiedGrid$rowInde;
800
+ occupiedGrid[rowIndex] = (_occupiedGrid$rowInde = occupiedGrid[rowIndex]) !== null && _occupiedGrid$rowInde !== void 0 ? _occupiedGrid$rowInde : [];
801
+ var columnIndex = 0;
802
+ cellOffset += 1;
803
+ rowNode.forEach(function (cellNode) {
804
+ while (occupiedGrid[rowIndex][columnIndex]) {
805
+ columnIndex += 1;
806
+ }
807
+ var colspan = cellNode.attrs.colspan || 1;
808
+ var rowspan = cellNode.attrs.rowspan || 1;
809
+ var cellLeft = columnIndex;
810
+ var cellRight = cellLeft + colspan;
811
+ var cellTop = rowIndex;
812
+ var cellBottom = cellTop + rowspan;
813
+ for (var row = cellTop; row < cellBottom; row += 1) {
814
+ var _occupiedGrid$row;
815
+ occupiedGrid[row] = (_occupiedGrid$row = occupiedGrid[row]) !== null && _occupiedGrid$row !== void 0 ? _occupiedGrid$row : [];
816
+ for (var column = cellLeft; column < cellRight; column += 1) {
817
+ occupiedGrid[row][column] = true;
818
+ }
819
+ }
820
+ tableWidth = Math.max(tableWidth, cellRight);
821
+ cellRightByCellOffset.set(cellOffset, cellRight);
822
+ cellEdgePropsByCellOffset.set(cellOffset, {
823
+ reachesBottom: cellBottom >= tableNode.childCount,
824
+ // With number column enabled, PM column 0 is not visually leftmost and must not get `data-reaches-left`.
825
+ reachesLeft: cellLeft === 0 && !isNumberColumnEnabled,
826
+ reachesRight: false,
827
+ reachesTop: cellTop === 0
828
+ });
829
+ columnIndex = cellRight;
830
+ cellOffset += cellNode.nodeSize;
831
+ });
832
+ cellOffset += 1;
833
+ });
834
+ cellRightByCellOffset.forEach(function (cellRight, currentCellOffset) {
835
+ var edgeProps = cellEdgePropsByCellOffset.get(currentCellOffset);
836
+ if (edgeProps) {
837
+ edgeProps.reachesRight = cellRight >= tableWidth;
838
+ }
839
+ });
840
+ return cellEdgePropsByCellOffset;
841
+ };
842
+ var isRenderedTableCell = function isRenderedTableCell(element) {
843
+ var _ref4 = element.props,
844
+ nodeType = _ref4.nodeType;
845
+ return nodeType === 'tableCell' || nodeType === 'tableHeader' || element.type === TableCell || element.type === TableHeader;
846
+ };
847
+ var addTableCellEdgePropsThroughWrappers = function addTableCellEdgePropsThroughWrappers(rows, tableNode, isNumberColumnEnabled) {
848
+ try {
849
+ if (!tableNode) {
850
+ return rows;
851
+ }
852
+ var cellEdgePropsByCellOffset = getCellEdgePropsByCellOffset(tableNode, isNumberColumnEnabled);
853
+ var cellOffset = 0;
854
+ return React.Children.map(rows, function (row, rowIndex) {
855
+ var rowNode = tableNode.child(rowIndex);
856
+ cellOffset += 1;
857
+ var cellIndex = 0;
858
+ var _addEdgePropsToRenderedCells = function addEdgePropsToRenderedCells(element) {
859
+ if (isRenderedTableCell(element)) {
860
+ var cellNode = rowNode.child(cellIndex);
861
+ var edgeProps = cellEdgePropsByCellOffset.get(cellOffset);
862
+ cellIndex += 1;
863
+ cellOffset += cellNode.nodeSize;
864
+ return edgeProps ? /*#__PURE__*/React.cloneElement(element, edgeProps) : element;
865
+ }
866
+ var _ref5 = element.props,
867
+ children = _ref5.children;
868
+ if (children === undefined) {
869
+ return element;
870
+ }
871
+ var childrenWithEdgeProps = React.Children.map(children, function (child) {
872
+ return /*#__PURE__*/React.isValidElement(child) ? _addEdgePropsToRenderedCells(child) : child;
873
+ });
874
+ return /*#__PURE__*/React.cloneElement(element, undefined, childrenWithEdgeProps);
875
+ };
876
+ var rowWithEdgeProps = _addEdgePropsToRenderedCells(row);
877
+ if (cellIndex !== rowNode.childCount) {
878
+ throw new Error('Rendered table row does not match its document node');
879
+ }
880
+ cellOffset += 1;
881
+ return rowWithEdgeProps;
882
+ });
883
+ } catch (_unused) {
884
+ // Renderer can receive malformed historical ADF. If the table shape cannot
885
+ // be described safely, keep rendering without rounded edge metadata.
886
+ return rows;
887
+ }
888
+ };
889
+
626
890
  /**
627
- *
891
+ * Processes table children before passing them to the styled table container.
628
892
  */
629
893
  // Ignored via go/ees005
630
894
  // eslint-disable-next-line @repo/internal/react/no-class-components
631
- export var TableProcessor = /*#__PURE__*/function (_React$Component2) {
632
- function TableProcessor() {
895
+ export var TableProcessorWithContainerStyles = /*#__PURE__*/function (_React$Component2) {
896
+ function TableProcessorWithContainerStyles() {
633
897
  var _this2;
634
- _classCallCheck(this, TableProcessor);
898
+ _classCallCheck(this, TableProcessorWithContainerStyles);
635
899
  for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
636
900
  args[_key2] = arguments[_key2];
637
901
  }
638
- _this2 = _callSuper(this, TableProcessor, [].concat(args));
902
+ _this2 = _callSuper(this, TableProcessorWithContainerStyles, [].concat(args));
639
903
  _defineProperty(_this2, "state", {
640
904
  tableOrderStatus: undefined
641
905
  });
@@ -664,36 +928,82 @@ export var TableProcessor = /*#__PURE__*/function (_React$Component2) {
664
928
  _defineProperty(_this2, "addNumberColumnIndexes", function (rows) {
665
929
  var isNumberColumnEnabled = _this2.props.isNumberColumnEnabled;
666
930
  var headerRowEnabled = isHeaderRowEnabled(rows);
931
+ var lastRowIndex = React.Children.count(rows) - 1;
667
932
  return React.Children.map(rows, function (row, index) {
668
933
  return /*#__PURE__*/React.cloneElement(React.Children.only(row), {
669
934
  isNumberColumnEnabled: isNumberColumnEnabled,
670
- index: headerRowEnabled ? index === 0 ? '' : index : index + 1
935
+ index: headerRowEnabled ? index === 0 ? '' : index : index + 1,
936
+ isFirstRow: index === 0,
937
+ isLastRow: index === lastRowIndex
671
938
  });
672
939
  });
673
940
  });
674
941
  return _this2;
675
942
  }
676
- _inherits(TableProcessor, _React$Component2);
677
- return _createClass(TableProcessor, [{
943
+ _inherits(TableProcessorWithContainerStyles, _React$Component2);
944
+ return _createClass(TableProcessorWithContainerStyles, [{
678
945
  key: "render",
679
946
  value:
680
947
  /**
948
+ * Renders processed table children inside the table container.
681
949
  *
682
950
  * @example
683
951
  */
684
952
  function render() {
685
- var children = this.props.children;
953
+ var _this$props2 = this.props,
954
+ allowColumnSorting = _this$props2.allowColumnSorting,
955
+ allowFixedColumnWidthOption = _this$props2.allowFixedColumnWidthOption,
956
+ allowTableAlignment = _this$props2.allowTableAlignment,
957
+ allowTableResizing = _this$props2.allowTableResizing,
958
+ children = _this$props2.children,
959
+ columnWidths = _this$props2.columnWidths,
960
+ disableTableOverflowShadow = _this$props2.disableTableOverflowShadow,
961
+ handleRef = _this$props2.handleRef,
962
+ isinsideMultiBodiedExtension = _this$props2.isinsideMultiBodiedExtension,
963
+ isInsideOfBlockNode = _this$props2.isInsideOfBlockNode,
964
+ isInsideOfNestedRenderer = _this$props2.isInsideOfNestedRenderer,
965
+ isInsideOfTable = _this$props2.isInsideOfTable,
966
+ isNumberColumnEnabled = _this$props2.isNumberColumnEnabled,
967
+ isPresentational = _this$props2.isPresentational,
968
+ layout = _this$props2.layout,
969
+ rendererAppearance = _this$props2.rendererAppearance,
970
+ renderWidth = _this$props2.renderWidth,
971
+ shadowClassNames = _this$props2.shadowClassNames,
972
+ smartCardStorage = _this$props2.smartCardStorage,
973
+ stickyHeaders = _this$props2.stickyHeaders,
974
+ tabIndex = _this$props2.tabIndex,
975
+ tableNode = _this$props2.tableNode;
686
976
  if (!children) {
687
977
  return null;
688
978
  }
689
979
  var childrenArray = React.Children.toArray(children);
980
+ var childrenWithTableEdgeProps = expValEquals('platform_editor_table_q4_loveability', 'isEnabled', true) ? addTableCellEdgePropsThroughWrappers(childrenArray, tableNode, isNumberColumnEnabled) : childrenArray;
690
981
  var orderedChildren = compose(this.addNumberColumnIndexes, this.addSortableColumn
691
982
  // @ts-expect-error TS2345: Argument of type '(ReactChild | ReactFragment | ReactPortal)[]' is not assignable to parameter of type 'ReactElement<any, string | JSXElementConstructor<any>>[]'
692
- )(childrenArray);
693
-
694
- // Ignored via go/ees005
695
- // eslint-disable-next-line react/jsx-props-no-spreading
696
- return /*#__PURE__*/React.createElement(TableContainer, this.props, orderedChildren);
983
+ )(childrenWithTableEdgeProps);
984
+ return /*#__PURE__*/React.createElement(TableContainer, {
985
+ allowColumnSorting: allowColumnSorting,
986
+ allowFixedColumnWidthOption: allowFixedColumnWidthOption,
987
+ allowTableAlignment: allowTableAlignment,
988
+ allowTableResizing: allowTableResizing,
989
+ columnWidths: columnWidths,
990
+ disableTableOverflowShadow: disableTableOverflowShadow,
991
+ handleRef: handleRef,
992
+ isinsideMultiBodiedExtension: isinsideMultiBodiedExtension,
993
+ isInsideOfBlockNode: isInsideOfBlockNode,
994
+ isInsideOfNestedRenderer: isInsideOfNestedRenderer,
995
+ isInsideOfTable: isInsideOfTable,
996
+ isNumberColumnEnabled: isNumberColumnEnabled,
997
+ isPresentational: isPresentational,
998
+ layout: layout,
999
+ rendererAppearance: rendererAppearance,
1000
+ renderWidth: renderWidth,
1001
+ shadowClassNames: shadowClassNames,
1002
+ smartCardStorage: smartCardStorage,
1003
+ stickyHeaders: stickyHeaders,
1004
+ tabIndex: tabIndex,
1005
+ tableNode: tableNode
1006
+ }, orderedChildren);
697
1007
  }
698
1008
  }]);
699
1009
  }(React.Component);
@@ -708,71 +1018,30 @@ var TableWithShadowsAndContainerStyles = overflowShadow(TableProcessorWithContai
708
1018
  overflowSelector: ":scope > .".concat(TableSharedCssClassName.TABLE_NODE_WRAPPER),
709
1019
  useShadowObserver: true
710
1020
  });
711
-
712
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
713
- var TableWithShadows = overflowShadow(TableProcessor, {
714
- /**
715
- * The :scope is in reference to table container and we are selecting only
716
- * direct children that match the table node wrapper selector, not their
717
- * descendants.
718
- */
719
- overflowSelector: ":scope > .".concat(TableSharedCssClassName.TABLE_NODE_WRAPPER),
720
- useShadowObserver: true
721
- });
722
1021
  var TableWithWidth = function TableWithWidth(props) {
723
- var _useRendererContext = useRendererContext(),
724
- isTopLevelRenderer = _useRendererContext.isTopLevelRenderer;
1022
+ var _props$columnWidths;
1023
+ var _useRendererContext2 = useRendererContext(),
1024
+ isTopLevelRenderer = _useRendererContext2.isTopLevelRenderer;
725
1025
  var isInsideOfNestedRenderer = isTopLevelRenderer === false && expValEquals('platform_editor_table_nested_content_mode_fix', 'isEnabled', true);
726
- if (fg('platform-ssr-table-resize')) {
727
- var _props$columnWidths;
728
- var colWidthsSum =
729
- // eslint-disable-next-line @atlassian/perf-linting/no-expensive-computations-in-render -- Ignored via go/ees017 (to be fixed)
730
- ((_props$columnWidths = props.columnWidths) === null || _props$columnWidths === void 0 ? void 0 : _props$columnWidths.reduce(function (total, val) {
731
- return total + val;
732
- }, 0)) || 0;
733
- if (colWidthsSum || props.allowTableResizing) {
734
- return /*#__PURE__*/React.createElement(TableWithShadowsAndContainerStyles
735
- // Ignored via go/ees005
736
- // eslint-disable-next-line react/jsx-props-no-spreading
737
- , _extends({}, props, {
738
- isInsideOfNestedRenderer: isInsideOfNestedRenderer
739
- }));
740
- }
741
- return /*#__PURE__*/React.createElement(TableProcessorWithContainerStyles
1026
+ var colWidthsSum =
1027
+ // eslint-disable-next-line @atlassian/perf-linting/no-expensive-computations-in-render -- Ignored via go/ees017 (to be fixed)
1028
+ ((_props$columnWidths = props.columnWidths) === null || _props$columnWidths === void 0 ? void 0 : _props$columnWidths.reduce(function (total, val) {
1029
+ return total + val;
1030
+ }, 0)) || 0;
1031
+ if (colWidthsSum || props.allowTableResizing) {
1032
+ return /*#__PURE__*/React.createElement(TableWithShadowsAndContainerStyles
742
1033
  // Ignored via go/ees005
743
1034
  // eslint-disable-next-line react/jsx-props-no-spreading
744
1035
  , _extends({}, props, {
745
1036
  isInsideOfNestedRenderer: isInsideOfNestedRenderer
746
1037
  }));
747
- } else {
748
- return /*#__PURE__*/React.createElement(WidthConsumer, null, function (_ref3) {
749
- var _props$columnWidths2;
750
- var width = _ref3.width;
751
- var renderWidth = props.rendererAppearance === 'full-page' ? width - FullPagePadding * 2 : width;
752
- var colWidthsSum =
753
- // eslint-disable-next-line @atlassian/perf-linting/no-expensive-computations-in-render -- Ignored via go/ees017 (to be fixed)
754
- ((_props$columnWidths2 = props.columnWidths) === null || _props$columnWidths2 === void 0 ? void 0 : _props$columnWidths2.reduce(function (total, val) {
755
- return total + val;
756
- }, 0)) || 0;
757
- if (colWidthsSum || props.allowTableResizing) {
758
- return /*#__PURE__*/React.createElement(TableWithShadows, _extends({
759
- renderWidth: renderWidth
760
- // Ignored via go/ees005
761
- // eslint-disable-next-line react/jsx-props-no-spreading
762
- }, props, {
763
- isInsideOfNestedRenderer: isInsideOfNestedRenderer
764
- }));
765
- }
766
- // there should not be a case when colWidthsSum is 0 and table is in overflow state - so no need to render shadows in this case
767
- return /*#__PURE__*/React.createElement(TableProcessor, _extends({
768
- renderWidth: renderWidth
769
- // Ignored via go/ees005
770
- // eslint-disable-next-line react/jsx-props-no-spreading
771
- }, props, {
772
- isInsideOfNestedRenderer: isInsideOfNestedRenderer
773
- }));
774
- });
775
1038
  }
1039
+ return /*#__PURE__*/React.createElement(TableProcessorWithContainerStyles
1040
+ // Ignored via go/ees005
1041
+ // eslint-disable-next-line react/jsx-props-no-spreading
1042
+ , _extends({}, props, {
1043
+ isInsideOfNestedRenderer: isInsideOfNestedRenderer
1044
+ }));
776
1045
  };
777
1046
  var _default_1 = withSmartCardStorage(TableWithWidth);
778
1047
  export default _default_1;