UNPKG

@react-spring/animated

Version:

Animated component props for React

386 lines (372 loc) 11.9 kB
"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/index.ts var src_exports = {}; __export(src_exports, { Animated: () => Animated, AnimatedArray: () => AnimatedArray, AnimatedObject: () => AnimatedObject, AnimatedString: () => AnimatedString, AnimatedValue: () => AnimatedValue, createHost: () => createHost, getAnimated: () => getAnimated, getAnimatedType: () => getAnimatedType, getPayload: () => getPayload, isAnimated: () => isAnimated, setAnimated: () => setAnimated }); module.exports = __toCommonJS(src_exports); // src/Animated.ts var import_shared = require("@react-spring/shared"); var $node = Symbol.for("Animated:node"); var isAnimated = (value) => !!value && value[$node] === value; var getAnimated = (owner) => owner && owner[$node]; var setAnimated = (owner, node) => (0, import_shared.defineHidden)(owner, $node, node); var getPayload = (owner) => owner && owner[$node] && owner[$node].getPayload(); var Animated = class { constructor() { setAnimated(this, this); } /** Get every `AnimatedValue` used by this node. */ getPayload() { return this.payload || []; } }; // src/AnimatedValue.ts var import_shared2 = require("@react-spring/shared"); var AnimatedValue = class _AnimatedValue extends Animated { constructor(_value) { super(); this._value = _value; this.done = true; this.durationProgress = 0; if (import_shared2.is.num(this._value)) { this.lastPosition = this._value; } } /** @internal */ static create(value) { return new _AnimatedValue(value); } getPayload() { return [this]; } getValue() { return this._value; } setValue(value, step) { if (import_shared2.is.num(value)) { this.lastPosition = value; if (step) { value = Math.round(value / step) * step; if (this.done) { this.lastPosition = value; } } } if (this._value === value) { return false; } this._value = value; return true; } reset() { const { done } = this; this.done = false; if (import_shared2.is.num(this._value)) { this.elapsedTime = 0; this.durationProgress = 0; this.lastPosition = this._value; if (done) this.lastVelocity = null; this.v0 = null; } } }; // src/AnimatedString.ts var import_shared3 = require("@react-spring/shared"); var AnimatedString = class _AnimatedString extends AnimatedValue { constructor(value) { super(0); this._string = null; this._toString = (0, import_shared3.createInterpolator)({ output: [value, value] }); } /** @internal */ static create(value) { return new _AnimatedString(value); } getValue() { const value = this._string; return value == null ? this._string = this._toString(this._value) : value; } setValue(value) { if (import_shared3.is.str(value)) { if (value == this._string) { return false; } this._string = value; this._value = 1; } else if (super.setValue(value)) { this._string = null; } else { return false; } return true; } reset(goal) { if (goal) { this._toString = (0, import_shared3.createInterpolator)({ output: [this.getValue(), goal] }); } this._value = 0; super.reset(); } }; // src/AnimatedArray.ts var import_shared5 = require("@react-spring/shared"); // src/AnimatedObject.ts var import_shared4 = require("@react-spring/shared"); // src/context.ts var TreeContext = { dependencies: null }; // src/AnimatedObject.ts var AnimatedObject = class extends Animated { constructor(source) { super(); this.source = source; this.setValue(source); } getValue(animated) { const values = {}; (0, import_shared4.eachProp)(this.source, (source, key) => { if (isAnimated(source)) { values[key] = source.getValue(animated); } else if ((0, import_shared4.hasFluidValue)(source)) { values[key] = (0, import_shared4.getFluidValue)(source); } else if (!animated) { values[key] = source; } }); return values; } /** Replace the raw object data */ setValue(source) { this.source = source; this.payload = this._makePayload(source); } reset() { if (this.payload) { (0, import_shared4.each)(this.payload, (node) => node.reset()); } } /** Create a payload set. */ _makePayload(source) { if (source) { const payload = /* @__PURE__ */ new Set(); (0, import_shared4.eachProp)(source, this._addToPayload, payload); return Array.from(payload); } } /** Add to a payload set. */ _addToPayload(source) { if (TreeContext.dependencies && (0, import_shared4.hasFluidValue)(source)) { TreeContext.dependencies.add(source); } const payload = getPayload(source); if (payload) { (0, import_shared4.each)(payload, (node) => this.add(node)); } } }; // src/AnimatedArray.ts var AnimatedArray = class _AnimatedArray extends AnimatedObject { constructor(source) { super(source); } /** @internal */ static create(source) { return new _AnimatedArray(source); } getValue() { return this.source.map((node) => node.getValue()); } setValue(source) { const payload = this.getPayload(); if (source.length == payload.length) { return payload.map((node, i) => node.setValue(source[i])).some(Boolean); } super.setValue(source.map(makeAnimated)); return true; } }; function makeAnimated(value) { const nodeType = (0, import_shared5.isAnimatedString)(value) ? AnimatedString : AnimatedValue; return nodeType.create(value); } // src/getAnimatedType.ts var import_shared6 = require("@react-spring/shared"); function getAnimatedType(value) { const parentNode = getAnimated(value); return parentNode ? parentNode.constructor : import_shared6.is.arr(value) ? AnimatedArray : (0, import_shared6.isAnimatedString)(value) ? AnimatedString : AnimatedValue; } // src/createHost.ts var import_shared8 = require("@react-spring/shared"); // src/withAnimated.tsx var React = __toESM(require("react")); var import_react = require("react"); var import_shared7 = require("@react-spring/shared"); var withAnimated = (Component, host) => { const hasInstance = ( // Function components must use "forwardRef" to avoid being // re-rendered on every animation frame. !import_shared7.is.fun(Component) || Component.prototype && Component.prototype.isReactComponent ); return (0, import_react.forwardRef)((givenProps, givenRef) => { const instanceRef = (0, import_react.useRef)(null); const ref = hasInstance && // eslint-disable-next-line react-hooks/rules-of-hooks (0, import_react.useCallback)( (value) => { instanceRef.current = updateRef(givenRef, value); }, [givenRef] ); const [props, deps] = getAnimatedState(givenProps, host); const forceUpdate = (0, import_shared7.useForceUpdate)(); const callback = () => { const instance = instanceRef.current; if (hasInstance && !instance) { return; } const didUpdate = instance ? host.applyAnimatedValues(instance, props.getValue(true)) : false; if (didUpdate === false) { forceUpdate(); } }; const observer = new PropsObserver(callback, deps); const observerRef = (0, import_react.useRef)(void 0); (0, import_shared7.useIsomorphicLayoutEffect)(() => { observerRef.current = observer; (0, import_shared7.each)(deps, (dep) => (0, import_shared7.addFluidObserver)(dep, observer)); return () => { if (observerRef.current) { (0, import_shared7.each)( observerRef.current.deps, (dep) => (0, import_shared7.removeFluidObserver)(dep, observerRef.current) ); import_shared7.raf.cancel(observerRef.current.update); } }; }); (0, import_react.useEffect)(callback, []); (0, import_shared7.useOnce)(() => () => { const observer2 = observerRef.current; (0, import_shared7.each)(observer2.deps, (dep) => (0, import_shared7.removeFluidObserver)(dep, observer2)); }); const usedProps = host.getComponentProps(props.getValue()); return /* @__PURE__ */ React.createElement(Component, { ...usedProps, ref }); }); }; var PropsObserver = class { constructor(update, deps) { this.update = update; this.deps = deps; } eventObserved(event) { if (event.type == "change") { import_shared7.raf.write(this.update); } } }; function getAnimatedState(props, host) { const dependencies = /* @__PURE__ */ new Set(); TreeContext.dependencies = dependencies; if (props.style) props = { ...props, style: host.createAnimatedStyle(props.style) }; props = new AnimatedObject(props); TreeContext.dependencies = null; return [props, dependencies]; } function updateRef(ref, value) { if (ref) { if (import_shared7.is.fun(ref)) ref(value); else ref.current = value; } return value; } // src/createHost.ts var cacheKey = Symbol.for("AnimatedComponent"); var createHost = (components, { applyAnimatedValues = () => false, createAnimatedStyle = (style) => new AnimatedObject(style), getComponentProps = (props) => props } = {}) => { const hostConfig = { applyAnimatedValues, createAnimatedStyle, getComponentProps }; const animated = (Component) => { const displayName = getDisplayName(Component) || "Anonymous"; if (import_shared8.is.str(Component)) { Component = animated[Component] || (animated[Component] = withAnimated(Component, hostConfig)); } else { Component = Component[cacheKey] || (Component[cacheKey] = withAnimated(Component, hostConfig)); } Component.displayName = `Animated(${displayName})`; return Component; }; (0, import_shared8.eachProp)(components, (Component, key) => { if (import_shared8.is.arr(components)) { key = getDisplayName(Component); } animated[key] = animated(Component); }); return { animated }; }; var getDisplayName = (arg) => import_shared8.is.str(arg) ? arg : arg && import_shared8.is.str(arg.displayName) ? arg.displayName : import_shared8.is.fun(arg) && arg.name || null; // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { Animated, AnimatedArray, AnimatedObject, AnimatedString, AnimatedValue, createHost, getAnimated, getAnimatedType, getPayload, isAnimated, setAnimated });