UNPKG

motion-v

Version:

<p align="center"> <img width="100" height="100" alt="Motion logo" src="https://user-images.githubusercontent.com/7850794/164965523-3eced4c4-6020-467e-acde-f11b7900ad62.png" /> </p> <h1 align="center">Motion for Vue</h1>

176 lines (175 loc) 6.03 kB
import { invariant } from "hey-listen"; import { isSVGElement, resolveVariant } from "./utils.mjs"; import { FeatureManager } from "../features/feature-manager.mjs"; import { doneCallbacks } from "../components/animate-presence/presence.mjs"; import { isVariantLabels } from "./utils/is-variant-labels.mjs"; import { noop } from "../external/.pnpm/motion-utils@12.23.6/external/motion-utils/dist/es/noop.mjs"; import { frame, cancelFrame } from "../external/.pnpm/motion-dom@12.23.12/external/motion-dom/dist/es/frameloop/frame.mjs"; const mountedStates = /* @__PURE__ */ new WeakMap(); let id = 0; const mountedLayoutIds = /* @__PURE__ */ new Set(); class MotionState { constructor(options, parent) { var _a; this.element = null; this.isSafeToRemove = false; this.isVShow = false; this.children = /* @__PURE__ */ new Set(); this.activeStates = { initial: true, animate: true }; this.currentProcess = null; this._context = null; this.animateUpdates = noop; this.id = `motion-state-${id++}`; this.options = options; this.parent = parent; (_a = parent == null ? void 0 : parent.children) == null ? void 0 : _a.add(this); const initial = options.initial === void 0 && options.variants ? this.context.initial : options.initial; const initialVariantSource = initial === false ? ["initial", "animate"] : ["initial"]; this.initTarget(initialVariantSource); this.featureManager = new FeatureManager(this); this.type = isSVGElement(this.options.as) ? "svg" : "html"; } // Get animation context, falling back to parent context for inheritance get context() { if (!this._context) { const handler = { get: (target, prop) => { var _a; return isVariantLabels(this.options[prop]) ? this.options[prop] : (_a = this.parent) == null ? void 0 : _a.context[prop]; } }; this._context = new Proxy({}, handler); } return this._context; } // Initialize animation target values initTarget(initialVariantSource) { var _a; const custom = this.options.custom ?? ((_a = this.options.animatePresenceContext) == null ? void 0 : _a.custom); this.baseTarget = initialVariantSource.reduce((acc, variant) => { return { ...acc, ...resolveVariant(this.options[variant] || this.context[variant], this.options.variants, custom) }; }, {}); this.target = {}; } // Update visual element with new options updateOptions(options) { var _a; this.options = options; (_a = this.visualElement) == null ? void 0 : _a.update({ ...this.options, whileTap: this.options.whilePress }, { isPresent: !doneCallbacks.has(this.element) }); } // Called before mounting, executes in parent-to-child order beforeMount() { this.featureManager.beforeMount(); } // Mount motion state to DOM element, handles parent-child relationships mount(element, options, notAnimate = false) { var _a; invariant( Boolean(element), "Animation state must be mounted with valid Element" ); this.element = element; this.updateOptions(options); this.featureManager.mount(); if (!notAnimate && this.options.animate) { (_a = this.startAnimation) == null ? void 0 : _a.call(this); } if (this.options.layoutId) { mountedLayoutIds.add(this.options.layoutId); frame.render(() => { mountedLayoutIds.clear(); }); } } clearAnimation() { var _a, _b; this.currentProcess && cancelFrame(this.currentProcess); this.currentProcess = null; (_b = (_a = this.visualElement) == null ? void 0 : _a.variantChildren) == null ? void 0 : _b.forEach((child) => { child.state.clearAnimation(); }); } // update trigger animation startAnimation() { this.clearAnimation(); this.currentProcess = frame.render(() => { this.currentProcess = null; this.animateUpdates(); }); } // Called before unmounting, executes in child-to-parent order beforeUnmount() { this.featureManager.beforeUnmount(); } unmount(unMountChildren = false) { const shouldDelay = this.options.layoutId && !mountedLayoutIds.has(this.options.layoutId); const unmount = () => { const unmountState = () => { var _a, _b, _c; if (unMountChildren) { Array.from(this.children).reverse().forEach(this.unmountChild); } (_b = (_a = this.parent) == null ? void 0 : _a.children) == null ? void 0 : _b.delete(this); mountedStates.delete(this.element); this.featureManager.unmount(); (_c = this.visualElement) == null ? void 0 : _c.unmount(); this.clearAnimation(); }; shouldDelay ? Promise.resolve().then(unmountState) : unmountState(); }; unmount(); } unmountChild(child) { child.unmount(true); } // Called before updating, executes in parent-to-child order beforeUpdate() { this.featureManager.beforeUpdate(); } // Update motion state with new options update(options) { this.updateOptions(options); this.featureManager.update(); this.startAnimation(); } // Set animation state active status and propagate to children setActive(name, isActive, isAnimate = true) { var _a; if (!this.element || this.activeStates[name] === isActive) return; this.activeStates[name] = isActive; (_a = this.visualElement.variantChildren) == null ? void 0 : _a.forEach((child) => { child.state.setActive(name, isActive, false); }); if (isAnimate) { this.animateUpdates({ isExit: name === "exit" && this.activeStates.exit }); } } isMounted() { return Boolean(this.element); } // Called before layout updates to prepare for changes willUpdate(label) { var _a; if (this.options.layout || this.options.layoutId) { (_a = this.visualElement.projection) == null ? void 0 : _a.willUpdate(); } } } export { MotionState, mountedStates };