UNPKG

@vueuse/components

Version:
1,611 lines (1,557 loc) 83.6 kB
(function (exports, core, vue, shared) { 'use strict'; const OnClickOutside = /* @__PURE__ */ vue.defineComponent({ name: "OnClickOutside", props: ["as", "options"], emits: ["trigger"], setup(props, { slots, emit }) { const target = vue.shallowRef(); core.onClickOutside(target, (e) => { emit("trigger", e); }, props.options); return () => { if (slots.default) return vue.h(props.as || "div", { ref: target }, slots.default()); }; } }); const defaultWindow = shared.isClient ? window : void 0; function unrefElement(elRef) { var _a; const plain = vue.toValue(elRef); return (_a = plain == null ? void 0 : plain.$el) != null ? _a : plain; } function useEventListener(...args) { const cleanups = []; const cleanup = () => { cleanups.forEach((fn) => fn()); cleanups.length = 0; }; const register = (el, event, listener, options) => { el.addEventListener(event, listener, options); return () => el.removeEventListener(event, listener, options); }; const firstParamTargets = vue.computed(() => { const test = shared.toArray(vue.toValue(args[0])).filter((e) => e != null); return test.every((e) => typeof e !== "string") ? test : void 0; }); const stopWatch = shared.watchImmediate( () => { var _a, _b; return [ (_b = (_a = firstParamTargets.value) == null ? void 0 : _a.map((e) => unrefElement(e))) != null ? _b : [defaultWindow].filter((e) => e != null), shared.toArray(vue.toValue(firstParamTargets.value ? args[1] : args[0])), shared.toArray(vue.unref(firstParamTargets.value ? args[2] : args[1])), // @ts-expect-error - TypeScript gets the correct types, but somehow still complains vue.toValue(firstParamTargets.value ? args[3] : args[2]) ]; }, ([raw_targets, raw_events, raw_listeners, raw_options]) => { cleanup(); if (!(raw_targets == null ? void 0 : raw_targets.length) || !(raw_events == null ? void 0 : raw_events.length) || !(raw_listeners == null ? void 0 : raw_listeners.length)) return; const optionsClone = shared.isObject(raw_options) ? { ...raw_options } : raw_options; cleanups.push( ...raw_targets.flatMap( (el) => raw_events.flatMap( (event) => raw_listeners.map((listener) => register(el, event, listener, optionsClone)) ) ) ); }, { flush: "post" } ); const stop = () => { stopWatch(); cleanup(); }; shared.tryOnScopeDispose(cleanup); return stop; } let _iOSWorkaround = false; function onClickOutside(target, handler, options = {}) { const { window = defaultWindow, ignore = [], capture = true, detectIframe = false, controls = false } = options; if (!window) { return controls ? { stop: shared.noop, cancel: shared.noop, trigger: shared.noop } : shared.noop; } if (shared.isIOS && !_iOSWorkaround) { _iOSWorkaround = true; const listenerOptions = { passive: true }; Array.from(window.document.body.children).forEach((el) => el.addEventListener("click", shared.noop, listenerOptions)); window.document.documentElement.addEventListener("click", shared.noop, listenerOptions); } let shouldListen = true; const shouldIgnore = (event) => { return vue.toValue(ignore).some((target2) => { if (typeof target2 === "string") { return Array.from(window.document.querySelectorAll(target2)).some((el) => el === event.target || event.composedPath().includes(el)); } else { const el = unrefElement(target2); return el && (event.target === el || event.composedPath().includes(el)); } }); }; function hasMultipleRoots(target2) { const vm = vue.toValue(target2); return vm && vm.$.subTree.shapeFlag === 16; } function checkMultipleRoots(target2, event) { const vm = vue.toValue(target2); const children = vm.$.subTree && vm.$.subTree.children; if (children == null || !Array.isArray(children)) return false; return children.some((child) => child.el === event.target || event.composedPath().includes(child.el)); } const listener = (event) => { const el = unrefElement(target); if (event.target == null) return; if (!(el instanceof Element) && hasMultipleRoots(target) && checkMultipleRoots(target, event)) return; if (!el || el === event.target || event.composedPath().includes(el)) return; if ("detail" in event && event.detail === 0) shouldListen = !shouldIgnore(event); if (!shouldListen) { shouldListen = true; return; } handler(event); }; let isProcessingClick = false; const cleanup = [ useEventListener(window, "click", (event) => { if (!isProcessingClick) { isProcessingClick = true; setTimeout(() => { isProcessingClick = false; }, 0); listener(event); } }, { passive: true, capture }), useEventListener(window, "pointerdown", (e) => { const el = unrefElement(target); shouldListen = !shouldIgnore(e) && !!(el && !e.composedPath().includes(el)); }, { passive: true }), detectIframe && useEventListener(window, "blur", (event) => { setTimeout(() => { var _a; const el = unrefElement(target); if (((_a = window.document.activeElement) == null ? void 0 : _a.tagName) === "IFRAME" && !(el == null ? void 0 : el.contains(window.document.activeElement))) { handler(event); } }, 0); }, { passive: true }) ].filter(Boolean); const stop = () => cleanup.forEach((fn) => fn()); if (controls) { return { stop, cancel: () => { shouldListen = false; }, trigger: (event) => { shouldListen = true; listener(event); shouldListen = false; } }; } return stop; } const stopClickOutsideMap = /* @__PURE__ */ new WeakMap(); const vOnClickOutside = { mounted(el, binding) { const capture = !binding.modifiers.bubble; let stop; if (typeof binding.value === "function") { stop = onClickOutside(el, binding.value, { capture }); } else { const [handler, options] = binding.value; stop = onClickOutside(el, handler, Object.assign({ capture }, options)); } stopClickOutsideMap.set(el, stop); }, unmounted(el) { const stop = stopClickOutsideMap.get(el); if (stop && typeof stop === "function") { stop(); } else { stop == null ? void 0 : stop.stop(); } stopClickOutsideMap.delete(el); } }; 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 && vue.toValue(dedupe)) return; if (predicate(e)) handler(e); }; return useEventListener(target, eventName, listener, passive); } const vOnKeyStroke = { mounted(el, binding) { var _a, _b; const keys = (_b = (_a = binding.arg) == null ? void 0 : _a.split(",")) != null ? _b : true; if (typeof binding.value === "function") { onKeyStroke(keys, binding.value, { target: el }); } else { const [handler, options] = binding.value; onKeyStroke(keys, handler, { target: el, ...options }); } } }; const DEFAULT_DELAY = 500; const DEFAULT_THRESHOLD = 10; function onLongPress(target, handler, options) { var _a, _b; const elementRef = 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 ? void 0 : options.delay; if (typeof delay === "function") { return delay(ev); } return delay != null ? delay : DEFAULT_DELAY; } function onRelease(ev) { var _a2, _b2, _c; const [_startTimestamp, _posStart, _hasLongPressed] = [startTimestamp, posStart, hasLongPressed]; clear(); if (!(options == null ? void 0 : options.onMouseUp) || !_posStart || !_startTimestamp) return; if (((_a2 = options == null ? void 0 : options.modifiers) == null ? void 0 : _a2.self) && ev.target !== elementRef.value) return; if ((_b2 = options == null ? void 0 : options.modifiers) == null ? void 0 : _b2.prevent) ev.preventDefault(); if ((_c = options == null ? void 0 : options.modifiers) == null ? void 0 : _c.stop) ev.stopPropagation(); const dx = ev.x - _posStart.x; const dy = ev.y - _posStart.y; const distance = Math.sqrt(dx * dx + dy * dy); options.onMouseUp(ev.timeStamp - _startTimestamp, distance, _hasLongPressed); } function onDown(ev) { var _a2, _b2, _c; if (((_a2 = options == null ? void 0 : options.modifiers) == null ? void 0 : _a2.self) && ev.target !== elementRef.value) return; clear(); if ((_b2 = options == null ? void 0 : options.modifiers) == null ? void 0 : _b2.prevent) ev.preventDefault(); if ((_c = options == null ? void 0 : options.modifiers) == null ? void 0 : _c.stop) ev.stopPropagation(); posStart = { x: ev.x, y: ev.y }; startTimestamp = ev.timeStamp; timeout = setTimeout( () => { hasLongPressed = true; handler(ev); }, getDelay(ev) ); } function onMove(ev) { var _a2, _b2, _c, _d; if (((_a2 = options == null ? void 0 : options.modifiers) == null ? void 0 : _a2.self) && ev.target !== elementRef.value) return; if (!posStart || (options == null ? void 0 : options.distanceThreshold) === false) return; if ((_b2 = options == null ? void 0 : options.modifiers) == null ? void 0 : _b2.prevent) ev.preventDefault(); if ((_c = options == null ? void 0 : options.modifiers) == null ? void 0 : _c.stop) ev.stopPropagation(); const dx = ev.x - posStart.x; const dy = ev.y - posStart.y; const distance = Math.sqrt(dx * dx + dy * dy); if (distance >= ((_d = options == null ? void 0 : options.distanceThreshold) != null ? _d : DEFAULT_THRESHOLD)) clear(); } const listenerOptions = { capture: (_a = options == null ? void 0 : options.modifiers) == null ? void 0 : _a.capture, once: (_b = options == null ? void 0 : options.modifiers) == null ? void 0 : _b.once }; const cleanup = [ useEventListener(elementRef, "pointerdown", onDown, listenerOptions), useEventListener(elementRef, "pointermove", onMove, listenerOptions), useEventListener(elementRef, ["pointerup", "pointerleave"], onRelease, listenerOptions) ]; const stop = () => cleanup.forEach((fn) => fn()); return stop; } const OnLongPress = /* @__PURE__ */ vue.defineComponent({ name: "OnLongPress", props: ["as", "options"], emits: ["trigger"], setup(props, { slots, emit }) { const target = vue.shallowRef(); onLongPress( target, (e) => { emit("trigger", e); }, props.options ); return () => { if (slots.default) return vue.h(props.as || "div", { ref: target }, slots.default()); }; } }); const vOnLongPress = { mounted(el, binding) { if (typeof binding.value === "function") onLongPress(el, binding.value, { modifiers: binding.modifiers }); else onLongPress(el, ...binding.value); } }; const UseActiveElement = /* @__PURE__ */ vue.defineComponent({ name: "UseActiveElement", setup(props, { slots }) { const data = vue.reactive({ element: core.useActiveElement() }); return () => { if (slots.default) return slots.default(data); }; } }); const UseBattery = /* @__PURE__ */ vue.defineComponent({ name: "UseBattery", setup(props, { slots }) { const data = vue.reactive(core.useBattery(props)); return () => { if (slots.default) return slots.default(data); }; } }); const UseBrowserLocation = /* @__PURE__ */ vue.defineComponent({ name: "UseBrowserLocation", setup(props, { slots }) { const data = vue.reactive(core.useBrowserLocation()); return () => { if (slots.default) return slots.default(data); }; } }); const UseClipboard = /* @__PURE__ */ vue.defineComponent({ name: "UseClipboard", props: [ "source", "read", "navigator", "copiedDuring", "legacy" ], setup(props, { slots }) { const data = vue.reactive(core.useClipboard(props)); return () => { var _a; return (_a = slots.default) == null ? void 0 : _a.call(slots, data); }; } }); 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; } const ssrWidthSymbol = Symbol("vueuse-ssr-width"); // @__NO_SIDE_EFFECTS__ function useSSRWidth() { const ssrWidth = vue.hasInjectionContext() ? shared.injectLocal(ssrWidthSymbol, null) : null; return typeof ssrWidth === "number" ? ssrWidth : void 0; } // @__NO_SIDE_EFFECTS__ function useMounted() { const isMounted = vue.shallowRef(false); const instance = vue.getCurrentInstance(); if (instance) { vue.onMounted(() => { isMounted.value = true; }, instance); } return isMounted; } // @__NO_SIDE_EFFECTS__ function useSupported(callback) { const isMounted = useMounted(); return vue.computed(() => { isMounted.value; return Boolean(callback()); }); } function useMediaQuery(query, options = {}) { const { window = defaultWindow, ssrWidth = useSSRWidth() } = options; const isSupported = useSupported(() => window && "matchMedia" in window && typeof window.matchMedia === "function"); const ssrSupport = vue.shallowRef(typeof ssrWidth === "number"); const mediaQuery = vue.shallowRef(); const matches = vue.shallowRef(false); const handler = (event) => { matches.value = event.matches; }; vue.watchEffect(() => { if (ssrSupport.value) { ssrSupport.value = !isSupported.value; const queryStrings = vue.toValue(query).split(","); matches.value = queryStrings.some((queryString) => { const not = queryString.includes("not all"); const minWidth = queryString.match(/\(\s*min-width:\s*(-?\d+(?:\.\d*)?[a-z]+\s*)\)/); const maxWidth = queryString.match(/\(\s*max-width:\s*(-?\d+(?:\.\d*)?[a-z]+\s*)\)/); let res = Boolean(minWidth || maxWidth); if (minWidth && res) { res = ssrWidth >= shared.pxValue(minWidth[1]); } if (maxWidth && res) { res = ssrWidth <= shared.pxValue(maxWidth[1]); } return not ? !res : res; }); return; } if (!isSupported.value) return; mediaQuery.value = window.matchMedia(vue.toValue(query)); matches.value = mediaQuery.value.matches; }); useEventListener(mediaQuery, "change", handler, { passive: true }); return vue.computed(() => matches.value); } // @__NO_SIDE_EFFECTS__ function usePreferredDark(options) { return useMediaQuery("(prefers-color-scheme: dark)", options); } 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 ? vue.shallowRef : vue.ref)(typeof defaults === "function" ? defaults() : defaults); const keyComputed = vue.computed(() => vue.toValue(key)); 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 = vue.toValue(defaults); const type = guessSerializerType(rawInit); const serializer = (_a = options.serializer) != null ? _a : StorageSerializers[type]; const { pause: pauseWatch, resume: resumeWatch } = shared.pausableWatch( data, (newValue) => write(newValue), { flush, deep, eventFilter } ); vue.watch(keyComputed, () => update(), { flush }); let firstMounted = false; const onStorageEvent = (ev) => { if (initOnMounted && !firstMounted) { return; } update(ev); }; const onStorageCustomEvent = (ev) => { if (initOnMounted && !firstMounted) { return; } updateFromCustomEvent(ev); }; if (window && listenToStorageChanges) { if (storage instanceof Storage) useEventListener(window, "storage", onStorageEvent, { passive: true }); else useEventListener(window, customStorageEventName, onStorageCustomEvent); } if (initOnMounted) { shared.tryOnMounted(() => { firstMounted = true; update(); }); } else { update(); } function dispatchWriteEvent(oldValue, newValue) { if (window) { const payload = { key: keyComputed.value, oldValue, newValue, storageArea: storage }; window.dispatchEvent(storage instanceof Storage ? new StorageEvent("storage", payload) : new CustomEvent(customStorageEventName, { detail: payload })); } } function write(v) { try { const oldValue = storage.getItem(keyComputed.value); if (v == null) { dispatchWriteEvent(oldValue, null); storage.removeItem(keyComputed.value); } else { const serialized = serializer.write(v); if (oldValue !== serialized) { storage.setItem(keyComputed.value, serialized); dispatchWriteEvent(oldValue, serialized); } } } catch (e) { onError(e); } } function read(event) { const rawValue = event ? event.newValue : storage.getItem(keyComputed.value); if (rawValue == null) { if (writeDefaults && rawInit != null) storage.setItem(keyComputed.value, 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 !== keyComputed.value) { return; } pauseWatch(); try { const serializedData = serializer.write(data.value); if (event === void 0 || (event == null ? void 0 : event.newValue) !== serializedData) { data.value = read(event); } } catch (e) { onError(e); } finally { if (event) vue.nextTick(resumeWatch); else resumeWatch(); } } function updateFromCustomEvent(event) { update(event.detail); } return data; } const CSS_DISABLE_TRANS = "*,*::before,*::after{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;-ms-transition:none!important;transition:none!important}"; function useColorMode(options = {}) { const { selector = "html", attribute = "class", initialValue = "auto", window = defaultWindow, storage, storageKey = "vueuse-color-scheme", listenToStorageChanges = true, storageRef, emitAuto, disableTransition = true } = options; const modes = { auto: "", light: "light", dark: "dark", ...options.modes || {} }; const preferredDark = usePreferredDark({ window }); const system = vue.computed(() => preferredDark.value ? "dark" : "light"); const store = storageRef || (storageKey == null ? shared.toRef(initialValue) : useStorage(storageKey, initialValue, storage, { window, listenToStorageChanges })); const state = vue.computed(() => store.value === "auto" ? system.value : store.value); const updateHTMLAttrs = getSSRHandler( "updateHTMLAttrs", (selector2, attribute2, value) => { const el = typeof selector2 === "string" ? window == null ? void 0 : window.document.querySelector(selector2) : unrefElement(selector2); if (!el) return; const classesToAdd = /* @__PURE__ */ new Set(); const classesToRemove = /* @__PURE__ */ new Set(); let attributeToChange = null; if (attribute2 === "class") { const current = value.split(/\s/g); Object.values(modes).flatMap((i) => (i || "").split(/\s/g)).filter(Boolean).forEach((v) => { if (current.includes(v)) classesToAdd.add(v); else classesToRemove.add(v); }); } else { attributeToChange = { key: attribute2, value }; } if (classesToAdd.size === 0 && classesToRemove.size === 0 && attributeToChange === null) return; let style; if (disableTransition) { style = window.document.createElement("style"); style.appendChild(document.createTextNode(CSS_DISABLE_TRANS)); window.document.head.appendChild(style); } for (const c of classesToAdd) { el.classList.add(c); } for (const c of classesToRemove) { el.classList.remove(c); } if (attributeToChange) { el.setAttribute(attributeToChange.key, attributeToChange.value); } if (disableTransition) { window.getComputedStyle(style).opacity; document.head.removeChild(style); } } ); function defaultOnChanged(mode) { var _a; updateHTMLAttrs(selector, attribute, (_a = modes[mode]) != null ? _a : mode); } function onChanged(mode) { if (options.onChanged) options.onChanged(mode, defaultOnChanged); else defaultOnChanged(mode); } vue.watch(state, onChanged, { flush: "post", immediate: true }); shared.tryOnMounted(() => onChanged(state.value)); const auto = vue.computed({ get() { return emitAuto ? store.value : state.value; }, set(v) { store.value = v; } }); return Object.assign(auto, { store, system, state }); } const UseColorMode = /* @__PURE__ */ vue.defineComponent({ name: "UseColorMode", props: ["selector", "attribute", "modes", "onChanged", "storageKey", "storage", "emitAuto"], setup(props, { slots }) { const mode = useColorMode(props); const data = vue.reactive({ mode, system: mode.system, store: mode.store }); return () => { if (slots.default) return slots.default(data); }; } }); const UseDark = /* @__PURE__ */ vue.defineComponent({ name: "UseDark", props: ["selector", "attribute", "valueDark", "valueLight", "onChanged", "storageKey", "storage"], setup(props, { slots }) { const isDark = core.useDark(props); const data = vue.reactive({ isDark, toggleDark: shared.useToggle(isDark) }); return () => { if (slots.default) return slots.default(data); }; } }); const UseDeviceMotion = /* @__PURE__ */ vue.defineComponent({ name: "UseDeviceMotion", setup(props, { slots }) { const data = core.useDeviceMotion(); return () => { if (slots.default) return slots.default(data); }; } }); const UseDeviceOrientation = /* @__PURE__ */ vue.defineComponent({ name: "UseDeviceOrientation", setup(props, { slots }) { const data = vue.reactive(core.useDeviceOrientation()); return () => { if (slots.default) return slots.default(data); }; } }); const UseDevicePixelRatio = /* @__PURE__ */ vue.defineComponent({ name: "UseDevicePixelRatio", setup(props, { slots }) { const data = vue.reactive({ pixelRatio: core.useDevicePixelRatio() }); return () => { if (slots.default) return slots.default(data); }; } }); const UseDevicesList = /* @__PURE__ */ vue.defineComponent({ name: "UseDevicesList", props: ["onUpdated", "requestPermissions", "constraints"], setup(props, { slots }) { const data = vue.reactive(core.useDevicesList(props)); return () => { if (slots.default) return slots.default(data); }; } }); const UseDocumentVisibility = /* @__PURE__ */ vue.defineComponent({ name: "UseDocumentVisibility", setup(props, { slots }) { const data = vue.reactive({ visibility: core.useDocumentVisibility() }); return () => { if (slots.default) return slots.default(data); }; } }); const UseDraggable = /* @__PURE__ */ vue.defineComponent({ name: "UseDraggable", props: [ "storageKey", "storageType", "initialValue", "exact", "preventDefault", "stopPropagation", "pointerTypes", "as", "handle", "axis", "onStart", "onMove", "onEnd", "disabled", "buttons", "containerElement", "capture" ], setup(props, { slots }) { const target = vue.shallowRef(); const handle = vue.computed(() => { var _a; return (_a = vue.toValue(props.handle)) != null ? _a : target.value; }); const containerElement = vue.computed(() => { var _a; return (_a = props.containerElement) != null ? _a : void 0; }); const disabled = vue.computed(() => !!props.disabled); const storageValue = props.storageKey && core.useStorage( props.storageKey, vue.toValue(props.initialValue) || { x: 0, y: 0 }, core.isClient ? props.storageType === "session" ? sessionStorage : localStorage : void 0 ); const initialValue = storageValue || props.initialValue || { x: 0, y: 0 }; const onEnd = (position, event) => { var _a; (_a = props.onEnd) == null ? void 0 : _a.call(props, position, event); if (!storageValue) return; storageValue.value.x = position.x; storageValue.value.y = position.y; }; const data = vue.reactive(core.useDraggable(target, { ...props, handle, initialValue, onEnd, disabled, containerElement })); return () => { if (slots.default) return vue.h(props.as || "div", { ref: target, style: `touch-action:none;${data.style}` }, slots.default(data)); }; } }); const UseElementBounding = /* @__PURE__ */ vue.defineComponent({ name: "UseElementBounding", props: ["box", "as"], setup(props, { slots }) { const target = vue.shallowRef(); const data = vue.reactive(core.useElementBounding(target)); return () => { if (slots.default) return vue.h(props.as || "div", { ref: target }, slots.default(data)); }; } }); 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 = vue.computed(() => { const value = vue.toValue(target); const items = shared.toArray(value).map(unrefElement).filter(shared.notNullish); return new Set(items); }); const stopWatch = vue.watch( targets, (newTargets) => { cleanup(); if (isSupported.value && newTargets.size) { observer = new MutationObserver(callback); newTargets.forEach((el) => observer.observe(el, mutationOptions)); } }, { immediate: true, flush: "post" } ); const takeRecords = () => { return observer == null ? void 0 : observer.takeRecords(); }; const stop = () => { stopWatch(); cleanup(); }; shared.tryOnScopeDispose(stop); return { isSupported, stop, takeRecords }; } function useResizeObserver(target, callback, options = {}) { const { window = defaultWindow, ...observerOptions } = options; let observer; const isSupported = useSupported(() => window && "ResizeObserver" in window); const cleanup = () => { if (observer) { observer.disconnect(); observer = void 0; } }; const targets = vue.computed(() => { const _targets = vue.toValue(target); return Array.isArray(_targets) ? _targets.map((el) => unrefElement(el)) : [unrefElement(_targets)]; }); const stopWatch = vue.watch( targets, (els) => { cleanup(); if (isSupported.value && window) { observer = new ResizeObserver(callback); for (const _el of els) { if (_el) observer.observe(_el, observerOptions); } } }, { immediate: true, flush: "post" } ); const stop = () => { cleanup(); stopWatch(); }; shared.tryOnScopeDispose(stop); return { isSupported, stop }; } function useElementBounding(target, options = {}) { const { reset = true, windowResize = true, windowScroll = true, immediate = true, updateTiming = "sync" } = options; const height = vue.shallowRef(0); const bottom = vue.shallowRef(0); const left = vue.shallowRef(0); const right = vue.shallowRef(0); const top = vue.shallowRef(0); const width = vue.shallowRef(0); const x = vue.shallowRef(0); const y = vue.shallowRef(0); function recalculate() { const el = unrefElement(target); if (!el) { if (reset) { height.value = 0; bottom.value = 0; left.value = 0; right.value = 0; top.value = 0; width.value = 0; x.value = 0; y.value = 0; } return; } const rect = el.getBoundingClientRect(); height.value = rect.height; bottom.value = rect.bottom; left.value = rect.left; right.value = rect.right; top.value = rect.top; width.value = rect.width; x.value = rect.x; y.value = rect.y; } function update() { if (updateTiming === "sync") recalculate(); else if (updateTiming === "next-frame") requestAnimationFrame(() => recalculate()); } useResizeObserver(target, update); vue.watch(() => unrefElement(target), (ele) => !ele && update()); useMutationObserver(target, update, { attributeFilter: ["style", "class"] }); if (windowScroll) useEventListener("scroll", update, { capture: true, passive: true }); if (windowResize) useEventListener("resize", update, { passive: true }); shared.tryOnMounted(() => { if (immediate) update(); }); return { height, bottom, left, right, top, width, x, y, update }; } const vElementBounding = { mounted(el, binding) { const [handler, options] = typeof binding.value === "function" ? [binding.value, {}] : binding.value; const { height, bottom, left, right, top, width, x, y } = useElementBounding(el, options); vue.watch([height, bottom, left, right, top, width, x, y], () => handler({ height, bottom, left, right, top, width, x, y })); } }; function onElementRemoval(target, callback, options = {}) { const { window = defaultWindow, document = window == null ? void 0 : window.document, flush = "sync" } = options; if (!window || !document) return shared.noop; let stopFn; const cleanupAndUpdate = (fn) => { stopFn == null ? void 0 : stopFn(); stopFn = fn; }; const stopWatch = vue.watchEffect(() => { const el = unrefElement(target); if (el) { const { stop } = useMutationObserver( document, (mutationsList) => { const targetRemoved = mutationsList.map((mutation) => [...mutation.removedNodes]).flat().some((node) => node === el || node.contains(el)); if (targetRemoved) { callback(mutationsList); } }, { window, childList: true, subtree: true } ); cleanupAndUpdate(stop); } }, { flush }); const stopHandle = () => { stopWatch(); cleanupAndUpdate(); }; shared.tryOnScopeDispose(stopHandle); return stopHandle; } function useElementHover(el, options = {}) { const { delayEnter = 0, delayLeave = 0, triggerOnRemoval = false, window = defaultWindow } = options; const isHovered = vue.shallowRef(false); let timer; const toggle = (entering) => { const delay = entering ? delayEnter : delayLeave; if (timer) { clearTimeout(timer); timer = void 0; } if (delay) timer = setTimeout(() => isHovered.value = entering, delay); else isHovered.value = entering; }; if (!window) return isHovered; useEventListener(el, "mouseenter", () => toggle(true), { passive: true }); useEventListener(el, "mouseleave", () => toggle(false), { passive: true }); if (triggerOnRemoval) { onElementRemoval( vue.computed(() => unrefElement(el)), () => toggle(false) ); } return isHovered; } const vElementHover = { mounted(el, binding) { const value = binding.value; if (typeof value === "function") { const isHovered = useElementHover(el); vue.watch(isHovered, (v) => value(v)); } else { const [handler, options] = value; const isHovered = useElementHover(el, options); vue.watch(isHovered, (v) => handler(v)); } } }; const UseElementSize = /* @__PURE__ */ vue.defineComponent({ name: "UseElementSize", props: ["width", "height", "box", "as"], setup(props, { slots }) { var _a, _b; const target = vue.shallowRef(); const data = vue.reactive(core.useElementSize(target, { width: (_a = props.width) != null ? _a : 0, height: (_b = props.height) != null ? _b : 0 }, { box: props.box })); return () => { if (slots.default) return vue.h(props.as || "div", { ref: target }, slots.default(data)); }; } }); function useElementSize(target, initialSize = { width: 0, height: 0 }, options = {}) { const { window = defaultWindow, box = "content-box" } = options; const isSVG = vue.computed(() => { var _a, _b; return (_b = (_a = unrefElement(target)) == null ? void 0 : _a.namespaceURI) == null ? void 0 : _b.includes("svg"); }); const width = vue.shallowRef(initialSize.width); const height = vue.shallowRef(initialSize.height); const { stop: stop1 } = useResizeObserver( target, ([entry]) => { const boxSize = box === "border-box" ? entry.borderBoxSize : box === "content-box" ? entry.contentBoxSize : entry.devicePixelContentBoxSize; if (window && isSVG.value) { const $elem = unrefElement(target); if ($elem) { const rect = $elem.getBoundingClientRect(); width.value = rect.width; height.value = rect.height; } } else { if (boxSize) { const formatBoxSize = shared.toArray(boxSize); width.value = formatBoxSize.reduce((acc, { inlineSize }) => acc + inlineSize, 0); height.value = formatBoxSize.reduce((acc, { blockSize }) => acc + blockSize, 0); } else { width.value = entry.contentRect.width; height.value = entry.contentRect.height; } } }, options ); shared.tryOnMounted(() => { const ele = unrefElement(target); if (ele) { width.value = "offsetWidth" in ele ? ele.offsetWidth : initialSize.width; height.value = "offsetHeight" in ele ? ele.offsetHeight : initialSize.height; } }); const stop2 = vue.watch( () => unrefElement(target), (ele) => { width.value = ele ? initialSize.width : 0; height.value = ele ? initialSize.height : 0; } ); function stop() { stop1(); stop2(); } return { width, height, stop }; } const vElementSize = { mounted(el, binding) { var _a; const handler = typeof binding.value === "function" ? binding.value : (_a = binding.value) == null ? void 0 : _a[0]; const options = typeof binding.value === "function" ? [] : binding.value.slice(1); const { width, height } = useElementSize(el, ...options); vue.watch([width, height], ([width2, height2]) => handler({ width: width2, height: height2 })); } }; const UseElementVisibility = /* @__PURE__ */ vue.defineComponent({ name: "UseElementVisibility", props: ["as"], setup(props, { slots }) { const target = vue.shallowRef(); const data = vue.reactive({ isVisible: core.useElementVisibility(target) }); return () => { if (slots.default) return vue.h(props.as || "div", { ref: target }, slots.default(data)); }; } }); function useIntersectionObserver(target, callback, options = {}) { const { root, rootMargin = "0px", threshold = 0, window = defaultWindow, immediate = true } = options; const isSupported = useSupported(() => window && "IntersectionObserver" in window); const targets = vue.computed(() => { const _target = vue.toValue(target); return shared.toArray(_target).map(unrefElement).filter(shared.notNullish); }); let cleanup = shared.noop; const isActive = vue.shallowRef(immediate); const stopWatch = isSupported.value ? vue.watch( () => [targets.value, unrefElement(root), isActive.value], ([targets2, root2]) => { cleanup(); if (!isActive.value) return; if (!targets2.length) return; const observer = new IntersectionObserver( callback, { root: unrefElement(root2), rootMargin, threshold } ); targets2.forEach((el) => el && observer.observe(el)); cleanup = () => { observer.disconnect(); cleanup = shared.noop; }; }, { immediate, flush: "post" } ) : shared.noop; const stop = () => { cleanup(); stopWatch(); isActive.value = false; }; shared.tryOnScopeDispose(stop); return { isSupported, isActive, pause() { cleanup(); isActive.value = false; }, resume() { isActive.value = true; }, stop }; } function useElementVisibility(element, options = {}) { const { window = defaultWindow, scrollTarget, threshold = 0, rootMargin, once = false } = options; const elementIsVisible = vue.shallowRef(false); const { stop } = useIntersectionObserver( element, (intersectionObserverEntries) => { let isIntersecting = elementIsVisible.value; let latestTime = 0; for (const entry of intersectionObserverEntries) { if (entry.time >= latestTime) { latestTime = entry.time; isIntersecting = entry.isIntersecting; } } elementIsVisible.value = isIntersecting; if (once) { shared.watchOnce(elementIsVisible, () => { stop(); }); } }, { root: scrollTarget, window, threshold, rootMargin: vue.toValue(rootMargin) } ); return elementIsVisible; } const vElementVisibility = { mounted(el, binding) { if (typeof binding.value === "function") { const handler = binding.value; const isVisible = useElementVisibility(el); vue.watch(isVisible, (v) => handler(v), { immediate: true }); } else { const [handler, options] = binding.value; const isVisible = useElementVisibility(el, options); vue.watch(isVisible, (v) => handler(v), { immediate: true }); } } }; const UseEyeDropper = /* @__PURE__ */ vue.defineComponent({ name: "UseEyeDropper", props: { sRGBHex: String }, setup(props, { slots }) { const data = vue.reactive(core.useEyeDropper()); return () => { if (slots.default) return slots.default(data); }; } }); const UseFullscreen = /* @__PURE__ */ vue.defineComponent({ name: "UseFullscreen", props: ["as"], setup(props, { slots }) { const target = vue.shallowRef(); const data = vue.reactive(core.useFullscreen(target)); return () => { if (slots.default) return vue.h(props.as || "div", { ref: target }, slots.default(data)); }; } }); const UseGeolocation = /* @__PURE__ */ vue.defineComponent({ name: "UseGeolocation", props: ["enableHighAccuracy", "maximumAge", "timeout", "navigator"], setup(props, { slots }) { const data = vue.reactive(core.useGeolocation(props)); return () => { if (slots.default) return slots.default(data); }; } }); const UseIdle = /* @__PURE__ */ vue.defineComponent({ name: "UseIdle", props: ["timeout", "events", "listenForVisibilityChange", "initialState"], setup(props, { slots }) { const data = vue.reactive(core.useIdle(props.timeout, props)); return () => { if (slots.default) return slots.default(data); }; } }); function useAsyncState(promise, initialState, options) { var _a; const { immediate = true, delay = 0, onError = (_a = globalThis.reportError) != null ? _a : shared.noop, onSuccess = shared.noop, resetOnExecute = true, shallow = true, throwError } = options != null ? options : {}; const state = shallow ? vue.shallowRef(initialState) : vue.ref(initialState); const isReady = vue.shallowRef(false); const isLoading = vue.shallowRef(false); const error = vue.shallowRef(void 0); async function execute(delay2 = 0, ...args) { if (resetOnExecute) state.value = vue.toValue(initialState); error.value = void 0; isReady.value = false; isLoading.value = true; if (delay2 > 0) await shared.promiseTimeout(delay2); const _promise = typeof promise === "function" ? promise(...args) : promise; try { const data = await _promise; state.value = data; isReady.value = true; onSuccess(data); } catch (e) { error.value = e; onError(e); if (throwError) throw e; } finally { isLoading.value = false; } return state.value; } if (immediate) { execute(delay); } const shell = { state, isReady, isLoading, error, execute, executeImmediate: (...args) => execute(0, ...args) }; function waitUntilIsLoaded() { return new Promise((resolve, reject) => { shared.until(isLoading).toBe(false).then(() => resolve(shell)).catch(reject); }); } return { ...shell, then(onFulfilled, onRejected) { return waitUntilIsLoaded().then(onFulfilled, onRejected); } }; } async function loadImage(options) { return new Promise((resolve, reject) => { const img = new Image(); const { src, srcset, sizes, class: clazz, loading, crossorigin, referrerPolicy, width, height, decoding, fetchPriority, ismap, usemap } = options; img.src = src; if (srcset != null) img.srcset = srcset; if (sizes != null) img.sizes = sizes; if (clazz != null) img.className = clazz; if (loading != null) img.loading = loading; if (crossorigin != null) img.crossOrigin = crossorigin; if (referrerPolicy != null) img.referrerPolicy = referrerPolicy; if (width != null) img.width = width; if (height != null) img.height = height; if (decoding != null) img.decoding = decoding; if (fetchPriority != null) img.fetchPriority = fetchPriority; if (ismap != null) img.isMap = ismap; if (usemap != null) img.useMap = usemap; img.onload = () => resolve(img); img.onerror = reject; }); } function useImage(options, asyncStateOptions = {}) { const state = useAsyncState( () => loadImage(vue.toValue(options)), void 0, { resetOnExecute: true, ...asyncStateOptions } ); vue.watch( () => vue.toValue(options), () => state.execute(asyncStateOptions.delay), { deep: true } ); return state; } const UseImage = /* @__PURE__ */ vue.defineComponent({ name: "UseImage", props: [ "src", "srcset", "sizes", "as", "alt", "class", "loading", "crossorigin", "referrerPolicy", "width", "height", "decoding", "fetchPriority", "ismap", "usemap" ], setup(props, { slots }) { const data = vue.reactive(useImage(props)); return () => { if (data.isLoading && slots.loading) return slots.loading(data); else if (data.error && slots.error) return slots.error(data.error); if (slots.default) return slots.default(data); return vue.h(props.as || "img