353 lines
9.2 KiB
JavaScript
353 lines
9.2 KiB
JavaScript
// src/Animated.ts
|
|
import { defineHidden } from "@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) => 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
|
|
import { is } from "@react-spring/shared";
|
|
var AnimatedValue = class _AnimatedValue extends Animated {
|
|
constructor(_value) {
|
|
super();
|
|
this._value = _value;
|
|
this.done = true;
|
|
this.durationProgress = 0;
|
|
if (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 (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 (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
|
|
import { is as is2, createInterpolator } from "@react-spring/shared";
|
|
var AnimatedString = class _AnimatedString extends AnimatedValue {
|
|
constructor(value) {
|
|
super(0);
|
|
this._string = null;
|
|
this._toString = 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 (is2.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 = createInterpolator({
|
|
output: [this.getValue(), goal]
|
|
});
|
|
}
|
|
this._value = 0;
|
|
super.reset();
|
|
}
|
|
};
|
|
|
|
// src/AnimatedArray.ts
|
|
import { isAnimatedString } from "@react-spring/shared";
|
|
|
|
// src/AnimatedObject.ts
|
|
import {
|
|
each,
|
|
eachProp,
|
|
getFluidValue,
|
|
hasFluidValue
|
|
} from "@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 = {};
|
|
eachProp(this.source, (source, key) => {
|
|
if (isAnimated(source)) {
|
|
values[key] = source.getValue(animated);
|
|
} else if (hasFluidValue(source)) {
|
|
values[key] = 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) {
|
|
each(this.payload, (node) => node.reset());
|
|
}
|
|
}
|
|
/** Create a payload set. */
|
|
_makePayload(source) {
|
|
if (source) {
|
|
const payload = /* @__PURE__ */ new Set();
|
|
eachProp(source, this._addToPayload, payload);
|
|
return Array.from(payload);
|
|
}
|
|
}
|
|
/** Add to a payload set. */
|
|
_addToPayload(source) {
|
|
if (TreeContext.dependencies && hasFluidValue(source)) {
|
|
TreeContext.dependencies.add(source);
|
|
}
|
|
const payload = getPayload(source);
|
|
if (payload) {
|
|
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 = isAnimatedString(value) ? AnimatedString : AnimatedValue;
|
|
return nodeType.create(value);
|
|
}
|
|
|
|
// src/getAnimatedType.ts
|
|
import { is as is3, isAnimatedString as isAnimatedString2 } from "@react-spring/shared";
|
|
function getAnimatedType(value) {
|
|
const parentNode = getAnimated(value);
|
|
return parentNode ? parentNode.constructor : is3.arr(value) ? AnimatedArray : isAnimatedString2(value) ? AnimatedString : AnimatedValue;
|
|
}
|
|
|
|
// src/createHost.ts
|
|
import { is as is5, eachProp as eachProp2 } from "@react-spring/shared";
|
|
|
|
// src/withAnimated.tsx
|
|
import * as React from "react";
|
|
import { forwardRef, useRef, useCallback, useEffect } from "react";
|
|
import {
|
|
is as is4,
|
|
each as each2,
|
|
raf,
|
|
useForceUpdate,
|
|
useOnce,
|
|
addFluidObserver,
|
|
removeFluidObserver,
|
|
useIsomorphicLayoutEffect
|
|
} from "@react-spring/shared";
|
|
var withAnimated = (Component, host) => {
|
|
const hasInstance = (
|
|
// Function components must use "forwardRef" to avoid being
|
|
// re-rendered on every animation frame.
|
|
!is4.fun(Component) || Component.prototype && Component.prototype.isReactComponent
|
|
);
|
|
return forwardRef((givenProps, givenRef) => {
|
|
const instanceRef = useRef(null);
|
|
const ref = hasInstance && // eslint-disable-next-line react-hooks/rules-of-hooks
|
|
useCallback(
|
|
(value) => {
|
|
instanceRef.current = updateRef(givenRef, value);
|
|
},
|
|
[givenRef]
|
|
);
|
|
const [props, deps] = getAnimatedState(givenProps, host);
|
|
const forceUpdate = 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 = useRef(void 0);
|
|
useIsomorphicLayoutEffect(() => {
|
|
observerRef.current = observer;
|
|
each2(deps, (dep) => addFluidObserver(dep, observer));
|
|
return () => {
|
|
if (observerRef.current) {
|
|
each2(
|
|
observerRef.current.deps,
|
|
(dep) => removeFluidObserver(dep, observerRef.current)
|
|
);
|
|
raf.cancel(observerRef.current.update);
|
|
}
|
|
};
|
|
});
|
|
useEffect(callback, []);
|
|
useOnce(() => () => {
|
|
const observer2 = observerRef.current;
|
|
each2(observer2.deps, (dep) => 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") {
|
|
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 (is4.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 (is5.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;
|
|
};
|
|
eachProp2(components, (Component, key) => {
|
|
if (is5.arr(components)) {
|
|
key = getDisplayName(Component);
|
|
}
|
|
animated[key] = animated(Component);
|
|
});
|
|
return {
|
|
animated
|
|
};
|
|
};
|
|
var getDisplayName = (arg) => is5.str(arg) ? arg : arg && is5.str(arg.displayName) ? arg.displayName : is5.fun(arg) && arg.name || null;
|
|
export {
|
|
Animated,
|
|
AnimatedArray,
|
|
AnimatedObject,
|
|
AnimatedString,
|
|
AnimatedValue,
|
|
createHost,
|
|
getAnimated,
|
|
getAnimatedType,
|
|
getPayload,
|
|
isAnimated,
|
|
setAnimated
|
|
};
|