@atlaskit/renderer 130.4.2 → 130.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -278,6 +278,7 @@ export class TableContainer extends React.Component {
278
278
  });
279
279
  }
280
280
  /**
281
+ * Starts observing table dimensions and wires sticky header/scrollbar behavior after mount.
281
282
  *
282
283
  * @example
283
284
  */
@@ -302,6 +303,7 @@ export class TableContainer extends React.Component {
302
303
  }
303
304
 
304
305
  /**
306
+ * Updates sticky header wiring and scroll synchronization after prop or state changes.
305
307
  *
306
308
  * @param prevProps
307
309
  * @param prevState
@@ -330,7 +332,7 @@ export class TableContainer extends React.Component {
330
332
  }
331
333
  }
332
334
  /**
333
- *
335
+ * Calculates the top offset used when the sticky header is pinned to the table bottom.
334
336
  */
335
337
  get pinTop() {
336
338
  if (!this.tableRef.current || !this.stickyHeaderRef.current) {
@@ -340,7 +342,7 @@ export class TableContainer extends React.Component {
340
342
  }
341
343
 
342
344
  /**
343
- *
345
+ * Determines whether sticky header positioning should include the default scroll root offset.
344
346
  */
345
347
  get shouldAddOverflowParentOffsetTop_DO_NOT_USE() {
346
348
  // IF the StickyHeaderConfig specifies that the default scroll root offsetTop should be added
@@ -351,7 +353,7 @@ export class TableContainer extends React.Component {
351
353
  }
352
354
 
353
355
  /**
354
- *
356
+ * Resolves the top position for the sticky header based on the current sticky mode.
355
357
  */
356
358
  get stickyTop() {
357
359
  switch (this.state.stickyMode) {
@@ -371,6 +373,7 @@ export class TableContainer extends React.Component {
371
373
  }
372
374
 
373
375
  /**
376
+ * Renders the table container, sticky header, table content, sticky scrollbar, and synced block borders.
374
377
  *
375
378
  * @example
376
379
  */
@@ -565,14 +568,91 @@ export class TableContainer extends React.Component {
565
568
  })));
566
569
  }
567
570
  }
571
+ const getCellEdgePropsByCellOffset = tableNode => {
572
+ const cellEdgePropsByCellOffset = new Map();
573
+ const cellRightByCellOffset = new Map();
574
+ const occupiedGrid = [];
575
+ let tableWidth = 0;
576
+ let cellOffset = 0;
577
+ tableNode.forEach((rowNode, _rowOffset, rowIndex) => {
578
+ var _occupiedGrid$rowInde;
579
+ occupiedGrid[rowIndex] = (_occupiedGrid$rowInde = occupiedGrid[rowIndex]) !== null && _occupiedGrid$rowInde !== void 0 ? _occupiedGrid$rowInde : [];
580
+ let columnIndex = 0;
581
+ cellOffset += 1;
582
+ rowNode.forEach(cellNode => {
583
+ while (occupiedGrid[rowIndex][columnIndex]) {
584
+ columnIndex += 1;
585
+ }
586
+ const colspan = cellNode.attrs.colspan || 1;
587
+ const rowspan = cellNode.attrs.rowspan || 1;
588
+ const cellLeft = columnIndex;
589
+ const cellRight = cellLeft + colspan;
590
+ const cellTop = rowIndex;
591
+ const cellBottom = cellTop + rowspan;
592
+ for (let row = cellTop; row < cellBottom; row += 1) {
593
+ var _occupiedGrid$row;
594
+ occupiedGrid[row] = (_occupiedGrid$row = occupiedGrid[row]) !== null && _occupiedGrid$row !== void 0 ? _occupiedGrid$row : [];
595
+ for (let column = cellLeft; column < cellRight; column += 1) {
596
+ occupiedGrid[row][column] = true;
597
+ }
598
+ }
599
+ tableWidth = Math.max(tableWidth, cellRight);
600
+ cellRightByCellOffset.set(cellOffset, cellRight);
601
+ cellEdgePropsByCellOffset.set(cellOffset, {
602
+ reachesBottom: cellBottom >= tableNode.childCount,
603
+ reachesLeft: cellLeft === 0,
604
+ reachesRight: false,
605
+ reachesTop: cellTop === 0
606
+ });
607
+ columnIndex = cellRight;
608
+ cellOffset += cellNode.nodeSize;
609
+ });
610
+ cellOffset += 1;
611
+ });
612
+ cellRightByCellOffset.forEach((cellRight, currentCellOffset) => {
613
+ const edgeProps = cellEdgePropsByCellOffset.get(currentCellOffset);
614
+ if (edgeProps) {
615
+ edgeProps.reachesRight = cellRight >= tableWidth;
616
+ }
617
+ });
618
+ return cellEdgePropsByCellOffset;
619
+ };
620
+ const addTableCellEdgeProps = (rows, tableNode) => {
621
+ try {
622
+ if (!tableNode) {
623
+ return rows;
624
+ }
625
+ const cellEdgePropsByCellOffset = getCellEdgePropsByCellOffset(tableNode);
626
+ let cellOffset = 0;
627
+ return React.Children.map(rows, (row, rowIndex) => {
628
+ const rowNode = tableNode.child(rowIndex);
629
+ cellOffset += 1;
630
+ let cellIndex = 0;
631
+ const rowChildren = React.Children.map(row.props.children, child => {
632
+ if (! /*#__PURE__*/React.isValidElement(child)) {
633
+ return child;
634
+ }
635
+ const cellNode = rowNode.child(cellIndex);
636
+ const edgeProps = cellEdgePropsByCellOffset.get(cellOffset);
637
+ cellIndex += 1;
638
+ cellOffset += cellNode.nodeSize;
639
+ return edgeProps ? /*#__PURE__*/React.cloneElement(child, edgeProps) : child;
640
+ });
641
+ cellOffset += 1;
642
+ return /*#__PURE__*/React.cloneElement(row, undefined, rowChildren);
643
+ });
644
+ } catch {
645
+ // Renderer can receive malformed historical ADF. If the table shape cannot
646
+ // be described safely, keep rendering without rounded edge metadata.
647
+ return rows;
648
+ }
649
+ };
650
+
568
651
  /**
569
- *
652
+ * Processes table children before passing them to the styled table container.
570
653
  */
