react-aria-components
Version:
A library of styleable components built using React Aria
140 lines (129 loc) • 6.57 kB
JavaScript
var $c5ccf687772c0422$exports = require("./utils.main.js");
var $aakJU$reactdom = require("react-dom");
var $aakJU$react = require("react");
var $aakJU$reactariautils = require("@react-aria/utils");
var $aakJU$reactaria = require("react-aria");
function $parcel$interopDefault(a) {
return a && a.__esModule ? a.default : a;
}
function $parcel$export(e, n, v, s) {
Object.defineProperty(e, n, {get: v, set: s, enumerable: true, configurable: true});
}
$parcel$export(module.exports, "SharedElementTransition", () => $2d10bc562fea46b3$export$758399f318e6385a);
$parcel$export(module.exports, "SharedElement", () => $2d10bc562fea46b3$export$c34620ff8881d89f);
/*
* Copyright 2025 Adobe. All rights reserved.
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may obtain a copy
* of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
const $2d10bc562fea46b3$var$SharedElementContext = /*#__PURE__*/ (0, $aakJU$react.createContext)(null);
function $2d10bc562fea46b3$export$758399f318e6385a(props) {
let ref = (0, $aakJU$react.useRef)({});
return /*#__PURE__*/ (0, ($parcel$interopDefault($aakJU$react))).createElement($2d10bc562fea46b3$var$SharedElementContext.Provider, {
value: ref
}, props.children);
}
const $2d10bc562fea46b3$export$c34620ff8881d89f = /*#__PURE__*/ (0, $aakJU$react.forwardRef)(function SharedElement(props, ref) {
let { name: name, isVisible: isVisible = true, children: children, className: className, style: style, ...divProps } = props;
let [state, setState] = (0, $aakJU$react.useState)(isVisible ? 'visible' : 'hidden');
let scopeRef = (0, $aakJU$react.useContext)($2d10bc562fea46b3$var$SharedElementContext);
if (!scopeRef) throw new Error('<SharedElement> must be rendered inside a <SharedElementTransition>');
if (isVisible && state === 'hidden') setState('visible');
ref = (0, $aakJU$reactaria.useObjectRef)(ref);
(0, $aakJU$reactariautils.useLayoutEffect)(()=>{
let element = ref.current;
let scope = scopeRef.current;
let prevSnapshot = scope[name];
let frame = null;
if (element && isVisible && prevSnapshot) {
// Element is transitioning from a previous instance.
setState('visible');
let animations = element.getAnimations();
// Set properties to animate from.
let values = prevSnapshot.style.map(([property, prevValue])=>{
let value = element.style[property];
if (property === 'translate') {
let prevRect = prevSnapshot.rect;
let currentItem = element.getBoundingClientRect();
let deltaX = prevRect.left - (currentItem === null || currentItem === void 0 ? void 0 : currentItem.left);
let deltaY = prevRect.top - (currentItem === null || currentItem === void 0 ? void 0 : currentItem.top);
element.style.translate = `${deltaX}px ${deltaY}px`;
} else element.style[property] = prevValue;
return [
property,
value
];
});
// Cancel any new animations triggered by these properties.
for (let a of element.getAnimations())if (!animations.includes(a)) a.cancel();
// Remove overrides after one frame to animate to the current values.
frame = requestAnimationFrame(()=>{
frame = null;
for (let [property, value] of values)element.style[property] = value;
});
delete scope[name];
} else if (element && isVisible && !prevSnapshot) {
// No previous instance exists, apply the entering state.
queueMicrotask(()=>(0, $aakJU$reactdom.flushSync)(()=>setState('entering')));
frame = requestAnimationFrame(()=>{
frame = null;
setState('visible');
});
} else if (element && !isVisible) // Wait until layout effects finish, and check if a snapshot still exists.
// If so, no new SharedElement consumed it, so enter the exiting state.
queueMicrotask(()=>{
if (scope[name]) {
delete scope[name];
(0, $aakJU$reactdom.flushSync)(()=>setState('exiting'));
Promise.all(element.getAnimations().map((a)=>a.finished)).then(()=>setState('hidden')).catch(()=>{});
} else // Snapshot was consumed by another instance, unmount.
setState('hidden');
});
return ()=>{
if (frame != null) cancelAnimationFrame(frame);
if (element && element.isConnected && !element.hasAttribute('data-exiting')) {
// On unmount, store a snapshot of the rectangle and computed style for transitioning properties.
let style = window.getComputedStyle(element);
if (style.transitionProperty !== 'none') {
let transitionProperty = style.transitionProperty.split(/\s*,\s*/);
scope[name] = {
rect: element.getBoundingClientRect(),
style: transitionProperty.map((p)=>[
p,
style[p]
])
};
}
}
};
}, [
ref,
scopeRef,
name,
isVisible
]);
let renderProps = (0, $c5ccf687772c0422$exports.useRenderProps)({
children: children,
className: className,
style: style,
values: {
isEntering: state === 'entering',
isExiting: state === 'exiting'
}
});
if (state === 'hidden') return null;
return /*#__PURE__*/ (0, ($parcel$interopDefault($aakJU$react))).createElement("div", {
...divProps,
...renderProps,
ref: ref,
"data-entering": state === 'entering' || undefined,
"data-exiting": state === 'exiting' || undefined
});
});
//# sourceMappingURL=SharedElementTransition.main.js.map