UNPKG

peerpigeon

Version:

WebRTC-based peer-to-peer mesh networking library with intelligent routing and signaling server

1,789 lines (1,751 loc) 217 kB
import { noop, makeDestructurable, camelize, toValue, isClient, isObject, tryOnScopeDispose, isIOS, tryOnMounted, notNullish, objectOmit, promiseTimeout, until, increaseWithUnit, objectEntries, createSingletonPromise, useTimeoutFn, pausableWatch, toRef, createEventHook, computedWithControl, timestamp, pausableFilter, watchIgnorable, debounceFilter, createFilterWrapper, bypassFilter, toRefs, useIntervalFn, containsProp, hasOwn, throttleFilter, useDebounceFn, useThrottleFn, clamp, syncRef, objectPick, tryOnUnmounted, watchWithFilter, tryOnBeforeUnmount, identity, isDef, isWorker } from '@vueuse/shared'; export * from '@vueuse/shared'; import { isRef, ref, shallowRef, watchEffect, computed, inject, isVue3, version, defineComponent, h, TransitionGroup, shallowReactive, Fragment, watch, getCurrentInstance, customRef, onUpdated, onMounted, isVue2, readonly, nextTick, reactive, markRaw, unref, getCurrentScope, set, del, isReadonly, onBeforeUpdate } from 'vue-demi'; function computedAsync(evaluationCallback, initialState, optionsOrRef) { let options; if (isRef(optionsOrRef)) { options = { evaluating: optionsOrRef }; } else { options = optionsOrRef || {}; } const { lazy = false, evaluating = void 0, shallow = true, onError = noop } = options; const started = ref(!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; } }); 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((ctx) => options(source, ctx)); } else { return computed({ get: (ctx) => options.get(source, ctx), set: options.set }); } } function createReusableTemplate(options = {}) { if (!isVue3 && !version.startsWith("2.7.")) { if (process.env.NODE_ENV !== "production") throw new Error("[VueUse] createReusableTemplate only works in Vue 2.7 or above."); return; } const { inheritAttrs = true } = options; const render = shallowRef(); const define = /* #__PURE__ */ defineComponent({ setup(_, { slots }) { return () => { render.value = slots.default; }; } }); const reuse = /* #__PURE__ */ defineComponent({ inheritAttrs, setup(_, { 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, { ...keysToCamelKebabCase(attrs), $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; } function createTemplatePromise(options = {}) { if (!isVue3) { if (process.env.NODE_ENV !== "production") throw new Error("[VueUse] createTemplatePromise only works in Vue 3 or above."); return; } 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; } function createUnrefFn(fn) { return function(...args) { return fn.apply(this, args.map((i) => toValue(i))); }; } function unrefElement(elRef) { var _a; const plain = toValue(elRef); return (_a = plain == null ? void 0 : plain.$el) != null ? _a : plain; } 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 useEventListener(...args) { let target; let events; let listeners; let options; if (typeof args[0] === "string" || Array.isArray(args[0])) { [events, listeners, options] = args; target = defaultWindow; } else { [target, events, listeners, options] = args; } if (!target) return noop; if (!Array.isArray(events)) events = [events]; if (!Array.isArray(listeners)) listeners = [listeners]; const cleanups = []; const cleanup = () => { cleanups.forEach((fn) => fn()); cleanups.length = 0; }; const register = (el, event, listener, options2) => { el.addEventListener(event, listener, options2); return () => el.removeEventListener(event, listener, options2); }; const stopWatch = watch( () => [unrefElement(target), toValue(options)], ([el, options2]) => { cleanup(); if (!el) return; const optionsClone = isObject(options2) ? { ...options2 } : options2; cleanups.push( ...events.flatMap((event) => { return listeners.map((listener) => register(el, event, listener, optionsClone)); }) ); }, { immediate: true, flush: "post" } ); const stop = () => { stopWatch(); cleanup(); }; tryOnScopeDispose(stop); return stop; } let _iOSWorkaround = false; function onClickOutside(target, handler, options = {}) { const { window = defaultWindow, ignore = [], capture = true, detectIframe = false } = options; if (!window) return noop; if (isIOS && !_iOSWorkaround) { _iOSWorkaround = true; Array.from(window.document.body.children).forEach((el) => el.addEventListener("click", noop)); window.document.documentElement.addEventListener("click", noop); } let shouldListen = true; const shouldIgnore = (event) => { return 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)); } }); }; const listener = (event) => { const el = unrefElement(target); if (!el || el === event.target || event.composedPath().includes(el)) return; if (event.detail === 0) shouldListen = !shouldIgnore(event); if (!shouldListen) { shouldListen = true; return; } handler(event); }; const cleanup = [ useEventListener(window, "click", listener, { 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); }) ].filter(Boolean); const stop = () => cleanup.forEach((fn) => fn()); return stop; } 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 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, _d; 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); }, (_d = options == null ? void 0 : options.delay) != null ? _d : DEFAULT_DELAY ); } 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) return true; if (keyCode >= 65 && keyCode <= 90) return true; if (keyCode >= 97 && keyCode <= 122) return true; return false; } function onStartTyping(callback, options = {}) { const { document: document2 = defaultDocument } = options; const keydown = (event) => { !isFocusedElementEditable() && isTypedCharValid(event) && callback(event); }; if (document2) useEventListener(document2, "keydown", keydown, { passive: true }); } 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; } function useMounted() { const isMounted = ref(false); const instance = getCurrentInstance(); if (instance) { onMounted(() => { isMounted.value = true; }, isVue2 ? void 0 : instance); } return isMounted; } 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 = (Array.isArray(value) ? value : [value]).map(unrefElement).filter(notNullish); return new Set(items); }); const stopWatch = watch( () => targets.value, (targets2) => { cleanup(); if (isSupported.value && targets2.size) { observer = new MutationObserver(callback); targets2.forEach((el) => observer.observe(el, mutationOptions)); } }, { immediate: true, flush: "post" } ); const takeRecords = () => { return observer == null ? void 0 : observer.takeRecords(); }; const stop = () => { cleanup(); stopWatch(); }; tryOnScopeDispose(stop); return { isSupported, stop, takeRecords }; } 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 = ref(); const trigger = () => { activeElement.value = getDeepActiveElement(); }; if (window) { useEventListener(window, "blur", (event) => { if (event.relatedTarget !== null) return; trigger(); }, true); useEventListener(window, "focus", trigger, true); } if (triggerOnRemoval) { useMutationObserver(document, (mutations) => { mutations.filter((m) => m.removedNodes.length).map((n) => Array.from(n.removedNodes)).flat().forEach((node) => { if (node === activeElement.value) trigger(); }); }, { childList: true, subtree: true }); } trigger(); return activeElement; } function useRafFn(fn, options = {}) { const { immediate = true, fpsLimit = void 0, window = defaultWindow } = options; const isActive = ref(false); const intervalLimit = fpsLimit ? 1e3 / 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 && delta < intervalLimit) { rafId = window.requestAnimationFrame(loop); return; } previousFrameTimestamp = timestamp; fn({ delta, timestamp }); 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; !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) => { el && update(); }); watch(() => keyframes, (value) => { !animate.value && update(); if (!unrefElement(target) && animate.value) { animate.value.effect = new KeyframeEffect( unrefElement(target), toValue(value), animateOptions ); } }, { deep: true }); tryOnMounted(() => { nextTick(() => update(true)); }); 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); } useEventListener(animate, ["cancel", "finish", "remove"], syncPause); useEventListener(animate, "finish", () => { var _a; if (commitStyles) (_a = animate.value) == null ? void 0 : _a.commitStyles(); }); 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 = ref(-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); 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) { const { immediate = true, delay = 0, onError = noop, onSuccess = noop, resetOnExecute = true, shallow = true, throwError } = options != null ? options : {}; const state = shallow ? shallowRef(initialState) : ref(initialState); const isReady = ref(false); const isLoading = ref(false); const error = shallowRef(void 0); async function execute(delay2 = 0, ...args) { if (resetOnExecute) state.value = 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 }; 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 = ref(""); const promise = ref(); 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 = 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); }); } 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 = ref(false); const chargingTime = ref(0); const dischargingTime = ref(0); const level = ref(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 }; } 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(void 0); 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 = ref(); const isConnected = computed(() => { var _a; return ((_a = server.value) == null ? void 0 : _a.connected) || false; }); async function connectToBluetoothGATTServer() { error.value = null; if (device.value && device.value.gatt) { device.value.addEventListener("gattserverdisconnected", () => { }); try { server.value = await device.value.gatt.connect(); } 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, // Device: device, requestDevice, // Server: server, // Errors: error }; } function useMediaQuery(query, options = {}) { const { window = defaultWindow } = options; const isSupported = useSupported(() => window && "matchMedia" in window && typeof window.matchMedia === "function"); let mediaQuery; const matches = ref(false); const handler = (event) => { matches.value = event.matches; }; const cleanup = () => { if (!mediaQuery) return; if ("removeEventListener" in mediaQuery) mediaQuery.removeEventListener("change", handler); else mediaQuery.removeListener(handler); }; const stopWatch = watchEffect(() => { if (!isSupported.value) return; cleanup(); mediaQuery = window.matchMedia(toValue(query)); if ("addEventListener" in mediaQuery) mediaQuery.addEventListener("change", handler); else mediaQuery.addListener(handler); matches.value = mediaQuery.matches; }); tryOnScopeDispose(() => { stopWatch(); cleanup(); mediaQuery = void 0; }); return matches; } 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 }; 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" } = options; function match(query) { if (!window) return false; return window.matchMedia(query).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((i) => [i, greaterOrEqual(i)]); 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-width: ${getValue(k, 0.1)})`); }, isGreaterOrEqual(k) { return match(`(min-width: ${getValue(k)})`); }, isSmaller(k) { return match(`(max-width: ${getValue(k, -0.1)})`); }, isSmallerOrEqual(k) { return match(`(max-width: ${getValue(k)})`); }, isInBetween(a, b) { return match(`(min-width: ${getValue(a)}) and (max-width: ${getValue(b, -0.1)})`); }, current, active() { const bps = current(); return computed(() => bps.value.length === 0 ? "" : bps.value.at(-1)); } }); } function useBroadcastChannel(options) { const { name, window = defaultWindow } = options; const isSupported = useSupported(() => window && "BroadcastChannel" in window); const isClosed = ref(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); channel.value.addEventListener("message", (e) => { data.value = e.data; }, { passive: true }); channel.value.addEventListener("messageerror", (e) => { error.value = e; }, { passive: true }); channel.value.addEventListener("close", () => { isClosed.value = true; }); }); } tryOnScopeDispose(() => { close(); }); return { isSupported, channel, data, post, close, error, isClosed }; } const WRITABLE_PROPERTIES = [ "hash", "host", "hostname", "href", "pathname", "port", "protocol", "search" ]; function useBrowserLocation(options = {}) { const { window = defaultWindow } = options; const refs = Object.fromEntries( WRITABLE_PROPERTIES.map((key) => [key, ref()]) ); for (const [key, ref2] of objectEntries(refs)) { watch(ref2, (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) { useEventListener(window, "popstate", () => state.value = buildState("popstate"), { passive: true }); useEventListener(window, "hashchange", () => state.value = buildState("hashchange"), { passive: true }); } return state; } function useCached(refValue, comparator = (a, b) => a === b, watchOptions) { const cachedValue = ref(refValue.value); watch(() => refValue.value, (value) => { if (!comparator(value, cachedValue.value)) cachedValue.value = value; }, watchOptions); return cachedValue; } function usePermission(permissionDesc, options = {}) { const { controls = false, navigator = defaultNavigator } = options; const isSupported = useSupported(() => navigator && "permissions" in navigator); let permissionStatus; const desc = typeof permissionDesc === "string" ? { name: permissionDesc } : permissionDesc; const state = ref(); const onChange = () => { if (permissionStatus) state.value = permissionStatus.state; }; const query = createSingletonPromise(async () => { if (!isSupported.value) return; if (!permissionStatus) { try { permissionStatus = await navigator.permissions.query(desc); useEventListener(permissionStatus, "change", onChange); onChange(); } catch (e) { state.value = "prompt"; } } return permissionStatus; }); 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 = ref(""); const copied = ref(false); const timeout = useTimeoutFn(() => copied.value = false, copiedDuring); function updateText() { if (isClipboardApiSupported.value && isAllowed(permissionRead.value)) { navigator.clipboard.readText().then((value) => { text.value = value; }); } else { text.value = legacyRead(); } } if (isSupported.value && read) useEventListener(["copy", "cut"], updateText); async function copy(value = toValue(source)) { if (isSupported.value && value != null) { if (isClipboardApiSupported.value && isAllowed(permissionWrite.value)) await navigator.clipboard.writeText(value); else 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 = ref(false); const timeout = useTimeoutFn(() => copied.value = false, copiedDuring); function updateContent() { if (isSupported.value) { navigator.clipboard.read().then((items) => { content.value = items; }); } } if (isSupported.value && read) useEventListener(["copy", "cut"], updateContent); async function copy(value = toValue(source)) { if (isSupported.value && value != null) { await navigator.clipboard.write(value); content.value = value; copied.value = true; timeout.start(); } } return { isSupported, content, copied, copy }; } function cloneFnJSON(source) { return JSON.parse(JSON.stringify(source)); } function useCloned(source, options = {}) { const cloned = ref({}); const { manual, clone = cloneFnJSON, // watch options deep = true, immediate = true } = options; function sync() { cloned.value = clone(toValue(source)); } if (!manual && (isRef(source) || typeof source === "function")) { watch(source, sync, { ...options, deep, immediate }); } else { sync(); } return { cloned, sync }; } const _global = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : {}; const globalKey = "__vueuse_ssr_handlers__"; const handlers = /* @__PURE__ */ getHandlers(); function getHandlers() { if (!(globalKey in _global)) _global[globalKey] = _global[globalKey] || {}; return _global[globalKey]; } function getSSRHandler(key, fallback) { return handlers[key] || fallback; } function setSSRHandler(key, fn) { handlers[key] = fn; } function guessSerializerType(rawInit) { return rawInit == null ? "any" : rawInit instanceof Set ? "set" : rawInit instanceof Map ? "map" : rawInit instanceof Date ? "date" : typeof rawInit === "boolean" ? "boolean" : typeof rawInit === "string" ? "string" : typeof rawInit === "object" ? "object" : !Number.isNaN(rawInit) ? "number" : "any"; } const StorageSerializers = { boolean: { read: (v) => v === "true", write: (v) => String(v) }, object: { read: (v) => JSON.parse(v), write: (v) => JSON.stringify(v) }, number: { read: (v) => Number.parseFloat(v), write: (v) => String(v) }, any: { read: (v) => v, write: (v) => String(v) }, string: { read: (v) => v, write: (v) => String(v) }, map: { read: (v) => new Map(JSON.parse(v)), write: (v) => JSON.stringify(Array.from(v.entries())) }, set: { read: (v) => new Set(JSON.parse(v)), write: (v) => JSON.stringify(Array.from(v)) }, date: { read: (v) => new Date(v), write: (v) => v.toISOString() } }; const customStorageEventName = "vueuse-storage"; function useStorage(key, defaults, storage, options = {}) { var _a; const { flush = "pre", deep = true, listenToStorageChanges = true, writeDefaults = true, mergeDefaults = false, shallow, window = defaultWindow, eventFilter, onError = (e) => { console.error(e); }, initOnMounted } = options; const data = (shallow ? shallowRef : ref)(typeof defaults === "function" ? defaults() : defaults); if (!storage) { try { storage = getSSRHandler("getDefaultStorage", () => { var _a2; return (_a2 = defaultWindow) == null ? void 0 : _a2.localStorage; })(); } catch (e) { onError(e); } } if (!storage) return data; const rawInit = toValue(defaults); const type = guessSerializerType(rawInit); const serializer = (_a = options.serializer) != null ? _a : StorageSerializers[type]; const { pause: pauseWatch, resume: resumeWatch } = pausableWatch( data, () => write(data.value), { flush, deep, eventFilter } ); if (window && listenToStorageChanges) { tryOnMounted(() => { useEventListener(window, "storage", update); useEventListener(window, customStorageEventName, updateFromCustomEvent); if (initOnMounted) update(); }); } if (!initOnMounted) update(); function dispatchWriteEvent(oldValue, newValue) { if (window) { window.dispatchEvent(new CustomEvent(customStorageEventName, { detail: { key, oldValue, newValue, storageArea: storage } })); } } function write(v) { try { const oldValue = storage.getItem(key); if (v == null) { dispatchWriteEvent(oldValue, null); storage.removeItem(key); } else { const serialized = serializer.write(v); if (oldValue !== serialized) { storage.setItem(key, serialized); dispatchWriteEvent(oldValue, serialized); } } } catch (e) { onError(e); } } function read(event) { const rawValue = event ? event.newValue : storage.getItem(key); if (rawValue == null) { if (writeDefaults && rawInit != null) storage.setItem(key, serializer.write(rawInit)); return rawInit; } else if (!event && mergeDefaults) { const value = serializer.read(rawValue); if (typeof mergeDefaults === "function") return mergeDefaults(value, rawInit); else if (type === "object" && !Array.isArray(value)) return { ...rawInit, ...value }; return value; } else if (typeof rawValue !== "string") { return rawValue; } else { return serializer.read(rawValue); } } function update(event) { if (event && event.storageArea !== storage) return; if (event && event.key == null) { data.value = rawInit; return; } if (event && event.key !== key) return; pauseWatch(); try { if ((event == null ? void 0 : event.newValue) !== serializer.write(data.value)) data.value = read(event); } catch (e) { onError(e); } finally { if (event) nextTi