571
654
  // Ignored via go/ees005
572
655
  // eslint-disable-next-line @repo/internal/react/no-class-components
573
- /**
574
- *
575
- */
576
656
  export class TableProcessorWithContainerStyles extends React.Component {
577
657
  constructor(...args) {
578
658
  super(...args);
@@ -618,23 +698,63 @@ export class TableProcessorWithContainerStyles extends React.Component {
618
698
  });
619
699
  }
620
700
  /**
701
+ * Renders processed table children inside the table container.
621
702
  *
622
703
  * @example
623
704
  */
624
705
  render() {
625
706
  const {
626
- children
707
+ allowColumnSorting,
708
+ allowFixedColumnWidthOption,
709
+ allowTableAlignment,
710
+ allowTableResizing,
711
+ children,
712
+ columnWidths,
713
+ disableTableOverflowShadow,
714
+ handleRef,
715
+ isinsideMultiBodiedExtension,
716
+ isInsideOfBlockNode,
717
+ isInsideOfTable,
718
+ isNumberColumnEnabled,
719
+ isPresentational,
720
+ layout,
721
+ rendererAppearance,
722
+ renderWidth,
723
+ shadowClassNames,
724
+ smartCardStorage,
725
+ stickyHeaders,
726
+ tabIndex,
727
+ tableNode
627
728
  } = this.props;
628
729
  if (!children) {
629
730
  return null;
630
731
  }
631
732
  const childrenArray = React.Children.toArray(children);
733
+ const childrenWithTableEdgeProps = expValEquals('platform_editor_table_q4_loveability', 'isEnabled', true) ? addTableCellEdgeProps(childrenArray, tableNode) : childrenArray;
632
734
  const orderedChildren = compose(this.addNumberColumnIndexes, this.addSortableColumn
633
735
  // @ts-expect-error TS2345: Argument of type '(ReactChild | ReactFragment | ReactPortal)[]' is not assignable to parameter of type 'ReactElement<any, string | JSXElementConstructor<any>>[]'
634
- )(childrenArray);
635
-
636
- // Ignored via go/ees005
637
- // eslint-disable-next-line react/jsx-props-no-spreading
638
- return /*#__PURE__*/React.createElement(TableContainer, this.props, orderedChildren);
736
+ )(childrenWithTableEdgeProps);
737
+ return /*#__PURE__*/React.createElement(TableContainer, {
738
+ allowColumnSorting: allowColumnSorting,
739
+ allowFixedColumnWidthOption: allowFixedColumnWidthOption,
740
+ allowTableAlignment: allowTableAlignment,
741
+ allowTableResizing: allowTableResizing,
742
+ columnWidths: columnWidths,
743
+ disableTableOverflowShadow: disableTableOverflowShadow,
744
+ handleRef: handleRef,
745
+ isinsideMultiBodiedExtension: isinsideMultiBodiedExtension,
746
+ isInsideOfBlockNode: isInsideOfBlockNode,
747
+ isInsideOfTable: isInsideOfTable,
748
+ isNumberColumnEnabled: isNumberColumnEnabled,
749
+ isPresentational: isPresentational,
750
+ layout: layout,
751
+ rendererAppearance: rendererAppearance,
752
+ renderWidth: renderWidth,
753
+ shadowClassNames: shadowClassNames,
754
+ smartCardStorage: smartCardStorage,
755
+ stickyHeaders: stickyHeaders,
756
+ tabIndex: tabIndex,
757
+ tableNode: tableNode
758
+ }, orderedChildren);
639
759
  }
