184 lines
8.1 KiB
JavaScript
184 lines
8.1 KiB
JavaScript
'use client';
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
function _export(target, all) {
|
|
for(var name in all)Object.defineProperty(target, name, {
|
|
enumerable: true,
|
|
get: all[name]
|
|
});
|
|
}
|
|
_export(exports, {
|
|
PRESENCE_MOTION_DEFINITION: function() {
|
|
return PRESENCE_MOTION_DEFINITION;
|
|
},
|
|
createPresenceComponent: function() {
|
|
return createPresenceComponent;
|
|
}
|
|
});
|
|
const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
|
|
const _reactutilities = require("@fluentui/react-utilities");
|
|
const _react = /*#__PURE__*/ _interop_require_wildcard._(require("react"));
|
|
const _PresenceGroupChildContext = require("../contexts/PresenceGroupChildContext");
|
|
const _useAnimateAtoms = require("../hooks/useAnimateAtoms");
|
|
const _useMotionImperativeRef = require("../hooks/useMotionImperativeRef");
|
|
const _useMountedState = require("../hooks/useMountedState");
|
|
const _useIsReducedMotion = require("../hooks/useIsReducedMotion");
|
|
const _useChildElement = require("../utils/useChildElement");
|
|
const _MotionBehaviourContext = require("../contexts/MotionBehaviourContext");
|
|
const _createMotionComponent = require("./createMotionComponent");
|
|
const PRESENCE_MOTION_DEFINITION = Symbol('PRESENCE_MOTION_DEFINITION');
|
|
const INTERRUPTABLE_MOTION_SYMBOL = Symbol.for('interruptablePresence');
|
|
function createPresenceComponent(value) {
|
|
return Object.assign((props)=>{
|
|
'use no memo';
|
|
const itemContext = _react.useContext(_PresenceGroupChildContext.PresenceGroupChildContext);
|
|
const merged = {
|
|
...itemContext,
|
|
...props
|
|
};
|
|
const skipMotions = (0, _MotionBehaviourContext.useMotionBehaviourContext)() === 'skip';
|
|
const { appear, children, imperativeRef, onExit, onMotionFinish, onMotionStart, onMotionCancel, visible, unmountOnExit, ..._rest } = merged;
|
|
const params = _rest;
|
|
const [mounted, setMounted] = (0, _useMountedState.useMountedState)(visible, unmountOnExit);
|
|
const [child, childRef] = (0, _useChildElement.useChildElement)(children, mounted);
|
|
const handleRef = (0, _useMotionImperativeRef.useMotionImperativeRef)(imperativeRef);
|
|
const optionsRef = _react.useRef({
|
|
appear,
|
|
params,
|
|
skipMotions
|
|
});
|
|
const animateAtoms = (0, _useAnimateAtoms.useAnimateAtoms)();
|
|
const isFirstMount = (0, _reactutilities.useFirstMount)();
|
|
const isReducedMotion = (0, _useIsReducedMotion.useIsReducedMotion)();
|
|
const handleMotionStart = (0, _reactutilities.useEventCallback)((direction)=>{
|
|
onMotionStart === null || onMotionStart === void 0 ? void 0 : onMotionStart(null, {
|
|
direction
|
|
});
|
|
});
|
|
const handleMotionFinish = (0, _reactutilities.useEventCallback)((direction)=>{
|
|
onMotionFinish === null || onMotionFinish === void 0 ? void 0 : onMotionFinish(null, {
|
|
direction
|
|
});
|
|
if (direction === 'exit' && unmountOnExit) {
|
|
setMounted(false);
|
|
onExit === null || onExit === void 0 ? void 0 : onExit();
|
|
}
|
|
});
|
|
const handleMotionCancel = (0, _reactutilities.useEventCallback)((direction)=>{
|
|
onMotionCancel === null || onMotionCancel === void 0 ? void 0 : onMotionCancel(null, {
|
|
direction
|
|
});
|
|
});
|
|
(0, _reactutilities.useIsomorphicLayoutEffect)(()=>{
|
|
// Heads up!
|
|
// We store the params in a ref to avoid re-rendering the component when the params change.
|
|
optionsRef.current = {
|
|
appear,
|
|
params,
|
|
skipMotions
|
|
};
|
|
});
|
|
(0, _reactutilities.useIsomorphicLayoutEffect)(()=>{
|
|
const element = childRef.current;
|
|
if (!element) {
|
|
return;
|
|
}
|
|
let handle;
|
|
function cleanup() {
|
|
if (!handle) {
|
|
return;
|
|
}
|
|
// Heads up!
|
|
//
|
|
// If the animation is interruptible & is running, we don't want to cancel it as it will be reversed in
|
|
// the next effect.
|
|
if (IS_EXPERIMENTAL_INTERRUPTIBLE_MOTION && handle.isRunning()) {
|
|
return;
|
|
}
|
|
handle.cancel();
|
|
handleRef.current = undefined;
|
|
}
|
|
const presenceMotion = typeof value === 'function' ? value({
|
|
element,
|
|
...optionsRef.current.params
|
|
}) : value;
|
|
const IS_EXPERIMENTAL_INTERRUPTIBLE_MOTION = presenceMotion[INTERRUPTABLE_MOTION_SYMBOL];
|
|
if (IS_EXPERIMENTAL_INTERRUPTIBLE_MOTION) {
|
|
handle = handleRef.current;
|
|
if (handle && handle.isRunning()) {
|
|
handle.reverse();
|
|
return cleanup;
|
|
}
|
|
}
|
|
const atoms = visible ? presenceMotion.enter : presenceMotion.exit;
|
|
const direction = visible ? 'enter' : 'exit';
|
|
// Heads up!
|
|
// Initial styles are applied when the component is mounted for the first time and "appear" is set to "false" (otherwise animations are triggered)
|
|
const applyInitialStyles = !optionsRef.current.appear && isFirstMount;
|
|
const skipAnimationByConfig = optionsRef.current.skipMotions;
|
|
if (!applyInitialStyles) {
|
|
handleMotionStart(direction);
|
|
}
|
|
handle = animateAtoms(element, atoms, {
|
|
isReducedMotion: isReducedMotion()
|
|
});
|
|
if (applyInitialStyles) {
|
|
// Heads up!
|
|
// .finish() is used in this case to skip animation and apply animation styles immediately
|
|
handle.finish();
|
|
return cleanup;
|
|
}
|
|
handleRef.current = handle;
|
|
handle.setMotionEndCallbacks(()=>handleMotionFinish(direction), ()=>handleMotionCancel(direction));
|
|
if (skipAnimationByConfig) {
|
|
handle.finish();
|
|
}
|
|
return cleanup;
|
|
}, // Excluding `isFirstMount` from deps to prevent re-triggering the animation on subsequent renders
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
[
|
|
animateAtoms,
|
|
childRef,
|
|
handleRef,
|
|
isReducedMotion,
|
|
handleMotionFinish,
|
|
handleMotionStart,
|
|
handleMotionCancel,
|
|
visible
|
|
]);
|
|
_react.useEffect(()=>{
|
|
// Heads up!
|
|
//
|
|
// Dispose the handle when unmounting the component to clean up retained references. Doing it in a separate
|
|
// effect to ensure that the component is unmounted.
|
|
if (unmountOnExit && !mounted) {
|
|
var _handleRef_current;
|
|
(_handleRef_current = handleRef.current) === null || _handleRef_current === void 0 ? void 0 : _handleRef_current.dispose();
|
|
}
|
|
}, [
|
|
handleRef,
|
|
unmountOnExit,
|
|
mounted
|
|
]);
|
|
if (mounted) {
|
|
return child;
|
|
}
|
|
return null;
|
|
}, {
|
|
// Heads up!
|
|
// Always normalize it to a function to simplify types
|
|
[PRESENCE_MOTION_DEFINITION]: typeof value === 'function' ? value : ()=>value
|
|
}, {
|
|
// Wrap `enter` in its own motion component as a static method, e.g. <Fade.In>
|
|
In: (0, _createMotionComponent.createMotionComponent)(// If we have a motion function, wrap it to forward the runtime params and pick `enter`.
|
|
// Otherwise, pass the `enter` motion object directly.
|
|
typeof value === 'function' ? (...args)=>value(...args).enter : value.enter),
|
|
// Wrap `exit` in its own motion component as a static method, e.g. <Fade.Out>
|
|
Out: (0, _createMotionComponent.createMotionComponent)(// If we have a motion function, wrap it to forward the runtime params and pick `exit`.
|
|
// Otherwise, pass the `exit` motion object directly.
|
|
typeof value === 'function' ? (...args)=>value(...args).exit : value.exit)
|
|
});
|
|
}
|