UNPKG

framer-motion

Version:

A simple and powerful JavaScript animation library

81 lines (78 loc) 2.69 kB
import { invariant } from 'motion-utils'; import { setTarget } from '../../render/utils/setters.mjs'; import { animateVisualElement } from '../interfaces/visual-element.mjs'; function stopAnimation(visualElement) { visualElement.values.forEach((value) => value.stop()); } function setVariants(visualElement, variantLabels) { const reversedLabels = [...variantLabels].reverse(); reversedLabels.forEach((key) => { const variant = visualElement.getVariant(key); variant && setTarget(visualElement, variant); if (visualElement.variantChildren) { visualElement.variantChildren.forEach((child) => { setVariants(child, variantLabels); }); } }); } function setValues(visualElement, definition) { if (Array.isArray(definition)) { return setVariants(visualElement, definition); } else if (typeof definition === "string") { return setVariants(visualElement, [definition]); } else { setTarget(visualElement, definition); } } /** * @public */ function animationControls() { /** * Track whether the host component has mounted. */ let hasMounted = false; /** * A collection of linked component animation controls. */ const subscribers = new Set(); const controls = { subscribe(visualElement) { subscribers.add(visualElement); return () => void subscribers.delete(visualElement); }, start(definition, transitionOverride) { invariant(hasMounted, "controls.start() should only be called after a component has mounted. Consider calling within a useEffect hook."); const animations = []; subscribers.forEach((visualElement) => { animations.push(animateVisualElement(visualElement, definition, { transitionOverride, })); }); return Promise.all(animations); }, set(definition) { invariant(hasMounted, "controls.set() should only be called after a component has mounted. Consider calling within a useEffect hook."); return subscribers.forEach((visualElement) => { setValues(visualElement, definition); }); }, stop() { subscribers.forEach((visualElement) => { stopAnimation(visualElement); }); }, mount() { hasMounted = true; return () => { hasMounted = false; controls.stop(); }; }, }; return controls; } export { animationControls, setValues };