640
760
  }
@@ -182,7 +182,10 @@ const headingAnchorStylesDuplicateAnchor = css({
182
182
  '> button': {
183
183
  opacity: 0,
184
184
  transform: 'translate(-8px, 0px)',
185
- transition: 'opacity 0.2s ease 0s, transform 0.2s ease 0s'
185
+ transitionProperty: 'opacity, transform',
186
+ transitionDuration: `${"var(--ds-duration-medium, 0.2s)"}, ${"var(--ds-duration-medium, 0.2s)"}`,
187
+ transitionTimingFunction: `${"var(--ds-easing-out-practical, ease)"}, ${"var(--ds-easing-out-practical, ease)"}`,
188
+ transitionDelay: '0s, 0s'
186
189
  }
187
190
  },
188
191
  '&:hover': {
@@ -1883,6 +1886,47 @@ const tableSharedStyle = css({
1883
1886
  }
1884
1887
  }
1885
1888
  });
1889
+ const roundedTableOuterBorderOverlayStyles = css({
1890
+ [`.${TableSharedCssClassName.TABLE_CONTAINER} > table,
1891
+ .${TableSharedCssClassName.TABLE_NODE_WRAPPER} > table,
1892
+ .${TableSharedCssClassName.TABLE_STICKY_WRAPPER} > table`]: {
1893
+ borderColor: 'transparent',
1894
+ position: 'relative',
1895
+ '&::after': {
1896
+ content: "''",
1897
+ position: 'absolute',
1898
+ inset: 0,
1899
+ border: `${tableCellBorderWidth}px solid ${"var(--ds-background-accent-gray-subtler, #DDDEE1)"}`,
1900
+ borderRadius: "var(--ds-radius-medium, 6px)",
1901
+ pointerEvents: 'none',
1902
+ zIndex: 1
1903
+ },
1904
+ '> tbody > tr:first-of-type > th, > tbody > tr:first-of-type > td, > tbody > tr > th[data-reaches-top], > tbody > tr > td[data-reaches-top]': {
1905
+ borderTopColor: 'transparent'
1906
+ },
1907
+ '> tbody > tr > th:first-child, > tbody > tr > td:first-child, > tbody > tr > th[data-reaches-left], > tbody > tr > td[data-reaches-left]': {
1908
+ borderLeftColor: 'transparent'
1909
+ },
1910
+ '> tbody > tr > th[data-reaches-right], > tbody > tr > td[data-reaches-right]': {
1911
+ borderRightColor: 'transparent'
1912
+ },
1913
+ '> tbody > tr > th[data-reaches-bottom], > tbody > tr > td[data-reaches-bottom]': {
1914
+ borderBottomColor: 'transparent'
1915
+ },
1916
+ '> tbody > tr > th[data-reaches-top][data-reaches-left], > tbody > tr > td[data-reaches-top][data-reaches-left]': {
1917
+ borderTopLeftRadius: "var(--ds-radius-medium, 6px)"
1918
+ },
1919
+ '> tbody > tr > th[data-reaches-top][data-reaches-right], > tbody > tr > td[data-reaches-top][data-reaches-right]': {
1920
+ borderTopRightRadius: "var(--ds-radius-medium, 6px)"
1921
+ },
1922
+ '> tbody > tr > th[data-reaches-bottom][data-reaches-left], > tbody > tr > td[data-reaches-bottom][data-reaches-left]': {
1923
+ borderBottomLeftRadius: "var(--ds-radius-medium, 6px)"
1924
+ },
1925
+ '> tbody > tr > th[data-reaches-bottom][data-reaches-right], > tbody > tr > td[data-reaches-bottom][data-reaches-right]': {
1926
+ borderBottomRightRadius: "var(--ds-radius-medium, 6px)"
1927
+ }
1928
+ }
1929
+ });
1886
1930
  const tableContentModeStyles = css({
1887
1931
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors
1888
1932
  [`.${RendererCssClassName.DOCUMENT} .${TableSharedCssClassName.TABLE_CONTAINER}:has(table[data-initial-width-mode="content"])`]: {
@@ -2690,6 +2734,14 @@ const tableFakeBorderStyles = css({
2690
2734
  borderRightColor: 'transparent'
2691
2735
  }
2692
2736
  });
2737
+ const roundedTableFakeBorderOverlayStyles = css({
2738
+ [`.${TableSharedCssClassName.TABLE_CONTAINER}`]: {
2739
+ [`.${TableSharedCssClassName.TABLE_RIGHT_BORDER},
2740
+ .${TableSharedCssClassName.TABLE_LEFT_BORDER}`]: {
2741
+ display: 'none'
2742
+ }
2743
+ }
2744
+ });
2693
2745
  const syncBlockStyles = css({
2694
2746
  [`.${SyncBlockSharedCssClassName.renderer}, .${BodiedSyncBlockSharedCssClassName.renderer}, .${SyncBlockSharedCssClassName.error}, .${SyncBlockSharedCssClassName.loading}`]: {
2695
2747
  borderRadius: "var(--ds-radius-small, 3px)",
@@ -2767,7 +2819,7 @@ export const RendererStyleContainer = props => {
2767
2819
  // this should be placed after baseOtherStyles
2768
2820
  expValEquals('platform_editor_render_bodied_extension_as_inline', 'isEnabled', true) && (expValEquals('platform_editor_remove_important_in_render_ext', 'isEnabled', true) ? extensionAsInlineStyle : oldExtensionAsInlineStyle), inlineExtensionRendererMarginFix, allowNestedHeaderLinks && (expValEquals('platform_editor_copy_link_a11y_inconsistency_fix', 'isEnabled', true) ? alignedHeadingAnchorStyle : alignedHeadingAnchorStyleDuplicateAnchor), mediaSingleSharedStyle,
2769
2821
  // merge firstWrappedMediaStyles with mediaSingleSharedStyle when clean up platform_editor_fix_media_in_renderer
2770
- fg('platform_editor_fix_media_in_renderer') && firstWrappedMediaStyles, tableSharedStyle, expValEquals('platform_editor_table_fit_to_content_auto_convert', 'isEnabled', true) && tableContentModeStyles, tableRendererHeaderStylesForTableCellOnly, fg('platform_editor_bordered_panel_nested_in_table') && tableRendererNestedPanelStyles, isBackgroundClipBrowserFixNeeded() && tableStylesBackGroundClipForGeckoForTableCellOnly, fg('platform_editor_nested_dnd_styles_changes') ? firstNodeWithNotMarginTopWithNestedDnD : firstNodeWithNotMarginTop, rendererTableStyles, isStickyScrollbarEnabled(appearance) && stickyScrollbarStyles, rendererTableHeaderEqualHeightStylesForTableCellOnly, allowColumnSorting && rendererTableSortableColumnStyles, allowColumnSorting && allowNestedHeaderLinks && (expValEquals('platform_editor_copy_link_a11y_inconsistency_fix', 'isEnabled', true) ? rendererTableHeaderEqualHeightStylesAllowNestedHeaderLinks : rendererTableHeaderEqualHeightStylesAllowNestedHeaderLinksDuplicateAnchor), rendererTableColumnStyles, stickyHeaderStyles, codeBlockAndLayoutStyles, columnLayoutSharedStyle, isAdvancedLayoutsOn && columnLayoutResponsiveSharedStyle, isAdvancedLayoutsOn && columnLayoutResponsiveRendererStyles, isAdvancedLayoutsOn && layoutSectionForAdvancedLayoutsStyles, !useBlockRenderForCodeBlock && gridRenderForCodeBlockStyles, browser.safari && codeBlockInListSafariFixStyles, appearance === 'full-page' && !isPreviewPanelResponsivenessOn && responsiveBreakoutWidth, appearance === 'full-page' && isPreviewPanelResponsivenessOn && responsiveBreakoutWidthWithReducedPadding, (appearance === 'full-width' || appearance === 'max' && (expValEquals('editor_tinymce_full_width_mode', 'isEnabled', true) || expValEquals('confluence_max_width_content_appearance', 'isEnabled', true))) && responsiveBreakoutWidthFullWidth, expValEquals('platform_editor_lovability_emoji_scaling', 'isEnabled', true) ? expValEquals('platform_editor_emojis_in_renderer_smart_links', 'isEnabled', true) ? isCompactModeEnabled ? scaledDenseEmojiStylesNew : scaledEmojiStylesNew : isCompactModeEnabled ? scaledDenseEmojiStyles : scaledEmojiStyles : isCompactModeEnabled ? denseStyles : undefined, editorExperiment('platform_synced_block', true) && syncBlockStyles, centerWrapperStyles, editorExperiment('platform_synced_block', true) && isInsideSyncBlock && fg('platform_synced_block_patch_9') ? syncBlockRendererStyles : null, isInsideSyncBlock && editorExperiment('platform_synced_block', true) && fg('platform_synced_block_patch_9') && tableFakeBorderStyles, expValEquals('platform_editor_hide_extension_renderer_support', 'isEnabled', true) && hideExtensionStyles],
2822
+ fg('platform_editor_fix_media_in_renderer') && firstWrappedMediaStyles, tableSharedStyle, expValEquals('platform_editor_table_q4_loveability', 'isEnabled', true) && roundedTableOuterBorderOverlayStyles, expValEquals('platform_editor_table_fit_to_content_auto_convert', 'isEnabled', true) && tableContentModeStyles, tableRendererHeaderStylesForTableCellOnly, fg('platform_editor_bordered_panel_nested_in_table') && tableRendererNestedPanelStyles, isBackgroundClipBrowserFixNeeded() && tableStylesBackGroundClipForGeckoForTableCellOnly, fg('platform_editor_nested_dnd_styles_changes') ? firstNodeWithNotMarginTopWithNestedDnD : firstNodeWithNotMarginTop, rendererTableStyles, isStickyScrollbarEnabled(appearance) && stickyScrollbarStyles, rendererTableHeaderEqualHeightStylesForTableCellOnly, allowColumnSorting && rendererTableSortableColumnStyles, allowColumnSorting && allowNestedHeaderLinks && (expValEquals('platform_editor_copy_link_a11y_inconsistency_fix', 'isEnabled', true) ? rendererTableHeaderEqualHeightStylesAllowNestedHeaderLinks : rendererTableHeaderEqualHeightStylesAllowNestedHeaderLinksDuplicateAnchor), rendererTableColumnStyles, stickyHeaderStyles, codeBlockAndLayoutStyles, columnLayoutSharedStyle, isAdvancedLayoutsOn && columnLayoutResponsiveSharedStyle, isAdvancedLayoutsOn && columnLayoutResponsiveRendererStyles, isAdvancedLayoutsOn && layoutSectionForAdvancedLayoutsStyles, !useBlockRenderForCodeBlock && gridRenderForCodeBlockStyles, browser.safari && codeBlockInListSafariFixStyles, appearance === 'full-page' && !isPreviewPanelResponsivenessOn && responsiveBreakoutWidth, appearance === 'full-page' && isPreviewPanelResponsivenessOn && responsiveBreakoutWidthWithReducedPadding, (appearance === 'full-width' || appearance === 'max' && (expValEquals('editor_tinymce_full_width_mode', 'isEnabled', true) || expValEquals('confluence_max_width_content_appearance', 'isEnabled', true))) && responsiveBreakoutWidthFullWidth, expValEquals('platform_editor_lovability_emoji_scaling', 'isEnabled', true) ? expValEquals('platform_editor_emojis_in_renderer_smart_links', 'isEnabled', true) ? isCompactModeEnabled ? scaledDenseEmojiStylesNew : scaledEmojiStylesNew : isCompactModeEnabled ? scaledDenseEmojiStyles : scaledEmojiStyles : isCompactModeEnabled ? denseStyles : undefined, editorExperiment('platform_synced_block', true) && syncBlockStyles, centerWrapperStyles, editorExperiment('platform_synced_block', true) && isInsideSyncBlock && fg('platform_synced_block_patch_9') ? syncBlockRendererStyles : null, isInsideSyncBlock && editorExperiment('platform_synced_block', true) && fg('platform_synced_block_patch_9') && tableFakeBorderStyles, isInsideSyncBlock && editorExperiment('platform_synced_block', true) && fg('platform_synced_block_patch_9') ? expValEquals('platform_editor_table_q4_loveability', 'isEnabled', true) ? roundedTableFakeBorderOverlayStyles : null : null, expValEquals('platform_editor_hide_extension_renderer_support', 'isEnabled', true) && hideExtensionStyles],
2771
2823
  "data-testid": testId
2772
2824
  }, children);
2773
2825
  };
@@ -57,7 +57,7 @@ export const DEGRADED_SEVERITY_THRESHOLD = 3000;
57
57
  const TABLE_INFO_TIMEOUT = 10000;
58
58
  const RENDER_EVENT_SAMPLE_RATE = 0.2;
59
59
  const packageName = "@atlaskit/renderer";
60
- const packageVersion = "130.4.1";
60
+ const packageVersion = "0.0.0-development";
61
61
  const setAsQueryContainerStyles = css({
62
62
  containerName: 'ak-renderer-wrapper',
63
63
  containerType: 'inline-size'
@@ -10,6 +10,7 @@ import { ACTION, ACTION_SUBJECT, EVENT_TYPE } from '@atlaskit/editor-common/anal
10
10
  import { RendererCssClassName } from '../../consts';
11
11
  import { useIntl } from 'react-intl';
12
12
  import { tableCellMessages } from '../../messages';
13
+ import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
13
14
  var IgnoreSorting = ['LABEL', 'INPUT'];
14
15
  var nextStatusOrder = function nextStatusOrder(currentSortOrder) {
15
16
  switch (currentSortOrder) {
@@ -37,16 +38,26 @@ var getSortOrderLabel = function getSortOrderLabel(intl, currentSortOrder) {
37
38
  return intl.formatMessage(noneSortingLabel);
38
39
  }
39
40
  };
40
-
41
- // Ignored via go/ees005
42
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
43
- var getDataAttributes = function getDataAttributes(colwidth, background) {
44
- // Ignored via go/ees005
45
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
41
+ var getDataAttributes = function getDataAttributes(colwidth, background, cellEdgeProps) {
46
42
  var attrs = {};
47
43
  if (colwidth) {
48
44
  attrs['data-colwidth'] = colwidth.join(',');
49
45
  }
46
+ if (expValEquals('platform_editor_table_q4_loveability', 'isEnabled', true)) {
47
+ if (cellEdgeProps !== null && cellEdgeProps !== void 0 && cellEdgeProps.reachesTop) {
48
+ attrs['data-reaches-top'] = true;
49
+ }
50
+ if (cellEdgeProps !== null && cellEdgeProps !== void 0 && cellEdgeProps.reachesBottom) {
51
+ attrs['data-reaches-bottom'] = true;
52
+ }
53
+ if (cellEdgeProps !== null && cellEdgeProps !== void 0 && cellEdgeProps.reachesLeft) {
54
+ attrs['data-reaches-left'] = true;
55
+ }
56
+ if (cellEdgeProps !== null && cellEdgeProps !== void 0 && cellEdgeProps.reachesRight) {
57
+ attrs['data-reaches-right'] = true;
58
+ }
59
+ }
60
+
50
61
  /**
51
62
  * Storing hex code in data-cell-background because
52
63
  * we want to have DST token (css variable) or
@@ -140,7 +151,11 @@ var getWithCellProps = function getWithCellProps(WrapperComponent) {
140
151
  colspan = props.colspan,
141
152
  background = props.background,
142
153
  offsetTop = props.offsetTop,
143
- ariaSort = props.ariaSort;
154
+ ariaSort = props.ariaSort,
155
+ reachesTop = props.reachesTop,
156
+ reachesBottom = props.reachesBottom,
157
+ reachesLeft = props.reachesLeft,
158
+ reachesRight = props.reachesRight;
144
159
 
145
160
  // This is used to set the background color of the cell
146
161
  // to a dark mode color in mobile dark mode
@@ -167,7 +182,12 @@ var getWithCellProps = function getWithCellProps(WrapperComponent) {
167
182
  className: className
168
183
  // Ignored via go/ees005
169
184
  // eslint-disable-next-line react/jsx-props-no-spreading
170
- }, getDataAttributes(colwidth, background), {
185
+ }, getDataAttributes(colwidth, background, {
186
+ reachesTop: reachesTop,
187
+ reachesBottom: reachesBottom,
188
+ reachesLeft: reachesLeft,
189
+ reachesRight: reachesRight
190
+ }), {
171
191
  "aria-sort": ariaSort
172
192
  }), children);
173
193
  };
@@ -319,6 +319,7 @@ export var TableContainer = /*#__PURE__*/function (_React$Component) {
319
319
  key: "componentDidMount",
320
320
  value:
321
321
  /**
322
+ * Starts observing table dimensions and wires sticky header/scrollbar behavior after mount.
322
323
  *
323
324
  * @example
324
325
  */
@@ -343,6 +344,7 @@ export var TableContainer = /*#__PURE__*/function (_React$Component) {
343
344
  }
344
345
 
345
346
  /**
347
+ * Updates sticky header wiring and scroll synchronization after prop or state changes.
346
348
  *
347
349
  * @param prevProps
348
350
  * @param prevState
@@ -376,7 +378,7 @@ export var TableContainer = /*#__PURE__*/function (_React$Component) {
376
378
  key: "pinTop",
377
379
  get:
378
380
  /**
379
- *
381
+ * Calculates the top offset used when the sticky header is pinned to the table bottom.
380
382
  */
381
383
  function get() {
382
384
  if (!this.tableRef.current || !this.stickyHeaderRef.current) {
@@ -386,7 +388,7 @@ export var TableContainer = /*#__PURE__*/function (_React$Component) {
386
388
  }
387
389
 
388
390
  /**
389
- *
391
+ * Determines whether sticky header positioning should include the default scroll root offset.
390
392
  */
391
393
  }, {
392
394
  key: "shouldAddOverflowParentOffsetTop_DO_NOT_USE",
@@ -399,7 +401,7 @@ export var TableContainer = /*#__PURE__*/function (_React$Component) {
399
401
  }
400
402
 
401
403
  /**
402
- *
404
+ * Resolves the top position for the sticky header based on the current sticky mode.
403
405
  */
404
406
  }, {
405
407
  key: "stickyTop",
@@ -421,6 +423,7 @@ export var TableContainer = /*#__PURE__*/function (_React$Component) {
421
423
  }
422
424
 
423
425
  /**
426
+ * Renders the table container, sticky header, table content, sticky scrollbar, and synced block borders.
424
427
  *
425
428
  * @example
426
429
  */
@@ -611,14 +614,91 @@ export var TableContainer = /*#__PURE__*/function (_React$Component) {
611
614
  }
612
615
  }]);
613
616
  }(React.Component);
617
+ var getCellEdgePropsByCellOffset = function getCellEdgePropsByCellOffset(tableNode) {
618
+ var cellEdgePropsByCellOffset = new Map();
619
+ var cellRightByCellOffset = new Map();
620
+ var occupiedGrid = [];
621
+ var tableWidth = 0;
622
+ var cellOffset = 0;
623
+ tableNode.forEach(function (rowNode, _rowOffset, rowIndex) {
624
+ var _occupiedGrid$rowInde;
625
+ occupiedGrid[rowIndex] = (_occupiedGrid$rowInde = occupiedGrid[rowIndex]) !== null && _occupiedGrid$rowInde !== void 0 ? _occupiedGrid$rowInde : [];
626
+ var columnIndex = 0;
627
+ cellOffset += 1;
628
+ rowNode.forEach(function (cellNode) {
629
+ while (occupiedGrid[rowIndex][columnIndex]) {
630
+ columnIndex += 1;
631
+ }
632
+ var colspan = cellNode.attrs.colspan || 1;
633
+ var rowspan = cellNode.attrs.rowspan || 1;
634
+ var cellLeft = columnIndex;
635
+ var cellRight = cellLeft + colspan;
636
+ var cellTop = rowIndex;
637
+ var cellBottom = cellTop + rowspan;
638
+ for (var row = cellTop; row < cellBottom; row += 1) {
639
+ var _occupiedGrid$row;
640
+ occupiedGrid[row] = (_occupiedGrid$row = occupiedGrid[row]) !== null && _occupiedGrid$row !== void 0 ? _occupiedGrid$row : [];
641
+ for (var column = cellLeft; column < cellRight; column += 1) {
642
+ occupiedGrid[row][column] = true;
643
+ }
644
+ }
645
+ tableWidth = Math.max(tableWidth, cellRight);
646
+ cellRightByCellOffset.set(cellOffset, cellRight);
647
+ cellEdgePropsByCellOffset.set(cellOffset, {
648
+ reachesBottom: cellBottom >= tableNode.childCount,
649
+ reachesLeft: cellLeft === 0,
650
+ reachesRight: false,
651
+ reachesTop: cellTop === 0
652
+ });
653
+ columnIndex = cellRight;
654
+ cellOffset += cellNode.nodeSize;
655
+ });
656
+ cellOffset += 1;
657
+ });
658
+ cellRightByCellOffset.forEach(function (cellRight, currentCellOffset) {
659
+ var edgeProps = cellEdgePropsByCellOffset.get(currentCellOffset);
660
+ if (edgeProps) {
661
+ edgeProps.reachesRight = cellRight >= tableWidth;
662
+ }
663
+ });
664
+ return cellEdgePropsByCellOffset;
665
+ };
666
+ var addTableCellEdgeProps = function addTableCellEdgeProps(rows, tableNode) {
667
+ try {
668
+ if (!tableNode) {
669
+ return rows;
670
+ }
671
+ var cellEdgePropsByCellOffset = getCellEdgePropsByCellOffset(tableNode);
672
+ var cellOffset = 0;
673
+ return React.Children.map(rows, function (row, rowIndex) {
674
+ var rowNode = tableNode.child(rowIndex);
675
+ cellOffset += 1;
676
+ var cellIndex = 0;
677
+ var rowChildren = React.Children.map(row.props.children, function (child) {
678
+ if (! /*#__PURE__*/React.isValidElement(child)) {
679
+ return child;
680
+ }
681
+ var cellNode = rowNode.child(cellIndex);
682
+ var edgeProps = cellEdgePropsByCellOffset.get(cellOffset);
683
+ cellIndex += 1;
684
+ cellOffset += cellNode.nodeSize;
685
+ return edgeProps ? /*#__PURE__*/React.cloneElement(child, edgeProps) : child;
686
+ });
687
+ cellOffset += 1;
688
+ return /*#__PURE__*/React.cloneElement(row, undefined, rowChildren);
689
+ });
690
+ } catch (_unused) {
691
+ // Renderer can receive malformed historical ADF. If the table shape cannot
692
+ // be described safely, keep rendering without rounded edge metadata.
693
+ return rows;
694
+ }
695
+ };
696
+
614
697
  /**
615
- *
698
+ * Processes table children before passing them to the styled table container.
616
699
  */
617
700
  // Ignored via go/ees005
618
701
  // eslint-disable-next-line @repo/internal/react/no-class-components
619
- /**
620
- *
621
- */
622
702
  export var TableProcessorWithContainerStyles = /*#__PURE__*/function (_React$Component2) {
623
703
  function TableProcessorWithContainerStyles() {
624
704
  var _this2;
@@ -669,22 +749,63 @@ export var TableProcessorWithContainerStyles = /*#__PURE__*/function (_React$Com
669
749
  key: "render",
670
750
  value:
671
751
  /**
752
+ * Renders processed table children inside the table container.
672
753
  *
673
754
  * @example
674
755
  */
675
756
  function render() {
676
- var children = this.props.children;
757
+ var _this$props2 = this.props,
758
+ allowColumnSorting = _this$props2.allowColumnSorting,
759
+ allowFixedColumnWidthOption = _this$props2.allowFixedColumnWidthOption,
760
+ allowTableAlignment = _this$props2.allowTableAlignment,
761
+ allowTableResizing = _this$props2.allowTableResizing,
762
+ children = _this$props2.children,
763
+ columnWidths = _this$props2.columnWidths,
764
+ disableTableOverflowShadow = _this$props2.disableTableOverflowShadow,
765
+ handleRef = _this$props2.handleRef,
766
+ isinsideMultiBodiedExtension = _this$props2.isinsideMultiBodiedExtension,
767
+ isInsideOfBlockNode = _this$props2.isInsideOfBlockNode,
768
+ isInsideOfTable = _this$props2.isInsideOfTable,
769
+ isNumberColumnEnabled = _this$props2.isNumberColumnEnabled,
770
+ isPresentational = _this$props2.isPresentational,
771
+ layout = _this$props2.layout,
772
+ rendererAppearance = _this$props2.rendererAppearance,
773
+ renderWidth = _this$props2.renderWidth,
774
+ shadowClassNames = _this$props2.shadowClassNames,
775
+ smartCardStorage = _this$props2.smartCardStorage,
776
+ stickyHeaders = _this$props2.stickyHeaders,
777
+ tabIndex = _this$props2.tabIndex,
778
+ tableNode = _this$props2.tableNode;
677
779
  if (!children) {
678
780
  return null;
679
781
  }
680
782
  var childrenArray = React.Children.toArray(children);
783
+ var childrenWithTableEdgeProps = expValEquals('platform_editor_table_q4_loveability', 'isEnabled', true) ? addTableCellEdgeProps(childrenArray, tableNode) : childrenArray;
681
784
  var orderedChildren = compose(this.addNumberColumnIndexes, this.addSortableColumn
682
785
  // @ts-expect-error TS2345: Argument of type '(ReactChild | ReactFragment | ReactPortal)[]' is not assignable to parameter of type 'ReactElement<any, string | JSXElementConstructor<any>>[]'
683
- )(childrenArray);
684
-
685
- // Ignored via go/ees005
686
- // eslint-disable-next-line react/jsx-props-no-spreading
687
- return /*#__PURE__*/React.createElement(TableContainer, this.props, orderedChildren);
786
+ )(childrenWithTableEdgeProps);
787
+ return /*#__PURE__*/React.createElement(TableContainer, {
788
+ allowColumnSorting: allowColumnSorting,
789
+ allowFixedColumnWidthOption: allowFixedColumnWidthOption,
790
+ allowTableAlignment: allowTableAlignment,
791
+ allowTableResizing: allowTableResizing,
792
+ columnWidths: columnWidths,
793
+ disableTableOverflowShadow: disableTableOverflowShadow,
794
+ handleRef: handleRef,
795
+ isinsideMultiBodiedExtension: isinsideMultiBodiedExtension,
796
+ isInsideOfBlockNode: isInsideOfBlockNode,
797
+ isInsideOfTable: isInsideOfTable,
798
+ isNumberColumnEnabled: isNumberColumnEnabled,
799
+ isPresentational: isPresentational,
800
+ layout: layout,
801
+ rendererAppearance: rendererAppearance,
802
+ renderWidth: renderWidth,
803
+ shadowClassNames: shadowClassNames,
804
+ smartCardStorage: smartCardStorage,
805
+ stickyHeaders: stickyHeaders,
806
+ tabIndex: tabIndex,
807
+ tableNode: tableNode
808
+ }, orderedChildren);
688
809
  }
689
810
  }]);
690
811
  }(React.Component);