peerpigeon
Version:
WebRTC-based peer-to-peer mesh networking library with intelligent routing and signaling server
1,789 lines (1,751 loc) • 217 kB
JavaScript
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