UNPKG

@vueuse/core

Version:

Collection of essential Vue Composition Utilities

1,745 lines (1,709 loc) 244 kB
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