UNPKG

@atlaskit/editor-plugin-media

Version:

Media plugin for @atlaskit/editor-core

222 lines (221 loc) 9.35 kB
import { mediaSingleSpec } from '@atlaskit/adf-schema'; import { convertToInlineCss } from '@atlaskit/editor-common/lazy-node-view'; import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals'; import { getAttrsFromNodeMediaSingle } from './toDOMAttrs'; const WRAPPED_LAYOUTS = ['wrap-left', 'wrap-right']; const ALIGNED_LAYOUTS = ['align-end', 'align-start']; const LEGACY_LAYOUTS = ['full-width', 'wide']; const DEFAULT_IMAGE_WIDTH = 250; const DEFAULT_IMAGE_HEIGHT = 200; const GUTTER_SIZE = '24px'; const HALF_GUTTER_SIZE = '12px'; export const mediaWidthCSSCalc = ({ mediaSingleDimensionWidth, layout, baseWidth, isPixelWidth, isExtendedResizeExperience }) => { const hasMediaDimensionWidth = typeof mediaSingleDimensionWidth === 'number'; const isMediaWrapped = WRAPPED_LAYOUTS.includes(layout); const isMediaAligned = ALIGNED_LAYOUTS.includes(layout); const isMediaLegacyLayout = LEGACY_LAYOUTS.includes(layout); const shouldUseAlignedLayoutCalc = isMediaAligned && !hasMediaDimensionWidth; const shouldUseWrappedLayoutCalc = isMediaWrapped && !hasMediaDimensionWidth; const shouldUseBreakoutWideLogic = layout === 'wide'; const shouldUseBreakoutFullWidthLogic = layout === 'full-width'; const shouldUseProportionalCalc = !isExtendedResizeExperience && !isPixelWidth && hasMediaDimensionWidth && !isMediaLegacyLayout && !isMediaWrapped; const shouldUseHalfContainerCalc = shouldUseProportionalCalc && isMediaAligned && mediaSingleDimensionWidth >= 100; const shouldHardCodePixelWidth = isExtendedResizeExperience && isPixelWidth && hasMediaDimensionWidth; const containerWidthPlusGutter = `(min(100cqw, 100%) + ${GUTTER_SIZE})`; const fullContainerWidth = 'var(--ak-editor-max-container-width, 100cqw)'; const applyContainerWidthBoundaries = calc => { // Safe measure to avoid bleeding return `min(${calc}, ${fullContainerWidth})`; }; let cssCalc = ''; if (shouldUseAlignedLayoutCalc) { cssCalc = `min(calc(${containerWidthPlusGutter} * 0.5 - ${GUTTER_SIZE}), ${baseWidth}px)`; } else if (shouldUseWrappedLayoutCalc) { cssCalc = `100%`; } else if (shouldUseHalfContainerCalc) { cssCalc = `min(min(${baseWidth}px, calc(50cqw - ${HALF_GUTTER_SIZE})), 100%)`; } else if (shouldUseProportionalCalc) { cssCalc = `calc(${containerWidthPlusGutter} * var(--ak-editor-media-single--proportion, 1px) - ${GUTTER_SIZE})`; } else if (shouldHardCodePixelWidth) { cssCalc = `min(${mediaSingleDimensionWidth}px, ${fullContainerWidth})`; } else if (shouldUseBreakoutWideLogic) { if (expValEquals('platform_editor_media_vc_fixes', 'isEnabled', true)) { cssCalc = `max(var(--ak-editor--line-length), min(var(--ak-editor--breakout-wide-layout-width), var(--ak-editor-max-container-width)))`; } else { cssCalc = `max(var(--ak-editor--line-length), min(var(--ak-editor--breakout-wide-layout-width), calc(100cqw - var(--ak-editor--breakout-full-page-guttering-padding))))`; } } else if (shouldUseBreakoutFullWidthLogic) { if (expValEquals('platform_editor_media_vc_fixes', 'isEnabled', true)) { cssCalc = `max(var(--ak-editor--line-length), min(var(--ak-editor--full-width-layout-width), var(--ak-editor-max-container-width)))`; } else { cssCalc = `max(var(--ak-editor--line-length), min(var(--ak-editor--full-width-layout-width), calc(100cqw - var(--ak-editor--breakout-full-page-guttering-padding))))`; } } else { cssCalc = `max(min(${baseWidth}px, min(100cqw, 100%)), ${GUTTER_SIZE})`; } return applyContainerWidthBoundaries(cssCalc); }; export const mediaContentWrapperWidthCSSCalc = ({ isMediaWrapped, isExternalMedia, isPixelWidth, childMediaWidth, mediaSingleDimensionWidth }) => { if (isExternalMedia || !isMediaWrapped) { return 'unset'; } const hasMediaDimensionWidth = typeof mediaSingleDimensionWidth === 'number'; if (!hasMediaDimensionWidth) { return `calc((100% / 2) - ${HALF_GUTTER_SIZE})`; } if (isPixelWidth) { return `min(calc((var(--ak-editor-max-container-width, 100%) / 2) - ${HALF_GUTTER_SIZE}), ${mediaSingleDimensionWidth}px)`; } const hasChildMediaWidth = typeof childMediaWidth === 'number'; if (hasChildMediaWidth) { return `min(calc(100% * (${mediaSingleDimensionWidth} / 100) - ${HALF_GUTTER_SIZE}), ${childMediaWidth}px)`; } return `calc(100% * (${mediaSingleDimensionWidth} / 100) - ${HALF_GUTTER_SIZE})`; }; export const mediaProportionalWidthCSSCalc = ({ isPixelWidth, isExtendedResizeExperience, mediaSingleDimensionWidth, isMediaWrapped }) => { const hasMediaWidth = typeof mediaSingleDimensionWidth === 'number'; if (isPixelWidth || isExtendedResizeExperience || !hasMediaWidth) { return 'unset'; } if (isMediaWrapped) { return mediaSingleDimensionWidth >= 50 ? '1' : `${1 - mediaSingleDimensionWidth / 100}`; } return `${mediaSingleDimensionWidth / 100}`; }; export const mediaJustifyContentCSS = ({ layout }) => { switch (layout) { case 'align-end': case 'wrap-right': return 'end'; case 'align-start': case 'wrap-left': return 'start'; default: return 'center'; } }; export const prepareWrapperContentDOM = ({ layout, dataAttrs, childMediaWidth, childMediaHeight, mediaSingleDimensionWidth, isPixelWidth, isExtendedResizeExperience }) => { const layoutStyleJustifyContent = mediaJustifyContentCSS({ layout }); const mediaWidthCalc = mediaWidthCSSCalc({ layout, mediaSingleDimensionWidth, baseWidth: childMediaWidth, isPixelWidth, isExtendedResizeExperience }); const paddingBottom = `calc((${childMediaHeight} / ${childMediaWidth}) * 100%)`; return ['div', { class: `rich-media-item mediaSingleView-content-wrap image-${layout}`, style: convertToInlineCss({ display: 'flex', justifyContent: layoutStyleJustifyContent, transform: 'unset', marginLeft: '0' }), ...dataAttrs }, ['div', { style: convertToInlineCss({ borderRadius: "var(--ds-radius-small, 3px)", width: mediaWidthCalc, minWidth: mediaWidthCalc, color: "var(--ds-icon, #292A2E)" }) }, ['figure', { class: 'media-single-node', style: convertToInlineCss({ '--ak-editor-media-padding-bottom': paddingBottom, margin: '0px' }) }, ['div', {}, ['div', { class: 'media-content-wrap' }, 0]]]]]; }; export const getToDom = allowPixelResizing => node => { var _mediaSingleAttrs$lay; const mediaSingleAttrs = node.attrs; const isPixelWidth = (mediaSingleAttrs === null || mediaSingleAttrs === void 0 ? void 0 : mediaSingleAttrs.widthType) === 'pixel'; const layout = (_mediaSingleAttrs$lay = mediaSingleAttrs === null || mediaSingleAttrs === void 0 ? void 0 : mediaSingleAttrs.layout) !== null && _mediaSingleAttrs$lay !== void 0 ? _mediaSingleAttrs$lay : 'center'; const childNode = node.firstChild; const isExternalMedia = (childNode === null || childNode === void 0 ? void 0 : childNode.attrs.type) === 'external'; const childMediaWidth = (childNode === null || childNode === void 0 ? void 0 : childNode.attrs.width) || DEFAULT_IMAGE_WIDTH; const childMediaHeight = (childNode === null || childNode === void 0 ? void 0 : childNode.attrs.height) || DEFAULT_IMAGE_HEIGHT; const dataAttrs = getAttrsFromNodeMediaSingle(true, node); const content = prepareWrapperContentDOM({ layout, dataAttrs, childMediaWidth, childMediaHeight, mediaSingleDimensionWidth: mediaSingleAttrs.width, isPixelWidth, isExtendedResizeExperience: allowPixelResizing }); const isMediaWrapped = WRAPPED_LAYOUTS.includes(layout); const proportionCalc = mediaProportionalWidthCSSCalc({ isPixelWidth, isMediaWrapped, mediaSingleDimensionWidth: mediaSingleAttrs === null || mediaSingleAttrs === void 0 ? void 0 : mediaSingleAttrs.width, isExtendedResizeExperience: allowPixelResizing }); const contentWrapperWidth = mediaContentWrapperWidthCSSCalc({ isMediaWrapped, isExternalMedia, isPixelWidth, childMediaWidth, mediaSingleDimensionWidth: mediaSingleAttrs === null || mediaSingleAttrs === void 0 ? void 0 : mediaSingleAttrs.width }); return ['div', { class: 'mediaSingleView-content-wrap', layout, 'data-media-vc-wrapper': 'true', style: convertToInlineCss({ '--ak-editor-media-single--proportion': proportionCalc, '--ak-editor-media-card-display': 'block', '--ak-editor-media-single--gutter-size': GUTTER_SIZE, '--ak-editor-media-margin-right': '0', '--ak-editor-media-card-background-color': "var(--ds-background-neutral, #0515240F)", marginTop: isMediaWrapped ? HALF_GUTTER_SIZE : "var(--ds-space-300, 24px)", marginBottom: isMediaWrapped ? HALF_GUTTER_SIZE : "var(--ds-space-300, 24px)", marginRight: isMediaWrapped ? layout === 'wrap-right' ? 'auto' : HALF_GUTTER_SIZE : 0, marginLeft: isMediaWrapped ? layout === 'wrap-left' ? 'auto' : HALF_GUTTER_SIZE : 0, width: contentWrapperWidth }) }, content]; }; // @nodeSpecException:toDOM patch export const mediaSingleSpecWithFixedToDOM = mediaSingleOption => { const mediaSingleNode = mediaSingleSpec(mediaSingleOption); const toDOM = getToDom(mediaSingleOption.withExtendedWidthTypes); return { ...mediaSingleNode, toDOM }; };