1849 lines
47 KiB
JavaScript
Raw Normal View History

2026-05-31 13:21:13 +02:00
'use strict';
const defu = require('defu');
const vue = require('vue');
const core = require('@vueuse/core');
const shared = require('@vueuse/shared');
const sync = require('framesync');
const popmotion = require('popmotion');
const styleValueTypes = require('style-value-types');
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
const defu__default = /*#__PURE__*/_interopDefaultCompat(defu);
const sync__default = /*#__PURE__*/_interopDefaultCompat(sync);
const motionState = {};
var __defProp$1 = Object.defineProperty;
var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField$1 = (obj, key, value) => {
__defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
return value;
};
class SubscriptionManager {
constructor() {
__publicField$1(this, "subscriptions", /* @__PURE__ */ new Set());
}
add(handler) {
this.subscriptions.add(handler);
return () => this.subscriptions.delete(handler);
}
notify(a, b, c) {
if (!this.subscriptions.size)
return;
for (const handler of this.subscriptions)
handler(a, b, c);
}
clear() {
this.subscriptions.clear();
}
}
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => {
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
return value;
};
function isFloat(value) {
return !Number.isNaN(Number.parseFloat(value));
}
class MotionValue {
/**
* init - The initiating value
* config - Optional configuration options
*/
constructor(init) {
/**
* The current state of the `MotionValue`.
*/
__publicField(this, "current");
/**
* The previous state of the `MotionValue`.
*/
__publicField(this, "prev");
/**
* Duration, in milliseconds, since last updating frame.
*/
__publicField(this, "timeDelta", 0);
/**
* Timestamp of the last time this `MotionValue` was updated.
*/
__publicField(this, "lastUpdated", 0);
/**
* Functions to notify when the `MotionValue` updates.
*/
__publicField(this, "updateSubscribers", new SubscriptionManager());
/**
* A reference to the currently-controlling Popmotion animation
*/
__publicField(this, "stopAnimation");
/**
* Tracks whether this value can output a velocity.
*/
__publicField(this, "canTrackVelocity", false);
/**
* Update and notify `MotionValue` subscribers.
*
* @param v
* @param render
*/
__publicField(this, "updateAndNotify", (v) => {
this.prev = this.current;
this.current = v;
const { delta, timestamp } = sync.getFrameData();
if (this.lastUpdated !== timestamp) {
this.timeDelta = delta;
this.lastUpdated = timestamp;
}
sync__default.postRender(this.scheduleVelocityCheck);
this.updateSubscribers.notify(this.current);
});
/**
* Schedule a velocity check for the next frame.
*/
__publicField(this, "scheduleVelocityCheck", () => sync__default.postRender(this.velocityCheck));
/**
* Updates `prev` with `current` if the value hasn't been updated this frame.
* This ensures velocity calculations return `0`.
*/
__publicField(this, "velocityCheck", ({ timestamp }) => {
if (!this.canTrackVelocity)
this.canTrackVelocity = isFloat(this.current);
if (timestamp !== this.lastUpdated)
this.prev = this.current;
});
this.prev = this.current = init;
this.canTrackVelocity = isFloat(this.current);
}
/**
* Adds a function that will be notified when the `MotionValue` is updated.
*
* It returns a function that, when called, will cancel the subscription.
*/
onChange(subscription) {
return this.updateSubscribers.add(subscription);
}
clearListeners() {
this.updateSubscribers.clear();
}
/**
* Sets the state of the `MotionValue`.
*
* @param v
* @param render
*/
set(v) {
this.updateAndNotify(v);
}
/**
* Returns the latest state of `MotionValue`
*
* @returns - The latest state of `MotionValue`
*/
get() {
return this.current;
}
/**
* Get previous value.
*
* @returns - The previous latest state of `MotionValue`
*/
getPrevious() {
return this.prev;
}
/**
* Returns the latest velocity of `MotionValue`
*
* @returns - The latest velocity of `MotionValue`. Returns `0` if the state is non-numerical.
*/
getVelocity() {
return this.canTrackVelocity ? popmotion.velocityPerSecond(Number.parseFloat(this.current) - Number.parseFloat(this.prev), this.timeDelta) : 0;
}
/**
* Registers a new animation to control this `MotionValue`. Only one
* animation can drive a `MotionValue` at one time.
*/
start(animation) {
this.stop();
return new Promise((resolve) => {
const { stop } = animation(resolve);
this.stopAnimation = stop;
}).then(() => this.clearAnimation());
}
/**
* Stop the currently active animation.
*/
stop() {
if (this.stopAnimation)
this.stopAnimation();
this.clearAnimation();
}
/**
* Returns `true` if this value is currently animating.
*/
isAnimating() {
return !!this.stopAnimation;
}
/**
* Clear the current animation reference.
*/
clearAnimation() {
this.stopAnimation = null;
}
/**
* Destroy and clean up subscribers to this `MotionValue`.
*/
destroy() {
this.updateSubscribers.clear();
this.stop();
}
}
function getMotionValue(init) {
return new MotionValue(init);
}
const { isArray } = Array;
function useMotionValues() {
const motionValues = vue.ref({});
const stop = (keys) => {
const destroyKey = (key) => {
if (!motionValues.value[key])
return;
motionValues.value[key].stop();
motionValues.value[key].destroy();
delete motionValues.value[key];
};
if (keys) {
if (isArray(keys)) {
keys.forEach(destroyKey);
} else {
destroyKey(keys);
}
} else {
Object.keys(motionValues.value).forEach(destroyKey);
}
};
const get = (key, from, target) => {
if (motionValues.value[key])
return motionValues.value[key];
const motionValue = getMotionValue(from);
motionValue.onChange((v) => target[key] = v);
motionValues.value[key] = motionValue;
return motionValue;
};
shared.tryOnUnmounted(stop);
return {
motionValues,
get,
stop
};
}
function isKeyframesTarget(v) {
return Array.isArray(v);
}
function underDampedSpring() {
return {
type: "spring",
stiffness: 500,
damping: 25,
restDelta: 0.5,
restSpeed: 10
};
}
function criticallyDampedSpring(to) {
return {
type: "spring",
stiffness: 550,
damping: to === 0 ? 2 * Math.sqrt(550) : 30,
restDelta: 0.01,
restSpeed: 10
};
}
function overDampedSpring(to) {
return {
type: "spring",
stiffness: 550,
damping: to === 0 ? 100 : 30,
restDelta: 0.01,
restSpeed: 10
};
}
function linearTween() {
return {
type: "keyframes",
ease: "linear",
duration: 300
};
}
function keyframes(values) {
return {
type: "keyframes",
duration: 800,
values
};
}
const defaultTransitions = {
default: overDampedSpring,
x: underDampedSpring,
y: underDampedSpring,
z: underDampedSpring,
rotate: underDampedSpring,
rotateX: underDampedSpring,
rotateY: underDampedSpring,
rotateZ: underDampedSpring,
scaleX: criticallyDampedSpring,
scaleY: criticallyDampedSpring,
scale: criticallyDampedSpring,
backgroundColor: linearTween,
color: linearTween,
opacity: linearTween
};
function getDefaultTransition(valueKey, to) {
let transitionFactory;
if (isKeyframesTarget(to)) {
transitionFactory = keyframes;
} else {
transitionFactory = defaultTransitions[valueKey] || defaultTransitions.default;
}
return { to, ...transitionFactory(to) };
}
const int = {
...styleValueTypes.number,
transform: Math.round
};
const valueTypes = {
// Color props
color: styleValueTypes.color,
backgroundColor: styleValueTypes.color,
outlineColor: styleValueTypes.color,
fill: styleValueTypes.color,
stroke: styleValueTypes.color,
// Border props
borderColor: styleValueTypes.color,
borderTopColor: styleValueTypes.color,
borderRightColor: styleValueTypes.color,
borderBottomColor: styleValueTypes.color,
borderLeftColor: styleValueTypes.color,
borderWidth: styleValueTypes.px,
borderTopWidth: styleValueTypes.px,
borderRightWidth: styleValueTypes.px,
borderBottomWidth: styleValueTypes.px,
borderLeftWidth: styleValueTypes.px,
borderRadius: styleValueTypes.px,
radius: styleValueTypes.px,
borderTopLeftRadius: styleValueTypes.px,
borderTopRightRadius: styleValueTypes.px,
borderBottomRightRadius: styleValueTypes.px,
borderBottomLeftRadius: styleValueTypes.px,
// Positioning props
width: styleValueTypes.px,
maxWidth: styleValueTypes.px,
height: styleValueTypes.px,
maxHeight: styleValueTypes.px,
size: styleValueTypes.px,
top: styleValueTypes.px,
right: styleValueTypes.px,
bottom: styleValueTypes.px,
left: styleValueTypes.px,
// Spacing props
padding: styleValueTypes.px,
paddingTop: styleValueTypes.px,
paddingRight: styleValueTypes.px,
paddingBottom: styleValueTypes.px,
paddingLeft: styleValueTypes.px,
margin: styleValueTypes.px,
marginTop: styleValueTypes.px,
marginRight: styleValueTypes.px,
marginBottom: styleValueTypes.px,
marginLeft: styleValueTypes.px,
// Transform props
rotate: styleValueTypes.degrees,
rotateX: styleValueTypes.degrees,
rotateY: styleValueTypes.degrees,
rotateZ: styleValueTypes.degrees,
scale: styleValueTypes.scale,
scaleX: styleValueTypes.scale,
scaleY: styleValueTypes.scale,
scaleZ: styleValueTypes.scale,
skew: styleValueTypes.degrees,
skewX: styleValueTypes.degrees,
skewY: styleValueTypes.degrees,
distance: styleValueTypes.px,
translateX: styleValueTypes.px,
translateY: styleValueTypes.px,
translateZ: styleValueTypes.px,
x: styleValueTypes.px,
y: styleValueTypes.px,
z: styleValueTypes.px,
perspective: styleValueTypes.px,
transformPerspective: styleValueTypes.px,
opacity: styleValueTypes.alpha,
originX: styleValueTypes.progressPercentage,
originY: styleValueTypes.progressPercentage,
originZ: styleValueTypes.px,
// Misc
zIndex: int,
filter: styleValueTypes.filter,
WebkitFilter: styleValueTypes.filter,
// SVG
fillOpacity: styleValueTypes.alpha,
strokeOpacity: styleValueTypes.alpha,
numOctaves: int
};
const getValueType = (key) => valueTypes[key];
function getValueAsType(value, type) {
return type && typeof value === "number" && type.transform ? type.transform(value) : value;
}
function getAnimatableNone(key, value) {
let defaultValueType = getValueType(key);
if (defaultValueType !== styleValueTypes.filter)
defaultValueType = styleValueTypes.complex;
return defaultValueType.getAnimatableNone ? defaultValueType.getAnimatableNone(value) : void 0;
}
const easingLookup = {
linear: popmotion.linear,
easeIn: popmotion.easeIn,
easeInOut: popmotion.easeInOut,
easeOut: popmotion.easeOut,
circIn: popmotion.circIn,
circInOut: popmotion.circInOut,
circOut: popmotion.circOut,
backIn: popmotion.backIn,
backInOut: popmotion.backInOut,
backOut: popmotion.backOut,
anticipate: popmotion.anticipate,
bounceIn: popmotion.bounceIn,
bounceInOut: popmotion.bounceInOut,
bounceOut: popmotion.bounceOut
};
function easingDefinitionToFunction(definition) {
if (Array.isArray(definition)) {
const [x1, y1, x2, y2] = definition;
return popmotion.cubicBezier(x1, y1, x2, y2);
} else if (typeof definition === "string") {
return easingLookup[definition];
}
return definition;
}
function isEasingArray(ease) {
return Array.isArray(ease) && typeof ease[0] !== "number";
}
function isAnimatable(key, value) {
if (key === "zIndex")
return false;
if (typeof value === "number" || Array.isArray(value))
return true;
if (typeof value === "string" && styleValueTypes.complex.test(value) && !value.startsWith("url(")) {
return true;
}
return false;
}
function hydrateKeyframes(options) {
if (Array.isArray(options.to) && options.to[0] === null) {
options.to = [...options.to];
options.to[0] = options.from;
}
return options;
}
function convertTransitionToAnimationOptions({ ease, times, delay, ...transition }) {
const options = { ...transition };
if (times)
options.offset = times;
if (ease) {
options.ease = isEasingArray(ease) ? ease.map(easingDefinitionToFunction) : easingDefinitionToFunction(ease);
}
if (delay)
options.elapsed = -delay;
return options;
}
function getPopmotionAnimationOptions(transition, options, key) {
if (Array.isArray(options.to)) {
if (!transition.duration)
transition.duration = 800;
}
hydrateKeyframes(options);
if (!isTransitionDefined(transition)) {
transition = {
...transition,
...getDefaultTransition(key, options.to)
};
}
return {
...options,
...convertTransitionToAnimationOptions(transition)
};
}
function isTransitionDefined({ delay, repeat, repeatType, repeatDelay, from, ...transition }) {
return !!Object.keys(transition).length;
}
function getValueTransition(transition, key) {
return transition[key] || transition.default || transition;
}
function getAnimation(key, value, target, transition, onComplete) {
const valueTransition = getValueTransition(transition, key);
let origin = valueTransition.from === null || valueTransition.from === void 0 ? value.get() : valueTransition.from;
const isTargetAnimatable = isAnimatable(key, target);
if (origin === "none" && isTargetAnimatable && typeof target === "string")
origin = getAnimatableNone(key, target);
const isOriginAnimatable = isAnimatable(key, origin);
function start(complete) {
const options = {
from: origin,
to: target,
velocity: transition.velocity ? transition.velocity : value.getVelocity(),
onUpdate: (v) => value.set(v)
};
return valueTransition.type === "inertia" || valueTransition.type === "decay" ? popmotion.inertia({ ...options, ...valueTransition }) : popmotion.animate({
...getPopmotionAnimationOptions(valueTransition, options, key),
onUpdate: (v) => {
options.onUpdate(v);
if (valueTransition.onUpdate)
valueTransition.onUpdate(v);
},
onComplete: () => {
if (onComplete)
onComplete();
if (complete)
complete();
}
});
}
function set(complete) {
value.set(target);
if (onComplete)
onComplete();
if (complete)
complete();
return { stop: () => {
} };
}
return !isOriginAnimatable || !isTargetAnimatable || valueTransition.type === false ? set : start;
}
function useMotionTransitions() {
const { motionValues, stop, get } = useMotionValues();
const push = (key, value, target, transition = {}, onComplete) => {
const from = target[key];
const motionValue = get(key, from, target);
if (transition && transition.immediate) {
motionValue.set(value);
return;
}
const animation = getAnimation(key, motionValue, value, transition, onComplete);
motionValue.start(animation);
};
return { motionValues, stop, push };
}
function useMotionControls(motionProperties, variants = {}, { motionValues, push, stop } = useMotionTransitions()) {
const _variants = vue.unref(variants);
const isAnimating = vue.ref(false);
vue.watch(
motionValues,
(newVal) => {
isAnimating.value = Object.values(newVal).filter((value) => value.isAnimating()).length > 0;
},
{
immediate: true,
deep: true
}
);
const getVariantFromKey = (variant) => {
if (!_variants || !_variants[variant])
throw new Error(`The variant ${variant} does not exist.`);
return _variants[variant];
};
const apply = (variant) => {
if (typeof variant === "string")
variant = getVariantFromKey(variant);
const animations = Object.entries(variant).map(([key, value]) => {
if (key === "transition")
return void 0;
return new Promise(
(resolve) => (
// @ts-expect-error - Fix errors later for typescript 5
push(key, value, motionProperties, variant.transition || getDefaultTransition(key, variant[key]), resolve)
)
);
}).filter(Boolean);
async function waitForComplete() {
await Promise.all(animations);
variant.transition?.onComplete?.();
}
return Promise.all([waitForComplete()]);
};
const set = (variant) => {
const variantData = core.isObject(variant) ? variant : getVariantFromKey(variant);
Object.entries(variantData).forEach(([key, value]) => {
if (key === "transition")
return;
push(key, value, motionProperties, {
immediate: true
});
});
};
const leave = async (done) => {
let leaveVariant;
if (_variants) {
if (_variants.leave)
leaveVariant = _variants.leave;
if (!_variants.leave && _variants.initial)
leaveVariant = _variants.initial;
}
if (!leaveVariant) {
done();
return;
}
await apply(leaveVariant);
done();
};
return {
isAnimating,
apply,
set,
leave,
stop
};
}
const isBrowser = typeof window !== "undefined";
const supportsPointerEvents = () => isBrowser && (window.onpointerdown === null || undefined.TEST);
const supportsTouchEvents = () => isBrowser && (window.ontouchstart === null || undefined.TEST);
const supportsMouseEvents = () => isBrowser && (window.onmousedown === null || undefined.TEST);
function registerEventListeners({ target, state, variants, apply }) {
const _variants = vue.unref(variants);
const hovered = vue.ref(false);
const tapped = vue.ref(false);
const focused = vue.ref(false);
const mutableKeys = vue.computed(() => {
let result = [...Object.keys(state.value || {})];
if (!_variants)
return result;
if (_variants.hovered)
result = [...result, ...Object.keys(_variants.hovered)];
if (_variants.tapped)
result = [...result, ...Object.keys(_variants.tapped)];
if (_variants.focused)
result = [...result, ...Object.keys(_variants.focused)];
return result;
});
const computedProperties = vue.computed(() => {
const result = {};
Object.assign(result, state.value);
if (hovered.value && _variants.hovered)
Object.assign(result, _variants.hovered);
if (tapped.value && _variants.tapped)
Object.assign(result, _variants.tapped);
if (focused.value && _variants.focused)
Object.assign(result, _variants.focused);
for (const key in result) {
if (!mutableKeys.value.includes(key))
delete result[key];
}
return result;
});
if (_variants.hovered) {
core.useEventListener(target, "mouseenter", () => hovered.value = true);
core.useEventListener(target, "mouseleave", () => {
hovered.value = false;
tapped.value = false;
});
}
if (_variants.tapped) {
if (supportsMouseEvents()) {
core.useEventListener(target, "mousedown", () => tapped.value = true);
core.useEventListener(target, "mouseup", () => tapped.value = false);
}
if (supportsPointerEvents()) {
core.useEventListener(target, "pointerdown", () => tapped.value = true);
core.useEventListener(target, "pointerup", () => tapped.value = false);
}
if (supportsTouchEvents()) {
core.useEventListener(target, "touchstart", () => tapped.value = true);
core.useEventListener(target, "touchend", () => tapped.value = false);
}
}
if (_variants.focused) {
core.useEventListener(target, "focus", () => focused.value = true);
core.useEventListener(target, "blur", () => focused.value = false);
}
vue.watch([hovered, tapped, focused], () => {
apply(computedProperties.value);
});
}
function registerLifeCycleHooks({ set, target, variants, variant }) {
const _variants = vue.unref(variants);
vue.watch(
() => target,
() => {
if (!_variants)
return;
if (_variants.initial) {
set("initial");
variant.value = "initial";
}
if (_variants.enter)
variant.value = "enter";
},
{
immediate: true,
flush: "pre"
}
);
}
function registerVariantsSync({ state, apply }) {
vue.watch(
state,
(newVal) => {
if (newVal)
apply(newVal);
},
{
immediate: true
}
);
}
function registerVisibilityHooks({ target, variants, variant }) {
const _variants = vue.unref(variants);
if (_variants && (_variants.visible || _variants.visibleOnce)) {
core.useIntersectionObserver(target, ([{ isIntersecting }]) => {
if (_variants.visible) {
if (isIntersecting)
variant.value = "visible";
else
variant.value = "initial";
} else if (_variants.visibleOnce) {
if (isIntersecting && variant.value !== "visibleOnce")
variant.value = "visibleOnce";
else if (!variant.value)
variant.value = "initial";
}
});
}
}
function useMotionFeatures(instance, options = {
syncVariants: true,
lifeCycleHooks: true,
visibilityHooks: true,
eventListeners: true
}) {
if (options.lifeCycleHooks)
registerLifeCycleHooks(instance);
if (options.syncVariants)
registerVariantsSync(instance);
if (options.visibilityHooks)
registerVisibilityHooks(instance);
if (options.eventListeners)
registerEventListeners(instance);
}
function reactiveStyle(props = {}) {
const state = vue.reactive({
...props
});
const style = vue.ref({});
vue.watch(
state,
() => {
const result = {};
for (const [key, value] of Object.entries(state)) {
const valueType = getValueType(key);
const valueAsType = getValueAsType(value, valueType);
result[key] = valueAsType;
}
style.value = result;
},
{
immediate: true,
deep: true
}
);
return {
state,
style
};
}
function usePermissiveTarget(target, onTarget) {
vue.watch(
() => core.unrefElement(target),
(el) => {
if (!el)
return;
onTarget(el);
},
{
immediate: true
}
);
}
const translateAlias = {
x: "translateX",
y: "translateY",
z: "translateZ"
};
function reactiveTransform(props = {}, enableHardwareAcceleration = true) {
const state = vue.reactive({ ...props });
const transform = vue.ref("");
vue.watch(
state,
(newVal) => {
let result = "";
let hasHardwareAcceleration = false;
if (enableHardwareAcceleration && (newVal.x || newVal.y || newVal.z)) {
const str = [newVal.x || 0, newVal.y || 0, newVal.z || 0].map((val) => getValueAsType(val, styleValueTypes.px)).join(",");
result += `translate3d(${str}) `;
hasHardwareAcceleration = true;
}
for (const [key, value] of Object.entries(newVal)) {
if (enableHardwareAcceleration && (key === "x" || key === "y" || key === "z"))
continue;
const valueType = getValueType(key);
const valueAsType = getValueAsType(value, valueType);
result += `${translateAlias[key] || key}(${valueAsType}) `;
}
if (enableHardwareAcceleration && !hasHardwareAcceleration)
result += "translateZ(0px) ";
transform.value = result.trim();
},
{
immediate: true,
deep: true
}
);
return {
state,
transform
};
}
const transformAxes = ["", "X", "Y", "Z"];
const order = ["perspective", "translate", "scale", "rotate", "skew"];
const transformProps = ["transformPerspective", "x", "y", "z"];
order.forEach((operationKey) => {
transformAxes.forEach((axesKey) => {
const key = operationKey + axesKey;
transformProps.push(key);
});
});
const transformPropSet = new Set(transformProps);
function isTransformProp(key) {
return transformPropSet.has(key);
}
const transformOriginProps = /* @__PURE__ */ new Set(["originX", "originY", "originZ"]);
function isTransformOriginProp(key) {
return transformOriginProps.has(key);
}
function splitValues(variant) {
const transform = {};
const style = {};
Object.entries(variant).forEach(([key, value]) => {
if (isTransformProp(key) || isTransformOriginProp(key))
transform[key] = value;
else
style[key] = value;
});
return { transform, style };
}
function variantToStyle(variant) {
const { transform: _transform, style: _style } = splitValues(variant);
const { transform } = reactiveTransform(_transform);
const { style } = reactiveStyle(_style);
if (transform.value)
style.value.transform = transform.value;
return style.value;
}
function useElementStyle(target, onInit) {
let _cache;
let _target;
const { state, style } = reactiveStyle();
usePermissiveTarget(target, (el) => {
_target = el;
for (const key of Object.keys(valueTypes)) {
if (el.style[key] === null || el.style[key] === "" || isTransformProp(key) || isTransformOriginProp(key))
continue;
state[key] = el.style[key];
}
if (_cache) {
Object.entries(_cache).forEach(([key, value]) => el.style[key] = value);
}
if (onInit)
onInit(state);
});
vue.watch(
style,
(newVal) => {
if (!_target) {
_cache = newVal;
return;
}
for (const key in newVal)
_target.style[key] = newVal[key];
},
{
immediate: true
}
);
return {
style: state
};
}
function parseTransform(transform) {
const transforms = transform.trim().split(/\) |\)/);
if (transforms.length === 1)
return {};
const parseValues = (value) => {
if (value.endsWith("px") || value.endsWith("deg"))
return Number.parseFloat(value);
if (Number.isNaN(Number(value)))
return Number(value);
return value;
};
return transforms.reduce((acc, transform2) => {
if (!transform2)
return acc;
const [name, transformValue] = transform2.split("(");
const valueArray = transformValue.split(",");
const values = valueArray.map((val) => {
return parseValues(val.endsWith(")") ? val.replace(")", "") : val.trim());
});
const value = values.length === 1 ? values[0] : values;
return {
...acc,
[name]: value
};
}, {});
}
function stateFromTransform(state, transform) {
Object.entries(parseTransform(transform)).forEach(([key, value]) => {
const axes = ["x", "y", "z"];
if (key === "translate3d") {
if (value === 0) {
axes.forEach((axis) => state[axis] = 0);
return;
}
value.forEach((axisValue, index) => state[axes[index]] = axisValue);
return;
}
value = Number.parseFloat(`${value}`);
if (key === "translateX") {
state.x = value;
return;
}
if (key === "translateY") {
state.y = value;
return;
}
if (key === "translateZ") {
state.z = value;
return;
}
state[key] = value;
});
}
function useElementTransform(target, onInit) {
let _cache;
let _target;
const { state, transform } = reactiveTransform();
usePermissiveTarget(target, (el) => {
_target = el;
if (el.style.transform)
stateFromTransform(state, el.style.transform);
if (_cache)
el.style.transform = _cache;
if (onInit)
onInit(state);
});
vue.watch(
transform,
(newValue) => {
if (!_target) {
_cache = newValue;
return;
}
_target.style.transform = newValue;
},
{
immediate: true
}
);
return {
transform: state
};
}
function objectEntries(obj) {
return Object.entries(obj);
}
function useMotionProperties(target, defaultValues) {
const motionProperties = vue.reactive({});
const apply = (values) => Object.entries(values).forEach(([key, value]) => motionProperties[key] = value);
const { style } = useElementStyle(target, apply);
const { transform } = useElementTransform(target, apply);
vue.watch(
motionProperties,
(newVal) => {
objectEntries(newVal).forEach(([key, value]) => {
const target2 = isTransformProp(key) ? transform : style;
if (target2[key] && target2[key] === value)
return;
target2[key] = value;
});
},
{
immediate: true,
deep: true
}
);
usePermissiveTarget(target, () => defaultValues && apply(defaultValues));
return {
motionProperties,
style,
transform
};
}
function useMotionVariants(variants = {}) {
const _variants = vue.unref(variants);
const variant = vue.ref();
const state = vue.computed(() => {
if (!variant.value)
return;
return _variants[variant.value];
});
return {
state,
variant
};
}
function useMotion(target, variants = {}, options) {
const { motionProperties } = useMotionProperties(target);
const { variant, state } = useMotionVariants(variants);
const controls = useMotionControls(motionProperties, variants);
const instance = {
target,
variant,
variants,
state,
motionProperties,
...controls
};
useMotionFeatures(instance, options);
return instance;
}
const transitionKeys = ["delay", "duration"];
const directivePropsKeys = ["initial", "enter", "leave", "visible", "visible-once", "visibleOnce", "hovered", "tapped", "focused", ...transitionKeys];
function isTransitionKey(val) {
return transitionKeys.includes(val);
}
function resolveVariants(node, variantsRef) {
const target = node.props ? node.props : node.data && node.data.attrs ? node.data.attrs : {};
if (target) {
if (target.variants && core.isObject(target.variants)) {
variantsRef.value = {
...variantsRef.value,
...target.variants
};
}
for (let key of directivePropsKeys) {
if (!target || !target[key])
continue;
if (isTransitionKey(key) && typeof target[key] === "number") {
for (const variantKey of ["enter", "visible", "visibleOnce"]) {
const variantConfig = variantsRef.value[variantKey];
if (variantConfig == null)
continue;
variantConfig.transition ?? (variantConfig.transition = {});
variantConfig.transition[key] = target[key];
}
continue;
}
if (core.isObject(target[key])) {
const prop = target[key];
if (key === "visible-once")
key = "visibleOnce";
variantsRef.value[key] = prop;
}
}
}
}
function directive(variants, isPreset = false) {
const register = (el, binding, node) => {
const key = binding.value && typeof binding.value === "string" ? binding.value : node.key;
if (key && motionState[key])
motionState[key].stop();
const variantsObject = isPreset ? structuredClone(vue.toRaw(variants) || {}) : variants || {};
const variantsRef = vue.ref(variantsObject);
if (typeof binding.value === "object")
variantsRef.value = binding.value;
resolveVariants(node, variantsRef);
const motionOptions = { eventListeners: true, lifeCycleHooks: true, syncVariants: true, visibilityHooks: false };
const motionInstance = useMotion(el, variantsRef, motionOptions);
el.motionInstance = motionInstance;
if (key)
motionState[key] = motionInstance;
};
const mounted = (el, _binding, _node) => {
el.motionInstance && registerVisibilityHooks(el.motionInstance);
};
return {
created: register,
mounted,
getSSRProps(binding, node) {
let { initial: bindingInitial } = binding.value || node && node?.props || {};
bindingInitial = vue.unref(bindingInitial);
const initial = defu__default({}, variants?.initial || {}, bindingInitial || {});
if (!initial || Object.keys(initial).length === 0)
return;
const style = variantToStyle(initial);
return {
style
};
}
};
}
const fade = {
initial: {
opacity: 0
},
enter: {
opacity: 1
}
};
const fadeVisible = {
initial: {
opacity: 0
},
visible: {
opacity: 1
}
};
const fadeVisibleOnce = {
initial: {
opacity: 0
},
visibleOnce: {
opacity: 1
}
};
const pop = {
initial: {
scale: 0,
opacity: 0
},
enter: {
scale: 1,
opacity: 1
}
};
const popVisible = {
initial: {
scale: 0,
opacity: 0
},
visible: {
scale: 1,
opacity: 1
}
};
const popVisibleOnce = {
initial: {
scale: 0,
opacity: 0
},
visibleOnce: {
scale: 1,
opacity: 1
}
};
const rollLeft = {
initial: {
x: -100,
rotate: 90,
opacity: 0
},
enter: {
x: 0,
rotate: 0,
opacity: 1
}
};
const rollVisibleLeft = {
initial: {
x: -100,
rotate: 90,
opacity: 0
},
visible: {
x: 0,
rotate: 0,
opacity: 1
}
};
const rollVisibleOnceLeft = {
initial: {
x: -100,
rotate: 90,
opacity: 0
},
visibleOnce: {
x: 0,
rotate: 0,
opacity: 1
}
};
const rollRight = {
initial: {
x: 100,
rotate: -90,
opacity: 0
},
enter: {
x: 0,
rotate: 0,
opacity: 1
}
};
const rollVisibleRight = {
initial: {
x: 100,
rotate: -90,
opacity: 0
},
visible: {
x: 0,
rotate: 0,
opacity: 1
}
};
const rollVisibleOnceRight = {
initial: {
x: 100,
rotate: -90,
opacity: 0
},
visibleOnce: {
x: 0,
rotate: 0,
opacity: 1
}
};
const rollTop = {
initial: {
y: -100,
rotate: -90,
opacity: 0
},
enter: {
y: 0,
rotate: 0,
opacity: 1
}
};
const rollVisibleTop = {
initial: {
y: -100,
rotate: -90,
opacity: 0
},
visible: {
y: 0,
rotate: 0,
opacity: 1
}
};
const rollVisibleOnceTop = {
initial: {
y: -100,
rotate: -90,
opacity: 0
},
visibleOnce: {
y: 0,
rotate: 0,
opacity: 1
}
};
const rollBottom = {
initial: {
y: 100,
rotate: 90,
opacity: 0
},
enter: {
y: 0,
rotate: 0,
opacity: 1
}
};
const rollVisibleBottom = {
initial: {
y: 100,
rotate: 90,
opacity: 0
},
visible: {
y: 0,
rotate: 0,
opacity: 1
}
};
const rollVisibleOnceBottom = {
initial: {
y: 100,
rotate: 90,
opacity: 0
},
visibleOnce: {
y: 0,
rotate: 0,
opacity: 1
}
};
const slideLeft = {
initial: {
x: -100,
opacity: 0
},
enter: {
x: 0,
opacity: 1
}
};
const slideVisibleLeft = {
initial: {
x: -100,
opacity: 0
},
visible: {
x: 0,
opacity: 1
}
};
const slideVisibleOnceLeft = {
initial: {
x: -100,
opacity: 0
},
visibleOnce: {
x: 0,
opacity: 1
}
};
const slideRight = {
initial: {
x: 100,
opacity: 0
},
enter: {
x: 0,
opacity: 1
}
};
const slideVisibleRight = {
initial: {
x: 100,
opacity: 0
},
visible: {
x: 0,
opacity: 1
}
};
const slideVisibleOnceRight = {
initial: {
x: 100,
opacity: 0
},
visibleOnce: {
x: 0,
opacity: 1
}
};
const slideTop = {
initial: {
y: -100,
opacity: 0
},
enter: {
y: 0,
opacity: 1
}
};
const slideVisibleTop = {
initial: {
y: -100,
opacity: 0
},
visible: {
y: 0,
opacity: 1
}
};
const slideVisibleOnceTop = {
initial: {
y: -100,
opacity: 0
},
visibleOnce: {
y: 0,
opacity: 1
}
};
const slideBottom = {
initial: {
y: 100,
opacity: 0
},
enter: {
y: 0,
opacity: 1
}
};
const slideVisibleBottom = {
initial: {
y: 100,
opacity: 0
},
visible: {
y: 0,
opacity: 1
}
};
const slideVisibleOnceBottom = {
initial: {
y: 100,
opacity: 0
},
visibleOnce: {
y: 0,
opacity: 1
}
};
const presets = {
__proto__: null,
fade: fade,
fadeVisible: fadeVisible,
fadeVisibleOnce: fadeVisibleOnce,
pop: pop,
popVisible: popVisible,
popVisibleOnce: popVisibleOnce,
rollBottom: rollBottom,
rollLeft: rollLeft,
rollRight: rollRight,
rollTop: rollTop,
rollVisibleBottom: rollVisibleBottom,
rollVisibleLeft: rollVisibleLeft,
rollVisibleOnceBottom: rollVisibleOnceBottom,
rollVisibleOnceLeft: rollVisibleOnceLeft,
rollVisibleOnceRight: rollVisibleOnceRight,
rollVisibleOnceTop: rollVisibleOnceTop,
rollVisibleRight: rollVisibleRight,
rollVisibleTop: rollVisibleTop,
slideBottom: slideBottom,
slideLeft: slideLeft,
slideRight: slideRight,
slideTop: slideTop,
slideVisibleBottom: slideVisibleBottom,
slideVisibleLeft: slideVisibleLeft,
slideVisibleOnceBottom: slideVisibleOnceBottom,
slideVisibleOnceLeft: slideVisibleOnceLeft,
slideVisibleOnceRight: slideVisibleOnceRight,
slideVisibleOnceTop: slideVisibleOnceTop,
slideVisibleRight: slideVisibleRight,
slideVisibleTop: slideVisibleTop
};
function slugify(str) {
const a = "\xE0\xE1\xE2\xE4\xE6\xE3\xE5\u0101\u0103\u0105\xE7\u0107\u010D\u0111\u010F\xE8\xE9\xEA\xEB\u0113\u0117\u0119\u011B\u011F\u01F5\u1E27\xEE\xEF\xED\u012B\u012F\xEC\u0142\u1E3F\xF1\u0144\u01F9\u0148\xF4\xF6\xF2\xF3\u0153\xF8\u014D\xF5\u0151\u1E55\u0155\u0159\xDF\u015B\u0161\u015F\u0219\u0165\u021B\xFB\xFC\xF9\xFA\u016B\u01D8\u016F\u0171\u0173\u1E83\u1E8D\xFF\xFD\u017E\u017A\u017C\xB7/_,:;";
const b = "aaaaaaaaaacccddeeeeeeeegghiiiiiilmnnnnoooooooooprrsssssttuuuuuuuuuwxyyzzz------";
const p = new RegExp(a.split("").join("|"), "g");
return str.toString().replace(/[A-Z]/g, (s) => `-${s}`).toLowerCase().replace(/\s+/g, "-").replace(p, (c) => b.charAt(a.indexOf(c))).replace(/&/g, "-and-").replace(/[^\w\-]+/g, "").replace(/-{2,}/g, "-").replace(/^-+/, "").replace(/-+$/, "");
}
const CUSTOM_PRESETS = Symbol(
undefined ? "motionCustomPresets" : ""
);
const MotionComponentProps = {
// Preset to be loaded
preset: {
type: String,
required: false
},
// Instance
instance: {
type: Object,
required: false
},
// Variants
variants: {
type: Object,
required: false
},
// Initial variant
initial: {
type: Object,
required: false
},
// Lifecycle hooks variants
enter: {
type: Object,
required: false
},
leave: {
type: Object,
required: false
},
// Intersection observer variants
visible: {
type: Object,
required: false
},
visibleOnce: {
type: Object,
required: false
},
// Event listeners variants
hovered: {
type: Object,
required: false
},
tapped: {
type: Object,
required: false
},
focused: {
type: Object,
required: false
},
// Helpers
delay: {
type: [Number, String],
required: false
},
duration: {
type: [Number, String],
required: false
}
};
function isObject(val) {
return Object.prototype.toString.call(val) === "[object Object]";
}
function clone(v) {
if (Array.isArray(v)) {
return v.map(clone);
}
if (isObject(v)) {
const res = {};
for (const key in v) {
res[key] = clone(v[key]);
}
return res;
}
return v;
}
function setupMotionComponent(props) {
const instances = vue.reactive({});
const customPresets = vue.inject(CUSTOM_PRESETS, {});
const preset = vue.computed(() => {
if (props.preset == null) {
return {};
}
if (customPresets != null && props.preset in customPresets) {
return structuredClone(vue.toRaw(customPresets)[props.preset]);
}
if (props.preset in presets) {
return structuredClone(presets[props.preset]);
}
return {};
});
const propsConfig = vue.computed(() => ({
initial: props.initial,
enter: props.enter,
leave: props.leave,
visible: props.visible,
visibleOnce: props.visibleOnce,
hovered: props.hovered,
tapped: props.tapped,
focused: props.focused
}));
function applyTransitionHelpers(config, values) {
for (const transitionKey of ["delay", "duration"]) {
if (values[transitionKey] == null)
continue;
const transitionValueParsed = Number.parseInt(
values[transitionKey]
);
for (const variantKey of ["enter", "visible", "visibleOnce"]) {
const variantConfig = config[variantKey];
if (variantConfig == null)
continue;
variantConfig.transition ?? (variantConfig.transition = {});
variantConfig.transition[transitionKey] = transitionValueParsed;
}
}
return config;
}
const motionConfig = vue.computed(() => {
const config = defu__default(
{},
propsConfig.value,
preset.value,
props.variants || {}
);
return applyTransitionHelpers({ ...config }, props);
});
if (undefined) {
if (props.preset != null && presets?.[props.preset] == null && customPresets?.[props.preset] == null) {
console.warn(`[@vueuse/motion]: Preset \`${props.preset}\` not found.`);
}
const replayAnimation = (instance) => {
if (instance.variants?.initial) {
instance.set("initial");
}
vue.nextTick(() => {
if (instance.variants?.enter)
instance.apply("enter");
if (instance.variants?.visible)
instance.apply("visible");
if (instance.variants?.visibleOnce)
instance.apply("visibleOnce");
});
};
vue.onUpdated(() => {
for (const key in instances) {
replayAnimation(instances[key]);
}
});
}
function setNodeInstance(node, index, style) {
var _a;
node.props ?? (node.props = {});
(_a = node.props).style ?? (_a.style = {});
node.props.style = { ...node.props.style, ...style };
const elementMotionConfig = applyTransitionHelpers(
clone(motionConfig.value),
node.props
);
node.props.onVnodeMounted = ({ el }) => {
instances[index] = useMotion(
el,
elementMotionConfig
);
};
node.props.onVnodeUpdated = ({ el }) => {
const styles = variantToStyle(instances[index].state);
for (const [key, val] of Object.entries(styles)) {
el.style[key] = val;
}
};
return node;
}
return {
motionConfig,
setNodeInstance
};
}
const MotionComponent = vue.defineComponent({
name: "Motion",
props: {
...MotionComponentProps,
is: {
type: [String, Object],
default: "div"
}
},
setup(props) {
const slots = vue.useSlots();
const { motionConfig, setNodeInstance } = setupMotionComponent(props);
return () => {
const style = variantToStyle(motionConfig.value.initial || {});
const node = vue.h(props.is, void 0, slots);
setNodeInstance(node, 0, style);
return node;
};
}
});
const MotionGroupComponent = vue.defineComponent({
name: "MotionGroup",
props: {
...MotionComponentProps,
is: {
type: [String, Object],
required: false
}
},
setup(props) {
const slots = vue.useSlots();
const { motionConfig, setNodeInstance } = setupMotionComponent(props);
return () => {
const style = variantToStyle(motionConfig.value.initial || {});
const nodes = slots.default?.() || [];
for (let i = 0; i < nodes.length; i++) {
const n = nodes[i];
if (n.type === vue.Fragment && Array.isArray(n.children)) {
n.children.forEach(function setChildInstance(child, index) {
if (child == null)
return;
if (Array.isArray(child)) {
setChildInstance(child, index);
return;
}
if (typeof child === "object") {
setNodeInstance(child, index, style);
}
});
} else {
setNodeInstance(n, i, style);
}
}
if (props.is) {
return vue.h(props.is, void 0, nodes);
}
return nodes;
};
}
});
const MotionPlugin = {
install(app, options) {
app.directive("motion", directive());
if (!options || options && !options.excludePresets) {
for (const key in presets) {
const preset = presets[key];
app.directive(`motion-${slugify(key)}`, directive(preset, true));
}
}
if (options && options.directives) {
for (const key in options.directives) {
const variants = options.directives[key];
if (!variants.initial && undefined) {
console.warn(
`Your directive v-motion-${key} is missing initial variant!`
);
}
app.directive(`motion-${key}`, directive(variants, true));
}
}
app.provide(CUSTOM_PRESETS, options?.directives);
app.component("Motion", MotionComponent);
app.component("MotionGroup", MotionGroupComponent);
}
};
function isMotionInstance(obj) {
const _obj = obj;
return _obj.apply !== void 0 && typeof _obj.apply === "function" && _obj.set !== void 0 && typeof _obj.set === "function" && _obj.target !== void 0 && vue.isRef(_obj.target);
}
function useMotions() {
return motionState;
}
function useSpring(values, spring) {
const { stop, get } = useMotionValues();
return {
values,
stop,
set: (properties) => Promise.all(
Object.entries(properties).map(([key, value]) => {
const motionValue = get(key, values[key], values);
return motionValue.start((onComplete) => {
const options = {
type: "spring",
...spring || getDefaultTransition(key, value)
};
return popmotion.animate({
from: motionValue.get(),
to: value,
velocity: motionValue.getVelocity(),
onUpdate: (v) => motionValue.set(v),
onComplete,
...options
});
});
})
)
};
}
function useReducedMotion(options = {}) {
return core.useMediaQuery("(prefers-reduced-motion: reduce)", options);
}
exports.MotionComponent = MotionComponent;
exports.MotionDirective = directive;
exports.MotionGroupComponent = MotionGroupComponent;
exports.MotionPlugin = MotionPlugin;
exports.fade = fade;
exports.fadeVisible = fadeVisible;
exports.fadeVisibleOnce = fadeVisibleOnce;
exports.isMotionInstance = isMotionInstance;
exports.pop = pop;
exports.popVisible = popVisible;
exports.popVisibleOnce = popVisibleOnce;
exports.reactiveStyle = reactiveStyle;
exports.reactiveTransform = reactiveTransform;
exports.rollBottom = rollBottom;
exports.rollLeft = rollLeft;
exports.rollRight = rollRight;
exports.rollTop = rollTop;
exports.rollVisibleBottom = rollVisibleBottom;
exports.rollVisibleLeft = rollVisibleLeft;
exports.rollVisibleOnceBottom = rollVisibleOnceBottom;
exports.rollVisibleOnceLeft = rollVisibleOnceLeft;
exports.rollVisibleOnceRight = rollVisibleOnceRight;
exports.rollVisibleOnceTop = rollVisibleOnceTop;
exports.rollVisibleRight = rollVisibleRight;
exports.rollVisibleTop = rollVisibleTop;
exports.slideBottom = slideBottom;
exports.slideLeft = slideLeft;
exports.slideRight = slideRight;
exports.slideTop = slideTop;
exports.slideVisibleBottom = slideVisibleBottom;
exports.slideVisibleLeft = slideVisibleLeft;
exports.slideVisibleOnceBottom = slideVisibleOnceBottom;
exports.slideVisibleOnceLeft = slideVisibleOnceLeft;
exports.slideVisibleOnceRight = slideVisibleOnceRight;
exports.slideVisibleOnceTop = slideVisibleOnceTop;
exports.slideVisibleRight = slideVisibleRight;
exports.slideVisibleTop = slideVisibleTop;
exports.slugify = slugify;
exports.useElementStyle = useElementStyle;
exports.useElementTransform = useElementTransform;
exports.useMotion = useMotion;
exports.useMotionControls = useMotionControls;
exports.useMotionFeatures = useMotionFeatures;
exports.useMotionProperties = useMotionProperties;
exports.useMotionTransitions = useMotionTransitions;
exports.useMotionVariants = useMotionVariants;
exports.useMotions = useMotions;
exports.useReducedMotion = useReducedMotion;
exports.useSpring = useSpring;