UNPKG

@atlaskit/renderer

Version:
705 lines (690 loc) • 33.4 kB
import _extends from "@babel/runtime/helpers/extends"; import _defineProperty from "@babel/runtime/helpers/defineProperty"; import React from 'react'; import { useIntl } from 'react-intl'; import { TableSharedCssClassName, tableMarginTop } from '@atlaskit/editor-common/styles'; import { tableMessages } from '@atlaskit/editor-common/messages'; import { WidthConsumer, overflowShadow } from '@atlaskit/editor-common/ui'; import { fg } from '@atlaskit/platform-feature-flags'; import { createCompareNodes, convertProsemirrorTableNodeToArrayOfRows, hasMergedCell, compose } from '@atlaskit/editor-common/utils'; import { SortOrder } from '@atlaskit/editor-common/types'; import { akEditorDefaultLayoutWidth, akEditorFullWidthLayoutWidth, akEditorMaxWidthLayoutWidth } from '@atlaskit/editor-shared-styles'; import { getTableContainerWidth } from '@atlaskit/editor-common/node-width'; import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments'; import { FullPagePadding } from '../../ui/Renderer/style'; import { TableHeader } from './tableCell'; import { withSmartCardStorage } from '../../ui/SmartCardStorage'; import { StickyTable, tableStickyPadding, OverflowParent } from './table/sticky'; import { Table } from './table/table'; import { isCommentAppearance, isFullPageAppearance, isFullWidthAppearance, isFullWidthOrFullPageAppearance, isMaxWidthAppearance } from '../utils/appearance'; import { TableStickyScrollbar } from './TableStickyScrollbar'; import { TableProcessorWithContainerStyles, RefSyncBlockFakeBorders } from './tableNew'; import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals'; import { isTableInContentMode } from '@atlaskit/editor-common/table'; import { isContentModeSupported } from './table/content-mode'; export const isTableResizingEnabled = appearance => isFullWidthOrFullPageAppearance(appearance) || isCommentAppearance(appearance); export const isStickyScrollbarEnabled = appearance => isFullWidthOrFullPageAppearance(appearance) && editorExperiment('platform_renderer_table_sticky_scrollbar', true, { exposure: true }); export const orderChildren = (children, tableNode, smartCardStorage, tableOrderStatus) => { if (!tableOrderStatus || tableOrderStatus.order === SortOrder.NO_ORDER) { return children; } const { order, columnIndex } = tableOrderStatus; const compareNodesInOrder = createCompareNodes({ getInlineCardTextFromStore(attrs) { const { url } = attrs; if (!url) { return null; } return smartCardStorage.get(url) || null; } }, order); const tableArray = convertProsemirrorTableNodeToArrayOfRows(tableNode); const tableArrayWithChildren = tableArray.map((rowNodes, index) => ({ rowNodes, rowReact: children[index] })); const headerRow = tableArrayWithChildren.shift(); const sortedTable = tableArrayWithChildren.sort((rowA, rowB) => compareNodesInOrder(rowA.rowNodes[columnIndex], rowB.rowNodes[columnIndex])); if (headerRow) { sortedTable.unshift(headerRow); } return sortedTable.map(elem => elem.rowReact); }; export const hasRowspan = row => { let hasRowspan = false; row.forEach(cell => hasRowspan = hasRowspan || cell.attrs.rowspan > 1); return hasRowspan; }; export const getRefTop = refElement => { return Math.round(refElement.getBoundingClientRect().top); }; export const shouldHeaderStick = (scrollTop, tableTop, tableBottom, rowHeight) => tableTop <= scrollTop && !(tableBottom - rowHeight <= scrollTop); export const shouldHeaderPinBottom = (scrollTop, tableBottom, rowHeight) => tableBottom - rowHeight <= scrollTop && !(tableBottom < scrollTop); export const addSortableColumn = (rows, tableOrderStatus, onSorting // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-explicit-any ) => { return React.Children.map(rows, (row, index) => { if (index === 0) { return /*#__PURE__*/React.cloneElement(React.Children.only(row), { tableOrderStatus, onSorting }); } return row; }); }; export const isHeaderRowEnabled = (rows // eslint-disable-next-line @typescript-eslint/no-explicit-any ) => { if (!rows.length) { return false; } // Ignored via go/ees005 // eslint-disable-next-line @typescript-eslint/no-explicit-any const { children } = rows[0].props; if (!children.length) { return false; } if (children.length === 1) { return children[0].type === TableHeader; } return children.every(node => node.type === TableHeader); }; /** * This TableWrapper component was created to make sure that the aria-label can be * internationalized without needing to add `intl` to the TableContainer. * * <TableWrapper wrapperRef={ref} onScroll={handleScroll} stickyHeaders={config}> * <Table>...</Table> * </TableWrapper> */ const TableWrapper = ({ children, wrapperRef, onScroll, stickyHeaders, tabIndex }) => { const { formatMessage } = useIntl(); const isScrollableRegion = tabIndex !== undefined; return /*#__PURE__*/React.createElement("div", { // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766 className: TableSharedCssClassName.TABLE_NODE_WRAPPER, ref: wrapperRef, onScroll: stickyHeaders ? onScroll : undefined // Adding tabIndex here because this is a scrollable container and it needs to be focusable so keyboard users can scroll it. // eslint-disable-next-line @atlassian/a11y/no-noninteractive-tabindex , tabIndex: tabIndex, role: isScrollableRegion ? 'region' : undefined, "aria-label": isScrollableRegion ? formatMessage(tableMessages.tableScrollRegion) : undefined }, children); }; export const tableCanBeSticky = (node, children // eslint-disable-next-line @typescript-eslint/no-explicit-any ) => { return isHeaderRowEnabled(children) && node && node.firstChild && !hasRowspan(node.firstChild); }; /** * */ // Ignored via go/ees005 // eslint-disable-next-line @repo/internal/react/no-class-components export class TableContainer extends React.Component { constructor(...args) { super(...args); _defineProperty(this, "state", { stickyMode: 'none', wrapperWidth: 0, headerRowHeight: 0 }); _defineProperty(this, "tableRef", /*#__PURE__*/React.createRef()); _defineProperty(this, "stickyHeaderRef", /*#__PURE__*/React.createRef()); _defineProperty(this, "stickyScrollbarRef", /*#__PURE__*/React.createRef()); // used for sync scroll + copying wrapper width to sticky header _defineProperty(this, "stickyWrapperRef", /*#__PURE__*/React.createRef()); _defineProperty(this, "wrapperRef", /*#__PURE__*/React.createRef()); _defineProperty(this, "overflowParent", null); _defineProperty(this, "resizeObserver", null); _defineProperty(this, "applyResizerChange", entries => { let wrapperWidth = this.state.wrapperWidth; let headerRowHeight = this.state.headerRowHeight; for (const entry of entries) { if (entry.target === this.wrapperRef.current) { wrapperWidth = entry.contentRect.width; } else if (entry.target === this.stickyHeaderRef.current) { headerRowHeight = Math.round(entry.contentRect.height); } } if (headerRowHeight !== this.state.headerRowHeight || wrapperWidth !== this.state.wrapperWidth) { this.setState({ wrapperWidth, headerRowHeight }); } }); _defineProperty(this, "componentWillUnmount", () => { if (this.overflowParent) { // Ignored via go/ees005 // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners this.overflowParent.removeEventListener('scroll', this.onScroll); } if (this.nextFrame) { cancelAnimationFrame(this.nextFrame); } if (this.resizeObserver) { this.resizeObserver.disconnect(); } if (this.stickyScrollbar) { this.stickyScrollbar.dispose(); } }); _defineProperty(this, "getScrollTop", () => { const { stickyHeaders } = this.props; const offsetTop = stickyHeaders && stickyHeaders.offsetTop || 0; return (this.overflowParent ? this.overflowParent.top : 0) + offsetTop; }); _defineProperty(this, "updateSticky", () => { const tableElem = this.tableRef.current; const refElem = this.stickyHeaderRef.current; if (!tableElem || !refElem) { return; } const scrollTop = this.getScrollTop() + tableStickyPadding; const tableTop = getRefTop(tableElem); const tableBottom = tableTop + tableElem.clientHeight; const shouldSticky = shouldHeaderStick(scrollTop, tableTop, tableBottom, refElem.clientHeight); const shouldPin = shouldHeaderPinBottom(scrollTop, tableBottom, refElem.clientHeight); let stickyMode = 'none'; if (shouldPin) { stickyMode = 'pin-bottom'; } else if (shouldSticky) { stickyMode = 'stick'; } if (this.state.stickyMode !== stickyMode) { this.setState({ stickyMode }); } this.nextFrame = undefined; }); _defineProperty(this, "onScroll", () => { if (!this.nextFrame) { this.nextFrame = requestAnimationFrame(this.updateSticky); } }); _defineProperty(this, "onWrapperScrolled", () => { if (!this.wrapperRef.current || !this.stickyWrapperRef.current) { return; } this.stickyWrapperRef.current.scrollLeft = this.wrapperRef.current.scrollLeft; if (this.stickyScrollbarRef.current) { this.stickyScrollbarRef.current.scrollLeft = this.wrapperRef.current.scrollLeft; } }); _defineProperty(this, "grabFirstRowRef", children => { // Ignored via go/ees005 // eslint-disable-next-line @typescript-eslint/no-explicit-any return React.Children.map(children || false, (child, idx) => { if (idx === 0 && /*#__PURE__*/React.isValidElement(child)) { return /*#__PURE__*/React.cloneElement(child, { innerRef: this.stickyHeaderRef }); } return child; }); }); } /** * * @example */ componentDidMount() { this.resizeObserver = new ResizeObserver(this.applyResizerChange); if (this.wrapperRef.current) { this.resizeObserver.observe(this.wrapperRef.current); } if (this.stickyHeaderRef.current) { this.resizeObserver.observe(this.stickyHeaderRef.current); } if (this.props.stickyHeaders) { var _this$props$stickyHea; this.overflowParent = OverflowParent.fromElement(this.tableRef.current, (_this$props$stickyHea = this.props.stickyHeaders) === null || _this$props$stickyHea === void 0 ? void 0 : _this$props$stickyHea.defaultScrollRootId_DO_NOT_USE); // Ignored via go/ees005 // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners this.overflowParent.addEventListener('scroll', this.onScroll); } if (this.wrapperRef.current && isStickyScrollbarEnabled(this.props.rendererAppearance)) { this.stickyScrollbar = new TableStickyScrollbar(this.wrapperRef.current); } } /** * * @param prevProps * @param prevState * @example */ componentDidUpdate(prevProps, prevState) { // toggling sticky headers visiblity if (this.props.stickyHeaders && !this.overflowParent) { var _this$props$stickyHea2; this.overflowParent = OverflowParent.fromElement(this.tableRef.current, (_this$props$stickyHea2 = this.props.stickyHeaders) === null || _this$props$stickyHea2 === void 0 ? void 0 : _this$props$stickyHea2.defaultScrollRootId_DO_NOT_USE); } else if (!this.props.stickyHeaders && this.overflowParent) { // Ignored via go/ees005 // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners this.overflowParent.removeEventListener('scroll', this.onScroll); this.overflowParent = null; } // offsetTop might have changed, re-position sticky header if (this.props.stickyHeaders !== prevProps.stickyHeaders) { this.updateSticky(); } // sync horizontal scroll in floating div when toggling modes if (prevState.stickyMode !== this.state.stickyMode) { this.onWrapperScrolled(); } } /** * */ get pinTop() { if (!this.tableRef.current || !this.stickyHeaderRef.current) { return; } return this.tableRef.current.offsetHeight - this.stickyHeaderRef.current.offsetHeight + tableMarginTop - tableStickyPadding; } /** * */ get shouldAddOverflowParentOffsetTop_DO_NOT_USE() { // IF the StickyHeaderConfig specifies that the default scroll root offsetTop should be added // AND the StickyHeaderConfig specifies a default scroll root id // AND the OverflowParent is the corresponding element // THEN we should add the OverflowParent offset top (RETURN TRUE) return this.props.stickyHeaders && !!this.props.stickyHeaders.shouldAddDefaultScrollRootOffsetTop_DO_NOT_USE && !!this.props.stickyHeaders.defaultScrollRootId_DO_NOT_USE && this.overflowParent && this.overflowParent.id === this.props.stickyHeaders.defaultScrollRootId_DO_NOT_USE; } /** * */ get stickyTop() { switch (this.state.stickyMode) { case 'pin-bottom': return this.pinTop; case 'stick': const offsetTop = this.props.stickyHeaders && this.props.stickyHeaders.offsetTop; if (typeof offsetTop === 'number' && this.shouldAddOverflowParentOffsetTop_DO_NOT_USE) { const overflowParentOffsetTop = this.overflowParent ? this.overflowParent.top : 0; return offsetTop + overflowParentOffsetTop; } else { return offsetTop; } default: return undefined; } } /** * * @example */ render() { var _this$tableRef$curren; const { isNumberColumnEnabled, layout, renderWidth, columnWidths, stickyHeaders, tableNode, rendererAppearance, isInsideOfBlockNode, isInsideOfTable, isinsideMultiBodiedExtension, allowTableAlignment, allowTableResizing, isPresentational, allowFixedColumnWidthOption } = this.props; const { stickyMode } = this.state; const lineLengthFixedWidth = akEditorDefaultLayoutWidth; let left; let updatedLayout; // The tableWidth and left offset logic below must stay aligned with the `breakout-ssr.tsx` logic // Please consider changes below carefully to not negatively impact SSR // `renderWidth` cannot be depended on during SSR const isRenderWidthValid = !!renderWidth && renderWidth > 0; const fullPageRendererWidthCSS = editorExperiment('platform_editor_preview_panel_responsiveness', true, { exposure: true }) ? 'calc(100cqw - var(--ak-renderer--full-page-gutter) * 2)' : `100cqw - ${FullPagePadding}px * 2`; const renderWidthCSS = rendererAppearance === 'full-page' ? fullPageRendererWidthCSS : `100cqw`; const calcDefaultLayoutWidthByAppearance = (rendererAppearance, tableNode) => { if (rendererAppearance === 'full-width' && !(tableNode !== null && tableNode !== void 0 && tableNode.attrs.width)) { return [isRenderWidthValid ? Math.min(akEditorFullWidthLayoutWidth, renderWidth) : akEditorFullWidthLayoutWidth, `min(${akEditorFullWidthLayoutWidth}px, ${renderWidthCSS})`]; } else if (rendererAppearance === 'max' && !(tableNode !== null && tableNode !== void 0 && tableNode.attrs.width)) { return [isRenderWidthValid ? Math.min(akEditorMaxWidthLayoutWidth, renderWidth) : akEditorMaxWidthLayoutWidth, `min(${akEditorMaxWidthLayoutWidth}px, ${renderWidthCSS})`]; } else if (rendererAppearance === 'comment' && allowTableResizing && !(tableNode !== null && tableNode !== void 0 && tableNode.attrs.width)) { const tableContainerWidth = getTableContainerWidth(tableNode); return [isRenderWidthValid ? renderWidth : tableContainerWidth, renderWidthCSS]; } else { // custom width, or width mapped to breakpoint const tableContainerWidth = getTableContainerWidth(tableNode); return [isRenderWidthValid ? Math.min(tableContainerWidth, renderWidth) : tableContainerWidth, `min(${tableContainerWidth}px, ${renderWidthCSS})`]; } }; const [tableWidth, tableWidthCSS] = calcDefaultLayoutWidthByAppearance(rendererAppearance, tableNode); // Logic for table alignment in renderer const isTableAlignStart = tableNode && tableNode.attrs && tableNode.attrs.layout === 'align-start' && allowTableAlignment; const fullWidthLineLength = isRenderWidthValid ? Math.min(akEditorFullWidthLayoutWidth, renderWidth) : akEditorFullWidthLayoutWidth; const fullWidthLineLengthCSS = `min(${akEditorFullWidthLayoutWidth}px, ${renderWidthCSS})`; const maxWidthLineLength = isRenderWidthValid ? Math.min(akEditorMaxWidthLayoutWidth, renderWidth) : akEditorMaxWidthLayoutWidth; const maxWidthLineLengthCSS = `min(${akEditorMaxWidthLayoutWidth}px, ${renderWidthCSS})`; const commentLineLength = isRenderWidthValid ? renderWidth : lineLengthFixedWidth; const isCommentAppearanceAndTableAlignmentEnabled = isCommentAppearance(rendererAppearance) && allowTableAlignment; const 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; const 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 : `${lineLengthFixedWidth}px`; // Setting fixTableSSRResizing to false while FG logic is true in tableNew const fixTableSSRResizing = false; const tableWidthNew = fixTableSSRResizing ? getTableContainerWidth(tableNode) : tableWidth; const 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); let leftCSS; if (shouldCalculateLeftForAlignment) { left = (tableWidth - lineLength) / 2; leftCSS = `(${tableWidthCSS} - ${lineLengthCSS}) / 2`; } if (fixTableSSRResizing) { if (!shouldCalculateLeftForAlignment && isFullPageAppearance(rendererAppearance)) { // Note tableWidthCSS here is the renderer width // When the screen is super wide we want table to break out. // However if screen is smaller than 760px. We want table align to left. leftCSS = `min(0px, ${lineLengthCSS} - ${tableWidthCSS}) / 2`; } } else { if (!shouldCalculateLeftForAlignment && isFullPageAppearance(rendererAppearance) && tableWidthNew > lineLengthFixedWidth) { left = lineLengthFixedWidth / 2 - tableWidth / 2; } } const children = React.Children.toArray(this.props.children); // Historically, tables in the full-width renderer had their layout set to 'default' which is deceiving. // This check caters for those tables and helps with SSR logic const isFullWidth = !(tableNode !== null && tableNode !== void 0 && tableNode.attrs.width) && rendererAppearance === 'full-width' && layout !== 'full-width'; if (isFullWidth) { updatedLayout = 'full-width'; // if table has width explicity set, ensure SSR is handled } else if (tableNode !== null && tableNode !== void 0 && tableNode.attrs.width) { updatedLayout = 'custom'; } else { updatedLayout = layout; } let finalTableContainerWidth = allowTableResizing ? tableWidthNew : 'inherit'; // We can only use CSS to determine the width when we have a known width in container. // When appearance is full-page, full-width or comment we use CSS based width calculation. // Otherwise it's fixed table width (customized width) or inherit. if ((rendererAppearance === 'full-page' || rendererAppearance === 'full-width' || rendererAppearance === 'max') && fixTableSSRResizing) { finalTableContainerWidth = allowTableResizing ? `calc(${tableWidthCSS})` : 'inherit'; } if (rendererAppearance === 'comment' && allowTableResizing && !allowTableAlignment) { // If table alignment is disabled and table width is akEditorDefaultLayoutWidth = 760, // it is most likely a table created before "Support Table in Comments" FF was enabled // and we would see a bug ED-24795. A table created before "Support Table in Comments", // should inhirit the width of the renderer container. // !NOTE: it a table resized to 760 is copied from 'full-page' editor and pasted in comment editor // where (allowTableResizing && !allowTableAlignment), the table will loose 760px width. finalTableContainerWidth = tableNode !== null && tableNode !== void 0 && tableNode.attrs.width && (tableNode === null || tableNode === void 0 ? void 0 : tableNode.attrs.width) !== akEditorDefaultLayoutWidth ? fixTableSSRResizing ? `calc(${tableWidthCSS})` : tableWidth : 'inherit'; } if (rendererAppearance === 'comment' && allowTableResizing && allowTableAlignment) { // If table alignment is enabled and layout is not 'align-start' or 'center', we are loading a table that was // created before "Support Table in Comments" FF was enabled. So the table should have the same width as renderer container // instead of 760 that was set on tableNode when the table had been published. 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(${tableWidthCSS})` : tableWidth : 'inherit'; } const isContentModeTable = isTableInContentMode({ tableNode, isSupported: isContentModeSupported({ allowTableResizing, rendererAppearance }), isTableNested: isInsideOfBlockNode || isInsideOfTable }) && expValEquals('platform_editor_table_fit_to_content_auto_convert', 'isEnabled', true); let style; if (fixTableSSRResizing) { style = { ...(isContentModeTable && { '--renderer-table-max-width': renderWidthCSS }), width: finalTableContainerWidth, left: leftCSS ? `calc(${leftCSS})` : undefined, marginLeft: shouldCalculateLeftForAlignment && leftCSS !== undefined ? `calc(-1 * (${leftCSS}))` : undefined }; } else { style = { ...(isContentModeTable && { '--renderer-table-max-width': `${renderWidth}px` }), width: finalTableContainerWidth, left: left, marginLeft: shouldCalculateLeftForAlignment && left !== undefined ? -left : undefined }; } return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", { // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766 className: `${TableSharedCssClassName.TABLE_CONTAINER} ${this.props.shadowClassNames || ''}`, "data-layout": updatedLayout, ref: this.props.handleRef // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766 , style: style }, isStickyScrollbarEnabled(this.props.rendererAppearance) && /*#__PURE__*/React.createElement("div", { // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766 className: TableSharedCssClassName.TABLE_STICKY_SCROLLBAR_SENTINEL_TOP, "data-testid": "sticky-scrollbar-sentinel-top" }), stickyHeaders && tableCanBeSticky(tableNode, children) && /*#__PURE__*/React.createElement(StickyTable, { isNumberColumnEnabled: isNumberColumnEnabled, tableWidth: tableWidth, layout: layout, renderWidth: renderWidth, handleRef: this.props.handleRef, shadowClassNames: this.props.shadowClassNames, top: this.stickyTop, mode: stickyMode, innerRef: this.stickyWrapperRef, wrapperWidth: this.state.wrapperWidth, columnWidths: columnWidths, rowHeight: this.state.headerRowHeight, tableNode: tableNode, rendererAppearance: rendererAppearance, allowTableResizing: allowTableResizing, allowFixedColumnWidthOption: allowFixedColumnWidthOption }, [children && children[0]]), /*#__PURE__*/React.createElement(TableWrapper, { wrapperRef: this.wrapperRef, onScroll: this.props.stickyHeaders ? this.onWrapperScrolled : undefined, stickyHeaders: stickyHeaders, tabIndex: this.props.tabIndex }, /*#__PURE__*/React.createElement(Table, { innerRef: this.tableRef, columnWidths: columnWidths, layout: layout, isNumberColumnEnabled: isNumberColumnEnabled, renderWidth: renderWidth, tableNode: tableNode, rendererAppearance: rendererAppearance, isInsideOfBlockNode: isInsideOfBlockNode, isInsideOfTable: isInsideOfTable, isinsideMultiBodiedExtension: isinsideMultiBodiedExtension, allowTableResizing: allowTableResizing, isPresentational: isPresentational, allowFixedColumnWidthOption: allowFixedColumnWidthOption }, this.grabFirstRowRef(children))), isStickyScrollbarEnabled(this.props.rendererAppearance) && /*#__PURE__*/React.createElement("div", { // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766 className: TableSharedCssClassName.TABLE_STICKY_SCROLLBAR_CONTAINER, ref: this.stickyScrollbarRef, style: { // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766 height: "var(--ds-space-250, 20px)", // MAX_BROWSER_SCROLLBAR_HEIGHT // Follow editor to hide by default so it does not show empty gap in SSR // https://bitbucket.org/atlassian/atlassian-frontend-monorepo/src/master/platform/packages/editor/editor-plugin-table/src/nodeviews/TableComponent.tsx#957 // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766 display: fixTableSSRResizing ? 'none' : 'block', // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop width: '100%' } }, /*#__PURE__*/React.createElement("div", { style: { width: (_this$tableRef$curren = this.tableRef.current) === null || _this$tableRef$curren === void 0 ? void 0 : _this$tableRef$curren.clientWidth, // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766 height: '100%' } })), isStickyScrollbarEnabled(this.props.rendererAppearance) && /*#__PURE__*/React.createElement("div", { // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766 className: TableSharedCssClassName.TABLE_STICKY_SCROLLBAR_SENTINEL_BOTTOM, "data-testid": "sticky-scrollbar-sentinel-bottom" }), /*#__PURE__*/React.createElement(RefSyncBlockFakeBorders, { isNumberColumnEnabled: isNumberColumnEnabled }))); } } /** * */ // Ignored via go/ees005 // eslint-disable-next-line @repo/internal/react/no-class-components export class TableProcessor extends React.Component { constructor(...args) { super(...args); _defineProperty(this, "state", { tableOrderStatus: undefined }); // adds sortable + re-orders children _defineProperty(this, "addSortableColumn", childrenArray => { const { tableNode, allowColumnSorting, smartCardStorage } = this.props; const { tableOrderStatus } = this.state; if (allowColumnSorting && isHeaderRowEnabled(childrenArray) && tableNode && !hasMergedCell(tableNode)) { return addSortableColumn(orderChildren(childrenArray, tableNode, smartCardStorage, tableOrderStatus), tableOrderStatus, this.changeSortOrder); } return childrenArray; }); _defineProperty(this, "changeSortOrder", (columnIndex, sortOrder) => { this.setState({ tableOrderStatus: { columnIndex, order: sortOrder } }); }); // Ignored via go/ees005 // eslint-disable-next-line @typescript-eslint/no-explicit-any _defineProperty(this, "addNumberColumnIndexes", rows => { const { isNumberColumnEnabled } = this.props; const headerRowEnabled = isHeaderRowEnabled(rows); return React.Children.map(rows, (row, index) => { return /*#__PURE__*/React.cloneElement(React.Children.only(row), { isNumberColumnEnabled, index: headerRowEnabled ? index === 0 ? '' : index : index + 1 }); }); }); } /** * * @example */ render() { const { children } = this.props; if (!children) { return null; } const childrenArray = React.Children.toArray(children); const orderedChildren = compose(this.addNumberColumnIndexes, this.addSortableColumn // @ts-expect-error TS2345: Argument of type '(ReactChild | ReactFragment | ReactPortal)[]' is not assignable to parameter of type 'ReactElement<any, string | JSXElementConstructor<any>>[]' )(childrenArray); // Ignored via go/ees005 // eslint-disable-next-line react/jsx-props-no-spreading return /*#__PURE__*/React.createElement(TableContainer, this.props, orderedChildren); } } // eslint-disable-next-line @typescript-eslint/no-explicit-any const TableWithShadowsAndContainerStyles = overflowShadow(TableProcessorWithContainerStyles, { /** * The :scope is in reference to table container and we are selecting only * direct children that match the table node wrapper selector, not their * descendants. */ overflowSelector: `:scope > .${TableSharedCssClassName.TABLE_NODE_WRAPPER}`, useShadowObserver: true }); // eslint-disable-next-line @typescript-eslint/no-explicit-any const TableWithShadows = overflowShadow(TableProcessor, { /** * The :scope is in reference to table container and we are selecting only * direct children that match the table node wrapper selector, not their * descendants. */ overflowSelector: `:scope > .${TableSharedCssClassName.TABLE_NODE_WRAPPER}`, useShadowObserver: true }); const TableWithWidth = props => { if (fg('platform-ssr-table-resize')) { var _props$columnWidths; const colWidthsSum = // eslint-disable-next-line @atlassian/perf-linting/no-expensive-computations-in-render -- Ignored via go/ees017 (to be fixed) ((_props$columnWidths = props.columnWidths) === null || _props$columnWidths === void 0 ? void 0 : _props$columnWidths.reduce((total, val) => total + val, 0)) || 0; if (colWidthsSum || props.allowTableResizing) { // Ignored via go/ees005 // eslint-disable-next-line react/jsx-props-no-spreading return /*#__PURE__*/React.createElement(TableWithShadowsAndContainerStyles, props); } return /*#__PURE__*/React.createElement(TableProcessorWithContainerStyles // Ignored via go/ees005 // eslint-disable-next-line react/jsx-props-no-spreading , props); } else { return /*#__PURE__*/React.createElement(WidthConsumer, null, ({ width }) => { var _props$columnWidths2; const renderWidth = props.rendererAppearance === 'full-page' ? width - FullPagePadding * 2 : width; const colWidthsSum = // eslint-disable-next-line @atlassian/perf-linting/no-expensive-computations-in-render -- Ignored via go/ees017 (to be fixed) ((_props$columnWidths2 = props.columnWidths) === null || _props$columnWidths2 === void 0 ? void 0 : _props$columnWidths2.reduce((total, val) => total + val, 0)) || 0; if (colWidthsSum || props.allowTableResizing) { // Ignored via go/ees005 // eslint-disable-next-line react/jsx-props-no-spreading return /*#__PURE__*/React.createElement(TableWithShadows, _extends({ renderWidth: renderWidth }, props)); } // 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 return /*#__PURE__*/React.createElement(TableProcessor, _extends({ renderWidth: renderWidth // Ignored via go/ees005 // eslint-disable-next-line react/jsx-props-no-spreading }, props)); }); } }; const _default_1 = withSmartCardStorage(TableWithWidth); export default _default_1;