@vueuse/core
Version:
Collection of essential Vue Composition Utilities
1,745 lines (1,709 loc) • 244 kB
JavaScript
import { noop, makeDestructurable, camelize, isClient, toArray, watchImmediate, isObject, tryOnScopeDispose, isIOS, notNullish, tryOnMounted, objectOmit, promiseTimeout, until, injectLocal, provideLocal, pxValue, increaseWithUnit, objectEntries, createRef, createSingletonPromise, useTimeoutFn, pausableWatch, toRef, createEventHook, useIntervalFn, computedWithControl, timestamp, pausableFilter, watchIgnorable, debounceFilter, bypassFilter, createFilterWrapper, toRefs, watchOnce, containsProp, hasOwn, throttleFilter, useDebounceFn, useThrottleFn, tryOnUnmounted, clamp, syncRef, objectPick, watchWithFilter, identity, isDef, whenever, isWorker } from '@vueuse/shared';
export * from '@vueuse/shared';
import { isRef, shallowRef, ref, watchEffect, computed, inject, defineComponent, h, TransitionGroup, Fragment, shallowReactive, toValue, unref, getCurrentInstance, onMounted, watch, customRef, onUpdated, readonly, reactive, hasInjectionContext, toRaw, shallowReadonly, nextTick, markRaw, getCurrentScope, isReadonly, onBeforeUpdate } from 'vue';
function computedAsync(evaluationCallback, initialState, optionsOrRef) {
var _a;
let options;
if (isRef(optionsOrRef)) {
options = {
evaluating: optionsOrRef
};
} else {
options = optionsOrRef || {};
}
const {
lazy = false,
flush = "pre",
evaluating = void 0,
shallow = true,
onError = (_a = globalThis.reportError) != null ? _a : noop
} = options;
const started = shallowRef(!lazy);
const current = shallow ? shallowRef(initialState) : ref(initialState);
let counter = 0;
watchEffect(async (onInvalidate) => {
if (!started.value)
return;
counter++;
const counterAtBeginning = counter;
let hasFinished = false;
if (evaluating) {
Promise.resolve().then(() => {
evaluating.value = true;
});
}
try {
const result = await evaluationCallback((cancelCallback) => {
onInvalidate(() => {
if (evaluating)
evaluating.value = false;
if (!hasFinished)
cancelCallback();
});
});
if (counterAtBeginning === counter)
current.value = result;
} catch (e) {
onError(e);
} finally {
if (evaluating && counterAtBeginning === counter)
evaluating.value = false;
hasFinished = true;
}
}, { flush });
if (lazy) {
return computed(() => {
started.value = true;
return current.value;
});
} else {
return current;
}
}
function computedInject(key, options, defaultSource, treatDefaultAsFactory) {
let source = inject(key);
if (defaultSource)
source = inject(key, defaultSource);
if (treatDefaultAsFactory)
source = inject(key, defaultSource, treatDefaultAsFactory);
if (typeof options === "function") {
return computed((oldValue) => options(source, oldValue));
} else {
return computed({
get: (oldValue) => options.get(source, oldValue),
set: options.set
});
}
}
// @__NO_SIDE_EFFECTS__
function createReusableTemplate(options = {}) {
const {
inheritAttrs = true
} = options;
const render = shallowRef();
const define = /*@__PURE__*/ defineComponent({
setup(_, { slots }) {
return () => {
render.value = slots.default;
};
}
});
const reuse = /*@__PURE__*/ defineComponent({
inheritAttrs,
props: options.props,
setup(props, { attrs, slots }) {
return () => {
var _a;
if (!render.value && process.env.NODE_ENV !== "production")
throw new Error("[VueUse] Failed to find the definition of reusable template");
const vnode = (_a = render.value) == null ? void 0 : _a.call(render, {
...options.props == null ? keysToCamelKebabCase(attrs) : props,
$slots: slots
});
return inheritAttrs && (vnode == null ? void 0 : vnode.length) === 1 ? vnode[0] : vnode;
};
}
});
return makeDestructurable(
{ define, reuse },
[define, reuse]
);
}
function keysToCamelKebabCase(obj) {
const newObj = {};
for (const key in obj)
newObj[camelize(key)] = obj[key];
return newObj;
}
// @__NO_SIDE_EFFECTS__
function createTemplatePromise(options = {}) {
let index = 0;
const instances = ref([]);
function create(...args) {
const props = shallowReactive({
key: index++,
args,
promise: void 0,
resolve: () => {
},
reject: () => {
},
isResolving: false,
options
});
instances.value.push(props);
props.promise = new Promise((_resolve, _reject) => {
props.resolve = (v) => {
props.isResolving = true;
return _resolve(v);
};
props.reject = _reject;
}).finally(() => {
props.promise = void 0;
const index2 = instances.value.indexOf(props);
if (index2 !== -1)
instances.value.splice(index2, 1);
});
return props.promise;
}
function start(...args) {
if (options.singleton && instances.value.length > 0)
return instances.value[0].promise;
return create(...args);
}
const component = /*@__PURE__*/ defineComponent((_, { slots }) => {
const renderList = () => instances.value.map((props) => {
var _a;
return h(Fragment, { key: props.key }, (_a = slots.default) == null ? void 0 : _a.call(slots, props));
});
if (options.transition)
return () => h(TransitionGroup, options.transition, renderList);
return renderList;
});
component.start = start;
return component;
}
// @__NO_SIDE_EFFECTS__
function createUnrefFn(fn) {
return function(...args) {
return fn.apply(this, args.map((i) => toValue(i)));
};
}
const defaultWindow = isClient ? window : void 0;
const defaultDocument = isClient ? window.document : void 0;
const defaultNavigator = isClient ? window.navigator : void 0;
const defaultLocation = isClient ? window.location : void 0;
function unrefElement(elRef) {
var _a;
const plain = toValue(elRef);
return (_a = plain == null ? void 0 : plain.$el) != null ? _a : plain;
}
function useEventListener(...args) {
const cleanups = [];
const cleanup = () => {
cleanups.forEach((fn) => fn());
cleanups.length = 0;
};
const register = (el, event, listener, options) => {
el.addEventListener(event, listener, options);
return () => el.removeEventListener(event, listener, options);
};
const firstParamTargets = computed(() => {
const test = toArray(toValue(args[0])).filter((e) => e != null);
return test.every((e) => typeof e !== "string") ? test : void 0;
});
const stopWatch = watchImmediate(
() => {
var _a, _b;
return [
(_b = (_a = firstParamTargets.value) == null ? void 0 : _a.map((e) => unrefElement(e))) != null ? _b : [defaultWindow].filter((e) => e != null),
toArray(toValue(firstParamTargets.value ? args[1] : args[0])),
toArray(unref(firstParamTargets.value ? args[2] : args[1])),
// @ts-expect-error - TypeScript gets the correct types, but somehow still complains
toValue(firstParamTargets.value ? args[3] : args[2])
];
},
([raw_targets, raw_events, raw_listeners, raw_options]) => {
cleanup();
if (!(raw_targets == null ? void 0 : raw_targets.length) || !(raw_events == null ? void 0 : raw_events.length) || !(raw_listeners == null ? void 0 : raw_listeners.length))
return;
const optionsClone = isObject(raw_options) ? { ...raw_options } : raw_options;
cleanups.push(
...raw_targets.flatMap(
(el) => raw_events.flatMap(
(event) => raw_listeners.map((listener) => register(el, event, listener, optionsClone))
)
)
);
},
{ flush: "post" }
);
const stop = () => {
stopWatch();
cleanup();
};
tryOnScopeDispose(cleanup);
return stop;
}
let _iOSWorkaround = false;
function onClickOutside(target, handler, options = {}) {
const { window = defaultWindow, ignore = [], capture = true, detectIframe = false, controls = false } = options;
if (!window) {
return controls ? { stop: noop, cancel: noop, trigger: noop } : noop;
}
if (isIOS && !_iOSWorkaround) {
_iOSWorkaround = true;
const listenerOptions = { passive: true };
Array.from(window.document.body.children).forEach((el) => el.addEventListener("click", noop, listenerOptions));
window.document.documentElement.addEventListener("click", noop, listenerOptions);
}
let shouldListen = true;
const shouldIgnore = (event) => {
return toValue(ignore).some((target2) => {
if (typeof target2 === "string") {
return Array.from(window.document.querySelectorAll(target2)).some((el) => el === event.target || event.composedPath().includes(el));
} else {
const el = unrefElement(target2);
return el && (event.target === el || event.composedPath().includes(el));
}
});
};
function hasMultipleRoots(target2) {
const vm = toValue(target2);
return vm && vm.$.subTree.shapeFlag === 16;
}
function checkMultipleRoots(target2, event) {
const vm = toValue(target2);
const children = vm.$.subTree && vm.$.subTree.children;
if (children == null || !Array.isArray(children))
return false;
return children.some((child) => child.el === event.target || event.composedPath().includes(child.el));
}
const listener = (event) => {
const el = unrefElement(target);
if (event.target == null)
return;
if (!(el instanceof Element) && hasMultipleRoots(target) && checkMultipleRoots(target, event))
return;
if (!el || el === event.target || event.composedPath().includes(el))
return;
if ("detail" in event && event.detail === 0)
shouldListen = !shouldIgnore(event);
if (!shouldListen) {
shouldListen = true;
return;
}
handler(event);
};
let isProcessingClick = false;
const cleanup = [
useEventListener(window, "click", (event) => {
if (!isProcessingClick) {
isProcessingClick = true;
setTimeout(() => {
isProcessingClick = false;
}, 0);
listener(event);
}
}, { passive: true, capture }),
useEventListener(window, "pointerdown", (e) => {
const el = unrefElement(target);
shouldListen = !shouldIgnore(e) && !!(el && !e.composedPath().includes(el));
}, { passive: true }),
detectIframe && useEventListener(window, "blur", (event) => {
setTimeout(() => {
var _a;
const el = unrefElement(target);
if (((_a = window.document.activeElement) == null ? void 0 : _a.tagName) === "IFRAME" && !(el == null ? void 0 : el.contains(window.document.activeElement))) {
handler(event);
}
}, 0);
}, { passive: true })
].filter(Boolean);
const stop = () => cleanup.forEach((fn) => fn());
if (controls) {
return {
stop,
cancel: () => {
shouldListen = false;
},
trigger: (event) => {
shouldListen = true;
listener(event);
shouldListen = false;
}
};
}
return stop;
}
// @__NO_SIDE_EFFECTS__
function useMounted() {
const isMounted = shallowRef(false);
const instance = getCurrentInstance();
if (instance) {
onMounted(() => {
isMounted.value = true;
}, instance);
}
return isMounted;
}
// @__NO_SIDE_EFFECTS__
function useSupported(callback) {
const isMounted = useMounted();
return computed(() => {
isMounted.value;
return Boolean(callback());
});
}
function useMutationObserver(target, callback, options = {}) {
const { window = defaultWindow, ...mutationOptions } = options;
let observer;
const isSupported = useSupported(() => window && "MutationObserver" in window);
const cleanup = () => {
if (observer) {
observer.disconnect();
observer = void 0;
}
};
const targets = computed(() => {
const value = toValue(target);
const items = toArray(value).map(unrefElement).filter(notNullish);
return new Set(items);
});
const stopWatch = watch(
targets,
(newTargets) => {
cleanup();
if (isSupported.value && newTargets.size) {
observer = new MutationObserver(callback);
newTargets.forEach((el) => observer.observe(el, mutationOptions));
}
},
{ immediate: true, flush: "post" }
);
const takeRecords = () => {
return observer == null ? void 0 : observer.takeRecords();
};
const stop = () => {
stopWatch();
cleanup();
};
tryOnScopeDispose(stop);
return {
isSupported,
stop,
takeRecords
};
}
function onElementRemoval(target, callback, options = {}) {
const {
window = defaultWindow,
document = window == null ? void 0 : window.document,
flush = "sync"
} = options;
if (!window || !document)
return noop;
let stopFn;
const cleanupAndUpdate = (fn) => {
stopFn == null ? void 0 : stopFn();
stopFn = fn;
};
const stopWatch = watchEffect(() => {
const el = unrefElement(target);
if (el) {
const { stop } = useMutationObserver(
document,
(mutationsList) => {
const targetRemoved = mutationsList.map((mutation) => [...mutation.removedNodes]).flat().some((node) => node === el || node.contains(el));
if (targetRemoved) {
callback(mutationsList);
}
},
{
window,
childList: true,
subtree: true
}
);
cleanupAndUpdate(stop);
}
}, { flush });
const stopHandle = () => {
stopWatch();
cleanupAndUpdate();
};
tryOnScopeDispose(stopHandle);
return stopHandle;
}
function createKeyPredicate(keyFilter) {
if (typeof keyFilter === "function")
return keyFilter;
else if (typeof keyFilter === "string")
return (event) => event.key === keyFilter;
else if (Array.isArray(keyFilter))
return (event) => keyFilter.includes(event.key);
return () => true;
}
function onKeyStroke(...args) {
let key;
let handler;
let options = {};
if (args.length === 3) {
key = args[0];
handler = args[1];
options = args[2];
} else if (args.length === 2) {
if (typeof args[1] === "object") {
key = true;
handler = args[0];
options = args[1];
} else {
key = args[0];
handler = args[1];
}
} else {
key = true;
handler = args[0];
}
const {
target = defaultWindow,
eventName = "keydown",
passive = false,
dedupe = false
} = options;
const predicate = createKeyPredicate(key);
const listener = (e) => {
if (e.repeat && toValue(dedupe))
return;
if (predicate(e))
handler(e);
};
return useEventListener(target, eventName, listener, passive);
}
function onKeyDown(key, handler, options = {}) {
return onKeyStroke(key, handler, { ...options, eventName: "keydown" });
}
function onKeyPressed(key, handler, options = {}) {
return onKeyStroke(key, handler, { ...options, eventName: "keypress" });
}
function onKeyUp(key, handler, options = {}) {
return onKeyStroke(key, handler, { ...options, eventName: "keyup" });
}
const DEFAULT_DELAY = 500;
const DEFAULT_THRESHOLD = 10;
function onLongPress(target, handler, options) {
var _a, _b;
const elementRef = computed(() => unrefElement(target));
let timeout;
let posStart;
let startTimestamp;
let hasLongPressed = false;
function clear() {
if (timeout) {
clearTimeout(timeout);
timeout = void 0;
}
posStart = void 0;
startTimestamp = void 0;
hasLongPressed = false;
}
function getDelay(ev) {
const delay = options == null ? void 0 : options.delay;
if (typeof delay === "function") {
return delay(ev);
}
return delay != null ? delay : DEFAULT_DELAY;
}
function onRelease(ev) {
var _a2, _b2, _c;
const [_startTimestamp, _posStart, _hasLongPressed] = [startTimestamp, posStart, hasLongPressed];
clear();
if (!(options == null ? void 0 : options.onMouseUp) || !_posStart || !_startTimestamp)
return;
if (((_a2 = options == null ? void 0 : options.modifiers) == null ? void 0 : _a2.self) && ev.target !== elementRef.value)
return;
if ((_b2 = options == null ? void 0 : options.modifiers) == null ? void 0 : _b2.prevent)
ev.preventDefault();
if ((_c = options == null ? void 0 : options.modifiers) == null ? void 0 : _c.stop)
ev.stopPropagation();
const dx = ev.x - _posStart.x;
const dy = ev.y - _posStart.y;
const distance = Math.sqrt(dx * dx + dy * dy);
options.onMouseUp(ev.timeStamp - _startTimestamp, distance, _hasLongPressed);
}
function onDown(ev) {
var _a2, _b2, _c;
if (((_a2 = options == null ? void 0 : options.modifiers) == null ? void 0 : _a2.self) && ev.target !== elementRef.value)
return;
clear();
if ((_b2 = options == null ? void 0 : options.modifiers) == null ? void 0 : _b2.prevent)
ev.preventDefault();
if ((_c = options == null ? void 0 : options.modifiers) == null ? void 0 : _c.stop)
ev.stopPropagation();
posStart = {
x: ev.x,
y: ev.y
};
startTimestamp = ev.timeStamp;
timeout = setTimeout(
() => {
hasLongPressed = true;
handler(ev);
},
getDelay(ev)
);
}
function onMove(ev) {
var _a2, _b2, _c, _d;
if (((_a2 = options == null ? void 0 : options.modifiers) == null ? void 0 : _a2.self) && ev.target !== elementRef.value)
return;
if (!posStart || (options == null ? void 0 : options.distanceThreshold) === false)
return;
if ((_b2 = options == null ? void 0 : options.modifiers) == null ? void 0 : _b2.prevent)
ev.preventDefault();
if ((_c = options == null ? void 0 : options.modifiers) == null ? void 0 : _c.stop)
ev.stopPropagation();
const dx = ev.x - posStart.x;
const dy = ev.y - posStart.y;
const distance = Math.sqrt(dx * dx + dy * dy);
if (distance >= ((_d = options == null ? void 0 : options.distanceThreshold) != null ? _d : DEFAULT_THRESHOLD))
clear();
}
const listenerOptions = {
capture: (_a = options == null ? void 0 : options.modifiers) == null ? void 0 : _a.capture,
once: (_b = options == null ? void 0 : options.modifiers) == null ? void 0 : _b.once
};
const cleanup = [
useEventListener(elementRef, "pointerdown", onDown, listenerOptions),
useEventListener(elementRef, "pointermove", onMove, listenerOptions),
useEventListener(elementRef, ["pointerup", "pointerleave"], onRelease, listenerOptions)
];
const stop = () => cleanup.forEach((fn) => fn());
return stop;
}
function isFocusedElementEditable() {
const { activeElement, body } = document;
if (!activeElement)
return false;
if (activeElement === body)
return false;
switch (activeElement.tagName) {
case "INPUT":
case "TEXTAREA":
return true;
}
return activeElement.hasAttribute("contenteditable");
}
function isTypedCharValid({
keyCode,
metaKey,
ctrlKey,
altKey
}) {
if (metaKey || ctrlKey || altKey)
return false;
if (keyCode >= 48 && keyCode <= 57 || keyCode >= 96 && keyCode <= 105)
return true;
if (keyCode >= 65 && keyCode <= 90)
return true;
return false;
}
function onStartTyping(callback, options = {}) {
const { document: document2 = defaultDocument } = options;
const keydown = (event) => {
if (!isFocusedElementEditable() && isTypedCharValid(event)) {
callback(event);
}
};
if (document2)
useEventListener(document2, "keydown", keydown, { passive: true });
}
// @__NO_SIDE_EFFECTS__
function templateRef(key, initialValue = null) {
const instance = getCurrentInstance();
let _trigger = () => {
};
const element = customRef((track, trigger) => {
_trigger = trigger;
return {
get() {
var _a, _b;
track();
return (_b = (_a = instance == null ? void 0 : instance.proxy) == null ? void 0 : _a.$refs[key]) != null ? _b : initialValue;
},
set() {
}
};
});
tryOnMounted(_trigger);
onUpdated(_trigger);
return element;
}
// @__NO_SIDE_EFFECTS__
function useActiveElement(options = {}) {
var _a;
const {
window = defaultWindow,
deep = true,
triggerOnRemoval = false
} = options;
const document = (_a = options.document) != null ? _a : window == null ? void 0 : window.document;
const getDeepActiveElement = () => {
var _a2;
let element = document == null ? void 0 : document.activeElement;
if (deep) {
while (element == null ? void 0 : element.shadowRoot)
element = (_a2 = element == null ? void 0 : element.shadowRoot) == null ? void 0 : _a2.activeElement;
}
return element;
};
const activeElement = shallowRef();
const trigger = () => {
activeElement.value = getDeepActiveElement();
};
if (window) {
const listenerOptions = {
capture: true,
passive: true
};
useEventListener(
window,
"blur",
(event) => {
if (event.relatedTarget !== null)
return;
trigger();
},
listenerOptions
);
useEventListener(
window,
"focus",
trigger,
listenerOptions
);
}
if (triggerOnRemoval) {
onElementRemoval(activeElement, trigger, { document });
}
trigger();
return activeElement;
}
function useRafFn(fn, options = {}) {
const {
immediate = true,
fpsLimit = void 0,
window = defaultWindow,
once = false
} = options;
const isActive = shallowRef(false);
const intervalLimit = computed(() => {
return fpsLimit ? 1e3 / toValue(fpsLimit) : null;
});
let previousFrameTimestamp = 0;
let rafId = null;
function loop(timestamp) {
if (!isActive.value || !window)
return;
if (!previousFrameTimestamp)
previousFrameTimestamp = timestamp;
const delta = timestamp - previousFrameTimestamp;
if (intervalLimit.value && delta < intervalLimit.value) {
rafId = window.requestAnimationFrame(loop);
return;
}
previousFrameTimestamp = timestamp;
fn({ delta, timestamp });
if (once) {
isActive.value = false;
rafId = null;
return;
}
rafId = window.requestAnimationFrame(loop);
}
function resume() {
if (!isActive.value && window) {
isActive.value = true;
previousFrameTimestamp = 0;
rafId = window.requestAnimationFrame(loop);
}
}
function pause() {
isActive.value = false;
if (rafId != null && window) {
window.cancelAnimationFrame(rafId);
rafId = null;
}
}
if (immediate)
resume();
tryOnScopeDispose(pause);
return {
isActive: readonly(isActive),
pause,
resume
};
}
function useAnimate(target, keyframes, options) {
let config;
let animateOptions;
if (isObject(options)) {
config = options;
animateOptions = objectOmit(options, ["window", "immediate", "commitStyles", "persist", "onReady", "onError"]);
} else {
config = { duration: options };
animateOptions = options;
}
const {
window = defaultWindow,
immediate = true,
commitStyles,
persist,
playbackRate: _playbackRate = 1,
onReady,
onError = (e) => {
console.error(e);
}
} = config;
const isSupported = useSupported(() => window && HTMLElement && "animate" in HTMLElement.prototype);
const animate = shallowRef(void 0);
const store = shallowReactive({
startTime: null,
currentTime: null,
timeline: null,
playbackRate: _playbackRate,
pending: false,
playState: immediate ? "idle" : "paused",
replaceState: "active"
});
const pending = computed(() => store.pending);
const playState = computed(() => store.playState);
const replaceState = computed(() => store.replaceState);
const startTime = computed({
get() {
return store.startTime;
},
set(value) {
store.startTime = value;
if (animate.value)
animate.value.startTime = value;
}
});
const currentTime = computed({
get() {
return store.currentTime;
},
set(value) {
store.currentTime = value;
if (animate.value) {
animate.value.currentTime = value;
syncResume();
}
}
});
const timeline = computed({
get() {
return store.timeline;
},
set(value) {
store.timeline = value;
if (animate.value)
animate.value.timeline = value;
}
});
const playbackRate = computed({
get() {
return store.playbackRate;
},
set(value) {
store.playbackRate = value;
if (animate.value)
animate.value.playbackRate = value;
}
});
const play = () => {
if (animate.value) {
try {
animate.value.play();
syncResume();
} catch (e) {
syncPause();
onError(e);
}
} else {
update();
}
};
const pause = () => {
var _a;
try {
(_a = animate.value) == null ? void 0 : _a.pause();
syncPause();
} catch (e) {
onError(e);
}
};
const reverse = () => {
var _a;
if (!animate.value)
update();
try {
(_a = animate.value) == null ? void 0 : _a.reverse();
syncResume();
} catch (e) {
syncPause();
onError(e);
}
};
const finish = () => {
var _a;
try {
(_a = animate.value) == null ? void 0 : _a.finish();
syncPause();
} catch (e) {
onError(e);
}
};
const cancel = () => {
var _a;
try {
(_a = animate.value) == null ? void 0 : _a.cancel();
syncPause();
} catch (e) {
onError(e);
}
};
watch(() => unrefElement(target), (el) => {
if (el) {
update(true);
} else {
animate.value = void 0;
}
});
watch(() => keyframes, (value) => {
if (animate.value) {
update();
const targetEl = unrefElement(target);
if (targetEl) {
animate.value.effect = new KeyframeEffect(
targetEl,
toValue(value),
animateOptions
);
}
}
}, { deep: true });
tryOnMounted(() => update(true), false);
tryOnScopeDispose(cancel);
function update(init) {
const el = unrefElement(target);
if (!isSupported.value || !el)
return;
if (!animate.value)
animate.value = el.animate(toValue(keyframes), animateOptions);
if (persist)
animate.value.persist();
if (_playbackRate !== 1)
animate.value.playbackRate = _playbackRate;
if (init && !immediate)
animate.value.pause();
else
syncResume();
onReady == null ? void 0 : onReady(animate.value);
}
const listenerOptions = { passive: true };
useEventListener(animate, ["cancel", "finish", "remove"], syncPause, listenerOptions);
useEventListener(animate, "finish", () => {
var _a;
if (commitStyles)
(_a = animate.value) == null ? void 0 : _a.commitStyles();
}, listenerOptions);
const { resume: resumeRef, pause: pauseRef } = useRafFn(() => {
if (!animate.value)
return;
store.pending = animate.value.pending;
store.playState = animate.value.playState;
store.replaceState = animate.value.replaceState;
store.startTime = animate.value.startTime;
store.currentTime = animate.value.currentTime;
store.timeline = animate.value.timeline;
store.playbackRate = animate.value.playbackRate;
}, { immediate: false });
function syncResume() {
if (isSupported.value)
resumeRef();
}
function syncPause() {
if (isSupported.value && window)
window.requestAnimationFrame(pauseRef);
}
return {
isSupported,
animate,
// actions
play,
pause,
reverse,
finish,
cancel,
// state
pending,
playState,
replaceState,
startTime,
currentTime,
timeline,
playbackRate
};
}
function useAsyncQueue(tasks, options) {
const {
interrupt = true,
onError = noop,
onFinished = noop,
signal
} = options || {};
const promiseState = {
aborted: "aborted",
fulfilled: "fulfilled",
pending: "pending",
rejected: "rejected"
};
const initialResult = Array.from(Array.from({ length: tasks.length }), () => ({ state: promiseState.pending, data: null }));
const result = reactive(initialResult);
const activeIndex = shallowRef(-1);
if (!tasks || tasks.length === 0) {
onFinished();
return {
activeIndex,
result
};
}
function updateResult(state, res) {
activeIndex.value++;
result[activeIndex.value].data = res;
result[activeIndex.value].state = state;
}
tasks.reduce((prev, curr) => {
return prev.then((prevRes) => {
var _a;
if (signal == null ? void 0 : signal.aborted) {
updateResult(promiseState.aborted, new Error("aborted"));
return;
}
if (((_a = result[activeIndex.value]) == null ? void 0 : _a.state) === promiseState.rejected && interrupt) {
onFinished();
return;
}
const done = curr(prevRes).then((currentRes) => {
updateResult(promiseState.fulfilled, currentRes);
if (activeIndex.value === tasks.length - 1)
onFinished();
return currentRes;
});
if (!signal)
return done;
return Promise.race([done, whenAborted(signal)]);
}).catch((e) => {
if (signal == null ? void 0 : signal.aborted) {
updateResult(promiseState.aborted, e);
return e;
}
updateResult(promiseState.rejected, e);
onError();
return e;
});
}, Promise.resolve());
return {
activeIndex,
result
};
}
function whenAborted(signal) {
return new Promise((resolve, reject) => {
const error = new Error("aborted");
if (signal.aborted)
reject(error);
else
signal.addEventListener("abort", () => reject(error), { once: true });
});
}
function useAsyncState(promise, initialState, options) {
var _a;
const {
immediate = true,
delay = 0,
onError = (_a = globalThis.reportError) != null ? _a : noop,
onSuccess = noop,
resetOnExecute = true,
shallow = true,
throwError
} = options != null ? options : {};
const state = shallow ? shallowRef(initialState) : ref(initialState);
const isReady = shallowRef(false);
const isLoading = shallowRef(false);
const error = shallowRef(void 0);
async function execute(delay2 = 0, ...args) {
if (resetOnExecute)
state.value = toValue(initialState);
error.value = void 0;
isReady.value = false;
isLoading.value = true;
if (delay2 > 0)
await promiseTimeout(delay2);
const _promise = typeof promise === "function" ? promise(...args) : promise;
try {
const data = await _promise;
state.value = data;
isReady.value = true;
onSuccess(data);
} catch (e) {
error.value = e;
onError(e);
if (throwError)
throw e;
} finally {
isLoading.value = false;
}
return state.value;
}
if (immediate) {
execute(delay);
}
const shell = {
state,
isReady,
isLoading,
error,
execute,
executeImmediate: (...args) => execute(0, ...args)
};
function waitUntilIsLoaded() {
return new Promise((resolve, reject) => {
until(isLoading).toBe(false).then(() => resolve(shell)).catch(reject);
});
}
return {
...shell,
then(onFulfilled, onRejected) {
return waitUntilIsLoaded().then(onFulfilled, onRejected);
}
};
}
const defaults = {
array: (v) => JSON.stringify(v),
object: (v) => JSON.stringify(v),
set: (v) => JSON.stringify(Array.from(v)),
map: (v) => JSON.stringify(Object.fromEntries(v)),
null: () => ""
};
function getDefaultSerialization(target) {
if (!target)
return defaults.null;
if (target instanceof Map)
return defaults.map;
else if (target instanceof Set)
return defaults.set;
else if (Array.isArray(target))
return defaults.array;
else
return defaults.object;
}
function useBase64(target, options) {
const base64 = shallowRef("");
const promise = shallowRef();
function execute() {
if (!isClient)
return;
promise.value = new Promise((resolve, reject) => {
try {
const _target = toValue(target);
if (_target == null) {
resolve("");
} else if (typeof _target === "string") {
resolve(blobToBase64(new Blob([_target], { type: "text/plain" })));
} else if (_target instanceof Blob) {
resolve(blobToBase64(_target));
} else if (_target instanceof ArrayBuffer) {
resolve(window.btoa(String.fromCharCode(...new Uint8Array(_target))));
} else if (_target instanceof HTMLCanvasElement) {
resolve(_target.toDataURL(options == null ? void 0 : options.type, options == null ? void 0 : options.quality));
} else if (_target instanceof HTMLImageElement) {
const img = _target.cloneNode(false);
img.crossOrigin = "Anonymous";
imgLoaded(img).then(() => {
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
resolve(canvas.toDataURL(options == null ? void 0 : options.type, options == null ? void 0 : options.quality));
}).catch(reject);
} else if (typeof _target === "object") {
const _serializeFn = (options == null ? void 0 : options.serializer) || getDefaultSerialization(_target);
const serialized = _serializeFn(_target);
return resolve(blobToBase64(new Blob([serialized], { type: "application/json" })));
} else {
reject(new Error("target is unsupported types"));
}
} catch (error) {
reject(error);
}
});
promise.value.then((res) => {
base64.value = (options == null ? void 0 : options.dataUrl) === false ? res.replace(/^data:.*?;base64,/, "") : res;
});
return promise.value;
}
if (isRef(target) || typeof target === "function")
watch(target, execute, { immediate: true });
else
execute();
return {
base64,
promise,
execute
};
}
function imgLoaded(img) {
return new Promise((resolve, reject) => {
if (!img.complete) {
img.onload = () => {
resolve();
};
img.onerror = reject;
} else {
resolve();
}
});
}
function blobToBase64(blob) {
return new Promise((resolve, reject) => {
const fr = new FileReader();
fr.onload = (e) => {
resolve(e.target.result);
};
fr.onerror = reject;
fr.readAsDataURL(blob);
});
}
// @__NO_SIDE_EFFECTS__
function useBattery(options = {}) {
const { navigator = defaultNavigator } = options;
const events = ["chargingchange", "chargingtimechange", "dischargingtimechange", "levelchange"];
const isSupported = useSupported(() => navigator && "getBattery" in navigator && typeof navigator.getBattery === "function");
const charging = shallowRef(false);
const chargingTime = shallowRef(0);
const dischargingTime = shallowRef(0);
const level = shallowRef(1);
let battery;
function updateBatteryInfo() {
charging.value = this.charging;
chargingTime.value = this.chargingTime || 0;
dischargingTime.value = this.dischargingTime || 0;
level.value = this.level;
}
if (isSupported.value) {
navigator.getBattery().then((_battery) => {
battery = _battery;
updateBatteryInfo.call(battery);
useEventListener(battery, events, updateBatteryInfo, { passive: true });
});
}
return {
isSupported,
charging,
chargingTime,
dischargingTime,
level
};
}
// @__NO_SIDE_EFFECTS__
function useBluetooth(options) {
let {
acceptAllDevices = false
} = options || {};
const {
filters = void 0,
optionalServices = void 0,
navigator = defaultNavigator
} = options || {};
const isSupported = useSupported(() => navigator && "bluetooth" in navigator);
const device = shallowRef();
const error = shallowRef(null);
watch(device, () => {
connectToBluetoothGATTServer();
});
async function requestDevice() {
if (!isSupported.value)
return;
error.value = null;
if (filters && filters.length > 0)
acceptAllDevices = false;
try {
device.value = await (navigator == null ? void 0 : navigator.bluetooth.requestDevice({
acceptAllDevices,
filters,
optionalServices
}));
} catch (err) {
error.value = err;
}
}
const server = shallowRef();
const isConnected = shallowRef(false);
function reset() {
isConnected.value = false;
device.value = void 0;
server.value = void 0;
}
async function connectToBluetoothGATTServer() {
error.value = null;
if (device.value && device.value.gatt) {
useEventListener(device, "gattserverdisconnected", reset, { passive: true });
try {
server.value = await device.value.gatt.connect();
isConnected.value = server.value.connected;
} catch (err) {
error.value = err;
}
}
}
tryOnMounted(() => {
var _a;
if (device.value)
(_a = device.value.gatt) == null ? void 0 : _a.connect();
});
tryOnScopeDispose(() => {
var _a;
if (device.value)
(_a = device.value.gatt) == null ? void 0 : _a.disconnect();
});
return {
isSupported,
isConnected: readonly(isConnected),
// Device:
device,
requestDevice,
// Server:
server,
// Errors:
error
};
}
const ssrWidthSymbol = Symbol("vueuse-ssr-width");
// @__NO_SIDE_EFFECTS__
function useSSRWidth() {
const ssrWidth = hasInjectionContext() ? injectLocal(ssrWidthSymbol, null) : null;
return typeof ssrWidth === "number" ? ssrWidth : void 0;
}
function provideSSRWidth(width, app) {
if (app !== void 0) {
app.provide(ssrWidthSymbol, width);
} else {
provideLocal(ssrWidthSymbol, width);
}
}
function useMediaQuery(query, options = {}) {
const { window = defaultWindow, ssrWidth = useSSRWidth() } = options;
const isSupported = useSupported(() => window && "matchMedia" in window && typeof window.matchMedia === "function");
const ssrSupport = shallowRef(typeof ssrWidth === "number");
const mediaQuery = shallowRef();
const matches = shallowRef(false);
const handler = (event) => {
matches.value = event.matches;
};
watchEffect(() => {
if (ssrSupport.value) {
ssrSupport.value = !isSupported.value;
const queryStrings = toValue(query).split(",");
matches.value = queryStrings.some((queryString) => {
const not = queryString.includes("not all");
const minWidth = queryString.match(/\(\s*min-width:\s*(-?\d+(?:\.\d*)?[a-z]+\s*)\)/);
const maxWidth = queryString.match(/\(\s*max-width:\s*(-?\d+(?:\.\d*)?[a-z]+\s*)\)/);
let res = Boolean(minWidth || maxWidth);
if (minWidth && res) {
res = ssrWidth >= pxValue(minWidth[1]);
}
if (maxWidth && res) {
res = ssrWidth <= pxValue(maxWidth[1]);
}
return not ? !res : res;
});
return;
}
if (!isSupported.value)
return;
mediaQuery.value = window.matchMedia(toValue(query));
matches.value = mediaQuery.value.matches;
});
useEventListener(mediaQuery, "change", handler, { passive: true });
return computed(() => matches.value);
}
const breakpointsTailwind = {
"sm": 640,
"md": 768,
"lg": 1024,
"xl": 1280,
"2xl": 1536
};
const breakpointsBootstrapV5 = {
xs: 0,
sm: 576,
md: 768,
lg: 992,
xl: 1200,
xxl: 1400
};
const breakpointsVuetifyV2 = {
xs: 0,
sm: 600,
md: 960,
lg: 1264,
xl: 1904
};
const breakpointsVuetifyV3 = {
xs: 0,
sm: 600,
md: 960,
lg: 1280,
xl: 1920,
xxl: 2560
};
const breakpointsVuetify = breakpointsVuetifyV2;
const breakpointsAntDesign = {
xs: 480,
sm: 576,
md: 768,
lg: 992,
xl: 1200,
xxl: 1600
};
const breakpointsQuasar = {
xs: 0,
sm: 600,
md: 1024,
lg: 1440,
xl: 1920
};
const breakpointsSematic = {
mobileS: 320,
mobileM: 375,
mobileL: 425,
tablet: 768,
laptop: 1024,
laptopL: 1440,
desktop4K: 2560
};
const breakpointsMasterCss = {
"3xs": 360,
"2xs": 480,
"xs": 600,
"sm": 768,
"md": 1024,
"lg": 1280,
"xl": 1440,
"2xl": 1600,
"3xl": 1920,
"4xl": 2560
};
const breakpointsPrimeFlex = {
sm: 576,
md: 768,
lg: 992,
xl: 1200
};
const breakpointsElement = {
xs: 0,
sm: 768,
md: 992,
lg: 1200,
xl: 1920
};
// @__NO_SIDE_EFFECTS__
function useBreakpoints(breakpoints, options = {}) {
function getValue(k, delta) {
let v = toValue(breakpoints[toValue(k)]);
if (delta != null)
v = increaseWithUnit(v, delta);
if (typeof v === "number")
v = `${v}px`;
return v;
}
const { window = defaultWindow, strategy = "min-width", ssrWidth = useSSRWidth() } = options;
const ssrSupport = typeof ssrWidth === "number";
const mounted = ssrSupport ? shallowRef(false) : { value: true };
if (ssrSupport) {
tryOnMounted(() => mounted.value = !!window);
}
function match(query, size) {
if (!mounted.value && ssrSupport) {
return query === "min" ? ssrWidth >= pxValue(size) : ssrWidth <= pxValue(size);
}
if (!window)
return false;
return window.matchMedia(`(${query}-width: ${size})`).matches;
}
const greaterOrEqual = (k) => {
return useMediaQuery(() => `(min-width: ${getValue(k)})`, options);
};
const smallerOrEqual = (k) => {
return useMediaQuery(() => `(max-width: ${getValue(k)})`, options);
};
const shortcutMethods = Object.keys(breakpoints).reduce((shortcuts, k) => {
Object.defineProperty(shortcuts, k, {
get: () => strategy === "min-width" ? greaterOrEqual(k) : smallerOrEqual(k),
enumerable: true,
configurable: true
});
return shortcuts;
}, {});
function current() {
const points = Object.keys(breakpoints).map((k) => [k, shortcutMethods[k], pxValue(getValue(k))]).sort((a, b) => a[2] - b[2]);
return computed(() => points.filter(([, v]) => v.value).map(([k]) => k));
}
return Object.assign(shortcutMethods, {
greaterOrEqual,
smallerOrEqual,
greater(k) {
return useMediaQuery(() => `(min-width: ${getValue(k, 0.1)})`, options);
},
smaller(k) {
return useMediaQuery(() => `(max-width: ${getValue(k, -0.1)})`, options);
},
between(a, b) {
return useMediaQuery(() => `(min-width: ${getValue(a)}) and (max-width: ${getValue(b, -0.1)})`, options);
},
isGreater(k) {
return match("min", getValue(k, 0.1));
},
isGreaterOrEqual(k) {
return match("min", getValue(k));
},
isSmaller(k) {
return match("max", getValue(k, -0.1));
},
isSmallerOrEqual(k) {
return match("max", getValue(k));
},
isInBetween(a, b) {
return match("min", getValue(a)) && match("max", getValue(b, -0.1));
},
current,
active() {
const bps = current();
return computed(() => bps.value.length === 0 ? "" : bps.value.at(strategy === "min-width" ? -1 : 0));
}
});
}
function useBroadcastChannel(options) {
const {
name,
window = defaultWindow
} = options;
const isSupported = useSupported(() => window && "BroadcastChannel" in window);
const isClosed = shallowRef(false);
const channel = ref();
const data = ref();
const error = shallowRef(null);
const post = (data2) => {
if (channel.value)
channel.value.postMessage(data2);
};
const close = () => {
if (channel.value)
channel.value.close();
isClosed.value = true;
};
if (isSupported.value) {
tryOnMounted(() => {
error.value = null;
channel.value = new BroadcastChannel(name);
const listenerOptions = {
passive: true
};
useEventListener(channel, "message", (e) => {
data.value = e.data;
}, listenerOptions);
useEventListener(channel, "messageerror", (e) => {
error.value = e;
}, listenerOptions);
useEventListener(channel, "close", () => {
isClosed.value = true;
}, listenerOptions);
});
}
tryOnScopeDispose(() => {
close();
});
return {
isSupported,
channel,
data,
post,
close,
error,
isClosed
};
}
const WRITABLE_PROPERTIES = [
"hash",
"host",
"hostname",
"href",
"pathname",
"port",
"protocol",
"search"
];
// @__NO_SIDE_EFFECTS__
function useBrowserLocation(options = {}) {
const { window = defaultWindow } = options;
const refs = Object.fromEntries(
WRITABLE_PROPERTIES.map((key) => [key, ref()])
);
for (const [key, ref] of objectEntries(refs)) {
watch(ref, (value) => {
if (!(window == null ? void 0 : window.location) || window.location[key] === value)
return;
window.location[key] = value;
});
}
const buildState = (trigger) => {
var _a;
const { state: state2, length } = (window == null ? void 0 : window.history) || {};
const { origin } = (window == null ? void 0 : window.location) || {};
for (const key of WRITABLE_PROPERTIES)
refs[key].value = (_a = window == null ? void 0 : window.location) == null ? void 0 : _a[key];
return reactive({
trigger,
state: state2,
length,
origin,
...refs
});
};
const state = ref(buildState("load"));
if (window) {
const listenerOptions = { passive: true };
useEventListener(window, "popstate", () => state.value = buildState("popstate"), listenerOptions);
useEventListener(window, "hashchange", () => state.value = buildState("hashchange"), listenerOptions);
}
return state;
}
function useCached(refValue, comparator = (a, b) => a === b, options) {
const { deepRefs = true, ...watchOptions } = options || {};
const cachedValue = createRef(refValue.value, deepRefs);
watch(() => refValue.value, (value) => {
if (!comparator(value, cachedValue.value))
cachedValue.value = value;
}, watchOptions);
return cachedValue;
}
// @__NO_SIDE_EFFECTS__
function usePermission(permissionDesc, options = {}) {
const {
controls = false,
navigator = defaultNavigator
} = options;
const isSupported = useSupported(() => navigator && "permissions" in navigator);
const permissionStatus = shallowRef();
const desc = typeof permissionDesc === "string" ? { name: permissionDesc } : permissionDesc;
const state = shallowRef();
const update = () => {
var _a, _b;
state.value = (_b = (_a = permissionStatus.value) == null ? void 0 : _a.state) != null ? _b : "prompt";
};
useEventListener(permissionStatus, "change", update, { passive: true });
const query = createSingletonPromise(async () => {
if (!isSupported.value)
return;
if (!permissionStatus.value) {
try {
permissionStatus.value = await navigator.permissions.query(desc);
} catch (e) {
permissionStatus.value = void 0;
} finally {
update();
}
}
if (controls)
return toRaw(permissionStatus.value);
});
query();
if (controls) {
return {
state,
isSupported,
query
};
} else {
return state;
}
}
function useClipboard(options = {}) {
const {
navigator = defaultNavigator,
read = false,
source,
copiedDuring = 1500,
legacy = false
} = options;
const isClipboardApiSupported = useSupported(() => navigator && "clipboard" in navigator);
const permissionRead = usePermission("clipboard-read");
const permissionWrite = usePermission("clipboard-write");
const isSupported = computed(() => isClipboardApiSupported.value || legacy);
const text = shallowRef("");
const copied = shallowRef(false);
const timeout = useTimeoutFn(() => copied.value = false, copiedDuring, { immediate: false });
async function updateText() {
let useLegacy = !(isClipboardApiSupported.value && isAllowed(permissionRead.value));
if (!useLegacy) {
try {
text.value = await navigator.clipboard.readText();
} catch (e) {
useLegacy = true;
}
}
if (useLegacy) {
text.value = legacyRead();
}
}
if (isSupported.value && read)
useEventListener(["copy", "cut"], updateText, { passive: true });
async function copy(value = toValue(source)) {
if (isSupported.value && value != null) {
let useLegacy = !(isClipboardApiSupported.value && isAllowed(permissionWrite.value));
if (!useLegacy) {
try {
await navigator.clipboard.writeText(value);
} catch (e) {
useLegacy = true;
}
}
if (useLegacy)
legacyCopy(value);
text.value = value;
copied.value = true;
timeout.start();
}
}
function legacyCopy(value) {
const ta = document.createElement("textarea");
ta.value = value != null ? value : "";
ta.style.position = "absolute";
ta.style.opacity = "0";
document.body.appendChild(ta);
ta.select();
document.execCommand("copy");
ta.remove();
}
function legacyRead() {
var _a, _b, _c;
return (_c = (_b = (_a = document == null ? void 0 : document.getSelection) == null ? void 0 : _a.call(document)) == null ? void 0 : _b.toString()) != null ? _c : "";
}
function isAllowed(status) {
return status === "granted" || status === "prompt";
}
return {
isSupported,
text,
copied,
copy
};
}
function useClipboardItems(options = {}) {
const {
navigator = defaultNavigator,
read = false,
source,
copiedDuring = 1500
} = options;
const isSupported = useSupported(() => navigator && "clipboard" in navigator);
const content = ref([]);
const copied = shallowRef(false);
const timeout = useTimeoutFn(() => copied.value = false, copiedDuring, { immediate: false });
function updateContent() {
if (isSupported.value) {
navigator.clipboard.read().then((items) => {
content.value = ite