@vueuse/components
Version:
Renderless components for VueUse
1,611 lines (1,557 loc) • 83.6 kB
JavaScript
(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