reactdesk-core
Version:
A powerful React-based desktop environment library for creating Windows 11-like desktop interfaces with window management, taskbar, themes, and more
3,211 lines • 110 kB
JavaScript
import { f as frame, n as noop, r as resolveVariantFromProps, i as invariant, a as isString, s as singleColorRegex, b as floatRegex, c as number, d as sanitize, e as alpha, g as clamp, p as percent, h as colorRegex, j as cssVariableRegex, w as warning, k as cancelFrame, l as frameData, t as transformProps, m as numberValueTypes, o as isMotionValue, q as px, u as degrees, v as vw, x as vh, y as resolveFinalValueInKeyframes, z as optimizedAppearDataAttribute, A as isAnimationControls, B as isKeyframesTarget, C as variantPriorityOrder, D as isVariantLabel, E as isCSSVariableToken, F as transformPropOrder, G as isBrowser, H as isControllingVariants, I as isVariantNode, J as isRefObject, K as featureDefinitions, L as variantProps, M as isCSSVariableName, N as buildHTMLStyles, O as scrapeMotionValuesFromProps, P as renderHTML, Q as camelCaseAttributes, R as camelToDash, S as scrapeMotionValuesFromProps$1, T as buildSVGAttrs, U as renderSVG, V as isSVGTag, W as isSVGComponent } from "./index-CGa3ZYCK.js";
function addDomEvent(target, eventName, handler, options = { passive: true }) {
target.addEventListener(eventName, handler, options);
return () => target.removeEventListener(eventName, handler);
}
const isPrimaryPointer = (event) => {
if (event.pointerType === "mouse") {
return typeof event.button !== "number" || event.button <= 0;
} else {
return event.isPrimary !== false;
}
};
function extractEventInfo(event, pointType = "page") {
return {
point: {
x: event[pointType + "X"],
y: event[pointType + "Y"]
}
};
}
const addPointerInfo = (handler) => {
return (event) => isPrimaryPointer(event) && handler(event, extractEventInfo(event));
};
function addPointerEvent(target, eventName, handler, options) {
return addDomEvent(target, eventName, addPointerInfo(handler), options);
}
const combineFunctions = (a, b) => (v) => b(a(v));
const pipe = (...transformers) => transformers.reduce(combineFunctions);
function createLock(name) {
let lock = null;
return () => {
const openLock = () => {
lock = null;
};
if (lock === null) {
lock = name;
return openLock;
}
return false;
};
}
const globalHorizontalLock = createLock("dragHorizontal");
const globalVerticalLock = createLock("dragVertical");
function getGlobalLock(drag) {
let lock = false;
{
const openHorizontal = globalHorizontalLock();
const openVertical = globalVerticalLock();
if (openHorizontal && openVertical) {
lock = () => {
openHorizontal();
openVertical();
};
} else {
if (openHorizontal)
openHorizontal();
if (openVertical)
openVertical();
}
}
return lock;
}
function isDragActive() {
const openGestureLock = getGlobalLock();
if (!openGestureLock)
return true;
openGestureLock();
return false;
}
class Feature {
constructor(node) {
this.isMounted = false;
this.node = node;
}
update() {
}
}
function addHoverEvent(node, isActive) {
const eventName = "pointer" + (isActive ? "enter" : "leave");
const callbackName = "onHover" + (isActive ? "Start" : "End");
const handleEvent = (event, info) => {
if (event.pointerType === "touch" || isDragActive())
return;
const props = node.getProps();
if (node.animationState && props.whileHover) {
node.animationState.setActive("whileHover", isActive);
}
if (props[callbackName]) {
frame.update(() => props[callbackName](event, info));
}
};
return addPointerEvent(node.current, eventName, handleEvent, {
passive: !node.getProps()[callbackName]
});
}
class HoverGesture extends Feature {
mount() {
this.unmount = pipe(addHoverEvent(this.node, true), addHoverEvent(this.node, false));
}
unmount() {
}
}
class FocusGesture extends Feature {
constructor() {
super(...arguments);
this.isActive = false;
}
onFocus() {
let isFocusVisible = false;
try {
isFocusVisible = this.node.current.matches(":focus-visible");
} catch (e) {
isFocusVisible = true;
}
if (!isFocusVisible || !this.node.animationState)
return;
this.node.animationState.setActive("whileFocus", true);
this.isActive = true;
}
onBlur() {
if (!this.isActive || !this.node.animationState)
return;
this.node.animationState.setActive("whileFocus", false);
this.isActive = false;
}
mount() {
this.unmount = pipe(addDomEvent(this.node.current, "focus", () => this.onFocus()), addDomEvent(this.node.current, "blur", () => this.onBlur()));
}
unmount() {
}
}
const isNodeOrChild = (parent, child) => {
if (!child) {
return false;
} else if (parent === child) {
return true;
} else {
return isNodeOrChild(parent, child.parentElement);
}
};
function fireSyntheticPointerEvent(name, handler) {
if (!handler)
return;
const syntheticPointerEvent = new PointerEvent("pointer" + name);
handler(syntheticPointerEvent, extractEventInfo(syntheticPointerEvent));
}
class PressGesture extends Feature {
constructor() {
super(...arguments);
this.removeStartListeners = noop;
this.removeEndListeners = noop;
this.removeAccessibleListeners = noop;
this.startPointerPress = (startEvent, startInfo) => {
if (this.isPressing)
return;
this.removeEndListeners();
const props = this.node.getProps();
const endPointerPress = (endEvent, endInfo) => {
if (!this.checkPressEnd())
return;
const { onTap, onTapCancel, globalTapTarget } = this.node.getProps();
frame.update(() => {
!globalTapTarget && !isNodeOrChild(this.node.current, endEvent.target) ? onTapCancel && onTapCancel(endEvent, endInfo) : onTap && onTap(endEvent, endInfo);
});
};
const removePointerUpListener = addPointerEvent(window, "pointerup", endPointerPress, { passive: !(props.onTap || props["onPointerUp"]) });
const removePointerCancelListener = addPointerEvent(window, "pointercancel", (cancelEvent, cancelInfo) => this.cancelPress(cancelEvent, cancelInfo), { passive: !(props.onTapCancel || props["onPointerCancel"]) });
this.removeEndListeners = pipe(removePointerUpListener, removePointerCancelListener);
this.startPress(startEvent, startInfo);
};
this.startAccessiblePress = () => {
const handleKeydown = (keydownEvent) => {
if (keydownEvent.key !== "Enter" || this.isPressing)
return;
const handleKeyup = (keyupEvent) => {
if (keyupEvent.key !== "Enter" || !this.checkPressEnd())
return;
fireSyntheticPointerEvent("up", (event, info) => {
const { onTap } = this.node.getProps();
if (onTap) {
frame.update(() => onTap(event, info));
}
});
};
this.removeEndListeners();
this.removeEndListeners = addDomEvent(this.node.current, "keyup", handleKeyup);
fireSyntheticPointerEvent("down", (event, info) => {
this.startPress(event, info);
});
};
const removeKeydownListener = addDomEvent(this.node.current, "keydown", handleKeydown);
const handleBlur = () => {
if (!this.isPressing)
return;
fireSyntheticPointerEvent("cancel", (cancelEvent, cancelInfo) => this.cancelPress(cancelEvent, cancelInfo));
};
const removeBlurListener = addDomEvent(this.node.current, "blur", handleBlur);
this.removeAccessibleListeners = pipe(removeKeydownListener, removeBlurListener);
};
}
startPress(event, info) {
this.isPressing = true;
const { onTapStart, whileTap } = this.node.getProps();
if (whileTap && this.node.animationState) {
this.node.animationState.setActive("whileTap", true);
}
if (onTapStart) {
frame.update(() => onTapStart(event, info));
}
}
checkPressEnd() {
this.removeEndListeners();
this.isPressing = false;
const props = this.node.getProps();
if (props.whileTap && this.node.animationState) {
this.node.animationState.setActive("whileTap", false);
}
return !isDragActive();
}
cancelPress(event, info) {
if (!this.checkPressEnd())
return;
const { onTapCancel } = this.node.getProps();
if (onTapCancel) {
frame.update(() => onTapCancel(event, info));
}
}
mount() {
const props = this.node.getProps();
const removePointerListener = addPointerEvent(props.globalTapTarget ? window : this.node.current, "pointerdown", this.startPointerPress, { passive: !(props.onTapStart || props["onPointerStart"]) });
const removeFocusListener = addDomEvent(this.node.current, "focus", this.startAccessiblePress);
this.removeStartListeners = pipe(removePointerListener, removeFocusListener);
}
unmount() {
this.removeStartListeners();
this.removeEndListeners();
this.removeAccessibleListeners();
}
}
const observerCallbacks = /* @__PURE__ */ new WeakMap();
const observers = /* @__PURE__ */ new WeakMap();
const fireObserverCallback = (entry) => {
const callback = observerCallbacks.get(entry.target);
callback && callback(entry);
};
const fireAllObserverCallbacks = (entries) => {
entries.forEach(fireObserverCallback);
};
function initIntersectionObserver({ root, ...options }) {
const lookupRoot = root || document;
if (!observers.has(lookupRoot)) {
observers.set(lookupRoot, {});
}
const rootObservers = observers.get(lookupRoot);
const key = JSON.stringify(options);
if (!rootObservers[key]) {
rootObservers[key] = new IntersectionObserver(fireAllObserverCallbacks, { root, ...options });
}
return rootObservers[key];
}
function observeIntersection(element, options, callback) {
const rootInteresectionObserver = initIntersectionObserver(options);
observerCallbacks.set(element, callback);
rootInteresectionObserver.observe(element);
return () => {
observerCallbacks.delete(element);
rootInteresectionObserver.unobserve(element);
};
}
const thresholdNames = {
some: 0,
all: 1
};
class InViewFeature extends Feature {
constructor() {
super(...arguments);
this.hasEnteredView = false;
this.isInView = false;
}
startObserver() {
this.unmount();
const { viewport = {} } = this.node.getProps();
const { root, margin: rootMargin, amount = "some", once } = viewport;
const options = {
root: root ? root.current : void 0,
rootMargin,
threshold: typeof amount === "number" ? amount : thresholdNames[amount]
};
const onIntersectionUpdate = (entry) => {
const { isIntersecting } = entry;
if (this.isInView === isIntersecting)
return;
this.isInView = isIntersecting;
if (once && !isIntersecting && this.hasEnteredView) {
return;
} else if (isIntersecting) {
this.hasEnteredView = true;
}
if (this.node.animationState) {
this.node.animationState.setActive("whileInView", isIntersecting);
}
const { onViewportEnter, onViewportLeave } = this.node.getProps();
const callback = isIntersecting ? onViewportEnter : onViewportLeave;
callback && callback(entry);
};
return observeIntersection(this.node.current, options, onIntersectionUpdate);
}
mount() {
this.startObserver();
}
update() {
if (typeof IntersectionObserver === "undefined")
return;
const { props, prevProps } = this.node;
const hasOptionsChanged = ["amount", "margin", "root"].some(hasViewportOptionChanged(props, prevProps));
if (hasOptionsChanged) {
this.startObserver();
}
}
unmount() {
}
}
function hasViewportOptionChanged({ viewport = {} }, { viewport: prevViewport = {} } = {}) {
return (name) => viewport[name] !== prevViewport[name];
}
const gestureAnimations = {
inView: {
Feature: InViewFeature
},
tap: {
Feature: PressGesture
},
focus: {
Feature: FocusGesture
},
hover: {
Feature: HoverGesture
}
};
function shallowCompare(next, prev) {
if (!Array.isArray(prev))
return false;
const prevLength = prev.length;
if (prevLength !== next.length)
return false;
for (let i = 0; i < prevLength; i++) {
if (prev[i] !== next[i])
return false;
}
return true;
}
function getCurrent(visualElement) {
const current = {};
visualElement.values.forEach((value, key) => current[key] = value.get());
return current;
}
function getVelocity(visualElement) {
const velocity = {};
visualElement.values.forEach((value, key) => velocity[key] = value.getVelocity());
return velocity;
}
function resolveVariant(visualElement, definition, custom) {
const props = visualElement.getProps();
return resolveVariantFromProps(props, definition, custom !== void 0 ? custom : props.custom, getCurrent(visualElement), getVelocity(visualElement));
}
const secondsToMilliseconds = (seconds) => seconds * 1e3;
const millisecondsToSeconds = (milliseconds) => milliseconds / 1e3;
const instantAnimationState = {
current: false
};
const isBezierDefinition = (easing) => Array.isArray(easing) && typeof easing[0] === "number";
function isWaapiSupportedEasing(easing) {
return Boolean(!easing || typeof easing === "string" && supportedWaapiEasing[easing] || isBezierDefinition(easing) || Array.isArray(easing) && easing.every(isWaapiSupportedEasing));
}
const cubicBezierAsString = ([a, b, c, d]) => `cubic-bezier(${a}, ${b}, ${c}, ${d})`;
const supportedWaapiEasing = {
linear: "linear",
ease: "ease",
easeIn: "ease-in",
easeOut: "ease-out",
easeInOut: "ease-in-out",
circIn: cubicBezierAsString([0, 0.65, 0.55, 1]),
circOut: cubicBezierAsString([0.55, 0, 1, 0.45]),
backIn: cubicBezierAsString([0.31, 0.01, 0.66, -0.59]),
backOut: cubicBezierAsString([0.33, 1.53, 0.69, 0.99])
};
function mapEasingToNativeEasing(easing) {
if (!easing)
return void 0;
return isBezierDefinition(easing) ? cubicBezierAsString(easing) : Array.isArray(easing) ? easing.map(mapEasingToNativeEasing) : supportedWaapiEasing[easing];
}
function animateStyle(element, valueName, keyframes2, { delay = 0, duration, repeat = 0, repeatType = "loop", ease: ease2, times } = {}) {
const keyframeOptions = { [valueName]: keyframes2 };
if (times)
keyframeOptions.offset = times;
const easing = mapEasingToNativeEasing(ease2);
if (Array.isArray(easing))
keyframeOptions.easing = easing;
return element.animate(keyframeOptions, {
delay,
duration,
easing: !Array.isArray(easing) ? easing : "linear",
fill: "both",
iterations: repeat + 1,
direction: repeatType === "reverse" ? "alternate" : "normal"
});
}
function getFinalKeyframe(keyframes2, { repeat, repeatType = "loop" }) {
const index = repeat && repeatType !== "loop" && repeat % 2 === 1 ? 0 : keyframes2.length - 1;
return keyframes2[index];
}
const calcBezier = (t, a1, a2) => (((1 - 3 * a2 + 3 * a1) * t + (3 * a2 - 6 * a1)) * t + 3 * a1) * t;
const subdivisionPrecision = 1e-7;
const subdivisionMaxIterations = 12;
function binarySubdivide(x, lowerBound, upperBound, mX1, mX2) {
let currentX;
let currentT;
let i = 0;
do {
currentT = lowerBound + (upperBound - lowerBound) / 2;
currentX = calcBezier(currentT, mX1, mX2) - x;
if (currentX > 0) {
upperBound = currentT;
} else {
lowerBound = currentT;
}
} while (Math.abs(currentX) > subdivisionPrecision && ++i < subdivisionMaxIterations);
return currentT;
}
function cubicBezier(mX1, mY1, mX2, mY2) {
if (mX1 === mY1 && mX2 === mY2)
return noop;
const getTForX = (aX) => binarySubdivide(aX, 0, 1, mX1, mX2);
return (t) => t === 0 || t === 1 ? t : calcBezier(getTForX(t), mY1, mY2);
}
const easeIn = cubicBezier(0.42, 0, 1, 1);
const easeOut = cubicBezier(0, 0, 0.58, 1);
const easeInOut = cubicBezier(0.42, 0, 0.58, 1);
const isEasingArray = (ease2) => {
return Array.isArray(ease2) && typeof ease2[0] !== "number";
};
const mirrorEasing = (easing) => (p) => p <= 0.5 ? easing(2 * p) / 2 : (2 - easing(2 * (1 - p))) / 2;
const reverseEasing = (easing) => (p) => 1 - easing(1 - p);
const circIn = (p) => 1 - Math.sin(Math.acos(p));
const circOut = reverseEasing(circIn);
const circInOut = mirrorEasing(circIn);
const backOut = cubicBezier(0.33, 1.53, 0.69, 0.99);
const backIn = reverseEasing(backOut);
const backInOut = mirrorEasing(backIn);
const anticipate = (p) => (p *= 2) < 1 ? 0.5 * backIn(p) : 0.5 * (2 - Math.pow(2, -10 * (p - 1)));
const easingLookup = {
linear: noop,
easeIn,
easeInOut,
easeOut,
circIn,
circInOut,
circOut,
backIn,
backInOut,
backOut,
anticipate
};
const easingDefinitionToFunction = (definition) => {
if (Array.isArray(definition)) {
invariant(definition.length === 4, `Cubic bezier arrays must contain four numerical values.`);
const [x1, y1, x2, y2] = definition;
return cubicBezier(x1, y1, x2, y2);
} else if (typeof definition === "string") {
invariant(easingLookup[definition] !== void 0, `Invalid easing type '${definition}'`);
return easingLookup[definition];
}
return definition;
};
const isColorString = (type, testProp) => (v) => {
return Boolean(isString(v) && singleColorRegex.test(v) && v.startsWith(type) || testProp && Object.prototype.hasOwnProperty.call(v, testProp));
};
const splitColor = (aName, bName, cName) => (v) => {
if (!isString(v))
return v;
const [a, b, c, alpha2] = v.match(floatRegex);
return {
[aName]: parseFloat(a),
[bName]: parseFloat(b),
[cName]: parseFloat(c),
alpha: alpha2 !== void 0 ? parseFloat(alpha2) : 1
};
};
const clampRgbUnit = (v) => clamp(0, 255, v);
const rgbUnit = {
...number,
transform: (v) => Math.round(clampRgbUnit(v))
};
const rgba = {
test: isColorString("rgb", "red"),
parse: splitColor("red", "green", "blue"),
transform: ({ red, green, blue, alpha: alpha$1 = 1 }) => "rgba(" + rgbUnit.transform(red) + ", " + rgbUnit.transform(green) + ", " + rgbUnit.transform(blue) + ", " + sanitize(alpha.transform(alpha$1)) + ")"
};
function parseHex(v) {
let r = "";
let g = "";
let b = "";
let a = "";
if (v.length > 5) {
r = v.substring(1, 3);
g = v.substring(3, 5);
b = v.substring(5, 7);
a = v.substring(7, 9);
} else {
r = v.substring(1, 2);
g = v.substring(2, 3);
b = v.substring(3, 4);
a = v.substring(4, 5);
r += r;
g += g;
b += b;
a += a;
}
return {
red: parseInt(r, 16),
green: parseInt(g, 16),
blue: parseInt(b, 16),
alpha: a ? parseInt(a, 16) / 255 : 1
};
}
const hex = {
test: isColorString("#"),
parse: parseHex,
transform: rgba.transform
};
const hsla = {
test: isColorString("hsl", "hue"),
parse: splitColor("hue", "saturation", "lightness"),
transform: ({ hue, saturation, lightness, alpha: alpha$1 = 1 }) => {
return "hsla(" + Math.round(hue) + ", " + percent.transform(sanitize(saturation)) + ", " + percent.transform(sanitize(lightness)) + ", " + sanitize(alpha.transform(alpha$1)) + ")";
}
};
const color = {
test: (v) => rgba.test(v) || hex.test(v) || hsla.test(v),
parse: (v) => {
if (rgba.test(v)) {
return rgba.parse(v);
} else if (hsla.test(v)) {
return hsla.parse(v);
} else {
return hex.parse(v);
}
},
transform: (v) => {
return isString(v) ? v : v.hasOwnProperty("red") ? rgba.transform(v) : hsla.transform(v);
}
};
const mix = (from, to, progress2) => -progress2 * from + progress2 * to + from;
function hueToRgb(p, q, t) {
if (t < 0)
t += 1;
if (t > 1)
t -= 1;
if (t < 1 / 6)
return p + (q - p) * 6 * t;
if (t < 1 / 2)
return q;
if (t < 2 / 3)
return p + (q - p) * (2 / 3 - t) * 6;
return p;
}
function hslaToRgba({ hue, saturation, lightness, alpha: alpha2 }) {
hue /= 360;
saturation /= 100;
lightness /= 100;
let red = 0;
let green = 0;
let blue = 0;
if (!saturation) {
red = green = blue = lightness;
} else {
const q = lightness < 0.5 ? lightness * (1 + saturation) : lightness + saturation - lightness * saturation;
const p = 2 * lightness - q;
red = hueToRgb(p, q, hue + 1 / 3);
green = hueToRgb(p, q, hue);
blue = hueToRgb(p, q, hue - 1 / 3);
}
return {
red: Math.round(red * 255),
green: Math.round(green * 255),
blue: Math.round(blue * 255),
alpha: alpha2
};
}
const mixLinearColor = (from, to, v) => {
const fromExpo = from * from;
return Math.sqrt(Math.max(0, v * (to * to - fromExpo) + fromExpo));
};
const colorTypes = [hex, rgba, hsla];
const getColorType = (v) => colorTypes.find((type) => type.test(v));
function asRGBA(color2) {
const type = getColorType(color2);
invariant(Boolean(type), `'${color2}' is not an animatable color. Use the equivalent color code instead.`);
let model = type.parse(color2);
if (type === hsla) {
model = hslaToRgba(model);
}
return model;
}
const mixColor = (from, to) => {
const fromRGBA = asRGBA(from);
const toRGBA = asRGBA(to);
const blended = { ...fromRGBA };
return (v) => {
blended.red = mixLinearColor(fromRGBA.red, toRGBA.red, v);
blended.green = mixLinearColor(fromRGBA.green, toRGBA.green, v);
blended.blue = mixLinearColor(fromRGBA.blue, toRGBA.blue, v);
blended.alpha = mix(fromRGBA.alpha, toRGBA.alpha, v);
return rgba.transform(blended);
};
};
function test(v) {
var _a, _b;
return isNaN(v) && isString(v) && (((_a = v.match(floatRegex)) === null || _a === void 0 ? void 0 : _a.length) || 0) + (((_b = v.match(colorRegex)) === null || _b === void 0 ? void 0 : _b.length) || 0) > 0;
}
const cssVarTokeniser = {
regex: cssVariableRegex,
countKey: "Vars",
token: "${v}",
parse: noop
};
const colorTokeniser = {
regex: colorRegex,
countKey: "Colors",
token: "${c}",
parse: color.parse
};
const numberTokeniser = {
regex: floatRegex,
countKey: "Numbers",
token: "${n}",
parse: number.parse
};
function tokenise(info, { regex, countKey, token, parse }) {
const matches = info.tokenised.match(regex);
if (!matches)
return;
info["num" + countKey] = matches.length;
info.tokenised = info.tokenised.replace(regex, token);
info.values.push(...matches.map(parse));
}
function analyseComplexValue(value) {
const originalValue = value.toString();
const info = {
value: originalValue,
tokenised: originalValue,
values: [],
numVars: 0,
numColors: 0,
numNumbers: 0
};
if (info.value.includes("var(--"))
tokenise(info, cssVarTokeniser);
tokenise(info, colorTokeniser);
tokenise(info, numberTokeniser);
return info;
}
function parseComplexValue(v) {
return analyseComplexValue(v).values;
}
function createTransformer(source) {
const { values, numColors, numVars, tokenised } = analyseComplexValue(source);
const numValues = values.length;
return (v) => {
let output = tokenised;
for (let i = 0; i < numValues; i++) {
if (i < numVars) {
output = output.replace(cssVarTokeniser.token, v[i]);
} else if (i < numVars + numColors) {
output = output.replace(colorTokeniser.token, color.transform(v[i]));
} else {
output = output.replace(numberTokeniser.token, sanitize(v[i]));
}
}
return output;
};
}
const convertNumbersToZero = (v) => typeof v === "number" ? 0 : v;
function getAnimatableNone$1(v) {
const parsed = parseComplexValue(v);
const transformer = createTransformer(v);
return transformer(parsed.map(convertNumbersToZero));
}
const complex = {
test,
parse: parseComplexValue,
createTransformer,
getAnimatableNone: getAnimatableNone$1
};
const mixImmediate = (origin, target) => (p) => `${p > 0 ? target : origin}`;
function getMixer(origin, target) {
if (typeof origin === "number") {
return (v) => mix(origin, target, v);
} else if (color.test(origin)) {
return mixColor(origin, target);
} else {
return origin.startsWith("var(") ? mixImmediate(origin, target) : mixComplex(origin, target);
}
}
const mixArray = (from, to) => {
const output = [...from];
const numValues = output.length;
const blendValue = from.map((fromThis, i) => getMixer(fromThis, to[i]));
return (v) => {
for (let i = 0; i < numValues; i++) {
output[i] = blendValue[i](v);
}
return output;
};
};
const mixObject = (origin, target) => {
const output = { ...origin, ...target };
const blendValue = {};
for (const key in output) {
if (origin[key] !== void 0 && target[key] !== void 0) {
blendValue[key] = getMixer(origin[key], target[key]);
}
}
return (v) => {
for (const key in blendValue) {
output[key] = blendValue[key](v);
}
return output;
};
};
const mixComplex = (origin, target) => {
const template = complex.createTransformer(target);
const originStats = analyseComplexValue(origin);
const targetStats = analyseComplexValue(target);
const canInterpolate = originStats.numVars === targetStats.numVars && originStats.numColors === targetStats.numColors && originStats.numNumbers >= targetStats.numNumbers;
if (canInterpolate) {
return pipe(mixArray(originStats.values, targetStats.values), template);
} else {
warning(true, `Complex values '${origin}' and '${target}' too different to mix. Ensure all colors are of the same type, and that each contains the same quantity of number and color values. Falling back to instant transition.`);
return mixImmediate(origin, target);
}
};
const progress = (from, to, value) => {
const toFromDifference = to - from;
return toFromDifference === 0 ? 1 : (value - from) / toFromDifference;
};
const mixNumber = (from, to) => (p) => mix(from, to, p);
function detectMixerFactory(v) {
if (typeof v === "number") {
return mixNumber;
} else if (typeof v === "string") {
return color.test(v) ? mixColor : mixComplex;
} else if (Array.isArray(v)) {
return mixArray;
} else if (typeof v === "object") {
return mixObject;
}
return mixNumber;
}
function createMixers(output, ease2, customMixer) {
const mixers = [];
const mixerFactory = customMixer || detectMixerFactory(output[0]);
const numMixers = output.length - 1;
for (let i = 0; i < numMixers; i++) {
let mixer = mixerFactory(output[i], output[i + 1]);
if (ease2) {
const easingFunction = Array.isArray(ease2) ? ease2[i] || noop : ease2;
mixer = pipe(easingFunction, mixer);
}
mixers.push(mixer);
}
return mixers;
}
function interpolate(input, output, { clamp: isClamp = true, ease: ease2, mixer } = {}) {
const inputLength = input.length;
invariant(inputLength === output.length, "Both input and output ranges must be the same length");
if (inputLength === 1)
return () => output[0];
if (input[0] > input[inputLength - 1]) {
input = [...input].reverse();
output = [...output].reverse();
}
const mixers = createMixers(output, ease2, mixer);
const numMixers = mixers.length;
const interpolator = (v) => {
let i = 0;
if (numMixers > 1) {
for (; i < input.length - 2; i++) {
if (v < input[i + 1])
break;
}
}
const progressInRange = progress(input[i], input[i + 1], v);
return mixers[i](progressInRange);
};
return isClamp ? (v) => interpolator(clamp(input[0], input[inputLength - 1], v)) : interpolator;
}
function fillOffset(offset, remaining) {
const min = offset[offset.length - 1];
for (let i = 1; i <= remaining; i++) {
const offsetProgress = progress(0, remaining, i);
offset.push(mix(min, 1, offsetProgress));
}
}
function defaultOffset(arr) {
const offset = [0];
fillOffset(offset, arr.length - 1);
return offset;
}
function convertOffsetToTimes(offset, duration) {
return offset.map((o) => o * duration);
}
function defaultEasing(values, easing) {
return values.map(() => easing || easeInOut).splice(0, values.length - 1);
}
function keyframes({ duration = 300, keyframes: keyframeValues, times, ease: ease2 = "easeInOut" }) {
const easingFunctions = isEasingArray(ease2) ? ease2.map(easingDefinitionToFunction) : easingDefinitionToFunction(ease2);
const state = {
done: false,
value: keyframeValues[0]
};
const absoluteTimes = convertOffsetToTimes(
// Only use the provided offsets if they're the correct length
// TODO Maybe we should warn here if there's a length mismatch
times && times.length === keyframeValues.length ? times : defaultOffset(keyframeValues),
duration
);
const mapTimeToKeyframe = interpolate(absoluteTimes, keyframeValues, {
ease: Array.isArray(easingFunctions) ? easingFunctions : defaultEasing(keyframeValues, easingFunctions)
});
return {
calculatedDuration: duration,
next: (t) => {
state.value = mapTimeToKeyframe(t);
state.done = t >= duration;
return state;
}
};
}
function velocityPerSecond(velocity, frameDuration) {
return frameDuration ? velocity * (1e3 / frameDuration) : 0;
}
const velocitySampleDuration = 5;
function calcGeneratorVelocity(resolveValue, t, current) {
const prevT = Math.max(t - velocitySampleDuration, 0);
return velocityPerSecond(current - resolveValue(prevT), t - prevT);
}
const safeMin = 1e-3;
const minDuration = 0.01;
const maxDuration$1 = 10;
const minDamping = 0.05;
const maxDamping = 1;
function findSpring({ duration = 800, bounce = 0.25, velocity = 0, mass = 1 }) {
let envelope;
let derivative;
warning(duration <= secondsToMilliseconds(maxDuration$1), "Spring duration must be 10 seconds or less");
let dampingRatio = 1 - bounce;
dampingRatio = clamp(minDamping, maxDamping, dampingRatio);
duration = clamp(minDuration, maxDuration$1, millisecondsToSeconds(duration));
if (dampingRatio < 1) {
envelope = (undampedFreq2) => {
const exponentialDecay = undampedFreq2 * dampingRatio;
const delta = exponentialDecay * duration;
const a = exponentialDecay - velocity;
const b = calcAngularFreq(undampedFreq2, dampingRatio);
const c = Math.exp(-delta);
return safeMin - a / b * c;
};
derivative = (undampedFreq2) => {
const exponentialDecay = undampedFreq2 * dampingRatio;
const delta = exponentialDecay * duration;
const d = delta * velocity + velocity;
const e = Math.pow(dampingRatio, 2) * Math.pow(undampedFreq2, 2) * duration;
const f = Math.exp(-delta);
const g = calcAngularFreq(Math.pow(undampedFreq2, 2), dampingRatio);
const factor = -envelope(undampedFreq2) + safeMin > 0 ? -1 : 1;
return factor * ((d - e) * f) / g;
};
} else {
envelope = (undampedFreq2) => {
const a = Math.exp(-undampedFreq2 * duration);
const b = (undampedFreq2 - velocity) * duration + 1;
return -safeMin + a * b;
};
derivative = (undampedFreq2) => {
const a = Math.exp(-undampedFreq2 * duration);
const b = (velocity - undampedFreq2) * (duration * duration);
return a * b;
};
}
const initialGuess = 5 / duration;
const undampedFreq = approximateRoot(envelope, derivative, initialGuess);
duration = secondsToMilliseconds(duration);
if (isNaN(undampedFreq)) {
return {
stiffness: 100,
damping: 10,
duration
};
} else {
const stiffness = Math.pow(undampedFreq, 2) * mass;
return {
stiffness,
damping: dampingRatio * 2 * Math.sqrt(mass * stiffness),
duration
};
}
}
const rootIterations = 12;
function approximateRoot(envelope, derivative, initialGuess) {
let result = initialGuess;
for (let i = 1; i < rootIterations; i++) {
result = result - envelope(result) / derivative(result);
}
return result;
}
function calcAngularFreq(undampedFreq, dampingRatio) {
return undampedFreq * Math.sqrt(1 - dampingRatio * dampingRatio);
}
const durationKeys = ["duration", "bounce"];
const physicsKeys = ["stiffness", "damping", "mass"];
function isSpringType(options, keys) {
return keys.some((key) => options[key] !== void 0);
}
function getSpringOptions(options) {
let springOptions = {
velocity: 0,
stiffness: 100,
damping: 10,
mass: 1,
isResolvedFromDuration: false,
...options
};
if (!isSpringType(options, physicsKeys) && isSpringType(options, durationKeys)) {
const derived = findSpring(options);
springOptions = {
...springOptions,
...derived,
mass: 1
};
springOptions.isResolvedFromDuration = true;
}
return springOptions;
}
function spring({ keyframes: keyframes2, restDelta, restSpeed, ...options }) {
const origin = keyframes2[0];
const target = keyframes2[keyframes2.length - 1];
const state = { done: false, value: origin };
const { stiffness, damping, mass, duration, velocity, isResolvedFromDuration } = getSpringOptions({
...options,
velocity: -millisecondsToSeconds(options.velocity || 0)
});
const initialVelocity = velocity || 0;
const dampingRatio = damping / (2 * Math.sqrt(stiffness * mass));
const initialDelta = target - origin;
const undampedAngularFreq = millisecondsToSeconds(Math.sqrt(stiffness / mass));
const isGranularScale = Math.abs(initialDelta) < 5;
restSpeed || (restSpeed = isGranularScale ? 0.01 : 2);
restDelta || (restDelta = isGranularScale ? 5e-3 : 0.5);
let resolveSpring;
if (dampingRatio < 1) {
const angularFreq = calcAngularFreq(undampedAngularFreq, dampingRatio);
resolveSpring = (t) => {
const envelope = Math.exp(-dampingRatio * undampedAngularFreq * t);
return target - envelope * ((initialVelocity + dampingRatio * undampedAngularFreq * initialDelta) / angularFreq * Math.sin(angularFreq * t) + initialDelta * Math.cos(angularFreq * t));
};
} else if (dampingRatio === 1) {
resolveSpring = (t) => target - Math.exp(-undampedAngularFreq * t) * (initialDelta + (initialVelocity + undampedAngularFreq * initialDelta) * t);
} else {
const dampedAngularFreq = undampedAngularFreq * Math.sqrt(dampingRatio * dampingRatio - 1);
resolveSpring = (t) => {
const envelope = Math.exp(-dampingRatio * undampedAngularFreq * t);
const freqForT = Math.min(dampedAngularFreq * t, 300);
return target - envelope * ((initialVelocity + dampingRatio * undampedAngularFreq * initialDelta) * Math.sinh(freqForT) + dampedAngularFreq * initialDelta * Math.cosh(freqForT)) / dampedAngularFreq;
};
}
return {
calculatedDuration: isResolvedFromDuration ? duration || null : null,
next: (t) => {
const current = resolveSpring(t);
if (!isResolvedFromDuration) {
let currentVelocity = initialVelocity;
if (t !== 0) {
if (dampingRatio < 1) {
currentVelocity = calcGeneratorVelocity(resolveSpring, t, current);
} else {
currentVelocity = 0;
}
}
const isBelowVelocityThreshold = Math.abs(currentVelocity) <= restSpeed;
const isBelowDisplacementThreshold = Math.abs(target - current) <= restDelta;
state.done = isBelowVelocityThreshold && isBelowDisplacementThreshold;
} else {
state.done = t >= duration;
}
state.value = state.done ? target : current;
return state;
}
};
}
function inertia({ keyframes: keyframes2, velocity = 0, power = 0.8, timeConstant = 325, bounceDamping = 10, bounceStiffness = 500, modifyTarget, min, max, restDelta = 0.5, restSpeed }) {
const origin = keyframes2[0];
const state = {
done: false,
value: origin
};
const isOutOfBounds = (v) => min !== void 0 && v < min || max !== void 0 && v > max;
const nearestBoundary = (v) => {
if (min === void 0)
return max;
if (max === void 0)
return min;
return Math.abs(min - v) < Math.abs(max - v) ? min : max;
};
let amplitude = power * velocity;
const ideal = origin + amplitude;
const target = modifyTarget === void 0 ? ideal : modifyTarget(ideal);
if (target !== ideal)
amplitude = target - origin;
const calcDelta = (t) => -amplitude * Math.exp(-t / timeConstant);
const calcLatest = (t) => target + calcDelta(t);
const applyFriction = (t) => {
const delta = calcDelta(t);
const latest = calcLatest(t);
state.done = Math.abs(delta) <= restDelta;
state.value = state.done ? target : latest;
};
let timeReachedBoundary;
let spring$1;
const checkCatchBoundary = (t) => {
if (!isOutOfBounds(state.value))
return;
timeReachedBoundary = t;
spring$1 = spring({
keyframes: [state.value, nearestBoundary(state.value)],
velocity: calcGeneratorVelocity(calcLatest, t, state.value),
damping: bounceDamping,
stiffness: bounceStiffness,
restDelta,
restSpeed
});
};
checkCatchBoundary(0);
return {
calculatedDuration: null,
next: (t) => {
let hasUpdatedFrame = false;
if (!spring$1 && timeReachedBoundary === void 0) {
hasUpdatedFrame = true;
applyFriction(t);
checkCatchBoundary(t);
}
if (timeReachedBoundary !== void 0 && t > timeReachedBoundary) {
return spring$1.next(t - timeReachedBoundary);
} else {
!hasUpdatedFrame && applyFriction(t);
return state;
}
}
};
}
const frameloopDriver = (update) => {
const passTimestamp = ({ timestamp }) => update(timestamp);
return {
start: () => frame.update(passTimestamp, true),
stop: () => cancelFrame(passTimestamp),
/**
* If we're processing this frame we can use the
* framelocked timestamp to keep things in sync.
*/
now: () => frameData.isProcessing ? frameData.timestamp : performance.now()
};
};
const maxGeneratorDuration = 2e4;
function calcGeneratorDuration(generator) {
let duration = 0;
const timeStep = 50;
let state = generator.next(duration);
while (!state.done && duration < maxGeneratorDuration) {
duration += timeStep;
state = generator.next(duration);
}
return duration >= maxGeneratorDuration ? Infinity : duration;
}
const types = {
decay: inertia,
inertia,
tween: keyframes,
keyframes,
spring
};
function animateValue({ autoplay = true, delay = 0, driver = frameloopDriver, keyframes: keyframes$1, type = "keyframes", repeat = 0, repeatDelay = 0, repeatType = "loop", onPlay, onStop, onComplete, onUpdate, ...options }) {
let speed = 1;
let hasStopped = false;
let resolveFinishedPromise;
let currentFinishedPromise;
const updateFinishedPromise = () => {
currentFinishedPromise = new Promise((resolve) => {
resolveFinishedPromise = resolve;
});
};
updateFinishedPromise();
let animationDriver;
const generatorFactory = types[type] || keyframes;
let mapNumbersToKeyframes;
if (generatorFactory !== keyframes && typeof keyframes$1[0] !== "number") {
if (process.env.NODE_ENV !== "production") {
invariant(keyframes$1.length === 2, `Only two keyframes currently supported with spring and inertia animations. Trying to animate ${keyframes$1}`);
}
mapNumbersToKeyframes = interpolate([0, 100], keyframes$1, {
clamp: false
});
keyframes$1 = [0, 100];
}
const generator = generatorFactory({ ...options, keyframes: keyframes$1 });
let mirroredGenerator;
if (repeatType === "mirror") {
mirroredGenerator = generatorFactory({
...options,
keyframes: [...keyframes$1].reverse(),
velocity: -(options.velocity || 0)
});
}
let playState = "idle";
let holdTime = null;
let startTime = null;
let cancelTime = null;
if (generator.calculatedDuration === null && repeat) {
generator.calculatedDuration = calcGeneratorDuration(generator);
}
const { calculatedDuration } = generator;
let resolvedDuration = Infinity;
let totalDuration = Infinity;
if (calculatedDuration !== null) {
resolvedDuration = calculatedDuration + repeatDelay;
totalDuration = resolvedDuration * (repeat + 1) - repeatDelay;
}
let currentTime = 0;
const tick = (timestamp) => {
if (startTime === null)
return;
if (speed > 0)
startTime = Math.min(startTime, timestamp);
if (speed < 0)
startTime = Math.min(timestamp - totalDuration / speed, startTime);
if (holdTime !== null) {
currentTime = holdTime;
} else {
currentTime = Math.round(timestamp - startTime) * speed;
}
const timeWithoutDelay = currentTime - delay * (speed >= 0 ? 1 : -1);
const isInDelayPhase = speed >= 0 ? timeWithoutDelay < 0 : timeWithoutDelay > totalDuration;
currentTime = Math.max(timeWithoutDelay, 0);
if (playState === "finished" && holdTime === null) {
currentTime = totalDuration;
}
let elapsed = currentTime;
let frameGenerator = generator;
if (repeat) {
const progress2 = Math.min(currentTime, totalDuration) / resolvedDuration;
let currentIteration = Math.floor(progress2);
let iterationProgress = progress2 % 1;
if (!iterationProgress && progress2 >= 1) {
iterationProgress = 1;
}
iterationProgress === 1 && currentIteration--;
currentIteration = Math.min(currentIteration, repeat + 1);
const isOddIteration = Boolean(currentIteration % 2);
if (isOddIteration) {
if (repeatType === "reverse") {
iterationProgress = 1 - iterationProgress;
if (repeatDelay) {
iterationProgress -= repeatDelay / resolvedDuration;
}
} else if (repeatType === "mirror") {
frameGenerator = mirroredGenerator;
}
}
elapsed = clamp(0, 1, iterationProgress) * resolvedDuration;
}
const state = isInDelayPhase ? { done: false, value: keyframes$1[0] } : frameGenerator.next(elapsed);
if (mapNumbersToKeyframes) {
state.value = mapNumbersToKeyframes(state.value);
}
let { done } = state;
if (!isInDelayPhase && calculatedDuration !== null) {
done = speed >= 0 ? currentTime >= totalDuration : currentTime <= 0;
}
const isAnimationFinished = holdTime === null && (playState === "finished" || playState === "running" && done);
if (onUpdate) {
onUpdate(state.value);
}
if (isAnimationFinished) {
finish();
}
return state;
};
const stopAnimationDriver = () => {
animationDriver && animationDriver.stop();
animationDriver = void 0;
};
const cancel = () => {
playState = "idle";
stopAnimationDriver();
resolveFinishedPromise();
updateFinishedPromise();
startTime = cancelTime = null;
};
const finish = () => {
playState = "finished";
onComplete && onComplete();
stopAnimationDriver();
resolveFinishedPromise();
};
const play = () => {
if (hasStopped)
return;
if (!animationDriver)
animationDriver = driver(tick);
const now = animationDriver.now();
onPlay && onPlay();
if (holdTime !== null) {
startTime = now - holdTime;
} else if (!startTime || playState === "finished") {
startTime = now;
}
if (playState === "finished") {
updateFinishedPromise();
}
cancelTime = startTime;
holdTime = null;
playState = "running";
animationDriver.start();
};
if (autoplay) {
play();
}
const controls = {
then(resolve, reject) {
return currentFinishedPromise.then(resolve, reject);
},
get time() {
return millisecondsToSeconds(currentTime);
},
set time(newTime) {
newTime = secondsToMilliseconds(newTime);
currentTime = newTime;
if (holdTime !== null || !animationDriver || speed === 0) {
holdTime = newTime;
} else {
startTime = animationDriver.now() - newTime / speed;
}
},
get duration() {
const duration = generator.calculatedDuration === null ? calcGeneratorDuration(generator) : generator.calculatedDuration;
return millisecondsToSeconds(duration);
},
get speed() {
return speed;
},
set speed(newSpeed) {
if (newSpeed === speed || !animationDriver)
return;
speed = newSpeed;
controls.time = millisecondsToSeconds(currentTime);
},
get state() {
return playState;
},
play,
pause: () => {
playState = "paused";
holdTime = currentTime;
},
stop: () => {
hasStopped = true;
if (playState === "idle")
return;
playState = "idle";
onStop && onStop();
cancel();
},
cancel: () => {
if (cancelTime !== null)
tick(cancelTime);
cancel();
},
complete: () => {
playState = "finished";
},
sample: (elapsed) => {
startTime = 0;
return tick(elapsed);
}
};
return controls;
}
function memo(callback) {
let result;
return () => {
if (result === void 0)
result = callback();
return result;
};
}
const supportsWaapi = memo(() => Object.hasOwnProperty.call(Element.prototype, "animate"));
const acceleratedValues = /* @__PURE__ */ new Set([
"opacity",
"clipPath",
"filter",
"transform",
"backgroundColor"
]);
const sampleDelta = 10;
const maxDuration = 2e4;
const requiresPregeneratedKeyframes = (valueName, options) => options.type === "spring" || valueName === "backgroundColor" || !isWaapiSupportedEasing(options.ease);
function createAcceleratedAnimation(value, valueName, { onUpdate, onComplete, ...options }) {
const canAccelerateAnimation = supportsWaapi() && acceleratedValues.has(valueName) && !options.repeatDelay && options.repeatType !== "mirror" && options.damping !== 0 && options.type !== "inertia";
if (!canAccelerateAnimation)
return false;
let hasStopped = false;
let resolveFinishedPromise;
let currentFinishedPromise;
let pendingCancel = false;
const updateFinishedPromise = () => {
currentFinishedPromise = new Promise((resolve) => {
resolveFinishedPromise = resolve;
});
};
updateFinishedPromise();
let { keyframes: keyframes2, duration = 300, ease: ease2, times } = options;
if (requiresPregeneratedKeyframes(valueName, options)) {
const sampleAnimation = animateValue({
...options,
repeat: 0,
delay: 0
});
let state = { done: false, value: keyframes2[0] };
const pregeneratedKeyframes = [];
let t = 0;
while (!state.done && t < maxDuration) {
state = sampleAnimation.sample(t);
pregeneratedKeyframes.push(state.value);
t += sampleDelta;
}
times = void 0;
keyframes2 = pregeneratedKeyframes;
duration = t - sampleDelta;
ease2 = "linear";
}
const animation = animateStyle(value.owner.current, valueName, keyframes2, {
...options,
duration,
/**
* This function is currently not called if ease is provided
* as a function so the cast is safe.
*
* However it would be possible for a future refinement to port
* in easing pregeneration from Motion One for browsers that
* support the upcoming `linear()` easing function.
*/
ease: ease2,
times
});
const cancelAnimation = () => {
pendingCancel = false;
animation.cancel();
};
const safeCancel = () => {
pendingCancel = true;
frame.update(cancelAnimation);
resolveFinishedPromise();
updateFinishedPromise();
};
animation.onfinish = () => {
if (pendingCancel)
return;
value.set(getFinalKeyframe(keyframes2, options));
onComplete && onComplete();
safeCancel();
};
const controls = {
then(resolve, reject) {
return currentFinishedPromise.then(resolve, reject);
},
attachTimeline(timeline) {
animation.timeline = timeline;
animation.onfinish = null;
return noop;
},
get time() {
return millisecondsToSeconds(animation.currentTime || 0);
},
set time(newTime) {
animation.currentTime = secondsToMilliseconds(newTime);
},
get speed() {
return animation.playbackRate;
},
set speed(newSpeed) {
animation.playbackRate = newSpeed;
},
get duration() {
return millisecondsToSeconds(duration);
},
play: () => {
if (hasStopped)
return;
animation.play();
cancelFrame(cancelAnimation);
},
pause: () => animation.pause(),
stop: () => {
hasStopped = true;
if (animation.playState === "idle")
return;
const { currentTime } = animation;
if (currentTime) {
const sampleAnimation = animateValue({
...options,
autoplay: false
});
value.setWithVelocity(sampleAnimation.sample(currentTime - sampleDelta).value, sampleAnimation.sample(currentTime).value, sampleDelta);
}
safeCancel();
},
complete: () => {
if (pendingCancel)
return;
animation.finish();
},
cancel: safeCancel
};
return controls;
}
function createInstantAnimation({ keyframes: keyframes2, delay, onUpdate, onComplete }) {
const setValue = () => {
onUpdate && onUpdate(keyframes2[keyframes2.length - 1]);
onComplete && onComplete();
return {
time: 0,
speed: 1,
duration: 0,
play: noop,
pause: noop,
stop: noop,
then: (resolve) => {
resolve();
return Promise.resolve();
},
cancel: noop,
complete: noop
};
};
return delay ? animateValue({
keyframes: [0, 1],
duration: 0,
delay,
onComplete: setValue
}) : setValue();
}
const underDampedSpring = {
type: "spring",
stiffness: 500,
damping: 25,
restSpeed: 10
};
const criticallyDampedSpring = (target) => ({
type: "spring",
stiffness: 550,
damping: target === 0 ? 2 * Math.sqrt(550) : 30,
restSpeed: 10
});
const keyframesTransition = {
type: "keyframes",
duration: 0.8
};
const ease = {
type: "keyframes",
ease: [0.25, 0.1, 0.35, 1],
duration: 0.3
};
const getDefaultTransition = (valueKey, { keyframes: keyframes2 }) => {
if (keyframes2.length > 2) {
return keyframesTransition;
} else if (transformProps.has(valueKey)) {
return valueKey.startsWith("scale") ? criticallyDampedSpring(keyframes2[1]) : underDampedSpring;
}
return ease;
};
const isAnimatable = (key, value) => {
if (key === "zIndex")
return false;
if (typeof value === "number" || Array.isArray(value))
return true;
if (typeof value === "string" && // It's animatable if we have a string
(complex.test(value) || value === "0") && // And it contains numbers and/or colors
!value.startsWith("url(")) {
return true;
}
return false;
};
const maxDefaults = /* @__PURE__ */ new Set(["brightness", "contrast", "saturate", "opacity"]);
function applyDefaultFilter(v) {
const [name, value] = v.slice(0, -1).split("(");
if (name === "drop-shadow")
return v;
const [number2] = value.match(floatRegex) || [];
if (!number2)
return v;
const unit = value.replace(number2, "");
let defaultValue = maxDefaults.has(name) ? 1 : 0;
if (number2 !== value)
defaultValue *= 100;
return name + "(" + defaultValue + unit + ")";
}
const functionRegex = /([a-z-]*)\(.*?\)/g;
const filter = {
...complex,
getAnimatableNone: (v) => {
const functions = v.match(functionRegex);
return functions ? functions.map(applyDefaultFilter).join(" ") : v;
}
};
const defaultValueTypes = {
...numberValueTypes,
// Color props
color,
backgroundColor: color,
outlineColor: color,
fill: color,
stroke: color,
// Border props
borderColor: color,
borderTopColor: color,
borderRightColor: color,
borderBottomColor: color,
borderLeftColor: color,
filter,
WebkitFilter: filter
};
const getDefaultValueType = (key) => defaultValueTypes[key];
function getAnimatableNone(key, value) {
let defaultValueType = getDefaultValueType(key);
if (defaultValueType !== filter)
defaultValueType = complex;
return defaultValueType.getAnimatableNone ? defaultValueType.getAnimatableNone(value) : void 0;
}
const isZeroValueString = (v) => /^0[^.\s]+$/.test(v);
function isNone(value) {
if (typeof value === "number") {
return value === 0;
} else if (value !== null) {
return value === "none" || value === "0" || isZeroValueString(value);
}
}
function getKeyframes(value, valueName, target, transition) {
const isTargetAnimatable = isAnimatable(valueName, target);
let keyframes2;
if (Array.isArray(target)) {
keyframes2 = [...target];
} else {
keyframes2 = [null, target];
}
const defaultOrigin = transition.from !== void 0 ? transition.from : value.get();
let animatableTemplateValue = void 0;
const noneKeyframeIndexes = [];
for (let i = 0; i < keyframes2.length; i++) {
if (keyframes2[i] === null) {
keyframes2[i] = i === 0 ? defaultOrigin : keyframes2[i - 1];
}
if (isNone(keyframes2[i])) {
noneKeyframeIndexes.push(i);
}
if (typeof keyframes2[i] === "string" && keyframes2[i] !== "none" && keyframes2[i] !== "0") {
animatableTemplateValue = keyframes2[i];
}
}
if (isTargetAnimatable && noneKeyframeIndexes.length && animatableTemplateValue) {
for (let i = 0; i < noneKeyframeIndexes.length; i++) {
const index = noneKeyframeIndexes[i];
keyframes2[index] = getAnimatableNone(valueName, animatableTemplateValue);
}
}
return keyframes2;
}
function isTransitionDefined({ when, delay: _delay, delayChildren, staggerChildren, staggerDirection, repeat, repeatType, repeatDelay, from, elapsed, ...transition }) {
return !!Object.keys(transition).length;
}
function getValueTransition(transition, key) {
return transition[key] || transition["default"] || transition;
}
const MotionGlobalConfig = {
skipAnimations: false
};
const animateMotionValue = (valueName, value, target, transition = {}) => {
return (onComplete) => {
const valueTransition = getValueTransition(transition, valueName) || {};
const delay = valueTransition.delay || transition.delay || 0;
let { elapsed = 0 } = transition;
elapsed = elapsed - secondsToMilliseconds(delay);
const keyframes2 = getKeyframes(value, valueName, target, valueTransition);
const originKeyframe = keyframes2[0];
const targetKeyframe = keyframes2[keyframes2.length - 1];
const isOriginAnimatable = isAnimatable(valueName, originKeyframe);
const isTargetAnimatable = isAnimatable(valueName, targetKeyframe);
warning(isOriginAnimatable === isTargetAnimatable, `You are trying to animate ${valueName} from "${originKeyframe}" to "${targetKeyframe}". ${originKeyframe} is not an animatable value - to enable this animation set ${originKeyframe} to a value animatable to ${targetKeyframe} via the \`style\` property.`);
let options = {
keyframes: keyframes2,
velocity: value.getVelocity(),
ease: "easeOut",
...valueTransition,
delay: -elapsed,
onUpdate: (v) => {
value.set(v);
valueTransition.onUpdate && valueTransition.onUpdate(v);
},
onComplete: () => {
onComplete();
valueTransition.onComplete && valueTransition.onComplete();
}
};
if (!isTransitionDefined(valueTransition)) {
options = {
...options,
...getDefaultTransition(valueName, options)
};
}
if (options.duration) {
options.duration = secondsToMilliseconds(options.duration);
}
if (options.repeatDelay) {
options.repeatDelay = secondsToMilliseconds(options.repeatDelay);
}
if (!isOriginAnimatable || !isTargetAnimatable || instantAnimationState.current || valueTransition.type === false || MotionGlobalConfig.skipAnimations) {
return createInstantAnimation(options);
}
if (
/**
* If this is a handoff animation, the optimised animation will be running via
* WAAPI. Therefore, this animation must be JS to ensure it runs "under" the
* optimised animation.
*/
!transition.isHandoff && value.owner && value.owner.current instanceof HTMLElement && /**
* If we're outputting values to onUpdate then we can't use WAAPI as there's
* no way to read the value from WAAPI every frame.
*/
!value.owner.getProps().onUpdate
) {
const acceleratedAnimation = createAcceleratedAnimation(value, valueName, options);
if (acceleratedAnimation)
return acceleratedAnimation;
}
return animateValue(options);
};
};
function isWillChangeMotionValue(value) {
return Boolean(isMotionValue(value) && value.add);
}
const isNumericalString = (v) => /^\-?\d*\.?\d+$/.test(v);
function addUniqueItem(arr, item) {
if (arr.indexOf(item) === -1)
arr.push(item);
}
function removeItem(arr, item) {
const index = arr.indexOf(item);
if (index > -1)
arr.splice(index, 1);
}
class SubscriptionManager {
constructor() {
this.subscriptions = [];
}
add(handler) {
addUniqueItem(this.subscriptions, handler);
return () => removeItem(this.subscriptions, handler);
}
notify(a, b, c) {
const numSubscriptions = this.subscriptions.length;
if (!numSubscriptions)
return;
if (numSubscriptions === 1) {
this.subscriptions[0](a, b, c);
} else {
for (let i = 0; i < numSubscriptions; i++) {
const handler = this.subscriptions[i];
handler && handler(a, b, c);
}
}
}
getSize() {
return this.subscriptions.length;
}
clear() {
this.subscriptions.length = 0;
}
}
const warned = /* @__PURE__ */ new Set();
function warnOnce(condition, message, element) {
if (condition || warned.has(message))
return;
console.warn(message);
warned.add(message);
}
const isFloat = (value) => {
return !isNaN(parseFloat(value));
};
class MotionValue {
/**
* @param init - The initiating value
* @param config - Optional configuration options
*
* - `transformer`: A function to transform incoming values with.
*
* @internal
*/
constructor(init, options = {}) {
this.version = "10.18.0";
this.timeDelta = 0;
this.lastUpdated = 0;
this.canTrackVelocity = false;
this.events = {};
this.updateAndNotify = (v, render = true) => {
this.prev = this.current;
this.current = v;
const { delta, timestamp } = frameData;
if (this.lastUpdated !== timestamp) {
this.timeDelta = delta;
this.lastUpdated = timestamp;
frame.postRender(this.scheduleVelocityCheck);
}
if (this.prev !== this.current && this.events.change) {
this.events.change.notify(this.current);
}
if (this.events.velocityChange) {
this.events.velocityChange.notify(this.getVelocity());
}
if (render && this.events.renderRequest) {
this.events.renderRequest.notify(this.current);
}
};
this.scheduleVelocityCheck = () => frame.postRender(this.velocityCheck);
this.velocityCheck = ({ timestamp }) => {
if (timestamp !== this.lastUpdated) {
this.prev = this.current;
if (this.events.velocityChange) {
this.events.velocityChange.notify(this.getVelocity());
}
}
};
this.hasAnimated = false;
this.prev = this.current = init;
this.canTrackVelocity = isFloat(this.current);
this.owner = options.owner;
}
/**
* Adds a function that will be notified when the `MotionValue` is updated.
*
* It returns a function that, when called, will cancel the subscription.
*
* When calling `onChange` inside a React component, it should be wrapped with the
* `useEffect` hook. As it returns an unsubscribe function, this should be returned
* from the `useEffect` function to ensure you don't add duplicate subscribers..
*
* ```jsx
* export const MyComponent = () => {
* const x = useMotionValue(0)
* const y = useMotionValue(0)
* const opacity = useMotionValue(1)
*
* useEffect(() => {
* function updateOpacity() {
* const maxXY = Math.max(x.get(), y.get())
* const newOpacity = transform(maxXY, [0, 100], [1, 0])
* opacity.set(newOpacity)
* }
*
* const unsubscribeX = x.on("change", updateOpacity)
* const unsubscribeY = y.on("change", updateOpacity)
*
* return () => {
* unsubscribeX()
* unsubscribeY()
* }
* }, [])
*
* return <motion.div style={{ x }} />
* }
* ```
*
* @param subscriber - A function that receives the latest value.
* @returns A function that, when called, will cancel this subscription.
*
* @deprecated
*/
onChange(subscription) {
if (process.env.NODE_ENV !== "production") {
warnOnce(false, `value.onChange(callback) is deprecated. Switch to value.on("change", callback).`);
}
return this.on("change", subscription);
}
on(eventName, callback) {
if (!this.events[eventName]) {
this.events[eventName] = new SubscriptionManager();
}
const unsubscribe = this.events[eventName].add(callback);
if (eventName === "change") {
return () => {
unsubscribe();
frame.read(() => {
if (!this.events.change.getSize()) {
this.stop();
}
});
};
}
return unsubscribe;
}
clearListeners() {
for (const eventManagers in this.events) {
this.events[eventManagers].clear();
}
}
/**
* Attaches a passive effect to the `MotionValue`.
*
* @internal
*/
attach(passiveEffect, stopPassiveEffect) {
this.passiveEffect = passiveEffect;
this.stopPassiveEffect = stopPassiveEffect;
}
/**
* Sets the state of the `MotionValue`.
*
* @remarks
*
* ```jsx
* const x = useMotionValue(0)
* x.set(10)
* ```
*
* @param latest - Latest value to set.
* @param render - Whether to notify render subscribers. Defaults to `true`
*
* @public
*/
set(v, render = true) {
if (!render || !this.passiveEffect) {
this.updateAndNotify(v, render);
} else {
this.passiveEffect(v, this.updateAndNotify);
}
}
setWithVelocity(prev, current, delta) {
this.set(current);
this.prev = prev;
this.timeDelta = delta;
}
/**
* Set the state of the `MotionValue`, stopping any active animations,
* effects, and resets velocity to `0`.
*/
jump(v) {
this.updateAndNotify(v);
this.prev = v;
this.stop();
if (this.stopPassiveEffect)
this.stopPassiveEffect();
}
/**
* Returns the latest state of `MotionValue`
*
* @returns - The latest state of `MotionValue`
*
* @public
*/
get() {
return this.current;
}
/**
* @public
*/
getPrevious() {
return this.prev;
}
/**
* Returns the latest velocity of `MotionValue`
*
* @returns - The latest velocity of `MotionValue`. Returns `0` if the state is non-numerical.
*
* @public
*/
getVelocity() {
return this.canTrackVelocity ? (
// These casts could be avoided if parseFloat would be typed better
velocityPerSecond(parseFloat(this.current) - parseFloat(this.prev), this.timeDelta)
) : 0;
}
/**
* Registers a new animation to control this `MotionValue`. Only one
* animation can drive a `MotionValue` at one time.
*
* ```jsx
* value.start()
* ```
*
* @param animation - A function that starts the provided animation
*
* @internal
*/
start(startAnimation) {
this.stop();
return new Promise((resolve) => {
this.hasAnimated = true;
this.animation = startAnimation(resolve);
if (this.events.animationStart) {
this.events.animationStart.notify();
}
}).then(() => {
if (this.events.animationComplete) {
this.events.animationComplete.notify();
}
this.clearAnimation();
});
}
/**
* Stop the currently active animation.
*
* @public
*/
stop() {
if (this.animation) {
this.animation.stop();
if (this.events.animationCancel) {
this.events.animationCancel.notify();
}
}
this.clearAnimation();
}
/**
* Returns `true` if this value is currently animating.
*
* @public
*/
isAnimating() {
return !!this.animation;
}
clearAnimation() {
delete this.animation;
}
/**
* Destroy and clean up subscribers to this `MotionValue`.
*
* The `MotionValue` hooks like `useMotionValue` and `useTransform` automatically
* handle the lifecycle of the returned `MotionValue`, so this method is only necessary if you've manually
* created a `MotionValue` via the `motionValue` function.
*
* @public
*/
destroy() {
this.clearListeners();
this.stop();
if (this.stopPassiveEffect) {
this.stopPassiveEffect();
}
}
}
function motionValue(init, options) {
return new MotionValue(init, options);
}
const testValueType = (v) => (type) => type.test(v);
const auto = {
test: (v) => v === "auto",
parse: (v) => v
};
const dimensionValueTypes = [number, px, percent, degrees, vw, vh, auto];
const findDimensionValueType = (v) => dimensionValueTypes.find(testValueType(v));
const valueTypes = [...dimensionValueTypes, color, complex];
const findValueType = (v) => valueTypes.find(testValueType(v));
function setMotionValue(visualElement, key, value) {
if (visualElement.hasValue(key)) {
visualElement.getValue(key).set(value);
} else {
visualElement.addValue(key, motionValue(value));
}
}
function setTarget(visualElement, definition) {
const resolved = resolveVariant(visualElement, definition);
let { transitionEnd = {}, transition = {}, ...target } = resolved ? visualElement.makeTargetAnimatable(resolved, false) : {};
target = { ...target, ...transitionEnd };
for (const key in target) {
const value = resolveFinalValueInKeyframes(target[key]);
setMotionValue(visualElement, key, value);
}
}
function checkTargetForNewValues(visualElement, target, origin) {
var _a, _b;
const newValueKeys = Object.keys(target).filter((key) => !visualElement.hasValue(key));
const numNewValues = newValueKeys.length;
if (!numNewValues)
return;
for (let i = 0; i < numNewValues; i++) {
const key = newValueKeys[i];
const targetValue = target[key];
let value = null;
if (Array.isArray(targetValue)) {
value = targetValue[0];
}
if (value === null) {
value = (_b = (_a = origin[key]) !== null && _a !== void 0 ? _a : visualElement.readValue(key)) !== null && _b !== void 0 ? _b : target[key];
}
if (value === void 0 || value === null)
continue;
if (typeof value === "string" && (isNumericalString(value) || isZeroValueString(value))) {
value = parseFloat(value);
} else if (!findValueType(value) && complex.test(targetValue)) {
value = getAnimatableNone(key, targetValue);
}
visualElement.addValue(key, motionValue(value, { owner: visualElement }));
if (origin[key] === void 0) {
origin[key] = value;
}
if (value !== null)
visualElement.setBaseTarget(key, value);
}
}
function getOriginFromTransition(key, transition) {
if (!transition)
return;
const valueTransition = transition[key] || transition["default"] || transition;
return valueTransition.from;
}
function getOrigin(target, transition, visualElement) {
const origin = {};
for (const key in target) {
const transitionOrigin = getOriginFromTransition(key, transition);
if (transitionOrigin !== void 0) {
origin[key] = transitionOrigin;
} else {
const value = visualElement.getValue(key);
if (value) {
origin[key] = value.get();
}
}
}
return origin;
}
function shouldBlockAnimation({ protectedKeys, needsAnimating }, key) {
const shouldBlock = protectedKeys.hasOwnProperty(key) && needsAnimating[key] !== true;
needsAnimating[key] = false;
return shouldBlock;
}
function hasKeyframesChanged(value, target) {
const current = value.get();
if (Array.isArray(target)) {
for (let i = 0; i < target.length; i++) {
if (target[i] !== current)
return true;
}
} else {
return current !== target;
}
}
function animateTarget(visualElement, definition, { delay = 0, transitionOverride, type } = {}) {
let { transition = visualElement.getDefaultTransition(), transitionEnd, ...target } = visualElement.makeTargetAnimatable(definition);
const willChange = visualElement.getValue("willChange");
if (transitionOverride)
transition = transitionOverride;
const animations2 = [];
const animationTypeState = type && visualElement.animationState && visualElement.animationState.getState()[type];
for (const key in target) {
const value = visualElement.getValue(key);
const valueTarget = target[key];
if (!value || valueTarget === void 0 || animationTypeState && shouldBlockAnimation(animationTypeState, key)) {
continue;
}
const valueTransition = {
delay,
elapsed: 0,
...getValueTransition(transition || {}, key)
};
if (window.HandoffAppearAnimations) {
const appearId = visualElement.getProps()[optimizedAppearDataAttribute];
if (appearId) {
const elapsed = window.HandoffAppearAnimations(appearId, key, value, frame);
if (elapsed !== null) {
valueTransition.elapsed = elapsed;
valueTransition.isHandoff = true;
}
}
}
let canSkip = !valueTransition.isHandoff && !hasKeyframesChanged(value, valueTarget);
if (valueTransition.type === "spring" && (value.getVelocity() || valueTransition.velocity)) {
canSkip = false;
}
if (value.animation) {
canSkip = false;
}
if (canSkip)
continue;
value.start(animateMotionValue(key, value, valueTarget, visualElement.shouldReduceMotion && transformProps.has(key) ? { type: false } : valueTransition));
const animation = value.animation;
if (isWillChangeMotionValue(willChange)) {
willChange.add(key);
animation.then(() => willChange.remove(key));
}
animations2.push(animation);
}
if (transitionEnd) {
Promise.all(animations2).then(() => {
transitionEnd && setTarget(visualElement, transitionEnd);
});
}
return animations2;
}
function animateVariant(visualElement, variant, options = {}) {
const resolved = resolveVariant(visualElement, variant, options.custom);
let { transition = visualElement.getDefaultTransition() || {} } = resolved || {};
if (options.transitionOverride) {
transition = options.transitionOverride;
}
const getAnimation = resolved ? () => Promise.all(animateTarget(visualElement, resolved, options)) : () => Promise.resolve();
const getChildAnimations = visualElement.variantChildren && visualElement.variantChildren.size ? (forwardDelay = 0) => {
const { delayChildren = 0, staggerChildren, staggerDirection } = transition;
return animateChildren(visualElement, variant, delayChildren + forwardDelay, staggerChildren, staggerDirection, options);
} : () => Promise.resolve();
const { when } = transition;
if (when) {
const [first, last] = when === "beforeChildren" ? [getAnimation, getChildAnimations] : [getChildAnimations, getAnimation];
return first().then(() => last());
} else {
return Promise.all([getAnimation(), getChildAnimations(options.delay)]);
}
}
function animateChildren(visualElement, variant, delayChildren = 0, staggerChildren = 0, staggerDirection = 1, options) {
const animations2 = [];
const maxStaggerDuration = (visualElement.variantChildren.size - 1) * staggerChildren;
const generateStaggerDuration = staggerDirection === 1 ? (i = 0) => i * staggerChildren : (i = 0) => maxStaggerDuration - i * staggerChildren;
Array.from(visualElement.variantChildren).sort(sortByTreeOrder).forEach((child, i) => {
child.notify("AnimationStart", variant);
animations2.push(animateVariant(child, variant, {
...options,
delay: delayChildren + generateStaggerDuration(i)
}).then(() => child.notify("AnimationComplete", variant)));
});
return Promise.all(animations2);
}
function sortByTreeOrder(a, b) {
return a.sortNodePosition(b);
}
function animateVisualElement(visualElement, definition, options = {}) {
visualElement.notify("AnimationStart", definition);
let animation;
if (Array.isArray(definition)) {
const animations2 = definition.map((variant) => animateVariant(visualElement, variant, options));
animation = Promise.all(animations2);
} else if (typeof definition === "string") {
animation = animateVariant(visualElement, definition, options);
} else {
const resolvedDefinition = typeof definition === "function" ? resolveVariant(visualElement, definition, options.custom) : definition;
animation = Promise.all(animateTarget(visualElement, resolvedDefinition, options));
}
return animation.then(() => visualElement.notify("AnimationComplete", definition));
}
const reversePriorityOrder = [...variantPriorityOrder].reverse();
const numAnimationTypes = variantPriorityOrder.length;
function animateList(visualElement) {
return (animations2) => Promise.all(animations2.map(({ animation, options }) => animateVisualElement(visualElement, animation, options)));
}
function createAnimationState(visualElement) {
let animate = animateList(visualElement);
const state = createState();
let isInitialRender = true;
const buildResolvedTypeValues = (acc, definition) => {
const resolved = resolveVariant(visualElement, definition);
if (resolved) {
const { transition, transitionEnd, ...target } = resolved;
acc = { ...acc, ...target, ...transitionEnd };
}
return acc;
};
function setAnimateFunction(makeAnimator) {
animate = makeAnimator(visualElement);
}
function animateChanges(options, changedActiveType) {
const props = visualElement.getProps();
const context = visualElement.getVariantContext(true) || {};
const animations2 = [];
const removedKeys = /* @__PURE__ */ new Set();
let encounteredKeys = {};
let removedVariantIndex = Infinity;
for (let i = 0; i < numAnimationTypes; i++) {
const type = reversePriorityOrder[i];
const typeState = state[type];
const prop = props[type] !== void 0 ? props[type] : context[type];
const propIsVariant = isVariantLabel(prop);
const activeDelta = type === changedActiveType ? typeState.isActive : null;
if (activeDelta === false)
removedVariantIndex = i;
let isInherited = prop === context[type] && prop !== props[type] && propIsVariant;
if (isInherited && isInitialRender && visualElement.manuallyAnimateOnMount) {
isInherited = false;
}
typeState.protectedKeys = { ...encounteredKeys };
if (
// If it isn't active and hasn't *just* been set as inactive
!typeState.isActive && activeDelta === null || // If we didn't and don't have any defined prop for this animation type
!prop && !typeState.prevProp || // Or if the prop doesn't define an animation
isAnimationControls(prop) || typeof prop === "boolean"
) {
continue;
}
const variantDidChange = checkVariantsDidChange(typeState.prevProp, prop);
let shouldAnimateType = variantDidChange || // If we're making this variant active, we want to always make it active
type === changedActiveType && typeState.isActive && !isInherited && propIsVariant || // If we removed a higher-priority variant (i is in reverse order)
i > removedVariantIndex && propIsVariant;
let handledRemovedValues = false;
const definitionList = Array.isArray(prop) ? prop : [prop];
let resolvedValues = definitionList.reduce(buildResolvedTypeValues, {});
if (activeDelta === false)
resolvedValues = {};
const { prevResolvedValues = {} } = typeState;
const allKeys = {
...prevResolvedValues,
...resolvedValues
};
const markToAnimate = (key) => {
shouldAnimateType = true;
if (removedKeys.has(key)) {
handledRemovedValues = true;
removedKeys.delete(key);
}
typeState.needsAnimating[key] = true;
};
for (const key in allKeys) {
const next = resolvedValues[key];
const prev = prevResolvedValues[key];
if (encounteredKeys.hasOwnProperty(key))
continue;
let valueHasChanged = false;
if (isKeyframesTarget(next) && isKeyframesTarget(prev)) {
valueHasChanged = !shallowCompare(next, prev);
} else {
valueHasChanged = next !== prev;
}
if (valueHasChanged) {
if (next !== void 0) {
markToAnimate(key);
} else {
removedKeys.add(key);
}
} else if (next !== void 0 && removedKeys.has(key)) {
markToAnimate(key);
} else {
typeState.protectedKeys[key] = true;
}
}
typeState.prevProp = prop;
typeState.prevResolvedValues = resolvedValues;
if (typeState.isActive) {
encounteredKeys = { ...encounteredKeys, ...resolvedValues };
}
if (isInitialRender && visualElement.blockInitialAnimation) {
shouldAnimateType = false;
}
if (shouldAnimateType && (!isInherited || handledRemovedValues)) {
animations2.push(...definitionList.map((animation) => ({
animation,
options: { type, ...options }
})));
}
}
if (removedKeys.size) {
const fallbackAnimation = {};
removedKeys.forEach((key) => {
const fallbackTarget = visualElement.getBaseTarget(key);
if (fallbackTarget !== void 0) {
fallbackAnimation[key] = fallbackTarget;
}
});
animations2.push({ animation: fallbackAnimation });
}
let shouldAnimate = Boolean(animations2.length);
if (isInitialRender && (props.initial === false || props.initial === props.animate) && !visualElement.manuallyAnimateOnMount) {
shouldAnimate = false;
}
isInitialRender = false;
return shouldAnimate ? animate(animations2) : Promise.resolve();
}
function setActive(type, isActive, options) {
var _a;
if (state[type].isActive === isActive)
return Promise.resolve();
(_a = visualElement.variantChildren) === null || _a === void 0 ? void 0 : _a.forEach((child) => {
var _a2;
return (_a2 = child.animationState) === null || _a2 === void 0 ? void 0 : _a2.setActive(type, isActive);
});
state[type].isActive = isActive;
const animations2 = animateChanges(options, type);
for (const key in state) {
state[key].protectedKeys = {};
}
return animations2;
}
return {
animateChanges,
setActive,
setAnimateFunction,
getState: () => state
};
}
function checkVariantsDidChange(prev, next) {
if (typeof next === "string") {
return next !== prev;
} else if (Array.isArray(next)) {
return !shallowCompare(next, prev);
}
return false;
}
function createTypeState(isActive = false) {
return {
isActive,
protectedKeys: {},
needsAnimating: {},
prevResolvedValues: {}
};
}
function createState() {
return {
animate: createTypeState(true),
whileInView: createTypeState(),
whileHover: createTypeState(),
whileTap: createTypeState(),
whileDrag: createTypeState(),
whileFocus: createTypeState(),
exit: createTypeState()
};
}
class AnimationFeature extends Feature {
/**
* We dynamically generate the AnimationState manager as it contains a reference
* to the underlying animation library. We only want to load that if we load this,
* so people can optionally code split it out using the `m` component.
*/
constructor(node) {
super(node);
node.animationState || (node.animationState = createAnimationState(node));
}
updateAnimationControlsSubscription() {
const { animate } = this.node.getProps();
this.unmount();
if (isAnimationControls(animate)) {
this.unmount = animate.subscribe(this.node);
}
}
/**
* Subscribe any provided AnimationControls to the component's VisualElement
*/
mount() {
this.updateAnimationControlsSubscription();
}
update() {
const { animate } = this.node.getProps();
const { animate: prevAnimate } = this.node.prevProps || {};
if (animate !== prevAnimate) {
this.updateAnimationControlsSubscription();
}
}
unmount() {
}
}
let id = 0;
class ExitAnimationFeature extends Feature {
constructor() {
super(...arguments);
this.id = id++;
}
update() {
if (!this.node.presenceContext)
return;
const { isPresent, onExitComplete, custom } = this.node.presenceContext;
const { isPresent: prevIsPresent } = this.node.prevPresenceContext || {};
if (!this.node.animationState || isPresent === prevIsPresent) {
return;
}
const exitAnimation = this.node.animationState.setActive("exit", !isPresent, { custom: custom !== null && custom !== void 0 ? custom : this.node.getProps().custom });
if (onExitComplete && !isPresent) {
exitAnimation.then(() => onExitComplete(this.id));
}
}
mount() {
const { register } = this.node.presenceContext || {};
if (register) {
this.unmount = register(this.id);
}
}
unmount() {
}
}
const animations = {
animation: {
Feature: AnimationFeature
},
exit: {
Feature: ExitAnimationFeature
}
};
const createAxis = () => ({ min: 0, max: 0 });
const createBox = () => ({
x: createAxis(),
y: createAxis()
});
function convertBoundingBoxToBox({ top, left, right, bottom }) {
return {
x: { min: left, max: right },
y: { min: top, max: bottom }
};
}
function transformBoxPoints(point, transformPoint) {
if (!transformPoint)
return point;
const topLeft = transformPoint({ x: point.left, y: point.top });
const bottomRight = transformPoint({ x: point.right, y: point.bottom });
return {
top: topLeft.y,
left: topLeft.x,
bottom: bottomRight.y,
right: bottomRight.x
};
}
function measureViewportBox(instance, transformPoint) {
return convertBoundingBoxToBox(transformBoxPoints(instance.getBoundingClientRect(), transformPoint));
}
const splitCSSVariableRegex = /var\((--[a-zA-Z0-9-_]+),? ?([a-zA-Z0-9 ()%#.,-]+)?\)/;
function parseCSSVariable(current) {
const match = splitCSSVariableRegex.exec(current);
if (!match)
return [,];
const [, token, fallback] = match;
return [token, fallback];
}
const maxDepth = 4;
function getVariableValue(current, element, depth = 1) {
invariant(depth <= maxDepth, `Max CSS variable fallback depth detected in property "${current}". This may indicate a circular fallback dependency.`);
const [token, fallback] = parseCSSVariable(current);
if (!token)
return;
const resolved = window.getComputedStyle(element).getPropertyValue(token);
if (resolved) {
const trimmed = resolved.trim();
return isNumericalString(trimmed) ? parseFloat(trimmed) : trimmed;
} else if (isCSSVariableToken(fallback)) {
return getVariableValue(fallback, element, depth + 1);
} else {
return fallback;
}
}
function resolveCSSVariables(visualElement, { ...target }, transitionEnd) {
const element = visualElement.current;
if (!(element instanceof Element))
return { target, transitionEnd };
if (transitionEnd) {
transitionEnd = { ...transitionEnd };
}
visualElement.values.forEach((value) => {
const current = value.get();
if (!isCSSVariableToken(current))
return;
const resolved = getVariableValue(current, element);
if (resolved)
value.set(resolved);
});
for (const key in target) {
const current = target[key];
if (!isCSSVariableToken(current))
continue;
const resolved = getVariableValue(current, element);
if (!resolved)
continue;
target[key] = resolved;
if (!transitionEnd)
transitionEnd = {};
if (transitionEnd[key] === void 0) {
transitionEnd[key] = current;
}
}
return { target, transitionEnd };
}
const positionalKeys = /* @__PURE__ */ new Set([
"width",
"height",
"top",
"left",
"right",
"bottom",
"x",
"y",
"translateX",
"translateY"
]);
const isPositionalKey = (key) => positionalKeys.has(key);
const hasPositionalKey = (target) => {
return Object.keys(target).some(isPositionalKey);
};
const isNumOrPxType = (v) => v === number || v === px;
const getPosFromMatrix = (matrix, pos) => parseFloat(matrix.split(", ")[pos]);
const getTranslateFromMatrix = (pos2, pos3) => (_bbox, { transform }) => {
if (transform === "none" || !transform)
return 0;
const matrix3d = transform.match(/^matrix3d\((.+)\)$/);
if (matrix3d) {
return getPosFromMatrix(matrix3d[1], pos3);
} else {
const matrix = transform.match(/^matrix\((.+)\)$/);
if (matrix) {
return getPosFromMatrix(matrix[1], pos2);
} else {
return 0;
}
}
};
const transformKeys = /* @__PURE__ */ new Set(["x", "y", "z"]);
const nonTranslationalTransformKeys = transformPropOrder.filter((key) => !transformKeys.has(key));
function removeNonTranslationalTransform(visualElement) {
const removedTransforms = [];
nonTranslationalTransformKeys.forEach((key) => {
const value = visualElement.getValue(key);
if (value !== void 0) {
removedTransforms.push([key, value.get()]);
value.set(key.startsWith("scale") ? 1 : 0);
}
});
if (removedTransforms.length)
visualElement.render();
return removedTransforms;
}
const positionalValues = {
// Dimensions
width: ({ x }, { paddingLeft = "0", paddingRight = "0" }) => x.max - x.min - parseFloat(paddingLeft) - parseFloat(paddingRight),
height: ({ y }, { paddingTop = "0", paddingBottom = "0" }) => y.max - y.min - parseFloat(paddingTop) - parseFloat(paddingBottom),
top: (_bbox, { top }) => parseFloat(top),
left: (_bbox, { left }) => parseFloat(left),
bottom: ({ y }, { top }) => parseFloat(top) + (y.max - y.min),
right: ({ x }, { left }) => parseFloat(left) + (x.max - x.min),
// Transform
x: getTranslateFromMatrix(4, 13),
y: getTranslateFromMatrix(5, 14)
};
positionalValues.translateX = positionalValues.x;
positionalValues.translateY = positionalValues.y;
const convertChangedValueTypes = (target, visualElement, changedKeys) => {
const originBbox = visualElement.measureViewportBox();
const element = visualElement.current;
const elementComputedStyle = getComputedStyle(element);
const { display } = elementComputedStyle;
const origin = {};
if (display === "none") {
visualElement.setStaticValue("display", target.display || "block");
}
changedKeys.forEach((key) => {
origin[key] = positionalValues[key](originBbox, elementComputedStyle);
});
visualElement.render();
const targetBbox = visualElement.measureViewportBox();
changedKeys.forEach((key) => {
const value = visualElement.getValue(key);
value && value.jump(origin[key]);
target[key] = positionalValues[key](targetBbox, elementComputedStyle);
});
return target;
};
const checkAndConvertChangedValueTypes = (visualElement, target, origin = {}, transitionEnd = {}) => {
target = { ...target };
transitionEnd = { ...transitionEnd };
const targetPositionalKeys = Object.keys(target).filter(isPositionalKey);
let removedTransformValues = [];
let hasAttemptedToRemoveTransformValues = false;
const changedValueTypeKeys = [];
targetPositionalKeys.forEach((key) => {
const value = visualElement.getValue(key);
if (!visualElement.hasValue(key))
return;
let from = origin[key];
let fromType = findDimensionValueType(from);
const to = target[key];
let toType;
if (isKeyframesTarget(to)) {
const numKeyframes = to.length;
const fromIndex = to[0] === null ? 1 : 0;
from = to[fromIndex];
fromType = findDimensionValueType(from);
for (let i = fromIndex; i < numKeyframes; i++) {
if (to[i] === null)
break;
if (!toType) {
toType = findDimensionValueType(to[i]);
invariant(toType === fromType || isNumOrPxType(fromType) && isNumOrPxType(toType), "Keyframes must be of the same dimension as the current value");
} else {
invariant(findDimensionValueType(to[i]) === toType, "All keyframes must be of the same type");
}
}
} else {
toType = findDimensionValueType(to);
}
if (fromType !== toType) {
if (isNumOrPxType(fromType) && isNumOrPxType(toType)) {
const current = value.get();
if (typeof current === "string") {
value.set(parseFloat(current));
}
if (typeof to === "string") {
target[key] = parseFloat(to);
} else if (Array.isArray(to) && toType === px) {
target[key] = to.map(parseFloat);
}
} else if ((fromType === null || fromType === void 0 ? void 0 : fromType.transform) && (toType === null || toType === void 0 ? void 0 : toType.transform) && (from === 0 || to === 0)) {
if (from === 0) {
value.set(toType.transform(from));
} else {
target[key] = fromType.transform(to);
}
} else {
if (!hasAttemptedToRemoveTransformValues) {
removedTransformValues = removeNonTranslationalTransform(visualElement);
hasAttemptedToRemoveTransformValues = true;
}
changedValueTypeKeys.push(key);
transitionEnd[key] = transitionEnd[key] !== void 0 ? transitionEnd[key] : target[key];
value.jump(to);
}
}
});
if (changedValueTypeKeys.length) {
const scrollY = changedValueTypeKeys.indexOf("height") >= 0 ? window.pageYOffset : null;
const convertedTarget = convertChangedValueTypes(target, visualElement, changedValueTypeKeys);
if (removedTransformValues.length) {
removedTransformValues.forEach(([key, value]) => {
visualElement.getValue(key).set(value);
});
}
visualElement.render();
if (isBrowser && scrollY !== null) {
window.scrollTo({ top: scrollY });
}
return { target: convertedTarget, transitionEnd };
} else {
return { target, transitionEnd };
}
};
function unitConversion(visualElement, target, origin, transitionEnd) {
return hasPositionalKey(target) ? checkAndConvertChangedValueTypes(visualElement, target, origin, transitionEnd) : { target, transitionEnd };
}
const parseDomVariant = (visualElement, target, origin, transitionEnd) => {
const resolved = resolveCSSVariables(visualElement, target, transitionEnd);
target = resolved.target;
transitionEnd = resolved.transitionEnd;
return unitConversion(visualElement, target, origin, transitionEnd);
};
const prefersReducedMotion = { current: null };
const hasReducedMotionListener = { current: false };
function initPrefersReducedMotion() {
hasReducedMotionListener.current = true;
if (!isBrowser)
return;
if (window.matchMedia) {
const motionMediaQuery = window.matchMedia("(prefers-reduced-motion)");
const setReducedMotionPreferences = () => prefersReducedMotion.current = motionMediaQuery.matches;
motionMediaQuery.addListener(setReducedMotionPreferences);
setReducedMotionPreferences();
} else {
prefersReducedMotion.current = false;
}
}
function updateMotionValuesFromProps(element, next, prev) {
const { willChange } = next;
for (const key in next) {
const nextValue = next[key];
const prevValue = prev[key];
if (isMotionValue(nextValue)) {
element.addValue(key, nextValue);
if (isWillChangeMotionValue(willChange)) {
willChange.add(key);
}
if (process.env.NODE_ENV === "development") {
warnOnce(nextValue.version === "10.18.0", `Attempting to mix Framer Motion versions ${nextValue.version} with 10.18.0 may not work as expected.`);
}
} else if (isMotionValue(prevValue)) {
element.addValue(key, motionValue(nextValue, { owner: element }));
if (isWillChangeMotionValue(willChange)) {
willChange.remove(key);
}
} else if (prevValue !== nextValue) {
if (element.hasValue(key)) {
const existingValue = element.getValue(key);
!existingValue.hasAnimated && existingValue.set(nextValue);
} else {
const latestValue = element.getStaticValue(key);
element.addValue(key, motionValue(latestValue !== void 0 ? latestValue : nextValue, { owner: element }));
}
}
}
for (const key in prev) {
if (next[key] === void 0)
element.removeValue(key);
}
return next;
}
const visualElementStore = /* @__PURE__ */ new WeakMap();
const featureNames = Object.keys(featureDefinitions);
const numFeatures = featureNames.length;
const propEventHandlers = [
"AnimationStart",
"AnimationComplete",
"Update",
"BeforeLayoutMeasure",
"LayoutMeasure",
"LayoutAnimationStart",
"LayoutAnimationComplete"
];
const numVariantProps = variantProps.length;
class VisualElement {
constructor({ parent, props, presenceContext, reducedMotionConfig, visualState }, options = {}) {
this.current = null;
this.children = /* @__PURE__ */ new Set();
this.isVariantNode = false;
this.isControllingVariants = false;
this.shouldReduceMotion = null;
this.values = /* @__PURE__ */ new Map();
this.features = {};
this.valueSubscriptions = /* @__PURE__ */ new Map();
this.prevMotionValues = {};
this.events = {};
this.propEventSubscriptions = {};
this.notifyUpdate = () => this.notify("Update", this.latestValues);
this.render = () => {
if (!this.current)
return;
this.triggerBuild();
this.renderInstance(this.current, this.renderState, this.props.style, this.projection);
};
this.scheduleRender = () => frame.render(this.render, false, true);
const { latestValues, renderState } = visualState;
this.latestValues = latestValues;
this.baseTarget = { ...latestValues };
this.initialValues = props.initial ? { ...latestValues } : {};
this.renderState = renderState;
this.parent = parent;
this.props = props;
this.presenceContext = presenceContext;
this.depth = parent ? parent.depth + 1 : 0;
this.reducedMotionConfig = reducedMotionConfig;
this.options = options;
this.isControllingVariants = isControllingVariants(props);
this.isVariantNode = isVariantNode(props);
if (this.isVariantNode) {
this.variantChildren = /* @__PURE__ */ new Set();
}
this.manuallyAnimateOnMount = Boolean(parent && parent.current);
const { willChange, ...initialMotionValues } = this.scrapeMotionValuesFromProps(props, {});
for (const key in initialMotionValues) {
const value = initialMotionValues[key];
if (latestValues[key] !== void 0 && isMotionValue(value)) {
value.set(latestValues[key], false);
if (isWillChangeMotionValue(willChange)) {
willChange.add(key);
}
}
}
}
/**
* This method takes React props and returns found MotionValues. For example, HTML
* MotionValues will be found within the style prop, whereas for Three.js within attribute arrays.
*
* This isn't an abstract method as it needs calling in the constructor, but it is
* intended to be one.
*/
scrapeMotionValuesFromProps(_props, _prevProps) {
return {};
}
mount(instance) {
this.current = instance;
visualElementStore.set(instance, this);
if (this.projection && !this.projection.instance) {
this.projection.mount(instance);
}
if (this.parent && this.isVariantNode && !this.isControllingVariants) {
this.removeFromVariantTree = this.parent.addVariantChild(this);
}
this.values.forEach((value, key) => this.bindToMotionValue(key, value));
if (!hasReducedMotionListener.current) {
initPrefersReducedMotion();
}
this.shouldReduceMotion = this.reducedMotionConfig === "never" ? false : this.reducedMotionConfig === "always" ? true : prefersReducedMotion.current;
if (process.env.NODE_ENV !== "production") {
warnOnce(this.shouldReduceMotion !== true, "You have Reduced Motion enabled on your device. Animations may not appear as expected.");
}
if (this.parent)
this.parent.children.add(this);
this.update(this.props, this.presenceContext);
}
unmount() {
visualElementStore.delete(this.current);
this.projection && this.projection.unmount();
cancelFrame(this.notifyUpdate);
cancelFrame(this.render);
this.valueSubscriptions.forEach((remove) => remove());
this.removeFromVariantTree && this.removeFromVariantTree();
this.parent && this.parent.children.delete(this);
for (const key in this.events) {
this.events[key].clear();
}
for (const key in this.features) {
this.features[key].unmount();
}
this.current = null;
}
bindToMotionValue(key, value) {
const valueIsTransform = transformProps.has(key);
const removeOnChange = value.on("change", (latestValue) => {
this.latestValues[key] = latestValue;
this.props.onUpdate && frame.update(this.notifyUpdate, false, true);
if (valueIsTransform && this.projection) {
this.projection.isTransformDirty = true;
}
});
const removeOnRenderRequest = value.on("renderRequest", this.scheduleRender);
this.valueSubscriptions.set(key, () => {
removeOnChange();
removeOnRenderRequest();
});
}
sortNodePosition(other) {
if (!this.current || !this.sortInstanceNodePosition || this.type !== other.type) {
return 0;
}
return this.sortInstanceNodePosition(this.current, other.current);
}
loadFeatures({ children, ...renderedProps }, isStrict, preloadedFeatures, initialLayoutGroupConfig) {
let ProjectionNodeConstructor;
let MeasureLayout;
if (process.env.NODE_ENV !== "production" && preloadedFeatures && isStrict) {
const strictMessage = "You have rendered a `motion` component within a `LazyMotion` component. This will break tree shaking. Import and render a `m` component instead.";
renderedProps.ignoreStrict ? warning(false, strictMessage) : invariant(false, strictMessage);
}
for (let i = 0; i < numFeatures; i++) {
const name = featureNames[i];
const { isEnabled, Feature: FeatureConstructor, ProjectionNode, MeasureLayout: MeasureLayoutComponent } = featureDefinitions[name];
if (ProjectionNode)
ProjectionNodeConstructor = ProjectionNode;
if (isEnabled(renderedProps)) {
if (!this.features[name] && FeatureConstructor) {
this.features[name] = new FeatureConstructor(this);
}
if (MeasureLayoutComponent) {
MeasureLayout = MeasureLayoutComponent;
}
}
}
if ((this.type === "html" || this.type === "svg") && !this.projection && ProjectionNodeConstructor) {
this.projection = new ProjectionNodeConstructor(this.latestValues, this.parent && this.parent.projection);
const { layoutId, layout, drag, dragConstraints, layoutScroll, layoutRoot } = renderedProps;
this.projection.setOptions({
layoutId,
layout,
alwaysMeasureLayout: Boolean(drag) || dragConstraints && isRefObject(dragConstraints),
visualElement: this,
scheduleRender: () => this.scheduleRender(),
/**
* TODO: Update options in an effect. This could be tricky as it'll be too late
* to update by the time layout animations run.
* We also need to fix this safeToRemove by linking it up to the one returned by usePresence,
* ensuring it gets called if there's no potential layout animations.
*
*/
animationType: typeof layout === "string" ? layout : "both",
initialPromotionConfig: initialLayoutGroupConfig,
layoutScroll,
layoutRoot
});
}
return MeasureLayout;
}
updateFeatures() {
for (const key in this.features) {
const feature = this.features[key];
if (feature.isMounted) {
feature.update();
} else {
feature.mount();
feature.isMounted = true;
}
}
}
triggerBuild() {
this.build(this.renderState, this.latestValues, this.options, this.props);
}
/**
* Measure the current viewport box with or without transforms.
* Only measures axis-aligned boxes, rotate and skew must be manually
* removed with a re-render to work.
*/
measureViewportBox() {
return this.current ? this.measureInstanceViewportBox(this.current, this.props) : createBox();
}
getStaticValue(key) {
return this.latestValues[key];
}
setStaticValue(key, value) {
this.latestValues[key] = value;
}
/**
* Make a target animatable by Popmotion. For instance, if we're
* trying to animate width from 100px to 100vw we need to measure 100vw
* in pixels to determine what we really need to animate to. This is also
* pluggable to support Framer's custom value types like Color,
* and CSS variables.
*/
makeTargetAnimatable(target, canMutate = true) {
return this.makeTargetAnimatableFromInstance(target, this.props, canMutate);
}
/**
* Update the provided props. Ensure any newly-added motion values are
* added to our map, old ones removed, and listeners updated.
*/
update(props, presenceContext) {
if (props.transformTemplate || this.props.transformTemplate) {
this.scheduleRender();
}
this.prevProps = this.props;
this.props = props;
this.prevPresenceContext = this.presenceContext;
this.presenceContext = presenceContext;
for (let i = 0; i < propEventHandlers.length; i++) {
const key = propEventHandlers[i];
if (this.propEventSubscriptions[key]) {
this.propEventSubscriptions[key]();
delete this.propEventSubscriptions[key];
}
const listener = props["on" + key];
if (listener) {
this.propEventSubscriptions[key] = this.on(key, listener);
}
}
this.prevMotionValues = updateMotionValuesFromProps(this, this.scrapeMotionValuesFromProps(props, this.prevProps), this.prevMotionValues);
if (this.handleChildMotionValue) {
this.handleChildMotionValue();
}
}
getProps() {
return this.props;
}
/**
* Returns the variant definition with a given name.
*/
getVariant(name) {
return this.props.variants ? this.props.variants[name] : void 0;
}
/**
* Returns the defined default transition on this component.
*/
getDefaultTransition() {
return this.props.transition;
}
getTransformPagePoint() {
return this.props.transformPagePoint;
}
getClosestVariantNode() {
return this.isVariantNode ? this : this.parent ? this.parent.getClosestVariantNode() : void 0;
}
getVariantContext(startAtParent = false) {
if (startAtParent) {
return this.parent ? this.parent.getVariantContext() : void 0;
}
if (!this.isControllingVariants) {
const context2 = this.parent ? this.parent.getVariantContext() || {} : {};
if (this.props.initial !== void 0) {
context2.initial = this.props.initial;
}
return context2;
}
const context = {};
for (let i = 0; i < numVariantProps; i++) {
const name = variantProps[i];
const prop = this.props[name];
if (isVariantLabel(prop) || prop === false) {
context[name] = prop;
}
}
return context;
}
/**
* Add a child visual element to our set of children.
*/
addVariantChild(child) {
const closestVariantNode = this.getClosestVariantNode();
if (closestVariantNode) {
closestVariantNode.variantChildren && closestVariantNode.variantChildren.add(child);
return () => closestVariantNode.variantChildren.delete(child);
}
}
/**
* Add a motion value and bind it to this visual element.
*/
addValue(key, value) {
if (value !== this.values.get(key)) {
this.removeValue(key);
this.bindToMotionValue(key, value);
}
this.values.set(key, value);
this.latestValues[key] = value.get();
}
/**
* Remove a motion value and unbind any active subscriptions.
*/
removeValue(key) {
this.values.delete(key);
const unsubscribe = this.valueSubscriptions.get(key);
if (unsubscribe) {
unsubscribe();
this.valueSubscriptions.delete(key);
}
delete this.latestValues[key];
this.removeValueFromRenderState(key, this.renderState);
}
/**
* Check whether we have a motion value for this key
*/
hasValue(key) {
return this.values.has(key);
}
getValue(key, defaultValue) {
if (this.props.values && this.props.values[key]) {
return this.props.values[key];
}
let value = this.values.get(key);
if (value === void 0 && defaultValue !== void 0) {
value = motionValue(defaultValue, { owner: this });
this.addValue(key, value);
}
return value;
}
/**
* If we're trying to animate to a previously unencountered value,
* we need to check for it in our state and as a last resort read it
* directly from the instance (which might have performance implications).
*/
readValue(key) {
var _a;
return this.latestValues[key] !== void 0 || !this.current ? this.latestValues[key] : (_a = this.getBaseTargetFromProps(this.props, key)) !== null && _a !== void 0 ? _a : this.readValueFromInstance(this.current, key, this.options);
}
/**
* Set the base target to later animate back to. This is currently
* only hydrated on creation and when we first read a value.
*/
setBaseTarget(key, value) {
this.baseTarget[key] = value;
}
/**
* Find the base target for a value thats been removed from all animation
* props.
*/
getBaseTarget(key) {
var _a;
const { initial } = this.props;
const valueFromInitial = typeof initial === "string" || typeof initial === "object" ? (_a = resolveVariantFromProps(this.props, initial)) === null || _a === void 0 ? void 0 : _a[key] : void 0;
if (initial && valueFromInitial !== void 0) {
return valueFromInitial;
}
const target = this.getBaseTargetFromProps(this.props, key);
if (target !== void 0 && !isMotionValue(target))
return target;
return this.initialValues[key] !== void 0 && valueFromInitial === void 0 ? void 0 : this.baseTarget[key];
}
on(eventName, callback) {
if (!this.events[eventName]) {
this.events[eventName] = new SubscriptionManager();
}
return this.events[eventName].add(callback);
}
notify(eventName, ...args) {
if (this.events[eventName]) {
this.events[eventName].notify(...args);
}
}
}
class DOMVisualElement extends VisualElement {
sortInstanceNodePosition(a, b) {
return a.compareDocumentPosition(b) & 2 ? 1 : -1;
}
getBaseTargetFromProps(props, key) {
return props.style ? props.style[key] : void 0;
}
removeValueFromRenderState(key, { vars, style }) {
delete vars[key];
delete style[key];
}
makeTargetAnimatableFromInstance({ transition, transitionEnd, ...target }, { transformValues }, isMounted) {
let origin = getOrigin(target, transition || {}, this);
if (transformValues) {
if (transitionEnd)
transitionEnd = transformValues(transitionEnd);
if (target)
target = transformValues(target);
if (origin)
origin = transformValues(origin);
}
if (isMounted) {
checkTargetForNewValues(this, target, origin);
const parsed = parseDomVariant(this, target, origin, transitionEnd);
transitionEnd = parsed.transitionEnd;
target = parsed.target;
}
return {
transition,
transitionEnd,
...target
};
}
}
function getComputedStyle$1(element) {
return window.getComputedStyle(element);
}
class HTMLVisualElement extends DOMVisualElement {
constructor() {
super(...arguments);
this.type = "html";
}
readValueFromInstance(instance, key) {
if (transformProps.has(key)) {
const defaultType = getDefaultValueType(key);
return defaultType ? defaultType.default || 0 : 0;
} else {
const computedStyle = getComputedStyle$1(instance);
const value = (isCSSVariableName(key) ? computedStyle.getPropertyValue(key) : computedStyle[key]) || 0;
return typeof value === "string" ? value.trim() : value;
}
}
measureInstanceViewportBox(instance, { transformPagePoint }) {
return measureViewportBox(instance, transformPagePoint);
}
build(renderState, latestValues, options, props) {
buildHTMLStyles(renderState, latestValues, options, props.transformTemplate);
}
scrapeMotionValuesFromProps(props, prevProps) {
return scrapeMotionValuesFromProps(props, prevProps);
}
handleChildMotionValue() {
if (this.childSubscription) {
this.childSubscription();
delete this.childSubscription;
}
const { children } = this.props;
if (isMotionValue(children)) {
this.childSubscription = children.on("change", (latest) => {
if (this.current)
this.current.textContent = `${latest}`;
});
}
}
renderInstance(instance, renderState, styleProp, projection) {
renderHTML(instance, renderState, styleProp, projection);
}
}
class SVGVisualElement extends DOMVisualElement {
constructor() {
super(...arguments);
this.type = "svg";
this.isSVGTag = false;
}
getBaseTargetFromProps(props, key) {
return props[key];
}
readValueFromInstance(instance, key) {
if (transformProps.has(key)) {
const defaultType = getDefaultValueType(key);
return defaultType ? defaultType.default || 0 : 0;
}
key = !camelCaseAttributes.has(key) ? camelToDash(key) : key;
return instance.getAttribute(key);
}
measureInstanceViewportBox() {
return createBox();
}
scrapeMotionValuesFromProps(props, prevProps) {
return scrapeMotionValuesFromProps$1(props, prevProps);
}
build(renderState, latestValues, options, props) {
buildSVGAttrs(renderState, latestValues, options, this.isSVGTag, props.transformTemplate);
}
renderInstance(instance, renderState, styleProp, projection) {
renderSVG(instance, renderState, styleProp, projection);
}
mount(instance) {
this.isSVGTag = isSVGTag(instance.tagName);
super.mount(instance);
}
}
const createDomVisualElement = (Component, options) => {
return isSVGComponent(Component) ? new SVGVisualElement(options, { enableHardwareAcceleration: false }) : new HTMLVisualElement(options, { enableHardwareAcceleration: true });
};
const domAnimation = {
renderer: createDomVisualElement,
...animations,
...gestureAnimations
};
export {
domAnimation as default
};
//# sourceMappingURL=motionFeatures-fPgnC-rR.js.map