UNPKG

@atlaskit/editor-plugin-show-diff

Version:

ShowDiff plugin for @atlaskit/editor-core

143 lines (132 loc) • 6.14 kB
import { agentBrandColorSchemes } from '@atlaskit/agent-color/agent-brand-color-schemes'; import { convertToInlineCss } from '@atlaskit/editor-common/lazy-node-view'; import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled'; import { buildDeletedInlineStyleStandard, getDeletedInlineRevealColors, getInsertedInlineRevealColors } from './colorSchemes/factory'; import { colorSchemeRegistry } from './colorSchemes/schemes'; import { getStandardDeletedContentStyle, getStandardDeletedContentStyleActive } from './colorSchemes/standard'; /** * Painting strategy for reveal highlights. Highlights are `linear-gradient`s with animated * `background-size` for the wipe effect. Colours live on elements as custom properties so the * attribution palette works per-contributor. */ /** Marks an element as taking part in the reveal, and says which side it represents. */ export const REVEAL_ATTR = 'data-show-diff-reveal'; /** Wipe colour, read by the animation as the gradient's colour stop. */ export const REVEAL_BG_VAR = '--show-diff-reveal-bg'; /** Underline colour, brought in on the same schedule as the highlight. */ export const REVEAL_BORDER_VAR = '--show-diff-reveal-border'; /** Only schemes with background highlights can be revealed; 'traditional' uses underline only. */ const schemeSupportsReveal = colorScheme => colorScheme !== 'traditional'; /** Convert a flat background colour into a wipeable gradient (zero width initially). */ export const buildWipeableBackground = color => convertToInlineCss({ backgroundColor: 'transparent', backgroundImage: `linear-gradient(${color}, ${color})`, backgroundRepeat: 'no-repeat', backgroundSize: '0% 100%', backgroundPosition: '0 0', // Each line fragment of a wrapped highlight gets its own background box, so they wipe // together rather than the gradient stretching across the whole wrapped run. WebkitBoxDecorationBreak: 'clone', boxDecorationBreak: 'clone' }); /** Base padding and transparent underline placeholder (no layout shift on reveal). */ const revealBaseStyle = convertToInlineCss({ padding: `1px 0 2px`, borderBottom: `2px solid transparent` }); const buildRevealVariables = ({ background, border }) => convertToInlineCss({ [REVEAL_BG_VAR]: background, [REVEAL_BORDER_VAR]: border }); /** Configuration that affects both resting state and reveal endpoint. */ /** Reveal colours from the refactored scheme registry (attribution palette ready). */ const revealColorsRefactored = (colors, { hideAddedDiffsUnderline, isActive, isInserted }) => isInserted ? getInsertedInlineRevealColors(colors, isActive, hideAddedDiffsUnderline) : getDeletedInlineRevealColors(colors); /** * Legacy cohort reveal colours. Values MUST match `revealColorsRefactored()` output for * `standard` scheme (test: `revealStyles.ts` in test package). */ const revealColorsLegacy = ({ hideAddedDiffsUnderline, isActive, isInserted }) => isInserted ? { // Mirrors `editingStyleExtended` / `editingStyleActiveExtended` and their // `*NoUnderline` variants in `colorSchemes/standard.ts`. background: isActive ? "var(--ds-background-accent-purple-subtler-pressed, #D8A0F7)" : "var(--ds-background-accent-purple-subtlest, #F8EEFE)", border: hideAddedDiffsUnderline ? 'transparent' : "var(--ds-border-accent-purple, #AF59E1)" } : { // Mirrors `deletedInlineContentStyleExtended` in `colorSchemes/standard.ts`. background: "var(--ds-background-accent-gray-subtlest, #F0F1F2)", border: "var(--ds-border-accent-gray, #7D818A)" }; const resolveRevealColors = (colors, variant) => isExperimentEnabled('platform_editor_show_diff_color_scheme_refactor') ? revealColorsRefactored(colors, variant) : revealColorsLegacy(variant); const getColorScheme = colorScheme => colorSchemeRegistry[colorScheme !== null && colorScheme !== void 0 ? colorScheme : 'standard']; /** Deleted text appearance (grey and strikethrough) without the highlight. */ const deletedTextOnlyStyle = (colors, isActive) => isExperimentEnabled('platform_editor_show_diff_color_scheme_refactor') ? buildDeletedInlineStyleStandard(colors, isActive ? 'active' : 'default') : isActive ? getStandardDeletedContentStyleActive() : getStandardDeletedContentStyle(); /** * Resolve reveal attribute and style for a decoration. Returned style REPLACES the decoration's * highlight (not an addition) so the animation has something to wipe. Gate resolved in showDiff * command for single shared answer between decorations and animation. */ export const resolveRevealStyle = ({ colorScheme, hideAddedDiffsUnderline = false, includeDeletedTextStyle = true, isActive, isInserted, reveal }) => { if ((reveal === null || reveal === void 0 ? void 0 : reveal.mode) !== 'phased' || !schemeSupportsReveal(colorScheme)) { return undefined; } const colors = getColorScheme(colorScheme); const brand = isInserted && Object.prototype.hasOwnProperty.call(agentBrandColorSchemes, colors.insertColor) ? agentBrandColorSchemes[colors.insertColor] : undefined; const { background, border } = resolveRevealColors(colors, { hideAddedDiffsUnderline, isActive, isInserted }); return { role: isInserted ? 'added' : 'deleted', style: (brand ? convertToInlineCss({ color: brand.text }) : '') + (isInserted || !includeDeletedTextStyle ? '' : deletedTextOnlyStyle(colors, isActive)) + revealBaseStyle + buildWipeableBackground(background) + buildRevealVariables({ background, border }) }; }; /** Reveal style for imperatively-built elements (deleted-content widget wrappers). */ export const applyRevealToElement = ({ colorScheme, element, hideAddedDiffsUnderline, isActive, isInserted, reveal }) => { const resolved = resolveRevealStyle({ colorScheme, hideAddedDiffsUnderline, isActive, isInserted, reveal, // The widget supplies the deleted text's own grey/strikethrough styling already. includeDeletedTextStyle: false }); if (!resolved) { return ''; } element.setAttribute(REVEAL_ATTR, resolved.role); return resolved.style; };