UNPKG

@atlaskit/editor-common

Version:

A package that contains common classes and components for editor and renderer

303 lines (272 loc) • 12.7 kB
/* eslint-disable @atlaskit/ui-styling-standard/use-compiled -- Pre-existing lint debt surfaced by this mechanical type-import-only PR. */ // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766 import { css } from '@emotion/react'; import { tableCellContentDomSelector, tableCellSelector, tableHeaderSelector, tablePrefixSelector } from '@atlaskit/adf-schema'; import { akEditorBreakoutPadding, akEditorFullWidthLayoutWidth, akEditorSelectedNodeClassName, akEditorTableNumberColumnWidth, akEditorWideLayoutWidth, overflowShadow } from '@atlaskit/editor-shared-styles'; import { fg } from '@atlaskit/platform-feature-flags'; import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals'; import { getBrowserInfo } from '../../utils/browser'; import { CodeBlockSharedCssClassName } from './code-block'; import { tableCellBackgroundStyleOverride } from './tableCell'; export const tableMarginTop = 24; export const tableMarginBottom = 16; export const tableMarginTopWithControl = 14; export const tableMarginSides = 8; export const tableCellMinWidth = 48; export const tableNewColumnMinWidth = 140; export const tableCellBorderWidth = 1; export const tableCellPadding = 8; export const tableResizeHandleWidth = 6; export const tablePadding = 8; export const tableControlsSpacing = tableMarginTop + tablePadding - tableCellBorderWidth; export const TableSharedCssClassName = { TABLE_CONTAINER: `${tablePrefixSelector}-container`, TABLE_NODE_WRAPPER: `${tablePrefixSelector}-wrapper`, TABLE_NODE_WRAPPER_NO_OVERFLOW: `${tablePrefixSelector}-wrapper-no-overflow`, TABLE_SCROLL_INLINE_SHADOW: `${tablePrefixSelector}-scroll-inline-shadow`, TABLE_RIGHT_BORDER: `${tablePrefixSelector}-right-border`, TABLE_LEFT_BORDER: `${tablePrefixSelector}-left-border`, TABLE_LEFT_SHADOW: `${tablePrefixSelector}-with-left-shadow`, TABLE_RIGHT_SHADOW: `${tablePrefixSelector}-with-right-shadow`, TABLE_STICKY_SHADOW: `${tablePrefixSelector}-sticky-shadow`, TABLE_STICKY_WRAPPER: `${tablePrefixSelector}-sticky-wrapper`, TABLE_STICKY_SCROLLBAR_CONTAINER: `${tablePrefixSelector}-sticky-scrollbar-container`, TABLE_STICKY_SENTINEL_TOP: `${tablePrefixSelector}-sticky-sentinel-top`, TABLE_STICKY_SENTINEL_BOTTOM: `${tablePrefixSelector}-sticky-sentinel-bottom`, TABLE_STICKY_SCROLLBAR_SENTINEL_TOP: `${tablePrefixSelector}-sticky-scrollbar-sentinel-top`, TABLE_STICKY_SCROLLBAR_SENTINEL_BOTTOM: `${tablePrefixSelector}-sticky-scrollbar-sentinel-bottom`, TABLE_SHADOW_SENTINEL_LEFT: `${tablePrefixSelector}-shadow-sentinel-left`, TABLE_SHADOW_SENTINEL_RIGHT: `${tablePrefixSelector}-shadow-sentinel-right`, // eslint-disable-next-line @atlaskit/editor/no-re-export TABLE_CELL_NODEVIEW_CONTENT_DOM: tableCellContentDomSelector, // eslint-disable-next-line @atlaskit/editor/no-re-export TABLE_CELL_WRAPPER: tableCellSelector, // eslint-disable-next-line @atlaskit/editor/no-re-export TABLE_HEADER_CELL_WRAPPER: tableHeaderSelector, TABLE_ROW_CONTROLS_WRAPPER: `${tablePrefixSelector}-row-controls-wrapper`, TABLE_COLUMN_CONTROLS_DECORATIONS: `${tablePrefixSelector}-column-controls-decoration`, TABLE_RESIZER_CONTAINER: `${tablePrefixSelector}-resizer-container`, TABLE_VIEW_CONTENT_WRAP: 'tableView-content-wrap' }; /* first block node has 0 top margin */ const firstNodeWithNotMarginTop = () => fg('platform_editor_nested_dnd_styles_changes') ? // eslint-disable-next-line @atlaskit/design-system/no-css-tagged-template-expression css` > :nth-child(1 of :not(style, .ProseMirror-gapcursor, .ProseMirror-widget, span)) { margin-top: 0; } ` : // eslint-disable-next-line @atlaskit/design-system/no-css-tagged-template-expression css` > :first-child:not(style), > style:first-child + * { margin-top: 0; } > .ProseMirror-gapcursor:first-child + *, > style:first-child + .ProseMirror-gapcursor + * { margin-top: 0; } > .ProseMirror-gapcursor:first-child + span + *, > style:first-child + .ProseMirror-gapcursor + span + * { margin-top: 0; } `; const tableSharedStyle = () => { const browser = getBrowserInfo(); // eslint-disable-next-line @atlaskit/design-system/no-css-tagged-template-expression -- Appears safe to auto-fix, but leaving it up to the team to remediate as the readability only gets worse with autofixing return css` ${tableCellBackgroundStyleOverride()} .${TableSharedCssClassName.TABLE_CONTAINER} { position: relative; margin: 0 auto ${"var(--ds-space-200, 16px)"}; box-sizing: border-box; /** * Fix block top alignment inside table cells. */ .decisionItemView-content-wrap:first-of-type > div { margin-top: 0; } ${expValEquals('platform_editor_table_q4_loveability', 'isEnabled', true) ? `/* Fake side borders are not needed when the rounded overlay owns the outer border. */ .${TableSharedCssClassName.TABLE_RIGHT_BORDER}, .${TableSharedCssClassName.TABLE_LEFT_BORDER} { display: none; } ` : `.${TableSharedCssClassName.TABLE_RIGHT_BORDER}, .${TableSharedCssClassName.TABLE_LEFT_BORDER} { display: block; width: 1px; height: calc(100% - ${"var(--ds-space-300, 24px)"}); background: ${"var(--ds-background-accent-gray-subtler, #DDDEE1)"}; position: absolute; top: ${"var(--ds-space-300, 24px)"}; } .${TableSharedCssClassName.TABLE_RIGHT_BORDER} { right: 0; } .${TableSharedCssClassName.TABLE_LEFT_BORDER} { left: 0; } .${TableSharedCssClassName.TABLE_LEFT_BORDER}[data-with-numbered-table='true'] { left: ${akEditorTableNumberColumnWidth - 1}px; }`} } .${TableSharedCssClassName.TABLE_CONTAINER}[data-number-column='true'] { padding-left: ${akEditorTableNumberColumnWidth - 1}px; clear: both; } .${TableSharedCssClassName.TABLE_RESIZER_CONTAINER} { will-change: width, margin-left; } .${TableSharedCssClassName.TABLE_RESIZER_CONTAINER} table { will-change: width; } .${TableSharedCssClassName.TABLE_NODE_WRAPPER} > table { margin: ${"var(--ds-space-300, 24px)"} 0 0 0; } .${TableSharedCssClassName.TABLE_CONTAINER} > table, .${TableSharedCssClassName.TABLE_STICKY_WRAPPER} > table { margin: ${"var(--ds-space-300, 24px)"} ${"var(--ds-space-100, 8px)"} 0 0; } /* support panel nested in table */ ${fg('platform_editor_bordered_panel_nested_in_table') ? `.${TableSharedCssClassName.TABLE_NODE_WRAPPER} .ak-editor-panel { border: ${"var(--ds-border-width, 1px)"} solid ${"var(--ds-border, #0B120E24)"}; }` : ''} /* avoid applying styles to nested tables (possible via extensions) */ .${TableSharedCssClassName.TABLE_CONTAINER} > table, .${TableSharedCssClassName.TABLE_NODE_WRAPPER} > table, .${TableSharedCssClassName.TABLE_STICKY_WRAPPER} > table { border-collapse: collapse; ${expValEquals('platform_editor_table_q4_loveability', 'isEnabled', true) ? `/* Keep a transparent border so the collapsed border model reserves the same 1px slot on the table edge; the ::after overlay draws the visible rounded border instead. */ border: ${tableCellBorderWidth}px solid transparent;` : `border: ${tableCellBorderWidth}px solid ${"var(--ds-background-accent-gray-subtler, #DDDEE1)"}; border-left-color: transparent; border-right-color: transparent;`} table-layout: fixed; font-size: 1em; width: 100%; ${expValEquals('platform_editor_table_q4_loveability', 'isEnabled', true) ? `position: relative; /* Table-width outer-border owner for overflow-safe rounded corners. */ &::after { content: ''; position: absolute; inset: 0; border: ${tableCellBorderWidth}px solid ${"var(--ds-background-accent-gray-subtler, #DDDEE1)"}; border-radius: ${"var(--ds-radius-medium, 6px)"}; pointer-events: none; z-index: 1; }` : ''} &[data-autosize='true'] { table-layout: auto; } & { * { box-sizing: border-box; } hr { box-sizing: content-box; } tbody { border-bottom: none; } th td { background-color: ${"var(--ds-background-neutral-subtle, #00000000)"}; } > tbody > tr > th, > tbody > tr > td { min-width: ${tableCellMinWidth}px; font-weight: ${"var(--ds-font-weight-regular, 400)"}; vertical-align: top; border: 1px solid ${"var(--ds-background-accent-gray-subtler, #DDDEE1)"}; border-right-width: 0; border-bottom-width: 0; padding: ${"var(--ds-space-100, 8px)"}; /* https://stackoverflow.com/questions/7517127/borders-not-shown-in-firefox-with-border-collapse-on-table-position-relative-o */ ${browser.gecko || browser.ie || browser.mac && browser.chrome ? 'background-clip: padding-box;' : ''} ${firstNodeWithNotMarginTop()} th p:not(:first-of-type), td p:not(:first-of-type) { margin-top: ${"var(--ds-space-150, 12px)"}; } } /* Ensures nested tables are compatible with parent table background color - uses specificity to ensure tables nested by extensions are not affected */ > tbody > tr > td { background-color: ${"var(--ds-surface, #FFFFFF)"}; } ${expValEquals('platform_editor_table_q4_loveability', 'isEnabled', true) ? `/* Let the wrapper overlay own the outer table perimeter. data-reaches-* attributes are set by the TableCell node view. */ > tbody > tr > th[data-reaches-top], > tbody > tr > td[data-reaches-top] { border-top-color: transparent; } > tbody > tr > th[data-reaches-left], > tbody > tr > td[data-reaches-left] { border-left-color: transparent; } > tbody > tr > td[data-reaches-left]::after { border-left-color: transparent; } > tbody > tr > td[data-reaches-bottom]::after, > tbody > tr > th[data-reaches-bottom]::after { border-bottom-color: transparent; }` : ''} th { background-color: ${"var(--ds-background-accent-gray-subtlest, #F0F1F2)"}; text-align: left; /* only apply this styling to codeblocks in default background headercells */ /* TODO this needs to be overhauled as it relies on unsafe selectors */ ${expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) ? '&:not(.danger)' : '&:not([style]):not(.danger)'} { .${CodeBlockSharedCssClassName.CODEBLOCK_CONTAINER}:not(.danger) { background-color: ${"var(--ds-surface-raised, #FFFFFF)"}; :not(.${akEditorSelectedNodeClassName}) { box-shadow: 0px 0px 0px 1px ${"var(--ds-border, #0B120E24)"}; } .${CodeBlockSharedCssClassName.CODEBLOCK_CONTENT_WRAPPER} { background-image: ${overflowShadow({ leftCoverWidth: "var(--ds-space-300, 24px)" })}; background-color: ${"var(--ds-background-neutral, #0515240F)"}; } .${CodeBlockSharedCssClassName.CODEBLOCK_LINE_NUMBER_GUTTER} { background-color: ${"var(--ds-background-neutral, #0515240F)"}; } /* this is only relevant to the element taken care of by renderer */ > [data-ds--code--code-block] { background-image: ${overflowShadow({ leftCoverWidth: "var(--ds-space-300, 24px)" })}!important; background-color: ${"var(--ds-background-neutral, #0515240F)"}!important; /* selector lives inside @atlaskit/code */ --ds--code--line-number-bg-color: ${"var(--ds-background-neutral, #0515240F)"}; } } } } } } ${expValEquals('platform_editor_table_q4_loveability', 'isEnabled', true) ? `/* When the number column is enabled, the left visual edge belongs to the number column. Remove the left border-radius and left border from the table's ::after overlay so it doesn't double-up or round where the number column already provides that edge. */ .${TableSharedCssClassName.TABLE_CONTAINER}[data-number-column='true'] { > .${TableSharedCssClassName.TABLE_NODE_WRAPPER} > table::after, > .${TableSharedCssClassName.TABLE_STICKY_WRAPPER} > table::after { border-top-left-radius: 0; border-bottom-left-radius: 0; border-left-color: transparent; } }` : ''} `; }; export const calcTableWidth = (layout, containerWidth, addControllerPadding = true) => { switch (layout) { case 'full-width': return containerWidth ? Math.min(containerWidth - (addControllerPadding ? akEditorBreakoutPadding : 0), akEditorFullWidthLayoutWidth) : akEditorFullWidthLayoutWidth; case 'wide': if (containerWidth) { return Math.min(containerWidth - (addControllerPadding ? akEditorBreakoutPadding : 0), akEditorWideLayoutWidth); } return akEditorWideLayoutWidth; default: return 'inherit'; } }; export { tableSharedStyle };