@atlaskit/renderer
Version:
Renderer component
284 lines (277 loc) • 11.5 kB
JavaScript
import _extends from "@babel/runtime/helpers/extends";
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
/**
* @jsxRuntime classic
* @jsx jsx
*/
import { default as React, Fragment, useCallback, useContext, useMemo, useEffect } from 'react';
// eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
import { css, jsx } from '@emotion/react';
import { injectIntl } from 'react-intl';
import { MediaSingle as UIMediaSingle, WidthContext } from '@atlaskit/editor-common/ui';
import { fg } from '@atlaskit/platform-feature-flags';
import { akEditorFullWidthLayoutWidth, akEditorDefaultLayoutWidth, akEditorWideLayoutWidth } from '@atlaskit/editor-shared-styles';
import { isSSR } from '@atlaskit/editor-common/core-utils';
import { FullPagePadding } from '../../../ui/Renderer/style';
import { useAnnotationRangeDispatch } from '../../../ui/annotations/contexts/AnnotationRangeContext';
import { useAnnotationHoverDispatch } from '../../../ui/annotations/contexts/AnnotationHoverContext';
var DEFAULT_WIDTH = 250;
var DEFAULT_HEIGHT = 200;
var uiMediaSingleBaseStyles = css({
transition: 'all 0.1s linear'
});
var uiMediaSingleLayoutStyles = css({
// eslint-disable-next-line @atlaskit/design-system/use-tokens-space
marginLeft: '50%',
transform: 'translateX(-50%)'
});
var isMediaElement = function isMediaElement(media) {
if (!media) {
return false;
}
// Ignored via go/ees005
// eslint-disable-next-line @typescript-eslint/no-explicit-any
var _ref = media.props || {},
nodeType = _ref.nodeType,
type = _ref.type;
// Use this to perform a rough check
// better than assume the first item in children is media
return nodeType === 'media' || ['external', 'file', 'link'].indexOf(type) >= 0;
};
var _checkForMediaElement = function checkForMediaElement(children) {
var _React$Children$toArr = React.Children.toArray(children),
_React$Children$toArr2 = _slicedToArray(_React$Children$toArr, 1),
media = _React$Children$toArr2[0];
// Ignored via go/ees005
// eslint-disable-next-line @typescript-eslint/no-explicit-any
if (media && !isMediaElement(media) && media.props.children) {
// Ignored via go/ees005
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return _checkForMediaElement(media.props.children);
}
return media;
};
// returns the existing container width if available (non SSR mode), otherwise
// we return a default width value
export var getMediaContainerWidth = function getMediaContainerWidth(currentContainerWidth, layout) {
if (!currentContainerWidth) {
// SSR mode fallback to default layout width
switch (layout) {
case 'full-width':
return akEditorFullWidthLayoutWidth;
case 'wide':
return akEditorWideLayoutWidth;
default:
return akEditorDefaultLayoutWidth;
}
}
return currentContainerWidth;
};
var MediaSingleWithChildren = function MediaSingleWithChildren(props) {
var rendererAppearance = props.rendererAppearance,
featureFlags = props.featureFlags,
isInsideOfBlockNode = props.isInsideOfBlockNode,
layout = props.layout,
widthAttr = props.width,
widthType = props.widthType,
_props$allowCaptions = props.allowCaptions,
allowCaptions = _props$allowCaptions === void 0 ? false : _props$allowCaptions,
_props$isInsideOfInli = props.isInsideOfInlineExtension,
isInsideOfInlineExtension = _props$isInsideOfInli === void 0 ? false : _props$isInsideOfInli,
dataAttributes = props.dataAttributes,
media = props.media,
caption = props.caption,
editorAppearance = props.editorAppearance;
var _React$useState = React.useState({
width: 0,
height: 0
}),
_React$useState2 = _slicedToArray(_React$useState, 2),
externalImageDimensions = _React$useState2[0],
setExternalImageDimensions = _React$useState2[1];
var ref = React.useRef(null);
var onExternalImageLoaded = React.useCallback(function (_ref2) {
var width = _ref2.width,
height = _ref2.height;
setExternalImageDimensions({
width: width,
height: height
});
}, []);
// Ignored via go/ees005
// eslint-disable-next-line prefer-const
var _media$props = media.props,
_media$props$width = _media$props.width,
width = _media$props$width === void 0 ? DEFAULT_WIDTH : _media$props$width,
_media$props$height = _media$props.height,
height = _media$props$height === void 0 ? DEFAULT_HEIGHT : _media$props$height,
type = _media$props.type;
if (type === 'external') {
var stateWidth = externalImageDimensions.width,
stateHeight = externalImageDimensions.height;
if (width === null) {
width = stateWidth || DEFAULT_WIDTH;
}
if (height === null) {
height = stateHeight || DEFAULT_HEIGHT;
}
}
if (width === null) {
width = DEFAULT_WIDTH;
height = DEFAULT_HEIGHT;
}
var isFullPage = rendererAppearance === 'full-page';
var isFullWidth = rendererAppearance === 'full-width';
var padding = isFullPage ? FullPagePadding * 2 : 0;
var calcDimensions = useCallback(function (mediaContainerWidth) {
var containerWidth = getMediaContainerWidth(mediaContainerWidth, layout);
var cardDimensions = {};
if (fg('media-perf-uplift-mutation-fix')) {
var maxWidth = widthAttr && typeof widthAttr === 'number' && widthType === 'pixel' ? widthAttr : containerWidth;
cardDimensions = {
width: "".concat(maxWidth, "px"),
height: "100%"
};
} else {
var _maxWidth = isSSR() && widthAttr && typeof widthAttr === 'number' ? Math.max(widthAttr, containerWidth) : containerWidth;
var maxHeight = height / width * _maxWidth;
cardDimensions = {
width: "".concat(_maxWidth, "px"),
height: "".concat(maxHeight, "px")
};
}
var nonFullWidthSize = containerWidth;
if (!isInsideOfBlockNode && rendererAppearance !== 'comment') {
var isContainerSizeGreaterThanMaxFullPageWidth = containerWidth - padding >= akEditorDefaultLayoutWidth;
if (isContainerSizeGreaterThanMaxFullPageWidth) {
nonFullWidthSize = akEditorDefaultLayoutWidth;
} else {
nonFullWidthSize = containerWidth - padding;
}
}
var minWidth = Math.min(akEditorFullWidthLayoutWidth, containerWidth - padding);
var lineLength = isFullWidth ? minWidth : nonFullWidthSize;
return {
cardDimensions: cardDimensions,
lineLength: lineLength
};
}, [height, isFullWidth, isInsideOfBlockNode, layout, padding, rendererAppearance, width, widthAttr, widthType]);
var originalDimensions = useMemo(function () {
return {
width: width,
height: height
};
}, [height, width]);
var _useAnnotationRangeDi = useAnnotationRangeDispatch(),
setHoverTarget = _useAnnotationRangeDi.setHoverTarget;
var _useAnnotationHoverDi = useAnnotationHoverDispatch(),
cancelTimeout = _useAnnotationHoverDi.cancelTimeout,
initiateTimeout = _useAnnotationHoverDi.initiateTimeout,
setIsWithinRange = _useAnnotationHoverDi.setIsWithinRange;
var isFullPageRenderer = isFullPage || isFullWidth;
useEffect(function () {
var mediaSingleElement = ref.current;
var handleMouseEnter = function handleMouseEnter(event) {
cancelTimeout();
if (event.buttons === 0) {
// Ignored via go/ees005
// eslint-disable-next-line @atlaskit/editor/no-as-casting
setHoverTarget && setHoverTarget(event.target);
setIsWithinRange(true);
}
};
var handleMouseLeave = function handleMouseLeave() {
initiateTimeout();
};
if (mediaSingleElement && isFullPageRenderer) {
// Ignored via go/ees005
// eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
mediaSingleElement.addEventListener('mouseenter', handleMouseEnter);
// Ignored via go/ees005
// eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
mediaSingleElement.addEventListener('mouseleave', handleMouseLeave);
}
return function () {
if (mediaSingleElement && isFullPageRenderer) {
// Ignored via go/ees005
// eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
mediaSingleElement.removeEventListener('mouseenter', handleMouseEnter);
// Ignored via go/ees005
// eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
mediaSingleElement.removeEventListener('mouseleave', handleMouseLeave);
}
};
}, [setHoverTarget, isFullPageRenderer, cancelTimeout, initiateTimeout, setIsWithinRange]);
// Note: in SSR mode the `window` object is not defined,
// therefore width here is 0, see:
// packages/editor/editor-common/src/ui/WidthProvider/index.tsx
var _useContext = useContext(WidthContext),
renderWidth = _useContext.width;
var containerWidth = getMediaContainerWidth(renderWidth, layout);
var _useMemo = useMemo(function () {
return calcDimensions(containerWidth);
}, [calcDimensions, containerWidth]),
cardDimensions = _useMemo.cardDimensions,
lineLength = _useMemo.lineLength;
var renderMediaSingle = function renderMediaSingle() {
var mediaComponent = /*#__PURE__*/React.cloneElement(media, {
resizeMode: 'stretchy-fit',
cardDimensions: cardDimensions,
originalDimensions: originalDimensions,
onExternalImageLoaded: onExternalImageLoaded,
disableOverlay: true,
featureFlags: featureFlags,
mediaSingleElement: ref.current
});
var uiMediaSingleStyles = layout === 'full-width' || layout === 'wide' ? [uiMediaSingleBaseStyles, uiMediaSingleLayoutStyles] : [uiMediaSingleBaseStyles];
return jsx(UIMediaSingle, {
css: uiMediaSingleStyles,
handleMediaSingleRef: ref,
layout: layout,
width: width,
height: height,
lineLength: isInsideOfBlockNode ? containerWidth : lineLength,
containerWidth: containerWidth
// eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed)
,
size: {
width: widthAttr,
widthType: widthType
},
fullWidthMode: isFullWidth,
isInsideOfInlineExtension: isInsideOfInlineExtension,
dataAttributes: dataAttributes,
editorAppearance: editorAppearance,
isInRenderer: true
}, jsx(Fragment, null, mediaComponent), allowCaptions && caption);
};
return renderMediaSingle();
};
var MediaSingle = function MediaSingle(props) {
var children = props.children;
var media;
var _React$Children$toArr3 = React.Children.toArray(children),
_React$Children$toArr4 = _slicedToArray(_React$Children$toArr3, 2),
node = _React$Children$toArr4[0],
caption = _React$Children$toArr4[1];
if (!isMediaElement(node)) {
// Ignored via go/ees005
// eslint-disable-next-line @typescript-eslint/no-explicit-any
var mediaElement = _checkForMediaElement(node.props.children);
if (!mediaElement) {
return node;
}
media = mediaElement;
} else {
media = node;
}
// Ignored via go/ees005
// eslint-disable-next-line react/jsx-props-no-spreading
return jsx(MediaSingleWithChildren, _extends({}, props, {
media: media,
caption: caption
}));
};
// eslint-disable-next-line @typescript-eslint/ban-types
var _default_1 = injectIntl(MediaSingle);
export default _default_1;