UNPKG

@vueuse/core

Version:

Collection of essential Vue Composition Utilities

1,521 lines (1,489 loc) 293 kB
(function(exports, __vueuse_shared, vue) { //#region rolldown:runtime var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") for (var keys$1 = __getOwnPropNames(from), i = 0, n = keys$1.length, key; i < n; i++) { key = keys$1[i]; if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: ((k) => from[k]).bind(null, key), enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod)); //#endregion __vueuse_shared = __toESM(__vueuse_shared); vue = __toESM(vue); //#region computedAsync/index.ts function computedAsync(evaluationCallback, initialState, optionsOrRef) { var _globalThis$reportErr; let options; if ((0, vue.isRef)(optionsOrRef)) options = { evaluating: optionsOrRef }; else options = optionsOrRef || {}; const { lazy = false, flush = "sync", evaluating = void 0, shallow = true, onError = (_globalThis$reportErr = globalThis.reportError) !== null && _globalThis$reportErr !== void 0 ? _globalThis$reportErr : __vueuse_shared.noop } = options; const started = (0, vue.shallowRef)(!lazy); const current = shallow ? (0, vue.shallowRef)(initialState) : (0, vue.ref)(initialState); let counter = 0; (0, vue.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 (0, vue.computed)(() => { started.value = true; return current.value; }); else return current; } /** @deprecated use `computedAsync` instead */ const asyncComputed = computedAsync; //#endregion //#region computedInject/index.ts function computedInject(key, options, defaultSource, treatDefaultAsFactory) { let source = (0, vue.inject)(key); if (defaultSource) source = (0, vue.inject)(key, defaultSource); if (treatDefaultAsFactory) source = (0, vue.inject)(key, defaultSource, treatDefaultAsFactory); if (typeof options === "function") return (0, vue.computed)((oldValue) => options(source, oldValue)); else return (0, vue.computed)({ get: (oldValue) => options.get(source, oldValue), set: options.set }); } //#endregion //#region createReusableTemplate/index.ts /** * This function creates `define` and `reuse` components in pair, * It also allow to pass a generic to bind with type. * * @see https://vueuse.org/createReusableTemplate * * @__NO_SIDE_EFFECTS__ */ function createReusableTemplate(options = {}) { const { inheritAttrs = true } = options; const render = (0, vue.shallowRef)(); const define = (0, vue.defineComponent)({ setup(_, { slots }) { return () => { render.value = slots.default; }; } }); const reuse = (0, vue.defineComponent)({ inheritAttrs, props: options.props, setup(props, { attrs, slots }) { return () => { var _render$value; if (!render.value && true) throw new Error("[VueUse] Failed to find the definition of reusable template"); const vnode = (_render$value = render.value) === null || _render$value === void 0 ? void 0 : _render$value.call(render, { ...options.props == null ? keysToCamelKebabCase(attrs) : props, $slots: slots }); return inheritAttrs && (vnode === null || vnode === void 0 ? void 0 : vnode.length) === 1 ? vnode[0] : vnode; }; } }); return (0, __vueuse_shared.makeDestructurable)({ define, reuse }, [define, reuse]); } function keysToCamelKebabCase(obj) { const newObj = {}; for (const key in obj) newObj[(0, __vueuse_shared.camelize)(key)] = obj[key]; return newObj; } //#endregion //#region createTemplatePromise/index.ts /** * Creates a template promise component. * * @see https://vueuse.org/createTemplatePromise * * @__NO_SIDE_EFFECTS__ */ function createTemplatePromise(options = {}) { let index = 0; const instances = (0, vue.ref)([]); function create(...args) { const props = (0, vue.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 index$1 = instances.value.indexOf(props); if (index$1 !== -1) instances.value.splice(index$1, 1); }); return props.promise; } function start(...args) { if (options.singleton && instances.value.length > 0) return instances.value[0].promise; return create(...args); } const component = (0, vue.defineComponent)((_, { slots }) => { const renderList = () => instances.value.map((props) => { var _slots$default; return (0, vue.h)(vue.Fragment, { key: props.key }, (_slots$default = slots.default) === null || _slots$default === void 0 ? void 0 : _slots$default.call(slots, props)); }); if (options.transition) return () => (0, vue.h)(vue.TransitionGroup, options.transition, renderList); return renderList; }); component.start = start; return component; } //#endregion //#region createUnrefFn/index.ts /** * Make a plain function accepting ref and raw values as arguments. * Returns the same value the unconverted function returns, with proper typing. * * @__NO_SIDE_EFFECTS__ */ function createUnrefFn(fn) { return function(...args) { return fn.apply(this, args.map((i) => (0, vue.toValue)(i))); }; } //#endregion //#region _configurable.ts const defaultWindow = __vueuse_shared.isClient ? window : void 0; const defaultDocument = __vueuse_shared.isClient ? window.document : void 0; const defaultNavigator = __vueuse_shared.isClient ? window.navigator : void 0; const defaultLocation = __vueuse_shared.isClient ? window.location : void 0; //#endregion //#region unrefElement/index.ts /** * Get the dom element of a ref of element or Vue component instance * * @param elRef */ function unrefElement(elRef) { var _$el; const plain = (0, vue.toValue)(elRef); return (_$el = plain === null || plain === void 0 ? void 0 : plain.$el) !== null && _$el !== void 0 ? _$el : plain; } //#endregion //#region useEventListener/index.ts function useEventListener(...args) { const register = (el, event, listener, options) => { el.addEventListener(event, listener, options); return () => el.removeEventListener(event, listener, options); }; const firstParamTargets = (0, vue.computed)(() => { const test = (0, __vueuse_shared.toArray)((0, vue.toValue)(args[0])).filter((e) => e != null); return test.every((e) => typeof e !== "string") ? test : void 0; }); return (0, __vueuse_shared.watchImmediate)(() => { var _firstParamTargets$va, _firstParamTargets$va2; return [ (_firstParamTargets$va = (_firstParamTargets$va2 = firstParamTargets.value) === null || _firstParamTargets$va2 === void 0 ? void 0 : _firstParamTargets$va2.map((e) => unrefElement(e))) !== null && _firstParamTargets$va !== void 0 ? _firstParamTargets$va : [defaultWindow].filter((e) => e != null), (0, __vueuse_shared.toArray)((0, vue.toValue)(firstParamTargets.value ? args[1] : args[0])), (0, __vueuse_shared.toArray)((0, vue.unref)(firstParamTargets.value ? args[2] : args[1])), (0, vue.toValue)(firstParamTargets.value ? args[3] : args[2]) ]; }, ([raw_targets, raw_events, raw_listeners, raw_options], _, onCleanup) => { if (!(raw_targets === null || raw_targets === void 0 ? void 0 : raw_targets.length) || !(raw_events === null || raw_events === void 0 ? void 0 : raw_events.length) || !(raw_listeners === null || raw_listeners === void 0 ? void 0 : raw_listeners.length)) return; const optionsClone = (0, __vueuse_shared.isObject)(raw_options) ? { ...raw_options } : raw_options; const cleanups = raw_targets.flatMap((el) => raw_events.flatMap((event) => raw_listeners.map((listener) => register(el, event, listener, optionsClone)))); onCleanup(() => { cleanups.forEach((fn) => fn()); }); }, { flush: "post" }); } //#endregion //#region onClickOutside/index.ts let _iOSWorkaround = false; function onClickOutside(target, handler, options = {}) { const { window: window$1 = defaultWindow, ignore = [], capture = true, detectIframe = false, controls = false } = options; if (!window$1) return controls ? { stop: __vueuse_shared.noop, cancel: __vueuse_shared.noop, trigger: __vueuse_shared.noop } : __vueuse_shared.noop; if (__vueuse_shared.isIOS && !_iOSWorkaround) { _iOSWorkaround = true; const listenerOptions = { passive: true }; Array.from(window$1.document.body.children).forEach((el) => el.addEventListener("click", __vueuse_shared.noop, listenerOptions)); window$1.document.documentElement.addEventListener("click", __vueuse_shared.noop, listenerOptions); } let shouldListen = true; const shouldIgnore = (event) => { return (0, vue.toValue)(ignore).some((target$1) => { if (typeof target$1 === "string") return Array.from(window$1.document.querySelectorAll(target$1)).some((el) => el === event.target || event.composedPath().includes(el)); else { const el = unrefElement(target$1); return el && (event.target === el || event.composedPath().includes(el)); } }); }; /** * Determines if the given target has multiple root elements. * Referenced from: https://github.com/vuejs/test-utils/blob/ccb460be55f9f6be05ab708500a41ec8adf6f4bc/src/vue-wrapper.ts#L21 */ function hasMultipleRoots(target$1) { const vm = (0, vue.toValue)(target$1); return vm && vm.$.subTree.shapeFlag === 16; } function checkMultipleRoots(target$1, event) { const vm = (0, vue.toValue)(target$1); 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$1, "click", (event) => { if (!isProcessingClick) { isProcessingClick = true; setTimeout(() => { isProcessingClick = false; }, 0); listener(event); } }, { passive: true, capture }), useEventListener(window$1, "pointerdown", (e) => { const el = unrefElement(target); shouldListen = !shouldIgnore(e) && !!(el && !e.composedPath().includes(el)); }, { passive: true }), detectIframe && useEventListener(window$1, "blur", (event) => { setTimeout(() => { var _window$document$acti; const el = unrefElement(target); if (((_window$document$acti = window$1.document.activeElement) === null || _window$document$acti === void 0 ? void 0 : _window$document$acti.tagName) === "IFRAME" && !(el === null || el === void 0 ? void 0 : el.contains(window$1.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; } //#endregion //#region useMounted/index.ts /** * Mounted state in ref. * * @see https://vueuse.org/useMounted * * @__NO_SIDE_EFFECTS__ */ function useMounted() { const isMounted = (0, vue.shallowRef)(false); const instance = (0, vue.getCurrentInstance)(); if (instance) (0, vue.onMounted)(() => { isMounted.value = true; }, instance); return isMounted; } //#endregion //#region useSupported/index.ts /* @__NO_SIDE_EFFECTS__ */ function useSupported(callback) { const isMounted = useMounted(); return (0, vue.computed)(() => { isMounted.value; return Boolean(callback()); }); } //#endregion //#region useMutationObserver/index.ts /** * Watch for changes being made to the DOM tree. * * @see https://vueuse.org/useMutationObserver * @see https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver MutationObserver MDN * @param target * @param callback * @param options */ function useMutationObserver(target, callback, options = {}) { const { window: window$1 = defaultWindow,...mutationOptions } = options; let observer; const isSupported = /* @__PURE__ */ useSupported(() => window$1 && "MutationObserver" in window$1); const cleanup = () => { if (observer) { observer.disconnect(); observer = void 0; } }; const stopWatch = (0, vue.watch)((0, vue.computed)(() => { const items = (0, __vueuse_shared.toArray)((0, vue.toValue)(target)).map(unrefElement).filter(__vueuse_shared.notNullish); return new Set(items); }), (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 || observer === void 0 ? void 0 : observer.takeRecords(); }; const stop = () => { stopWatch(); cleanup(); }; (0, __vueuse_shared.tryOnScopeDispose)(stop); return { isSupported, stop, takeRecords }; } //#endregion //#region onElementRemoval/index.ts /** * Fires when the element or any element containing it is removed. * * @param target * @param callback * @param options */ function onElementRemoval(target, callback, options = {}) { const { window: window$1 = defaultWindow, document: document$1 = window$1 === null || window$1 === void 0 ? void 0 : window$1.document, flush = "sync" } = options; if (!window$1 || !document$1) return __vueuse_shared.noop; let stopFn; const cleanupAndUpdate = (fn) => { stopFn === null || stopFn === void 0 || stopFn(); stopFn = fn; }; const stopWatch = (0, vue.watchEffect)(() => { const el = unrefElement(target); if (el) { const { stop } = useMutationObserver(document$1, (mutationsList) => { if (mutationsList.map((mutation) => [...mutation.removedNodes]).flat().some((node) => node === el || node.contains(el))) callback(mutationsList); }, { window: window$1, childList: true, subtree: true }); cleanupAndUpdate(stop); } }, { flush }); const stopHandle = () => { stopWatch(); cleanupAndUpdate(); }; (0, __vueuse_shared.tryOnScopeDispose)(stopHandle); return stopHandle; } //#endregion //#region onKeyStroke/index.ts 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 && (0, vue.toValue)(dedupe)) return; if (predicate(e)) handler(e); }; return useEventListener(target, eventName, listener, passive); } /** * Listen to the keydown event of the given key. * * @see https://vueuse.org/onKeyStroke * @param key * @param handler * @param options */ function onKeyDown(key, handler, options = {}) { return onKeyStroke(key, handler, { ...options, eventName: "keydown" }); } /** * Listen to the keypress event of the given key. * * @see https://vueuse.org/onKeyStroke * @param key * @param handler * @param options */ function onKeyPressed(key, handler, options = {}) { return onKeyStroke(key, handler, { ...options, eventName: "keypress" }); } /** * Listen to the keyup event of the given key. * * @see https://vueuse.org/onKeyStroke * @param key * @param handler * @param options */ function onKeyUp(key, handler, options = {}) { return onKeyStroke(key, handler, { ...options, eventName: "keyup" }); } //#endregion //#region onLongPress/index.ts const DEFAULT_DELAY = 500; const DEFAULT_THRESHOLD = 10; function onLongPress(target, handler, options) { var _options$modifiers10, _options$modifiers11; const elementRef = (0, vue.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 || options === void 0 ? void 0 : options.delay; if (typeof delay === "function") return delay(ev); return delay !== null && delay !== void 0 ? delay : DEFAULT_DELAY; } function onRelease(ev) { var _options$modifiers, _options$modifiers2, _options$modifiers3; const [_startTimestamp, _posStart, _hasLongPressed] = [ startTimestamp, posStart, hasLongPressed ]; clear(); if (!(options === null || options === void 0 ? void 0 : options.onMouseUp) || !_posStart || !_startTimestamp) return; if ((options === null || options === void 0 || (_options$modifiers = options.modifiers) === null || _options$modifiers === void 0 ? void 0 : _options$modifiers.self) && ev.target !== elementRef.value) return; if (options === null || options === void 0 || (_options$modifiers2 = options.modifiers) === null || _options$modifiers2 === void 0 ? void 0 : _options$modifiers2.prevent) ev.preventDefault(); if (options === null || options === void 0 || (_options$modifiers3 = options.modifiers) === null || _options$modifiers3 === void 0 ? void 0 : _options$modifiers3.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 _options$modifiers4, _options$modifiers5, _options$modifiers6; if ((options === null || options === void 0 || (_options$modifiers4 = options.modifiers) === null || _options$modifiers4 === void 0 ? void 0 : _options$modifiers4.self) && ev.target !== elementRef.value) return; clear(); if (options === null || options === void 0 || (_options$modifiers5 = options.modifiers) === null || _options$modifiers5 === void 0 ? void 0 : _options$modifiers5.prevent) ev.preventDefault(); if (options === null || options === void 0 || (_options$modifiers6 = options.modifiers) === null || _options$modifiers6 === void 0 ? void 0 : _options$modifiers6.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 _options$modifiers7, _options$modifiers8, _options$modifiers9, _options$distanceThre; if ((options === null || options === void 0 || (_options$modifiers7 = options.modifiers) === null || _options$modifiers7 === void 0 ? void 0 : _options$modifiers7.self) && ev.target !== elementRef.value) return; if (!posStart || (options === null || options === void 0 ? void 0 : options.distanceThreshold) === false) return; if (options === null || options === void 0 || (_options$modifiers8 = options.modifiers) === null || _options$modifiers8 === void 0 ? void 0 : _options$modifiers8.prevent) ev.preventDefault(); if (options === null || options === void 0 || (_options$modifiers9 = options.modifiers) === null || _options$modifiers9 === void 0 ? void 0 : _options$modifiers9.stop) ev.stopPropagation(); const dx = ev.x - posStart.x; const dy = ev.y - posStart.y; if (Math.sqrt(dx * dx + dy * dy) >= ((_options$distanceThre = options === null || options === void 0 ? void 0 : options.distanceThreshold) !== null && _options$distanceThre !== void 0 ? _options$distanceThre : DEFAULT_THRESHOLD)) clear(); } const listenerOptions = { capture: options === null || options === void 0 || (_options$modifiers10 = options.modifiers) === null || _options$modifiers10 === void 0 ? void 0 : _options$modifiers10.capture, once: options === null || options === void 0 || (_options$modifiers11 = options.modifiers) === null || _options$modifiers11 === void 0 ? void 0 : _options$modifiers11.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; } //#endregion //#region onStartTyping/index.ts 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; } /** * Fires when users start typing on non-editable elements. * * @see https://vueuse.org/onStartTyping * @param callback * @param options */ function onStartTyping(callback, options = {}) { const { document: document$1 = defaultDocument } = options; const keydown = (event) => { if (!isFocusedElementEditable() && isTypedCharValid(event)) callback(event); }; if (document$1) useEventListener(document$1, "keydown", keydown, { passive: true }); } //#endregion //#region templateRef/index.ts /** * @deprecated Use Vue's built-in `useTemplateRef` instead. * * Shorthand for binding ref to template element. * * @see https://vueuse.org/templateRef * @param key * @param initialValue * * @__NO_SIDE_EFFECTS__ */ function templateRef(key, initialValue = null) { const instance = (0, vue.getCurrentInstance)(); let _trigger = () => {}; const element = (0, vue.customRef)((track, trigger) => { _trigger = trigger; return { get() { var _instance$proxy$$refs, _instance$proxy; track(); return (_instance$proxy$$refs = instance === null || instance === void 0 || (_instance$proxy = instance.proxy) === null || _instance$proxy === void 0 ? void 0 : _instance$proxy.$refs[key]) !== null && _instance$proxy$$refs !== void 0 ? _instance$proxy$$refs : initialValue; }, set() {} }; }); (0, __vueuse_shared.tryOnMounted)(_trigger); (0, vue.onUpdated)(_trigger); return element; } //#endregion //#region useActiveElement/index.ts /** * Reactive `document.activeElement` * * @see https://vueuse.org/useActiveElement * @param options * * @__NO_SIDE_EFFECTS__ */ function useActiveElement(options = {}) { var _options$document; const { window: window$1 = defaultWindow, deep = true, triggerOnRemoval = false } = options; const document$1 = (_options$document = options.document) !== null && _options$document !== void 0 ? _options$document : window$1 === null || window$1 === void 0 ? void 0 : window$1.document; const getDeepActiveElement = () => { let element = document$1 === null || document$1 === void 0 ? void 0 : document$1.activeElement; if (deep) { var _element$shadowRoot; while (element === null || element === void 0 ? void 0 : element.shadowRoot) element = element === null || element === void 0 || (_element$shadowRoot = element.shadowRoot) === null || _element$shadowRoot === void 0 ? void 0 : _element$shadowRoot.activeElement; } return element; }; const activeElement = (0, vue.shallowRef)(); const trigger = () => { activeElement.value = getDeepActiveElement(); }; if (window$1) { const listenerOptions = { capture: true, passive: true }; useEventListener(window$1, "blur", (event) => { if (event.relatedTarget !== null) return; trigger(); }, listenerOptions); useEventListener(window$1, "focus", trigger, listenerOptions); } if (triggerOnRemoval) onElementRemoval(activeElement, trigger, { document: document$1 }); trigger(); return activeElement; } //#endregion //#region useRafFn/index.ts /** * Call function on every `requestAnimationFrame`. With controls of pausing and resuming. * * @see https://vueuse.org/useRafFn * @param fn * @param options */ function useRafFn(fn, options = {}) { const { immediate = true, fpsLimit = void 0, window: window$1 = defaultWindow, once = false } = options; const isActive = (0, vue.shallowRef)(false); const intervalLimit = (0, vue.computed)(() => { return fpsLimit ? 1e3 / (0, vue.toValue)(fpsLimit) : null; }); let previousFrameTimestamp = 0; let rafId = null; function loop(timestamp$3) { if (!isActive.value || !window$1) return; if (!previousFrameTimestamp) previousFrameTimestamp = timestamp$3; const delta = timestamp$3 - previousFrameTimestamp; if (intervalLimit.value && delta < intervalLimit.value) { rafId = window$1.requestAnimationFrame(loop); return; } previousFrameTimestamp = timestamp$3; fn({ delta, timestamp: timestamp$3 }); if (once) { isActive.value = false; rafId = null; return; } rafId = window$1.requestAnimationFrame(loop); } function resume() { if (!isActive.value && window$1) { isActive.value = true; previousFrameTimestamp = 0; rafId = window$1.requestAnimationFrame(loop); } } function pause() { isActive.value = false; if (rafId != null && window$1) { window$1.cancelAnimationFrame(rafId); rafId = null; } } if (immediate) resume(); (0, __vueuse_shared.tryOnScopeDispose)(pause); return { isActive: (0, vue.readonly)(isActive), pause, resume }; } //#endregion //#region useAnimate/index.ts /** * Reactive Web Animations API * * @see https://vueuse.org/useAnimate * @param target * @param keyframes * @param options */ function useAnimate(target, keyframes, options) { let config; let animateOptions; if ((0, __vueuse_shared.isObject)(options)) { config = options; animateOptions = (0, __vueuse_shared.objectOmit)(options, [ "window", "immediate", "commitStyles", "persist", "onReady", "onError" ]); } else { config = { duration: options }; animateOptions = options; } const { window: window$1 = defaultWindow, immediate = true, commitStyles, persist, playbackRate: _playbackRate = 1, onReady, onError = (e) => { console.error(e); } } = config; const isSupported = /* @__PURE__ */ useSupported(() => window$1 && HTMLElement && "animate" in HTMLElement.prototype); const animate = (0, vue.shallowRef)(void 0); const store = (0, vue.shallowReactive)({ startTime: null, currentTime: null, timeline: null, playbackRate: _playbackRate, pending: false, playState: immediate ? "idle" : "paused", replaceState: "active" }); const pending = (0, vue.computed)(() => store.pending); const playState = (0, vue.computed)(() => store.playState); const replaceState = (0, vue.computed)(() => store.replaceState); const startTime = (0, vue.computed)({ get() { return store.startTime; }, set(value) { store.startTime = value; if (animate.value) animate.value.startTime = value; } }); const currentTime = (0, vue.computed)({ get() { return store.currentTime; }, set(value) { store.currentTime = value; if (animate.value) { animate.value.currentTime = value; syncResume(); } } }); const timeline = (0, vue.computed)({ get() { return store.timeline; }, set(value) { store.timeline = value; if (animate.value) animate.value.timeline = value; } }); const playbackRate = (0, vue.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 = () => { try { var _animate$value; (_animate$value = animate.value) === null || _animate$value === void 0 || _animate$value.pause(); syncPause(); } catch (e) { onError(e); } }; const reverse = () => { if (!animate.value) update(); try { var _animate$value2; (_animate$value2 = animate.value) === null || _animate$value2 === void 0 || _animate$value2.reverse(); syncResume(); } catch (e) { syncPause(); onError(e); } }; const finish = () => { try { var _animate$value3; (_animate$value3 = animate.value) === null || _animate$value3 === void 0 || _animate$value3.finish(); syncPause(); } catch (e) { onError(e); } }; const cancel = () => { try { var _animate$value4; (_animate$value4 = animate.value) === null || _animate$value4 === void 0 || _animate$value4.cancel(); syncPause(); } catch (e) { onError(e); } }; (0, vue.watch)(() => unrefElement(target), (el) => { if (el) update(true); else animate.value = void 0; }); (0, vue.watch)(() => keyframes, (value) => { if (animate.value) { update(); const targetEl = unrefElement(target); if (targetEl) animate.value.effect = new KeyframeEffect(targetEl, (0, vue.toValue)(value), animateOptions); } }, { deep: true }); (0, __vueuse_shared.tryOnMounted)(() => update(true), false); (0, __vueuse_shared.tryOnScopeDispose)(cancel); function update(init) { const el = unrefElement(target); if (!isSupported.value || !el) return; if (!animate.value) animate.value = el.animate((0, vue.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 || onReady === void 0 || onReady(animate.value); } const listenerOptions = { passive: true }; useEventListener(animate, [ "cancel", "finish", "remove" ], syncPause, listenerOptions); useEventListener(animate, "finish", () => { var _animate$value5; if (commitStyles) (_animate$value5 = animate.value) === null || _animate$value5 === void 0 || _animate$value5.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$1) window$1.requestAnimationFrame(pauseRef); } return { isSupported, animate, play, pause, reverse, finish, cancel, pending, playState, replaceState, startTime, currentTime, timeline, playbackRate }; } //#endregion //#region useAsyncQueue/index.ts /** * Asynchronous queue task controller. * * @see https://vueuse.org/useAsyncQueue * @param tasks * @param options */ function useAsyncQueue(tasks, options) { const { interrupt = true, onError = __vueuse_shared.noop, onFinished = __vueuse_shared.noop, signal } = options || {}; const promiseState = { aborted: "aborted", fulfilled: "fulfilled", pending: "pending", rejected: "rejected" }; const result = (0, vue.reactive)(Array.from(Array.from({ length: tasks.length }), () => ({ state: promiseState.pending, data: null }))); const activeIndex = (0, vue.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 _result$activeIndex$v; if (signal === null || signal === void 0 ? void 0 : signal.aborted) { updateResult(promiseState.aborted, /* @__PURE__ */ new Error("aborted")); return; } if (((_result$activeIndex$v = result[activeIndex.value]) === null || _result$activeIndex$v === void 0 ? void 0 : _result$activeIndex$v.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 || signal === void 0 ? void 0 : signal.aborted) { updateResult(promiseState.aborted, e); return e; } updateResult(promiseState.rejected, e); onError(); if (activeIndex.value === tasks.length - 1) onFinished(); return e; }); }, Promise.resolve()); return { activeIndex, result }; } function whenAborted(signal) { return new Promise((resolve, reject) => { const error = /* @__PURE__ */ new Error("aborted"); if (signal.aborted) reject(error); else signal.addEventListener("abort", () => reject(error), { once: true }); }); } //#endregion //#region useAsyncState/index.ts /** * Reactive async state. Will not block your setup function and will trigger changes once * the promise is ready. * * @see https://vueuse.org/useAsyncState * @param promise The promise / async function to be resolved * @param initialState The initial state, used until the first evaluation finishes * @param options */ function useAsyncState(promise, initialState, options) { var _globalThis$reportErr; const { immediate = true, delay = 0, onError = (_globalThis$reportErr = globalThis.reportError) !== null && _globalThis$reportErr !== void 0 ? _globalThis$reportErr : __vueuse_shared.noop, onSuccess = __vueuse_shared.noop, resetOnExecute = true, shallow = true, throwError } = options !== null && options !== void 0 ? options : {}; const state = shallow ? (0, vue.shallowRef)(initialState) : (0, vue.ref)(initialState); const isReady = (0, vue.shallowRef)(false); const isLoading = (0, vue.shallowRef)(false); const error = (0, vue.shallowRef)(void 0); let executionsCount = 0; async function execute(delay$1 = 0, ...args) { const executionId = executionsCount += 1; if (resetOnExecute) state.value = (0, vue.toValue)(initialState); error.value = void 0; isReady.value = false; isLoading.value = true; if (delay$1 > 0) await (0, __vueuse_shared.promiseTimeout)(delay$1); const _promise = typeof promise === "function" ? promise(...args) : promise; try { const data = await _promise; if (executionId === executionsCount) { state.value = data; isReady.value = true; } onSuccess(data); } catch (e) { if (executionId === executionsCount) error.value = e; onError(e); if (throwError) throw e; } finally { if (executionId === executionsCount) 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) => { (0, __vueuse_shared.until)(isLoading).toBe(false).then(() => resolve(shell)).catch(reject); }); } return { ...shell, then(onFulfilled, onRejected) { return waitUntilIsLoaded().then(onFulfilled, onRejected); } }; } //#endregion //#region useBase64/serialization.ts 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; } //#endregion //#region useBase64/index.ts function useBase64(target, options) { const base64 = (0, vue.shallowRef)(""); const promise = (0, vue.shallowRef)(); function execute() { if (!__vueuse_shared.isClient) return; promise.value = new Promise((resolve, reject) => { try { const _target = (0, vue.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 || options === void 0 ? void 0 : options.type, options === null || options === void 0 ? 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 || options === void 0 ? void 0 : options.type, options === null || options === void 0 ? void 0 : options.quality)); }).catch(reject); } else if (typeof _target === "object") { const serialized = ((options === null || options === void 0 ? void 0 : options.serializer) || getDefaultSerialization(_target))(_target); return resolve(blobToBase64(new Blob([serialized], { type: "application/json" }))); } else reject(/* @__PURE__ */ new Error("target is unsupported types")); } catch (error) { reject(error); } }); promise.value.then((res) => { base64.value = (options === null || options === void 0 ? void 0 : options.dataUrl) === false ? res.replace(/^data:.*?;base64,/, "") : res; }); return promise.value; } if ((0, vue.isRef)(target) || typeof target === "function") (0, vue.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); }); } //#endregion //#region useBattery/index.ts /** * Reactive Battery Status API. * * @see https://vueuse.org/useBattery * * @__NO_SIDE_EFFECTS__ */ function useBattery(options = {}) { const { navigator: navigator$1 = defaultNavigator } = options; const events$1 = [ "chargingchange", "chargingtimechange", "dischargingtimechange", "levelchange" ]; const isSupported = /* @__PURE__ */ useSupported(() => navigator$1 && "getBattery" in navigator$1 && typeof navigator$1.getBattery === "function"); const charging = (0, vue.shallowRef)(false); const chargingTime = (0, vue.shallowRef)(0); const dischargingTime = (0, vue.shallowRef)(0); const level = (0, vue.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$1.getBattery().then((_battery) => { battery = _battery; updateBatteryInfo.call(battery); useEventListener(battery, events$1, updateBatteryInfo, { passive: true }); }); return { isSupported, charging, chargingTime, dischargingTime, level }; } //#endregion //#region useBluetooth/index.ts /* @__NO_SIDE_EFFECTS__ */ function useBluetooth(options) { let { acceptAllDevices = false } = options || {}; const { filters = void 0, optionalServices = void 0, navigator: navigator$1 = defaultNavigator } = options || {}; const isSupported = /* @__PURE__ */ useSupported(() => navigator$1 && "bluetooth" in navigator$1); const device = (0, vue.shallowRef)(); const error = (0, vue.shallowRef)(null); (0, vue.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$1 === null || navigator$1 === void 0 ? void 0 : navigator$1.bluetooth.requestDevice({ acceptAllDevices, filters, optionalServices })); } catch (err) { error.value = err; } } const server = (0, vue.shallowRef)(); const isConnected = (0, vue.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; } } } (0, __vueuse_shared.tryOnMounted)(() => { var _device$value$gatt; if (device.value) (_device$value$gatt = device.value.gatt) === null || _device$value$gatt === void 0 || _device$value$gatt.connect(); }); (0, __vueuse_shared.tryOnScopeDispose)(() => { var _device$value$gatt2; if (device.value) (_device$value$gatt2 = device.value.gatt) === null || _device$value$gatt2 === void 0 || _device$value$gatt2.disconnect(); }); return { isSupported, isConnected: (0, vue.readonly)(isConnected), device, requestDevice, server, error }; } //#endregion //#region useSSRWidth/index.ts const ssrWidthSymbol = Symbol("vueuse-ssr-width"); /* @__NO_SIDE_EFFECTS__ */ function useSSRWidth() { const ssrWidth = (0, vue.hasInjectionContext)() ? (0, __vueuse_shared.injectLocal)(ssrWidthSymbol, null) : null; return typeof ssrWidth === "number" ? ssrWidth : void 0; } function provideSSRWidth(width, app) { if (app !== void 0) app.provide(ssrWidthSymbol, width); else (0, __vueuse_shared.provideLocal)(ssrWidthSymbol, width); } //#endregion //#region useMediaQuery/index.ts /** * Reactive Media Query. * * @see https://vueuse.org/useMediaQuery * @param query * @param options */ function useMediaQuery(query, options = {}) { const { window: window$1 = defaultWindow, ssrWidth = /* @__PURE__ */ useSSRWidth() } = options; const isSupported = /* @__PURE__ */ useSupported(() => window$1 && "matchMedia" in window$1 && typeof window$1.matchMedia === "function"); const ssrSupport = (0, vue.shallowRef)(typeof ssrWidth === "number"); const mediaQuery = (0, vue.shallowRef)(); const matches = (0, vue.shallowRef)(false); const handler = (event) => { matches.value = event.matches; }; (0, vue.watchEffect)(() => { if (ssrSupport.value) { ssrSupport.value = !isSupported.value; matches.value = (0, vue.toValue)(query).split(",").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 >= (0, __vueuse_shared.pxValue)(minWidth[1]); if (maxWidth && res) res = ssrWidth <= (0, __vueuse_shared.pxValue)(maxWidth[1]); return not ? !res : res; }); return; } if (!isSupported.value) return; mediaQuery.value = window$1.matchMedia((0, vue.toValue)(query)); matches.value = mediaQuery.value.matches; }); useEventListener(mediaQuery, "change", handler, { passive: true }); return (0, vue.computed)(() => matches.value); } //#endregion //#region useBreakpoints/breakpoints.ts /** * Breakpoints from Tailwind V2 * * @see https://tailwindcss.com/docs/breakpoints */ const breakpointsTailwind = { "sm": 640, "md": 768, "lg": 1024, "xl": 1280, "2xl": 1536 }; /** * Breakpoints from Bootstrap V5 * * @see https://getbootstrap.com/docs/5.0/layout/breakpoints */ const breakpointsBootstrapV5 = { xs: 0, sm: 576, md: 768, lg: 992, xl: 1200, xxl: 1400 }; /** * Breakpoints from Vuetify V2 * * @see https://v2.vuetifyjs.com/en/features/breakpoints/ */ const breakpointsVuetifyV2 = { xs: 0, sm: 600, md: 960, lg: 1264, xl: 1904 }; /** * Breakpoints from Vuetify V3 * * @see https://vuetifyjs.com/en/styles/float/#overview */ const breakpointsVuetifyV3 = { xs: 0, sm: 600, md: 960, lg: 1280, xl: 1920, xxl: 2560 }; /** * Alias to `breakpointsVuetifyV2` * * @deprecated explictly use `breakpointsVuetifyV2` or `breakpointsVuetifyV3` instead */ const breakpointsVuetify = breakpointsVuetifyV2; /** * Breakpoints from Ant Design * * @see https://ant.design/components/layout/#breakpoint-width */ const breakpointsAntDesign = { xs: 480, sm: 576, md: 768, lg: 992, xl: 1200, xxl: 1600 }; /** * Breakpoints from Quasar V2 * * @see https://quasar.dev/style/breakpoints */ const breakpointsQuasar = { xs: 0, sm: 600, md: 1024, lg: 1440, xl: 1920 }; /** * Sematic Breakpoints */ const breakpointsSematic = { mobileS: 320, mobileM: 375, mobileL: 425, tablet: 768, laptop: 1024, laptopL: 1440, desktop4K: 2560 }; /** * Breakpoints from Master CSS * * @see https://docs.master.co/css/breakpoints */ const breakpointsMasterCss = { "3xs": 360, "2xs": 480, "xs": 600, "sm": 768, "md": 1024, "lg": 1280, "xl": 1440, "2xl": 1600, "3xl": 1920, "4xl": 2560 }; /** * Breakpoints from PrimeFlex * * @see https://primeflex.org/installation */ const breakpointsPrimeFlex = { sm: 576, md: 768, lg: 992, xl: 1200 }; /** * Breakpoints from ElementUI/ElementPlus * * @see https://element.eleme.io/#/en-US/component/layout * @see https://element-plus.org/en-US/component/layout.html */ const breakpointsElement = { xs: 0, sm: 768, md: 992, lg: 1200, xl: 1920 }; //#endregion //#region useBreakpoints/index.ts /** * Reactively viewport breakpoints * * @see https://vueuse.org/useBreakpoints * * @__NO_SIDE_EFFECTS__ */ function useBreakpoints(breakpoints, options = {}) { function getValue$1(k, delta) { let v = (0, vue.toValue)(breakpoints[(0, vue.toValue)(k)]); if (delta != null) v = (0, __vueuse_shared.increaseWithUnit)(v, delta); if (typeof v === "number") v = `${v}px`; return v; } const { window: window$1 = defaultWindow, strategy = "min-width", ssrWidth = /* @__PURE__ */ useSSRWidth() } = options; const ssrSupport = typeof ssrWidth === "number"; const mounted = ssrSupport ? (0, vue.shallowRef)(false) : { value: true }; if (ssrSupport) (0, __vueuse_shared.tryOnMounted)(() => mounted.value = !!window$1); function match(query, size) { if (!mounted.value && ssrSupport) return query === "min" ? ssrWidth >= (0, __vueuse_shared.pxValue)(size) : ssrWidth <= (0, __vueuse_shared.pxValue)(size); if (!window$1) return