@atlaskit/editor-plugin-media
Version:
Media plugin for @atlaskit/editor-core
101 lines (95 loc) • 4.27 kB
JavaScript
/* GeneratedMediaReveal.tsx generated by @compiled/babel-plugin v3.0.2 */
import "./GeneratedMediaReveal.compiled.css";
import { ax, ix } from "@compiled/react/runtime";
import React, { useEffect, useState } from 'react';
/**
* Only `collapsed` and `revealing` size and clip the content. `open` drops back to plain
* block layout, so the reveal leaves nothing behind for selection outlines, resize handles
* or badges to collide with.
*/
/** Which path opened the node. Surfaced as a data attribute for debugging. */
// A `0fr -> 1fr` grid row opens out to the content's natural height without anyone having to
// measure it, which matters because the card's height comes from an aspect-ratio padding
// further down the tree.
const openRow = null;
const collapsedStyles = null;
const revealStyles = null;
const clippedStyles = null;
/**
* Fail-safe, not a normal path: opens the node even if the preview never reports itself
* rendered, so a failed or hanging image still ends up visible rather than staying collapsed.
* Also covers lazy loading, where a card collapsed to zero height may never satisfy the
* IntersectionObserver that triggers its fetch.
*
* Deliberately generous, because opening early is worse than opening late — the space then
* reveals the card's own loading treatment instead of the image, and an AI-generated image has
* to be generated, uploaded, processed and fetched first. `data-media-reveal-trigger` shows
* which path fired; `timeout` in normal use means the readiness signal is broken.
*/
const READY_TIMEOUT_MS = 30_000;
// Backstop for reduced motion and browsers that don't interpolate grid-template-rows, where no
// animationend fires. Must stay comfortably longer than the reveal, or it cuts it off part way.
const REVEAL_TIMEOUT_MS = 1000;
/**
* Opens the document out to make room for a media node once its preview is ready, rather than
* having the node snap into place at full height. For AI-generated media in the Create with
* Rovo preview, where images are inserted after the surrounding content has streamed in:
* holding the node closed until the preview has rendered means the space opens exactly once,
* with the image already fading in, so there is no placeholder to look at in between.
*/
export const GeneratedMediaReveal = ({
children,
isEnabled,
isReady,
mediaKey
}) => {
const [state, setState] = useState('collapsed');
const [trigger, setTrigger] = useState();
// Reset during render rather than remounting on a `key`, which would also remount the card
// below and restart its fetch. The reveal's effect only runs while `collapsed`, so without
// this a replacement would appear at once, having inherited the previous file's `open`.
const [renderedMediaKey, setRenderedMediaKey] = useState(mediaKey);
if (mediaKey !== renderedMediaKey) {
setRenderedMediaKey(mediaKey);
setState('collapsed');
setTrigger(undefined);
}
useEffect(() => {
if (!isEnabled || state !== 'collapsed') {
return;
}
if (isReady) {
setTrigger('ready');
setState('revealing');
return;
}
const timer = setTimeout(() => {
setTrigger('timeout');
setState('revealing');
}, READY_TIMEOUT_MS);
return () => clearTimeout(timer);
}, [isEnabled, isReady, state]);
useEffect(() => {
if (state !== 'revealing') {
return;
}
const timer = setTimeout(() => setState('open'), REVEAL_TIMEOUT_MS);
return () => clearTimeout(timer);
}, [state]);
if (!isEnabled) {
return /*#__PURE__*/React.createElement(React.Fragment, null, children);
}
return /*#__PURE__*/React.createElement("div", {
"data-media-reveal": state,
"data-media-reveal-trigger": trigger,
onAnimationEnd: event => {
// The media card runs animations of its own, which bubble through here.
if (event.target === event.currentTarget) {
setState('open');
}
},
className: ax([state === 'collapsed' && "_1e0c11p5 _2z0563bf", state === 'revealing' && "", state === 'revealing' && "_1e0c11p5 _2z05hkll _j7hq8gkt _5sag15uc _1pglindk _1o51eoah _1bumglyw"])
}, /*#__PURE__*/React.createElement("div", {
className: ax([state !== 'open' && "_1reo15vq _18m915vq _1tkeidpf"])
}, children));
};