UNPKG

@wfrog/vc

Version:

vue3 组件库 vc

676 lines (658 loc) 22.6 kB
import { i as isDef, t as tryOnScopeDispose, b as isClient, n as noop, p as pausableWatch, c as tryOnMounted, d as toArray, w as watchImmediate, e as isObject, f as pxValue, g as injectLocal } from './GvCnndsC.mjs'; import { getCurrentInstance, ref, watch, nextTick, computed, shallowRef, onMounted, toValue, unref, watchEffect, hasInjectionContext } from 'vue'; //#endregion //#region _configurable.ts const defaultWindow = isClient ? window : void 0; const defaultNavigator = isClient ? window.navigator : void 0; //#endregion //#region unrefElement/index.ts /** * Get the dom element of a ref of element or Vue component instance * * @param elRef */ function unrefElement(elRef) { var _$el; const plain = toValue(elRef); return (_$el = plain === null || plain === void 0 ? void 0 : plain.$el) !== null && _$el !== void 0 ? _$el : plain; } //#endregion //#region useEventListener/index.ts function useEventListener(...args) { const 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 = computed(() => { const test = toArray(toValue(args[0])).filter((e) => e != null); return test.every((e) => typeof e !== "string") ? test : void 0; }); const stopWatch = watchImmediate(() => { var _firstParamTargets$va, _firstParamTargets$va2; return [ (_firstParamTargets$va = (_firstParamTargets$va2 = firstParamTargets.value) === null || _firstParamTargets$va2 === void 0 ? void 0 : _firstParamTargets$va2.map((e) => unrefElement(e))) !== null && _firstParamTargets$va !== void 0 ? _firstParamTargets$va : [defaultWindow].filter((e) => e != null), toArray(toValue(firstParamTargets.value ? args[1] : args[0])), toArray(unref(firstParamTargets.value ? args[2] : args[1])), toValue(firstParamTargets.value ? args[3] : args[2]) ]; }, ([raw_targets, raw_events, raw_listeners, raw_options]) => { cleanup(); if (!(raw_targets === null || raw_targets === void 0 ? void 0 : raw_targets.length) || !(raw_events === null || raw_events === void 0 ? void 0 : raw_events.length) || !(raw_listeners === null || raw_listeners === void 0 ? void 0 : raw_listeners.length)) return; const optionsClone = 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(); }; tryOnScopeDispose(cleanup); return stop; } function onClickOutside(target, handler, options = {}) { const { window: window$1 = defaultWindow, ignore = [], capture = true, detectIframe = false, controls = false } = options; if (!window$1) return controls ? { stop: noop, cancel: noop, trigger: noop } : noop; let shouldListen = true; const shouldIgnore = (event) => { return toValue(ignore).some((target$1) => { if (typeof target$1 === "string") return Array.from(window$1.document.querySelectorAll(target$1)).some((el) => el === event.target || event.composedPath().includes(el)); else { const el = unrefElement(target$1); return el && (event.target === el || event.composedPath().includes(el)); } }); }; /** * Determines if the given target has multiple root elements. * Referenced from: https://github.com/vuejs/test-utils/blob/ccb460be55f9f6be05ab708500a41ec8adf6f4bc/src/vue-wrapper.ts#L21 */ function hasMultipleRoots(target$1) { const vm = toValue(target$1); return vm && vm.$.subTree.shapeFlag === 16; } function checkMultipleRoots(target$1, event) { const vm = toValue(target$1); const children = vm.$.subTree && vm.$.subTree.children; if (children == null || !Array.isArray(children)) return false; return children.some((child) => child.el === event.target || event.composedPath().includes(child.el)); } const listener = (event) => { const el = unrefElement(target); if (event.target == null) return; if (!(el instanceof Element) && hasMultipleRoots(target) && checkMultipleRoots(target, event)) return; if (!el || el === event.target || event.composedPath().includes(el)) return; if ("detail" in event && event.detail === 0) shouldListen = !shouldIgnore(event); if (!shouldListen) { shouldListen = true; return; } handler(event); }; let isProcessingClick = false; const cleanup = [ useEventListener(window$1, "click", (event) => { if (!isProcessingClick) { isProcessingClick = true; setTimeout(() => { isProcessingClick = false; }, 0); listener(event); } }, { passive: true, capture }), useEventListener(window$1, "pointerdown", (e) => { const el = unrefElement(target); shouldListen = !shouldIgnore(e) && !!(el && !e.composedPath().includes(el)); }, { passive: true }), detectIframe && useEventListener(window$1, "blur", (event) => { setTimeout(() => { var _window$document$acti; const el = unrefElement(target); if (((_window$document$acti = window$1.document.activeElement) === null || _window$document$acti === void 0 ? void 0 : _window$document$acti.tagName) === "IFRAME" && !(el === null || el === void 0 ? void 0 : el.contains(window$1.document.activeElement))) handler(event); }, 0); }, { passive: true }) ].filter(Boolean); const stop = () => cleanup.forEach((fn) => fn()); if (controls) return { stop, cancel: () => { shouldListen = false; }, trigger: (event) => { shouldListen = true; listener(event); shouldListen = false; } }; return stop; } //#endregion //#region useMounted/index.ts /** * Mounted state in ref. * * @see https://vueuse.org/useMounted * * @__NO_SIDE_EFFECTS__ */ function useMounted() { const isMounted = shallowRef(false); const instance = getCurrentInstance(); if (instance) onMounted(() => { isMounted.value = true; }, instance); return isMounted; } //#endregion //#region useSupported/index.ts /* @__NO_SIDE_EFFECTS__ */ function useSupported(callback) { const isMounted = useMounted(); return computed(() => { isMounted.value; return Boolean(callback()); }); } //#endregion //#region useSSRWidth/index.ts const ssrWidthSymbol = Symbol("vueuse-ssr-width"); /* @__NO_SIDE_EFFECTS__ */ function useSSRWidth() { const ssrWidth = hasInjectionContext() ? injectLocal(ssrWidthSymbol, null) : null; return typeof ssrWidth === "number" ? ssrWidth : void 0; } //#endregion //#region useMediaQuery/index.ts /** * Reactive Media Query. * * @see https://vueuse.org/useMediaQuery * @param query * @param options */ function useMediaQuery(query, options = {}) { const { window: window$1 = defaultWindow, ssrWidth = /* @__PURE__ */ useSSRWidth() } = options; const isSupported = /* @__PURE__ */ useSupported(() => window$1 && "matchMedia" in window$1 && typeof window$1.matchMedia === "function"); const ssrSupport = shallowRef(typeof ssrWidth === "number"); const mediaQuery = shallowRef(); const matches = shallowRef(false); const handler = (event) => { matches.value = event.matches; }; watchEffect(() => { if (ssrSupport.value) { ssrSupport.value = !isSupported.value; matches.value = toValue(query).split(",").some((queryString) => { const not = queryString.includes("not all"); const minWidth = queryString.match(/\(\s*min-width:\s*(-?\d+(?:\.\d*)?[a-z]+\s*)\)/); const maxWidth = queryString.match(/\(\s*max-width:\s*(-?\d+(?:\.\d*)?[a-z]+\s*)\)/); let res = Boolean(minWidth || maxWidth); if (minWidth && res) res = ssrWidth >= pxValue(minWidth[1]); if (maxWidth && res) res = ssrWidth <= pxValue(maxWidth[1]); return not ? !res : res; }); return; } if (!isSupported.value) return; mediaQuery.value = window$1.matchMedia(toValue(query)); matches.value = mediaQuery.value.matches; }); useEventListener(mediaQuery, "change", handler, { passive: true }); return computed(() => matches.value); } //#endregion //#region useCloned/index.ts function cloneFnJSON(source) { return JSON.parse(JSON.stringify(source)); } //#endregion //#region ssr-handlers.ts 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; } //#endregion //#region useStorage/guess.ts 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"; } //#endregion //#region useStorage/index.ts 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"; /** * Reactive LocalStorage/SessionStorage. * * @see https://vueuse.org/useStorage */ function useStorage(key, defaults$1, storage, options = {}) { var _options$serializer; const { flush = "pre", deep = true, listenToStorageChanges = true, writeDefaults = true, mergeDefaults = false, shallow, window: window$1 = defaultWindow, eventFilter, onError = (e) => { console.error(e); }, initOnMounted } = options; const data = (shallow ? shallowRef : ref)(typeof defaults$1 === "function" ? defaults$1() : defaults$1); const keyComputed = computed(() => toValue(key)); if (!storage) try { storage = getSSRHandler("getDefaultStorage", () => defaultWindow === null || defaultWindow === void 0 ? void 0 : defaultWindow.localStorage)(); } catch (e) { onError(e); } if (!storage) return data; const rawInit = toValue(defaults$1); const type = guessSerializerType(rawInit); const serializer = (_options$serializer = options.serializer) !== null && _options$serializer !== void 0 ? _options$serializer : StorageSerializers[type]; const { pause: pauseWatch, resume: resumeWatch } = pausableWatch(data, (newValue) => write(newValue), { flush, deep, eventFilter }); 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); }; /** * The custom event is needed for same-document syncing when using custom * storage backends, but it doesn't work across different documents. * * TODO: Consider implementing a BroadcastChannel-based solution that fixes this. */ if (window$1 && listenToStorageChanges) if (storage instanceof Storage) useEventListener(window$1, "storage", onStorageEvent, { passive: true }); else useEventListener(window$1, customStorageEventName, onStorageCustomEvent); if (initOnMounted) tryOnMounted(() => { firstMounted = true; update(); }); else update(); function dispatchWriteEvent(oldValue, newValue) { if (window$1) { const payload = { key: keyComputed.value, oldValue, newValue, storageArea: storage }; window$1.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 || event === void 0 ? void 0 : event.newValue) !== serializedData) data.value = read(event); } catch (e) { onError(e); } finally { if (event) nextTick(resumeWatch); else resumeWatch(); } } function updateFromCustomEvent(event) { update(event.detail); } return data; } //#endregion //#region useResizeObserver/index.ts /** * Reports changes to the dimensions of an Element's content or the border-box * * @see https://vueuse.org/useResizeObserver * @param target * @param callback * @param options */ function useResizeObserver(target, callback, options = {}) { const { window: window$1 = defaultWindow,...observerOptions } = options; let observer; const isSupported = /* @__PURE__ */ useSupported(() => window$1 && "ResizeObserver" in window$1); const cleanup = () => { if (observer) { observer.disconnect(); observer = void 0; } }; const stopWatch = watch(computed(() => { const _targets = toValue(target); return Array.isArray(_targets) ? _targets.map((el) => unrefElement(el)) : [unrefElement(_targets)]; }), (els) => { cleanup(); if (isSupported.value && window$1) { observer = new ResizeObserver(callback); for (const _el of els) if (_el) observer.observe(_el, observerOptions); } }, { immediate: true, flush: "post" }); const stop = () => { cleanup(); stopWatch(); }; tryOnScopeDispose(stop); return { isSupported, stop }; } //#endregion //#region useElementSize/index.ts /** * Reactive size of an HTML element. * * @see https://vueuse.org/useElementSize */ function useElementSize(target, initialSize = { width: 0, height: 0 }, options = {}) { const { window: window$1 = defaultWindow, box = "content-box" } = options; const isSVG = computed(() => { var _unrefElement; return (_unrefElement = unrefElement(target)) === null || _unrefElement === void 0 || (_unrefElement = _unrefElement.namespaceURI) === null || _unrefElement === void 0 ? void 0 : _unrefElement.includes("svg"); }); const width = shallowRef(initialSize.width); const height = 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$1 && 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 = 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); 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 = watch(() => unrefElement(target), (ele) => { width.value = ele ? initialSize.width : 0; height.value = ele ? initialSize.height : 0; }); function stop() { stop1(); stop2(); } return { width, height, stop }; } //#endregion //#region useUserMedia/index.ts /** * Reactive `mediaDevices.getUserMedia` streaming * * @see https://vueuse.org/useUserMedia * @param options */ function useUserMedia(options = {}) { var _options$enabled, _options$autoSwitch; const enabled = shallowRef((_options$enabled = options.enabled) !== null && _options$enabled !== void 0 ? _options$enabled : false); const autoSwitch = shallowRef((_options$autoSwitch = options.autoSwitch) !== null && _options$autoSwitch !== void 0 ? _options$autoSwitch : true); const constraints = ref(options.constraints); const { navigator: navigator$1 = defaultNavigator } = options; const isSupported = /* @__PURE__ */ useSupported(() => { var _navigator$mediaDevic; return navigator$1 === null || navigator$1 === void 0 || (_navigator$mediaDevic = navigator$1.mediaDevices) === null || _navigator$mediaDevic === void 0 ? void 0 : _navigator$mediaDevic.getUserMedia; }); const stream = shallowRef(); function getDeviceOptions(type) { switch (type) { case "video": if (constraints.value) return constraints.value.video || false; break; case "audio": if (constraints.value) return constraints.value.audio || false; break; } } async function _start() { if (!isSupported.value || stream.value) return; stream.value = await navigator$1.mediaDevices.getUserMedia({ video: getDeviceOptions("video"), audio: getDeviceOptions("audio") }); return stream.value; } function _stop() { var _stream$value; (_stream$value = stream.value) === null || _stream$value === void 0 || _stream$value.getTracks().forEach((t) => t.stop()); stream.value = void 0; } function stop() { _stop(); enabled.value = false; } async function start() { await _start(); if (stream.value) enabled.value = true; return stream.value; } async function restart() { _stop(); return await start(); } watch(enabled, (v) => { if (v) _start(); else _stop(); }, { immediate: true }); watch(constraints, () => { if (autoSwitch.value && stream.value) restart(); }, { immediate: true, deep: true }); tryOnScopeDispose(() => { stop(); }); return { isSupported, stream, start, stop, restart, constraints, enabled, autoSwitch }; } //#endregion //#region useVModel/index.ts /** * Shorthand for v-model binding, props + emit -> ref * * @see https://vueuse.org/useVModel * @param props * @param key (default 'modelValue') * @param emit * @param options * * @__NO_SIDE_EFFECTS__ */ function useVModel(props, key, emit, options = {}) { var _vm$$emit, _vm$proxy; const { clone = false, passive = false, eventName, deep = false, defaultValue, shouldEmit } = options; const vm = getCurrentInstance(); const _emit = emit || (vm === null || vm === void 0 ? void 0 : vm.emit) || (vm === null || vm === void 0 || (_vm$$emit = vm.$emit) === null || _vm$$emit === void 0 ? void 0 : _vm$$emit.bind(vm)) || (vm === null || vm === void 0 || (_vm$proxy = vm.proxy) === null || _vm$proxy === void 0 || (_vm$proxy = _vm$proxy.$emit) === null || _vm$proxy === void 0 ? void 0 : _vm$proxy.bind(vm === null || vm === void 0 ? void 0 : vm.proxy)); let event = eventName; event = event || `update:${key.toString()}`; const cloneFn = (val) => !clone ? val : typeof clone === "function" ? clone(val) : cloneFnJSON(val); const getValue$1 = () => isDef(props[key]) ? cloneFn(props[key]) : defaultValue; const triggerEmit = (value) => { if (shouldEmit) { if (shouldEmit(value)) _emit(event, value); } else _emit(event, value); }; if (passive) { const proxy = ref(getValue$1()); let isUpdating = false; watch(() => props[key], (v) => { if (!isUpdating) { isUpdating = true; proxy.value = cloneFn(v); nextTick(() => isUpdating = false); } }); watch(proxy, (v) => { if (!isUpdating && (v !== props[key] || deep)) triggerEmit(v); }, { deep }); return proxy; } else return computed({ get() { return getValue$1(); }, set(value) { triggerEmit(value); } }); } //#endregion //#region useWindowSize/index.ts /** * Reactive window size. * * @see https://vueuse.org/useWindowSize * @param options * * @__NO_SIDE_EFFECTS__ */ function useWindowSize(options = {}) { const { window: window$1 = defaultWindow, initialWidth = Number.POSITIVE_INFINITY, initialHeight = Number.POSITIVE_INFINITY, listenOrientation = true, includeScrollbar = true, type = "inner" } = options; const width = shallowRef(initialWidth); const height = shallowRef(initialHeight); const update = () => { if (window$1) if (type === "outer") { width.value = window$1.outerWidth; height.value = window$1.outerHeight; } else if (type === "visual" && window$1.visualViewport) { const { width: visualViewportWidth, height: visualViewportHeight, scale } = window$1.visualViewport; width.value = Math.round(visualViewportWidth * scale); height.value = Math.round(visualViewportHeight * scale); } else if (includeScrollbar) { width.value = window$1.innerWidth; height.value = window$1.innerHeight; } else { width.value = window$1.document.documentElement.clientWidth; height.value = window$1.document.documentElement.clientHeight; } }; update(); tryOnMounted(update); const listenerOptions = { passive: true }; useEventListener("resize", update, listenerOptions); if (window$1 && type === "visual" && window$1.visualViewport) useEventListener(window$1.visualViewport, "resize", update, listenerOptions); if (listenOrientation) watch(useMediaQuery("(orientation: portrait)"), () => update()); return { width, height }; } export { useUserMedia as a, useStorage as b, useElementSize as c, useWindowSize as d, onClickOutside as o, useVModel as u };