From acec2a694aaebf8568c13e249c329dee18594c10 Mon Sep 17 00:00:00 2001 From: Jeppe Bundgaard Date: Mon, 13 Jul 2026 22:11:51 +0200 Subject: [PATCH] Add loading screen for session confirmation and enhance vehicle management labels --- index.html | 437 +- playwright/.cache/.htaccess | 57 + playwright/.cache/.well-known/assetlinks.json | 12 + .../assets/DatePeriodSelector-B7d5SXAv.js | 123620 +++++++++++++++ .../assets/DatePeriodSelector-B7d5SXAv.js.map | 1 + .../assets/DatePeriodSelector-C3h44B1J.css | 2715 + playwright/.cache/assets/browser-CIlJ6MKH.js | 3140 + .../.cache/assets/browser-CIlJ6MKH.js.map | 1 + playwright/.cache/assets/index-6ljr7rTu.js | 47540 ++++++ .../.cache/assets/index-6ljr7rTu.js.map | 1 + playwright/.cache/assets/index-Cq5akw1E.css | 26019 +++ playwright/.cache/favicon.ico | Bin 0 -> 15086 bytes playwright/.cache/favicon_default.ico | Bin 0 -> 4286 bytes .../.cache/favicons/apple-touch-icon.png | Bin 0 -> 14959 bytes playwright/.cache/favicons/favicon-96x96.png | Bin 0 -> 7945 bytes playwright/.cache/favicons/favicon.ico | Bin 0 -> 15086 bytes playwright/.cache/favicons/favicon.svg | 3 + .../favicons/web-app-manifest-192x192.png | Bin 0 -> 16857 bytes .../favicons/web-app-manifest-512x512.png | Bin 0 -> 82160 bytes playwright/.cache/icons/icon-192x192.png | Bin 0 -> 18343 bytes playwright/.cache/icons/icon-512x512.png | Bin 0 -> 82160 bytes .../.cache/icons/icon-favicon-256x256.png | Bin 0 -> 15091 bytes .../.cache/icons/icon-favicon-512x512.png | Bin 0 -> 34087 bytes .../.cache/icons/pleno-icon-192x192.png | Bin 0 -> 23293 bytes .../.cache/icons/pleno-icon-512x512.png | Bin 0 -> 61096 bytes playwright/.cache/img/jm-signature.png | Bin 0 -> 10170 bytes playwright/.cache/img/my-signature.png | Bin 0 -> 16818 bytes playwright/.cache/index.html | 13 + playwright/.cache/manifest.json | 26 + playwright/.cache/metainfo.json | 1860 + playwright/.cache/pleno-favicon.ico | Bin 0 -> 113287 bytes playwright/.cache/sounds/favicon.ico | Bin 0 -> 15086 bytes playwright/.cache/sounds/success.mp3 | Bin 0 -> 9264 bytes .../truckwash-banner-white-compressed.png | Bin 0 -> 5046 bytes src/App.vue | 111 +- .../buttons/ActionSettingsWheelButton.vue | 179 +- .../system/SystemStatusDashboard.vue | 118 + .../displays/user/vehicles/vehiclesTable.vue | 8 +- .../global/BrandedLoadingScreen.vue | 516 + .../page/wrappers/RestrictedPageWrapper.vue | 16 +- .../useStoredSessionGuestRedirect.js | 43 + src/i18n/generated/da-v2.json | 14 +- src/i18n/generated/de-v2.json | 14 +- src/i18n/generated/en-v2.json | 14 +- src/i18n/generated/global-v2.json | 13 + src/i18n/generated/no-v2.json | 14 +- src/i18n/generated/sv-v2.json | 14 +- .../da/phrases/compat/admin/index-02.json | 4 +- .../phrases/compat/system_status/index.json | 10 + .../de/phrases/compat/admin/index-02.json | 4 +- .../phrases/compat/system_status/index.json | 10 + .../en/phrases/compat/admin/index-02.json | 4 +- .../phrases/compat/system_status/index.json | 10 + .../source/global/shared/admin/index-02.json | 2 + .../source/global/shared/superuser/index.json | 1 + .../global/shared/system_status/index.json | 10 + .../no/phrases/compat/admin/index-02.json | 4 +- .../phrases/compat/system_status/index.json | 10 + .../sv/phrases/compat/admin/index-02.json | 4 +- .../phrases/compat/system_status/index.json | 10 + src/main.js | 15 + src/router.js | 2 +- src/views/DefaultPage.vue | 35 +- src/views/auth/Employee.vue | 19 +- src/views/auth/Login.vue | 14 +- src/views/auth/SubuserLogin.vue | 14 +- src/views/pages/LandingPage.vue | 49 +- tests/e2e/admin-pos-orders.spec.ts | 21 +- .../public-htaccess.local-prod.spec.ts | 4 +- tests/e2e/release/release.live-smoke.spec.ts | 2 +- .../e2e/superuser-system-status.smoke.spec.js | 32 +- tests/e2e/superuser-users.spec.ts | 6 + .../unit/action-settings-wheel-button.spec.js | 101 + tests/unit/app-loading-shell.spec.js | 88 + tests/unit/branded-loading-screen.spec.js | 87 + .../unit/default-page-mobile-redirect.spec.js | 62 +- tests/unit/guest-auth-entry-loader.spec.js | 180 + tests/unit/i18n-action-settings-wheel.spec.js | 14 +- ...vigation-menu-items-admin-contract.spec.js | 4 + tests/unit/restricted-page-wrapper.spec.js | 8 +- .../superuser-system-status-dashboard.spec.js | 36 + tests/unit/superuser-users-i18n.spec.js | 32 + .../unit/user-vehicles-table-actions.spec.js | 5 + 83 files changed, 207312 insertions(+), 120 deletions(-) create mode 100644 playwright/.cache/.htaccess create mode 100644 playwright/.cache/.well-known/assetlinks.json create mode 100644 playwright/.cache/assets/DatePeriodSelector-B7d5SXAv.js create mode 100644 playwright/.cache/assets/DatePeriodSelector-B7d5SXAv.js.map create mode 100644 playwright/.cache/assets/DatePeriodSelector-C3h44B1J.css create mode 100644 playwright/.cache/assets/browser-CIlJ6MKH.js create mode 100644 playwright/.cache/assets/browser-CIlJ6MKH.js.map create mode 100644 playwright/.cache/assets/index-6ljr7rTu.js create mode 100644 playwright/.cache/assets/index-6ljr7rTu.js.map create mode 100644 playwright/.cache/assets/index-Cq5akw1E.css create mode 100644 playwright/.cache/favicon.ico create mode 100644 playwright/.cache/favicon_default.ico create mode 100644 playwright/.cache/favicons/apple-touch-icon.png create mode 100644 playwright/.cache/favicons/favicon-96x96.png create mode 100644 playwright/.cache/favicons/favicon.ico create mode 100644 playwright/.cache/favicons/favicon.svg create mode 100644 playwright/.cache/favicons/web-app-manifest-192x192.png create mode 100644 playwright/.cache/favicons/web-app-manifest-512x512.png create mode 100644 playwright/.cache/icons/icon-192x192.png create mode 100644 playwright/.cache/icons/icon-512x512.png create mode 100644 playwright/.cache/icons/icon-favicon-256x256.png create mode 100644 playwright/.cache/icons/icon-favicon-512x512.png create mode 100644 playwright/.cache/icons/pleno-icon-192x192.png create mode 100644 playwright/.cache/icons/pleno-icon-512x512.png create mode 100644 playwright/.cache/img/jm-signature.png create mode 100644 playwright/.cache/img/my-signature.png create mode 100644 playwright/.cache/index.html create mode 100644 playwright/.cache/manifest.json create mode 100644 playwright/.cache/metainfo.json create mode 100644 playwright/.cache/pleno-favicon.ico create mode 100644 playwright/.cache/sounds/favicon.ico create mode 100644 playwright/.cache/sounds/success.mp3 create mode 100644 public/assets/branding/truckwash-banner-white-compressed.png create mode 100644 src/components/global/BrandedLoadingScreen.vue create mode 100644 src/composables/useStoredSessionGuestRedirect.js create mode 100644 tests/unit/app-loading-shell.spec.js create mode 100644 tests/unit/branded-loading-screen.spec.js create mode 100644 tests/unit/guest-auth-entry-loader.spec.js create mode 100644 tests/unit/superuser-users-i18n.spec.js diff --git a/index.html b/index.html index 88edfde1..ab236d60 100644 --- a/index.html +++ b/index.html @@ -1,9 +1,12 @@ - + diff --git a/playwright/.cache/.htaccess b/playwright/.cache/.htaccess new file mode 100644 index 00000000..8db24b7b --- /dev/null +++ b/playwright/.cache/.htaccess @@ -0,0 +1,57 @@ + + Options -MultiViews + + + + AddType application/manifest+json .webmanifest + + + + RewriteEngine On + + RewriteRule ^index\.html$ - [L] + + RewriteCond %{REQUEST_FILENAME} !-f + RewriteCond %{REQUEST_FILENAME} !-d + RewriteRule ^.+/((?:assets|resources|favicons|icons|img|sounds|\.well-known)/.+)$ $1 [L] + + RewriteCond %{REQUEST_FILENAME} !-f + RewriteCond %{REQUEST_FILENAME} !-d + RewriteCond %{DOCUMENT_ROOT}/public/$1 -f + RewriteRule ^(?:.*?/)?((?:assets|resources|favicons|icons|img|sounds|\.well-known)/.+)$ public/$1 [L] + + RewriteCond %{REQUEST_FILENAME} !-f + RewriteCond %{REQUEST_FILENAME} !-d + RewriteCond %{DOCUMENT_ROOT}/dist/$1 -f + RewriteRule ^(?:.*?/)?((?:assets|resources|favicons|icons|img|sounds|\.well-known)/.+)$ dist/$1 [L] + + RewriteCond %{REQUEST_FILENAME} !-f + RewriteCond %{REQUEST_FILENAME} !-d + RewriteRule ^.+/((?:index\.html|manifest\.json|manifest\.webmanifest|favicon\.ico|favicon_default\.ico|pleno-favicon\.ico|release-entry\.json|release-manifest\.json|registerSW\.js|sw\.js|workbox-[^/]+\.js))$ $1 [L] + + RewriteCond %{REQUEST_FILENAME} !-f + RewriteCond %{REQUEST_FILENAME} !-d + RewriteCond %{DOCUMENT_ROOT}/public/$1 -f + RewriteRule ^(?:.*?/)?((?:index\.html|manifest\.json|manifest\.webmanifest|favicon\.ico|favicon_default\.ico|pleno-favicon\.ico|release-entry\.json|release-manifest\.json|registerSW\.js|sw\.js|workbox-[^/]+\.js))$ public/$1 [L] + + RewriteCond %{REQUEST_FILENAME} !-f + RewriteCond %{REQUEST_FILENAME} !-d + RewriteCond %{DOCUMENT_ROOT}/dist/$1 -f + RewriteRule ^(?:.*?/)?((?:index\.html|manifest\.json|manifest\.webmanifest|favicon\.ico|favicon_default\.ico|pleno-favicon\.ico|release-entry\.json|release-manifest\.json|registerSW\.js|sw\.js|workbox-[^/]+\.js))$ dist/$1 [L] + + RewriteCond %{REQUEST_FILENAME} !-f + RewriteCond %{REQUEST_FILENAME} !-d + RewriteRule ^(?:.*?/)?(?:assets|resources|favicons|icons|img|sounds|\.well-known)/ - [R=404,L] + + RewriteCond %{REQUEST_FILENAME} !-f + RewriteCond %{REQUEST_FILENAME} !-d + RewriteRule ^(?:.*?/)?(?:index\.html|manifest\.json|manifest\.webmanifest|favicon\.ico|favicon_default\.ico|pleno-favicon\.ico|release-entry\.json|release-manifest\.json|registerSW\.js|sw\.js|workbox-[^/]+\.js)$ - [R=404,L] + + RewriteCond %{REQUEST_FILENAME} !-f + RewriteCond %{REQUEST_FILENAME} !-d + RewriteRule \.[^/]+$ - [R=404,L] + + RewriteCond %{REQUEST_FILENAME} !-f + RewriteCond %{REQUEST_FILENAME} !-d + RewriteRule . index.html [L] + diff --git a/playwright/.cache/.well-known/assetlinks.json b/playwright/.cache/.well-known/assetlinks.json new file mode 100644 index 00000000..c9bc1e09 --- /dev/null +++ b/playwright/.cache/.well-known/assetlinks.json @@ -0,0 +1,12 @@ +[ + { + "relation": ["delegate_permission/common.handle_all_urls"], + "target": { + "namespace": "android_app", + "package_name": "io.truckwash.twa", + "sha256_cert_fingerprints": [ + "29:56:F7:8D:BD:A0:2E:A9:32:82:97:28:A3:E2:65:16:23:73:DD:2C:16:F6:7A:97:AD:63:27:14:5C:8C:FB:89" + ] + } + } +] diff --git a/playwright/.cache/assets/DatePeriodSelector-B7d5SXAv.js b/playwright/.cache/assets/DatePeriodSelector-B7d5SXAv.js new file mode 100644 index 00000000..4292afa5 --- /dev/null +++ b/playwright/.cache/assets/DatePeriodSelector-B7d5SXAv.js @@ -0,0 +1,123620 @@ +import { s as shallowRef, w as watchEffect, r as readonly, a as watch, c as customRef, g as getCurrentScope, o as onScopeDispose, e as effectScope, b as getCurrentInstance, h as hasInjectionContext, i as inject, p as provide, d as ref, f as isRef, u as unref, t as toValue$1, j as computed, k as reactive, l as toRefs$1, m as toRef$1, n as onBeforeMount, q as nextTick, v as onBeforeUnmount, x as onMounted, y as onUnmounted, z as isReactive, A as defineComponent, B as shallowReactive, C as h, F as Fragment, T as TransitionGroup, D as onUpdated, E as toRaw, G as markRaw, H as isReadonly, I as onBeforeUpdate, _ as __vitePreload, J as i18n, K as useI18n, L as openBlock, M as createElementBlock, N as createCommentVNode, O as createBaseVNode, P as withDirectives, Q as vModelText, R as renderSlot, S as normalizeClass, U as toDisplayString, V as withModifiers, W as vShow, X as createTextVNode, Y as renderList, Z as vModelSelect, $ as createVNode, a0 as createBlock, a1 as createSlots, a2 as withCtx, a3 as onDeactivated, a4 as onActivated, a5 as setupDevtoolsPlugin, a6 as resolveComponent, a7 as useSlots, a8 as Tooltip$1, a9 as withKeys, aa as createStaticVNode, ab as BLoading, ac as BIcon, ad as BButton, ae as createApp, af as version$2, ag as isProxy, ah as normalizeStyle, ai as resolveDynamicComponent, aj as useAttrs, ak as BDatepicker, al as mergeProps, am as useModel, an as mergeModels, ao as Switch, ap as BAutocomplete, aq as vModelCheckbox, ar as BCheckbox } from './index-6ljr7rTu.js'; + +const parseBoolean = (value, fallback = false) => { + if (typeof value === "boolean") { + return value; + } + if (typeof value === "string") { + const normalized = value.trim().toLowerCase(); + if (["1", "true", "yes", "on"].includes(normalized)) { + return true; + } + if (["0", "false", "no", "off"].includes(normalized)) { + return false; + } + } + return fallback; +}; +const normalizeApiUrl$1 = (value) => String(value || "").replace(/\/+$/, ""); +const IS_DEV = parseBoolean( + undefined , + false +); +const normalizeReleaseSource = (value) => { + const normalized = String(value || "").trim().toLowerCase(); + if (["local", "deployment", "auto"].includes(normalized)) { + return normalized; + } + return IS_DEV ? "local" : "deployment"; +}; +const RELEASE_SOURCE_ENV = String(undefined || "").trim().toLowerCase(); +const RELEASE_SOURCE = normalizeReleaseSource(RELEASE_SOURCE_ENV); +const DEFAULT_LEGACY_API_URL = "https://api.truckwash.io"; +const DEFAULT_PUBLIC_GATEWAY_API_URL = "https://api-v2.truckwash.io"; +const DEFAULT_STABLE_API_URL = `${DEFAULT_PUBLIC_GATEWAY_API_URL}/master/api`; +const POS_STEP_1_VERSION = 2; +const API_URL = normalizeApiUrl$1( + undefined || (IS_DEV ? "/api" : DEFAULT_STABLE_API_URL) +); +const RELEASE_MANAGER_CONTROL_API_URL = normalizeApiUrl$1( + undefined || API_URL +); +const RELEASE_PUBLIC_GATEWAY_API_URL = normalizeApiUrl$1( + undefined || DEFAULT_PUBLIC_GATEWAY_API_URL +); +const RELEASE_MANAGER_CONTROL_API_FALLBACK_URLS = String( + undefined || (IS_DEV ? `${DEFAULT_STABLE_API_URL},${DEFAULT_PUBLIC_GATEWAY_API_URL}` : "") +).split(",").map((url) => normalizeApiUrl$1(url.trim())).filter(Boolean); +const RELEASE_TRUSTED_ORIGINS = String(undefined || "").split(",").map((origin) => origin.trim().replace(/\/+$/, "")).filter(Boolean); +const SELF_SERVE_ATTACHMENT_TRUSTED_ORIGINS = String( + undefined || "" +).split(",").map((origin) => origin.trim().replace(/\/+$/, "")).filter(Boolean); +const ALLOWED_ORIGINS = [ + "https://truckwash.io", + "https://www.truckwash.io", + new URL(DEFAULT_PUBLIC_GATEWAY_API_URL).origin, + "http://localhost:5173", + "http://localhost:4173", + "http://localhost:4174", + "http://127.0.0.1:5173", + "http://127.0.0.1:4173", + "http://127.0.0.1:4174", + "https://dev.truckwash.io" +]; +const MIGRATION_ORIGIN = "https://truckwash.io"; +const REQUEST_QUEUE_CONFIG = Object.freeze({ + // Per-method concurrency limits + concurrency: Object.freeze({ + GET: 10, + POST: 4, + PATCH: 4, + PUT: 4, + DELETE: 4, + DEFAULT: 4 + }), + // Delay between queue starts (0 = no pacing delay) + spacingMs: 0, + // Retries by HTTP status code + retryByStatusCode: Object.freeze({ + 429: 4, + 500: 1, + 502: 2, + 503: 2, + 504: 2 + }), + retryDelay: Object.freeze({ + baseMs: 300, + maxMs: 3e3, + jitterMs: 50 + }), + ping: Object.freeze({ + endpoint: "/ping", + intervalMs: 3e4, + timeoutMs: 5e3 + }), + inspector: Object.freeze({ + expandedByDefault: false, + timerRefreshMs: 250, + recentRequestsLimit: 8, + errorHistoryLimit: 10, + missingPermissionsLimit: 20, + componentPermissionReportWindowMs: 2e3, + payloadMaxChars: 4e3 + }), + // Queue progress widget behavior + progress: Object.freeze({ + minBatchSizeToShow: 2, + completedVisibleMs: 2500 + }) +}); + +function computedEager(fn, options) { + var _a; + const result = shallowRef(); + watchEffect(() => { + result.value = fn(); + }, { + ...options, + flush: (_a = options == null ? void 0 : options.flush) != null ? _a : "sync" + }); + return readonly(result); +} + +function computedWithControl(source, fn) { + let v = void 0; + let track; + let trigger; + const dirty = shallowRef(true); + const update = () => { + dirty.value = true; + trigger(); + }; + watch(source, update, { flush: "sync" }); + const get = typeof fn === "function" ? fn : fn.get; + const set = typeof fn === "function" ? void 0 : fn.set; + const result = customRef((_track, _trigger) => { + track = _track; + trigger = _trigger; + return { + get() { + if (dirty.value) { + v = get(v); + dirty.value = false; + } + track(); + return v; + }, + set(v2) { + set == null ? void 0 : set(v2); + } + }; + }); + if (Object.isExtensible(result)) + result.trigger = update; + return result; +} + +function tryOnScopeDispose(fn) { + if (getCurrentScope()) { + onScopeDispose(fn); + return true; + } + return false; +} + +function createEventHook() { + const fns = /* @__PURE__ */ new Set(); + const off = (fn) => { + fns.delete(fn); + }; + const clear = () => { + fns.clear(); + }; + const on = (fn) => { + fns.add(fn); + const offFn = () => off(fn); + tryOnScopeDispose(offFn); + return { + off: offFn + }; + }; + const trigger = (...args) => { + return Promise.all(Array.from(fns).map((fn) => fn(...args))); + }; + return { + on, + off, + trigger, + clear + }; +} + +function createGlobalState(stateFactory) { + let initialized = false; + let state; + const scope = effectScope(true); + return (...args) => { + if (!initialized) { + state = scope.run(() => stateFactory(...args)); + initialized = true; + } + return state; + }; +} + +const localProvidedStateMap = /* @__PURE__ */ new WeakMap(); + +const injectLocal = (...args) => { + var _a; + const key = args[0]; + const instance = (_a = getCurrentInstance()) == null ? void 0 : _a.proxy; + if (instance == null && !hasInjectionContext()) + throw new Error("injectLocal must be called in setup"); + if (instance && localProvidedStateMap.has(instance) && key in localProvidedStateMap.get(instance)) + return localProvidedStateMap.get(instance)[key]; + return inject(...args); +}; + +const provideLocal = (key, value) => { + var _a; + const instance = (_a = getCurrentInstance()) == null ? void 0 : _a.proxy; + if (instance == null) + throw new Error("provideLocal must be called in setup"); + if (!localProvidedStateMap.has(instance)) + localProvidedStateMap.set(instance, /* @__PURE__ */ Object.create(null)); + const localProvidedState = localProvidedStateMap.get(instance); + localProvidedState[key] = value; + provide(key, value); +}; + +function createInjectionState(composable, options) { + const key = (options == null ? void 0 : options.injectionKey) || Symbol(composable.name || "InjectionState"); + const defaultValue = options == null ? void 0 : options.defaultValue; + const useProvidingState = (...args) => { + const state = composable(...args); + provideLocal(key, state); + return state; + }; + const useInjectedState = () => injectLocal(key, defaultValue); + return [useProvidingState, useInjectedState]; +} + +function createRef(value, deep) { + if (deep === true) { + return ref(value); + } else { + return shallowRef(value); + } +} + +function createSharedComposable(composable) { + let subscribers = 0; + let state; + let scope; + const dispose = () => { + subscribers -= 1; + if (scope && subscribers <= 0) { + scope.stop(); + state = void 0; + scope = void 0; + } + }; + return (...args) => { + subscribers += 1; + if (!scope) { + scope = effectScope(true); + state = scope.run(() => composable(...args)); + } + tryOnScopeDispose(dispose); + return state; + }; +} + +function extendRef(ref, extend, { enumerable = false, unwrap = true } = {}) { + for (const [key, value] of Object.entries(extend)) { + if (key === "value") + continue; + if (isRef(value) && unwrap) { + Object.defineProperty(ref, key, { + get() { + return value.value; + }, + set(v) { + value.value = v; + }, + enumerable + }); + } else { + Object.defineProperty(ref, key, { value, enumerable }); + } + } + return ref; +} + +function get(obj, key) { + if (key == null) + return unref(obj); + return unref(obj)[key]; +} + +function isDefined(v) { + return unref(v) != null; +} + +function makeDestructurable(obj, arr) { + if (typeof Symbol !== "undefined") { + const clone = { ...obj }; + Object.defineProperty(clone, Symbol.iterator, { + enumerable: false, + value() { + let index = 0; + return { + next: () => ({ + value: arr[index++], + done: index > arr.length + }) + }; + } + }); + return clone; + } else { + return Object.assign([...arr], obj); + } +} + +function reactify(fn, options) { + const unrefFn = (options == null ? void 0 : options.computedGetter) === false ? unref : toValue$1; + return function(...args) { + return computed(() => fn.apply(this, args.map((i) => unrefFn(i)))); + }; +} + +function reactifyObject(obj, optionsOrKeys = {}) { + let keys = []; + let options; + if (Array.isArray(optionsOrKeys)) { + keys = optionsOrKeys; + } else { + options = optionsOrKeys; + const { includeOwnProperties = true } = optionsOrKeys; + keys.push(...Object.keys(obj)); + if (includeOwnProperties) + keys.push(...Object.getOwnPropertyNames(obj)); + } + return Object.fromEntries( + keys.map((key) => { + const value = obj[key]; + return [ + key, + typeof value === "function" ? reactify(value.bind(obj), options) : value + ]; + }) + ); +} + +function toReactive(objectRef) { + if (!isRef(objectRef)) + return reactive(objectRef); + const proxy = new Proxy({}, { + get(_, p, receiver) { + return unref(Reflect.get(objectRef.value, p, receiver)); + }, + set(_, p, value) { + if (isRef(objectRef.value[p]) && !isRef(value)) + objectRef.value[p].value = value; + else + objectRef.value[p] = value; + return true; + }, + deleteProperty(_, p) { + return Reflect.deleteProperty(objectRef.value, p); + }, + has(_, p) { + return Reflect.has(objectRef.value, p); + }, + ownKeys() { + return Object.keys(objectRef.value); + }, + getOwnPropertyDescriptor() { + return { + enumerable: true, + configurable: true + }; + } + }); + return reactive(proxy); +} + +function reactiveComputed(fn) { + return toReactive(computed(fn)); +} + +function reactiveOmit(obj, ...keys) { + const flatKeys = keys.flat(); + const predicate = flatKeys[0]; + return reactiveComputed(() => typeof predicate === "function" ? Object.fromEntries(Object.entries(toRefs$1(obj)).filter(([k, v]) => !predicate(toValue$1(v), k))) : Object.fromEntries(Object.entries(toRefs$1(obj)).filter((e) => !flatKeys.includes(e[0])))); +} + +const isClient = typeof window !== "undefined" && typeof document !== "undefined"; +const isWorker = typeof WorkerGlobalScope !== "undefined" && globalThis instanceof WorkerGlobalScope; +const isDef = (val) => typeof val !== "undefined"; +const notNullish = (val) => val != null; +const assert = (condition, ...infos) => { + if (!condition) + console.warn(...infos); +}; +const toString$1 = Object.prototype.toString; +const isObject$2 = (val) => toString$1.call(val) === "[object Object]"; +const now = () => Date.now(); +const timestamp = () => +Date.now(); +const clamp = (n, min, max) => Math.min(max, Math.max(min, n)); +const noop$3 = () => { +}; +const rand = (min, max) => { + min = Math.ceil(min); + max = Math.floor(max); + return Math.floor(Math.random() * (max - min + 1)) + min; +}; +const hasOwn$2 = (val, key) => Object.prototype.hasOwnProperty.call(val, key); +const isIOS = /* @__PURE__ */ getIsIOS(); +function getIsIOS() { + var _a, _b; + return isClient && ((_a = window == null ? void 0 : window.navigator) == null ? void 0 : _a.userAgent) && (/iP(?:ad|hone|od)/.test(window.navigator.userAgent) || ((_b = window == null ? void 0 : window.navigator) == null ? void 0 : _b.maxTouchPoints) > 2 && /iPad|Macintosh/.test(window == null ? void 0 : window.navigator.userAgent)); +} + +function createFilterWrapper(filter, fn) { + function wrapper(...args) { + return new Promise((resolve, reject) => { + Promise.resolve(filter(() => fn.apply(this, args), { fn, thisArg: this, args })).then(resolve).catch(reject); + }); + } + return wrapper; +} +const bypassFilter = (invoke) => { + return invoke(); +}; +function debounceFilter(ms, options = {}) { + let timer; + let maxTimer; + let lastRejector = noop$3; + const _clearTimeout = (timer2) => { + clearTimeout(timer2); + lastRejector(); + lastRejector = noop$3; + }; + let lastInvoker; + const filter = (invoke) => { + const duration = toValue$1(ms); + const maxDuration = toValue$1(options.maxWait); + if (timer) + _clearTimeout(timer); + if (duration <= 0 || maxDuration !== void 0 && maxDuration <= 0) { + if (maxTimer) { + _clearTimeout(maxTimer); + maxTimer = null; + } + return Promise.resolve(invoke()); + } + return new Promise((resolve, reject) => { + lastRejector = options.rejectOnCancel ? reject : resolve; + lastInvoker = invoke; + if (maxDuration && !maxTimer) { + maxTimer = setTimeout(() => { + if (timer) + _clearTimeout(timer); + maxTimer = null; + resolve(lastInvoker()); + }, maxDuration); + } + timer = setTimeout(() => { + if (maxTimer) + _clearTimeout(maxTimer); + maxTimer = null; + resolve(invoke()); + }, duration); + }); + }; + return filter; +} +function throttleFilter(...args) { + let lastExec = 0; + let timer; + let isLeading = true; + let lastRejector = noop$3; + let lastValue; + let ms; + let trailing; + let leading; + let rejectOnCancel; + if (!isRef(args[0]) && typeof args[0] === "object") + ({ delay: ms, trailing = true, leading = true, rejectOnCancel = false } = args[0]); + else + [ms, trailing = true, leading = true, rejectOnCancel = false] = args; + const clear = () => { + if (timer) { + clearTimeout(timer); + timer = void 0; + lastRejector(); + lastRejector = noop$3; + } + }; + const filter = (_invoke) => { + const duration = toValue$1(ms); + const elapsed = Date.now() - lastExec; + const invoke = () => { + return lastValue = _invoke(); + }; + clear(); + if (duration <= 0) { + lastExec = Date.now(); + return invoke(); + } + if (elapsed > duration && (leading || !isLeading)) { + lastExec = Date.now(); + invoke(); + } else if (trailing) { + lastValue = new Promise((resolve, reject) => { + lastRejector = rejectOnCancel ? reject : resolve; + timer = setTimeout(() => { + lastExec = Date.now(); + isLeading = true; + resolve(invoke()); + clear(); + }, Math.max(0, duration - elapsed)); + }); + } + if (!leading && !timer) + timer = setTimeout(() => isLeading = true, duration); + isLeading = false; + return lastValue; + }; + return filter; +} +function pausableFilter(extendFilter = bypassFilter, options = {}) { + const { + initialState = "active" + } = options; + const isActive = toRef(initialState === "active"); + function pause() { + isActive.value = false; + } + function resume() { + isActive.value = true; + } + const eventFilter = (...args) => { + if (isActive.value) + extendFilter(...args); + }; + return { isActive: readonly(isActive), pause, resume, eventFilter }; +} + +function cacheStringFunction(fn) { + const cache = /* @__PURE__ */ Object.create(null); + return (str) => { + const hit = cache[str]; + return hit || (cache[str] = fn(str)); + }; +} +const hyphenateRE = /\B([A-Z])/g; +const hyphenate = cacheStringFunction((str) => str.replace(hyphenateRE, "-$1").toLowerCase()); +const camelizeRE = /-(\w)/g; +const camelize = cacheStringFunction((str) => { + return str.replace(camelizeRE, (_, c) => c ? c.toUpperCase() : ""); +}); + +function promiseTimeout(ms, throwOnTimeout = false, reason = "Timeout") { + return new Promise((resolve, reject) => { + if (throwOnTimeout) + setTimeout(() => reject(reason), ms); + else + setTimeout(resolve, ms); + }); +} +function identity(arg) { + return arg; +} +function createSingletonPromise(fn) { + let _promise; + function wrapper() { + if (!_promise) + _promise = fn(); + return _promise; + } + wrapper.reset = async () => { + const _prev = _promise; + _promise = void 0; + if (_prev) + await _prev; + }; + return wrapper; +} +function invoke(fn) { + return fn(); +} +function containsProp(obj, ...props) { + return props.some((k) => k in obj); +} +function increaseWithUnit(target, delta) { + var _a; + if (typeof target === "number") + return target + delta; + const value = ((_a = target.match(/^-?\d+\.?\d*/)) == null ? void 0 : _a[0]) || ""; + const unit = target.slice(value.length); + const result = Number.parseFloat(value) + delta; + if (Number.isNaN(result)) + return target; + return result + unit; +} +function pxValue(px) { + return px.endsWith("rem") ? Number.parseFloat(px) * 16 : Number.parseFloat(px); +} +function objectPick(obj, keys, omitUndefined = false) { + return keys.reduce((n, k) => { + if (k in obj) { + if (!omitUndefined || obj[k] !== void 0) + n[k] = obj[k]; + } + return n; + }, {}); +} +function objectOmit(obj, keys, omitUndefined = false) { + return Object.fromEntries(Object.entries(obj).filter(([key, value]) => { + return (!omitUndefined || value !== void 0) && !keys.includes(key); + })); +} +function objectEntries(obj) { + return Object.entries(obj); +} +function getLifeCycleTarget(target) { + return target || getCurrentInstance(); +} +function toArray$1(value) { + return Array.isArray(value) ? value : [value]; +} + +function toRef(...args) { + if (args.length !== 1) + return toRef$1(...args); + const r = args[0]; + return typeof r === "function" ? readonly(customRef(() => ({ get: r, set: noop$3 }))) : ref(r); +} +const resolveRef = toRef; + +function reactivePick(obj, ...keys) { + const flatKeys = keys.flat(); + const predicate = flatKeys[0]; + return reactiveComputed(() => typeof predicate === "function" ? Object.fromEntries(Object.entries(toRefs$1(obj)).filter(([k, v]) => predicate(toValue$1(v), k))) : Object.fromEntries(flatKeys.map((k) => [k, toRef(obj, k)]))); +} + +function refAutoReset(defaultValue, afterMs = 1e4) { + return customRef((track, trigger) => { + let value = toValue$1(defaultValue); + let timer; + const resetAfter = () => setTimeout(() => { + value = toValue$1(defaultValue); + trigger(); + }, toValue$1(afterMs)); + tryOnScopeDispose(() => { + clearTimeout(timer); + }); + return { + get() { + track(); + return value; + }, + set(newValue) { + value = newValue; + trigger(); + clearTimeout(timer); + timer = resetAfter(); + } + }; + }); +} + +function useDebounceFn(fn, ms = 200, options = {}) { + return createFilterWrapper( + debounceFilter(ms, options), + fn + ); +} + +function refDebounced(value, ms = 200, options = {}) { + const debounced = ref(value.value); + const updater = useDebounceFn(() => { + debounced.value = value.value; + }, ms, options); + watch(value, () => updater()); + return debounced; +} + +function refDefault(source, defaultValue) { + return computed({ + get() { + var _a; + return (_a = source.value) != null ? _a : defaultValue; + }, + set(value) { + source.value = value; + } + }); +} + +function useThrottleFn(fn, ms = 200, trailing = false, leading = true, rejectOnCancel = false) { + return createFilterWrapper( + throttleFilter(ms, trailing, leading, rejectOnCancel), + fn + ); +} + +function refThrottled(value, delay = 200, trailing = true, leading = true) { + if (delay <= 0) + return value; + const throttled = ref(value.value); + const updater = useThrottleFn(() => { + throttled.value = value.value; + }, delay, trailing, leading); + watch(value, () => updater()); + return throttled; +} + +function refWithControl(initial, options = {}) { + let source = initial; + let track; + let trigger; + const ref = customRef((_track, _trigger) => { + track = _track; + trigger = _trigger; + return { + get() { + return get(); + }, + set(v) { + set(v); + } + }; + }); + function get(tracking = true) { + if (tracking) + track(); + return source; + } + function set(value, triggering = true) { + var _a, _b; + if (value === source) + return; + const old = source; + if (((_a = options.onBeforeChange) == null ? void 0 : _a.call(options, value, old)) === false) + return; + source = value; + (_b = options.onChanged) == null ? void 0 : _b.call(options, value, old); + if (triggering) + trigger(); + } + const untrackedGet = () => get(false); + const silentSet = (v) => set(v, false); + const peek = () => get(false); + const lay = (v) => set(v, false); + return extendRef( + ref, + { + get, + set, + untrackedGet, + silentSet, + peek, + lay + }, + { enumerable: true } + ); +} +const controlledRef = refWithControl; + +function set$1(...args) { + if (args.length === 2) { + const [ref, value] = args; + ref.value = value; + } + if (args.length === 3) { + const [target, key, value] = args; + target[key] = value; + } +} + +function watchWithFilter(source, cb, options = {}) { + const { + eventFilter = bypassFilter, + ...watchOptions + } = options; + return watch( + source, + createFilterWrapper( + eventFilter, + cb + ), + watchOptions + ); +} + +function watchPausable(source, cb, options = {}) { + const { + eventFilter: filter, + initialState = "active", + ...watchOptions + } = options; + const { eventFilter, pause, resume, isActive } = pausableFilter(filter, { initialState }); + const stop = watchWithFilter( + source, + cb, + { + ...watchOptions, + eventFilter + } + ); + return { stop, pause, resume, isActive }; +} + +function syncRef(left, right, ...[options]) { + const { + flush = "sync", + deep = false, + immediate = true, + direction = "both", + transform = {} + } = options || {}; + const watchers = []; + const transformLTR = "ltr" in transform && transform.ltr || ((v) => v); + const transformRTL = "rtl" in transform && transform.rtl || ((v) => v); + if (direction === "both" || direction === "ltr") { + watchers.push(watchPausable( + left, + (newValue) => { + watchers.forEach((w) => w.pause()); + right.value = transformLTR(newValue); + watchers.forEach((w) => w.resume()); + }, + { flush, deep, immediate } + )); + } + if (direction === "both" || direction === "rtl") { + watchers.push(watchPausable( + right, + (newValue) => { + watchers.forEach((w) => w.pause()); + left.value = transformRTL(newValue); + watchers.forEach((w) => w.resume()); + }, + { flush, deep, immediate } + )); + } + const stop = () => { + watchers.forEach((w) => w.stop()); + }; + return stop; +} + +function syncRefs(source, targets, options = {}) { + const { + flush = "sync", + deep = false, + immediate = true + } = options; + const targetsArray = toArray$1(targets); + return watch( + source, + (newValue) => targetsArray.forEach((target) => target.value = newValue), + { flush, deep, immediate } + ); +} + +function toRefs(objectRef, options = {}) { + if (!isRef(objectRef)) + return toRefs$1(objectRef); + const result = Array.isArray(objectRef.value) ? Array.from({ length: objectRef.value.length }) : {}; + for (const key in objectRef.value) { + result[key] = customRef(() => ({ + get() { + return objectRef.value[key]; + }, + set(v) { + var _a; + const replaceRef = (_a = toValue$1(options.replaceRef)) != null ? _a : true; + if (replaceRef) { + if (Array.isArray(objectRef.value)) { + const copy = [...objectRef.value]; + copy[key] = v; + objectRef.value = copy; + } else { + const newObject = { ...objectRef.value, [key]: v }; + Object.setPrototypeOf(newObject, Object.getPrototypeOf(objectRef.value)); + objectRef.value = newObject; + } + } else { + objectRef.value[key] = v; + } + } + })); + } + return result; +} + +const toValue = toValue$1; +const resolveUnref = toValue$1; + +function tryOnBeforeMount(fn, sync = true, target) { + const instance = getLifeCycleTarget(target); + if (instance) + onBeforeMount(fn, target); + else if (sync) + fn(); + else + nextTick(fn); +} + +function tryOnBeforeUnmount(fn, target) { + const instance = getLifeCycleTarget(target); + if (instance) + onBeforeUnmount(fn, target); +} + +function tryOnMounted(fn, sync = true, target) { + const instance = getLifeCycleTarget(); + if (instance) + onMounted(fn, target); + else if (sync) + fn(); + else + nextTick(fn); +} + +function tryOnUnmounted(fn, target) { + const instance = getLifeCycleTarget(target); + if (instance) + onUnmounted(fn, target); +} + +function createUntil(r, isNot = false) { + function toMatch(condition, { flush = "sync", deep = false, timeout, throwOnTimeout } = {}) { + let stop = null; + const watcher = new Promise((resolve) => { + stop = watch( + r, + (v) => { + if (condition(v) !== isNot) { + if (stop) + stop(); + else + nextTick(() => stop == null ? void 0 : stop()); + resolve(v); + } + }, + { + flush, + deep, + immediate: true + } + ); + }); + const promises = [watcher]; + if (timeout != null) { + promises.push( + promiseTimeout(timeout, throwOnTimeout).then(() => toValue$1(r)).finally(() => stop == null ? void 0 : stop()) + ); + } + return Promise.race(promises); + } + function toBe(value, options) { + if (!isRef(value)) + return toMatch((v) => v === value, options); + const { flush = "sync", deep = false, timeout, throwOnTimeout } = options != null ? options : {}; + let stop = null; + const watcher = new Promise((resolve) => { + stop = watch( + [r, value], + ([v1, v2]) => { + if (isNot !== (v1 === v2)) { + if (stop) + stop(); + else + nextTick(() => stop == null ? void 0 : stop()); + resolve(v1); + } + }, + { + flush, + deep, + immediate: true + } + ); + }); + const promises = [watcher]; + if (timeout != null) { + promises.push( + promiseTimeout(timeout, throwOnTimeout).then(() => toValue$1(r)).finally(() => { + stop == null ? void 0 : stop(); + return toValue$1(r); + }) + ); + } + return Promise.race(promises); + } + function toBeTruthy(options) { + return toMatch((v) => Boolean(v), options); + } + function toBeNull(options) { + return toBe(null, options); + } + function toBeUndefined(options) { + return toBe(void 0, options); + } + function toBeNaN(options) { + return toMatch(Number.isNaN, options); + } + function toContains(value, options) { + return toMatch((v) => { + const array = Array.from(v); + return array.includes(value) || array.includes(toValue$1(value)); + }, options); + } + function changed(options) { + return changedTimes(1, options); + } + function changedTimes(n = 1, options) { + let count = -1; + return toMatch(() => { + count += 1; + return count >= n; + }, options); + } + if (Array.isArray(toValue$1(r))) { + const instance = { + toMatch, + toContains, + changed, + changedTimes, + get not() { + return createUntil(r, !isNot); + } + }; + return instance; + } else { + const instance = { + toMatch, + toBe, + toBeTruthy, + toBeNull, + toBeNaN, + toBeUndefined, + changed, + changedTimes, + get not() { + return createUntil(r, !isNot); + } + }; + return instance; + } +} +function until(r) { + return createUntil(r); +} + +function defaultComparator(value, othVal) { + return value === othVal; +} +function useArrayDifference(...args) { + var _a, _b; + const list = args[0]; + const values = args[1]; + let compareFn = (_a = args[2]) != null ? _a : defaultComparator; + const { + symmetric = false + } = (_b = args[3]) != null ? _b : {}; + if (typeof compareFn === "string") { + const key = compareFn; + compareFn = (value, othVal) => value[key] === othVal[key]; + } + const diff1 = computed(() => toValue$1(list).filter((x) => toValue$1(values).findIndex((y) => compareFn(x, y)) === -1)); + if (symmetric) { + const diff2 = computed(() => toValue$1(values).filter((x) => toValue$1(list).findIndex((y) => compareFn(x, y)) === -1)); + return computed(() => symmetric ? [...toValue$1(diff1), ...toValue$1(diff2)] : toValue$1(diff1)); + } else { + return diff1; + } +} + +function useArrayEvery(list, fn) { + return computed(() => toValue$1(list).every((element, index, array) => fn(toValue$1(element), index, array))); +} + +function useArrayFilter(list, fn) { + return computed(() => toValue$1(list).map((i) => toValue$1(i)).filter(fn)); +} + +function useArrayFind(list, fn) { + return computed(() => toValue$1( + toValue$1(list).find((element, index, array) => fn(toValue$1(element), index, array)) + )); +} + +function useArrayFindIndex(list, fn) { + return computed(() => toValue$1(list).findIndex((element, index, array) => fn(toValue$1(element), index, array))); +} + +function findLast(arr, cb) { + let index = arr.length; + while (index-- > 0) { + if (cb(arr[index], index, arr)) + return arr[index]; + } + return void 0; +} +function useArrayFindLast(list, fn) { + return computed(() => toValue$1( + !Array.prototype.findLast ? findLast(toValue$1(list), (element, index, array) => fn(toValue$1(element), index, array)) : toValue$1(list).findLast((element, index, array) => fn(toValue$1(element), index, array)) + )); +} + +function isArrayIncludesOptions(obj) { + return isObject$2(obj) && containsProp(obj, "formIndex", "comparator"); +} +function useArrayIncludes(...args) { + var _a; + const list = args[0]; + const value = args[1]; + let comparator = args[2]; + let formIndex = 0; + if (isArrayIncludesOptions(comparator)) { + formIndex = (_a = comparator.fromIndex) != null ? _a : 0; + comparator = comparator.comparator; + } + if (typeof comparator === "string") { + const key = comparator; + comparator = (element, value2) => element[key] === toValue$1(value2); + } + comparator = comparator != null ? comparator : (element, value2) => element === toValue$1(value2); + return computed(() => toValue$1(list).slice(formIndex).some((element, index, array) => comparator( + toValue$1(element), + toValue$1(value), + index, + toValue$1(array) + ))); +} + +function useArrayJoin(list, separator) { + return computed(() => toValue$1(list).map((i) => toValue$1(i)).join(toValue$1(separator))); +} + +function useArrayMap(list, fn) { + return computed(() => toValue$1(list).map((i) => toValue$1(i)).map(fn)); +} + +function useArrayReduce(list, reducer, ...args) { + const reduceCallback = (sum, value, index) => reducer(toValue$1(sum), toValue$1(value), index); + return computed(() => { + const resolved = toValue$1(list); + return args.length ? resolved.reduce(reduceCallback, typeof args[0] === "function" ? toValue$1(args[0]()) : toValue$1(args[0])) : resolved.reduce(reduceCallback); + }); +} + +function useArraySome(list, fn) { + return computed(() => toValue$1(list).some((element, index, array) => fn(toValue$1(element), index, array))); +} + +function uniq(array) { + return Array.from(new Set(array)); +} +function uniqueElementsBy(array, fn) { + return array.reduce((acc, v) => { + if (!acc.some((x) => fn(v, x, array))) + acc.push(v); + return acc; + }, []); +} +function useArrayUnique(list, compareFn) { + return computed(() => { + const resolvedList = toValue$1(list).map((element) => toValue$1(element)); + return compareFn ? uniqueElementsBy(resolvedList, compareFn) : uniq(resolvedList); + }); +} + +function useCounter(initialValue = 0, options = {}) { + let _initialValue = unref(initialValue); + const count = shallowRef(initialValue); + const { + max = Number.POSITIVE_INFINITY, + min = Number.NEGATIVE_INFINITY + } = options; + const inc = (delta = 1) => count.value = Math.max(Math.min(max, count.value + delta), min); + const dec = (delta = 1) => count.value = Math.min(Math.max(min, count.value - delta), max); + const get = () => count.value; + const set = (val) => count.value = Math.max(min, Math.min(max, val)); + const reset = (val = _initialValue) => { + _initialValue = val; + return set(val); + }; + return { count, inc, dec, get, set, reset }; +} + +const REGEX_PARSE = /^(\d{4})[-/]?(\d{1,2})?[-/]?(\d{0,2})[T\s]*(\d{1,2})?:?(\d{1,2})?:?(\d{1,2})?[.:]?(\d+)?$/i; +const REGEX_FORMAT = /[YMDHhms]o|\[([^\]]+)\]|Y{1,4}|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a{1,2}|A{1,2}|m{1,2}|s{1,2}|Z{1,2}|z{1,4}|SSS/g; +function defaultMeridiem(hours, minutes, isLowercase, hasPeriod) { + let m = hours < 12 ? "AM" : "PM"; + if (hasPeriod) + m = m.split("").reduce((acc, curr) => acc += `${curr}.`, ""); + return isLowercase ? m.toLowerCase() : m; +} +function formatOrdinal(num) { + const suffixes = ["th", "st", "nd", "rd"]; + const v = num % 100; + return num + (suffixes[(v - 20) % 10] || suffixes[v] || suffixes[0]); +} +function formatDate$1(date, formatStr, options = {}) { + var _a; + const years = date.getFullYear(); + const month = date.getMonth(); + const days = date.getDate(); + const hours = date.getHours(); + const minutes = date.getMinutes(); + const seconds = date.getSeconds(); + const milliseconds = date.getMilliseconds(); + const day = date.getDay(); + const meridiem = (_a = options.customMeridiem) != null ? _a : defaultMeridiem; + const stripTimeZone = (dateString) => { + var _a2; + return (_a2 = dateString.split(" ")[1]) != null ? _a2 : ""; + }; + const matches = { + Yo: () => formatOrdinal(years), + YY: () => String(years).slice(-2), + YYYY: () => years, + M: () => month + 1, + Mo: () => formatOrdinal(month + 1), + MM: () => `${month + 1}`.padStart(2, "0"), + MMM: () => date.toLocaleDateString(toValue$1(options.locales), { month: "short" }), + MMMM: () => date.toLocaleDateString(toValue$1(options.locales), { month: "long" }), + D: () => String(days), + Do: () => formatOrdinal(days), + DD: () => `${days}`.padStart(2, "0"), + H: () => String(hours), + Ho: () => formatOrdinal(hours), + HH: () => `${hours}`.padStart(2, "0"), + h: () => `${hours % 12 || 12}`.padStart(1, "0"), + ho: () => formatOrdinal(hours % 12 || 12), + hh: () => `${hours % 12 || 12}`.padStart(2, "0"), + m: () => String(minutes), + mo: () => formatOrdinal(minutes), + mm: () => `${minutes}`.padStart(2, "0"), + s: () => String(seconds), + so: () => formatOrdinal(seconds), + ss: () => `${seconds}`.padStart(2, "0"), + SSS: () => `${milliseconds}`.padStart(3, "0"), + d: () => day, + dd: () => date.toLocaleDateString(toValue$1(options.locales), { weekday: "narrow" }), + ddd: () => date.toLocaleDateString(toValue$1(options.locales), { weekday: "short" }), + dddd: () => date.toLocaleDateString(toValue$1(options.locales), { weekday: "long" }), + A: () => meridiem(hours, minutes), + AA: () => meridiem(hours, minutes, false, true), + a: () => meridiem(hours, minutes, true), + aa: () => meridiem(hours, minutes, true, true), + z: () => stripTimeZone(date.toLocaleDateString(toValue$1(options.locales), { timeZoneName: "shortOffset" })), + zz: () => stripTimeZone(date.toLocaleDateString(toValue$1(options.locales), { timeZoneName: "shortOffset" })), + zzz: () => stripTimeZone(date.toLocaleDateString(toValue$1(options.locales), { timeZoneName: "shortOffset" })), + zzzz: () => stripTimeZone(date.toLocaleDateString(toValue$1(options.locales), { timeZoneName: "longOffset" })) + }; + return formatStr.replace(REGEX_FORMAT, (match, $1) => { + var _a2, _b; + return (_b = $1 != null ? $1 : (_a2 = matches[match]) == null ? void 0 : _a2.call(matches)) != null ? _b : match; + }); +} +function normalizeDate(date) { + if (date === null) + return new Date(Number.NaN); + if (date === void 0) + return /* @__PURE__ */ new Date(); + if (date instanceof Date) + return new Date(date); + if (typeof date === "string" && !/Z$/i.test(date)) { + const d = date.match(REGEX_PARSE); + if (d) { + const m = d[2] - 1 || 0; + const ms = (d[7] || "0").substring(0, 3); + return new Date(d[1], m, d[3] || 1, d[4] || 0, d[5] || 0, d[6] || 0, ms); + } + } + return new Date(date); +} +function useDateFormat(date, formatStr = "HH:mm:ss", options = {}) { + return computed(() => formatDate$1(normalizeDate(toValue$1(date)), toValue$1(formatStr), options)); +} + +function useIntervalFn(cb, interval = 1e3, options = {}) { + const { + immediate = true, + immediateCallback = false + } = options; + let timer = null; + const isActive = shallowRef(false); + function clean() { + if (timer) { + clearInterval(timer); + timer = null; + } + } + function pause() { + isActive.value = false; + clean(); + } + function resume() { + const intervalValue = toValue$1(interval); + if (intervalValue <= 0) + return; + isActive.value = true; + if (immediateCallback) + cb(); + clean(); + if (isActive.value) + timer = setInterval(cb, intervalValue); + } + if (immediate && isClient) + resume(); + if (isRef(interval) || typeof interval === "function") { + const stopWatch = watch(interval, () => { + if (isActive.value && isClient) + resume(); + }); + tryOnScopeDispose(stopWatch); + } + tryOnScopeDispose(pause); + return { + isActive, + pause, + resume + }; +} + +function useInterval(interval = 1e3, options = {}) { + const { + controls: exposeControls = false, + immediate = true, + callback + } = options; + const counter = shallowRef(0); + const update = () => counter.value += 1; + const reset = () => { + counter.value = 0; + }; + const controls = useIntervalFn( + callback ? () => { + update(); + callback(counter.value); + } : update, + interval, + { immediate } + ); + if (exposeControls) { + return { + counter, + reset, + ...controls + }; + } else { + return counter; + } +} + +function useLastChanged(source, options = {}) { + var _a; + const ms = shallowRef((_a = options.initialValue) != null ? _a : null); + watch( + source, + () => ms.value = timestamp(), + options + ); + return ms; +} + +function useTimeoutFn(cb, interval, options = {}) { + const { + immediate = true, + immediateCallback = false + } = options; + const isPending = shallowRef(false); + let timer = null; + function clear() { + if (timer) { + clearTimeout(timer); + timer = null; + } + } + function stop() { + isPending.value = false; + clear(); + } + function start(...args) { + if (immediateCallback) + cb(); + clear(); + isPending.value = true; + timer = setTimeout(() => { + isPending.value = false; + timer = null; + cb(...args); + }, toValue$1(interval)); + } + if (immediate) { + isPending.value = true; + if (isClient) + start(); + } + tryOnScopeDispose(stop); + return { + isPending: readonly(isPending), + start, + stop + }; +} + +function useTimeout(interval = 1e3, options = {}) { + const { + controls: exposeControls = false, + callback + } = options; + const controls = useTimeoutFn( + callback != null ? callback : noop$3, + interval, + options + ); + const ready = computed(() => !controls.isPending.value); + if (exposeControls) { + return { + ready, + ...controls + }; + } else { + return ready; + } +} + +function useToNumber(value, options = {}) { + const { + method = "parseFloat", + radix, + nanToZero + } = options; + return computed(() => { + let resolved = toValue$1(value); + if (typeof method === "function") + resolved = method(resolved); + else if (typeof resolved === "string") + resolved = Number[method](resolved, radix); + if (nanToZero && Number.isNaN(resolved)) + resolved = 0; + return resolved; + }); +} + +function useToString(value) { + return computed(() => `${toValue$1(value)}`); +} + +function useToggle(initialValue = false, options = {}) { + const { + truthyValue = true, + falsyValue = false + } = options; + const valueIsRef = isRef(initialValue); + const _value = shallowRef(initialValue); + function toggle(value) { + if (arguments.length) { + _value.value = value; + return _value.value; + } else { + const truthy = toValue$1(truthyValue); + _value.value = _value.value === truthy ? toValue$1(falsyValue) : truthy; + return _value.value; + } + } + if (valueIsRef) + return toggle; + else + return [_value, toggle]; +} + +function watchArray(source, cb, options) { + let oldList = (options == null ? void 0 : options.immediate) ? [] : [...typeof source === "function" ? source() : Array.isArray(source) ? source : toValue$1(source)]; + return watch(source, (newList, _, onCleanup) => { + const oldListRemains = Array.from({ length: oldList.length }); + const added = []; + for (const obj of newList) { + let found = false; + for (let i = 0; i < oldList.length; i++) { + if (!oldListRemains[i] && obj === oldList[i]) { + oldListRemains[i] = true; + found = true; + break; + } + } + if (!found) + added.push(obj); + } + const removed = oldList.filter((_2, i) => !oldListRemains[i]); + cb(newList, oldList, added, removed, onCleanup); + oldList = [...newList]; + }, options); +} + +function watchAtMost(source, cb, options) { + const { + count, + ...watchOptions + } = options; + const current = shallowRef(0); + const stop = watchWithFilter( + source, + (...args) => { + current.value += 1; + if (current.value >= toValue$1(count)) + nextTick(() => stop()); + cb(...args); + }, + watchOptions + ); + return { count: current, stop }; +} + +function watchDebounced(source, cb, options = {}) { + const { + debounce = 0, + maxWait = void 0, + ...watchOptions + } = options; + return watchWithFilter( + source, + cb, + { + ...watchOptions, + eventFilter: debounceFilter(debounce, { maxWait }) + } + ); +} + +function watchDeep(source, cb, options) { + return watch( + source, + cb, + { + ...options, + deep: true + } + ); +} + +function watchIgnorable(source, cb, options = {}) { + const { + eventFilter = bypassFilter, + ...watchOptions + } = options; + const filteredCb = createFilterWrapper( + eventFilter, + cb + ); + let ignoreUpdates; + let ignorePrevAsyncUpdates; + let stop; + if (watchOptions.flush === "sync") { + const ignore = shallowRef(false); + ignorePrevAsyncUpdates = () => { + }; + ignoreUpdates = (updater) => { + ignore.value = true; + updater(); + ignore.value = false; + }; + stop = watch( + source, + (...args) => { + if (!ignore.value) + filteredCb(...args); + }, + watchOptions + ); + } else { + const disposables = []; + const ignoreCounter = shallowRef(0); + const syncCounter = shallowRef(0); + ignorePrevAsyncUpdates = () => { + ignoreCounter.value = syncCounter.value; + }; + disposables.push( + watch( + source, + () => { + syncCounter.value++; + }, + { ...watchOptions, flush: "sync" } + ) + ); + ignoreUpdates = (updater) => { + const syncCounterPrev = syncCounter.value; + updater(); + ignoreCounter.value += syncCounter.value - syncCounterPrev; + }; + disposables.push( + watch( + source, + (...args) => { + const ignore = ignoreCounter.value > 0 && ignoreCounter.value === syncCounter.value; + ignoreCounter.value = 0; + syncCounter.value = 0; + if (ignore) + return; + filteredCb(...args); + }, + watchOptions + ) + ); + stop = () => { + disposables.forEach((fn) => fn()); + }; + } + return { stop, ignoreUpdates, ignorePrevAsyncUpdates }; +} + +function watchImmediate(source, cb, options) { + return watch( + source, + cb, + { + ...options, + immediate: true + } + ); +} + +function watchOnce(source, cb, options) { + const stop = watch(source, (...args) => { + nextTick(() => stop()); + return cb(...args); + }, options); + return stop; +} + +function watchThrottled(source, cb, options = {}) { + const { + throttle = 0, + trailing = true, + leading = true, + ...watchOptions + } = options; + return watchWithFilter( + source, + cb, + { + ...watchOptions, + eventFilter: throttleFilter(throttle, trailing, leading) + } + ); +} + +function watchTriggerable(source, cb, options = {}) { + let cleanupFn; + function onEffect() { + if (!cleanupFn) + return; + const fn = cleanupFn; + cleanupFn = void 0; + fn(); + } + function onCleanup(callback) { + cleanupFn = callback; + } + const _cb = (value, oldValue) => { + onEffect(); + return cb(value, oldValue, onCleanup); + }; + const res = watchIgnorable(source, _cb, options); + const { ignoreUpdates } = res; + const trigger = () => { + let res2; + ignoreUpdates(() => { + res2 = _cb(getWatchSources(source), getOldValue(source)); + }); + return res2; + }; + return { + ...res, + trigger + }; +} +function getWatchSources(sources) { + if (isReactive(sources)) + return sources; + if (Array.isArray(sources)) + return sources.map((item) => toValue$1(item)); + return toValue$1(sources); +} +function getOldValue(source) { + return Array.isArray(source) ? source.map(() => void 0) : void 0; +} + +function whenever(source, cb, options) { + const stop = watch( + source, + (v, ov, onInvalidate) => { + if (v) { + if (options == null ? void 0 : options.once) + nextTick(() => stop()); + cb(v, ov, onInvalidate); + } + }, + { + ...options, + once: false + } + ); + return stop; +} + +function computedAsync(evaluationCallback, initialState, optionsOrRef) { + let options; + if (isRef(optionsOrRef)) { + options = { + evaluating: optionsOrRef + }; + } else { + options = optionsOrRef || {}; + } + const { + lazy = false, + evaluating = void 0, + shallow = true, + onError = noop$3 + } = options; + const started = shallowRef(!lazy); + const current = shallow ? shallowRef(initialState) : ref(initialState); + let counter = 0; + watchEffect(async (onInvalidate) => { + if (!started.value) + return; + counter++; + const counterAtBeginning = counter; + let hasFinished = false; + if (evaluating) { + Promise.resolve().then(() => { + evaluating.value = true; + }); + } + try { + const result = await evaluationCallback((cancelCallback) => { + onInvalidate(() => { + if (evaluating) + evaluating.value = false; + if (!hasFinished) + cancelCallback(); + }); + }); + if (counterAtBeginning === counter) + current.value = result; + } catch (e) { + onError(e); + } finally { + if (evaluating && counterAtBeginning === counter) + evaluating.value = false; + hasFinished = true; + } + }); + if (lazy) { + return computed(() => { + started.value = true; + return current.value; + }); + } else { + return current; + } +} +function computedInject(key, options, defaultSource, treatDefaultAsFactory) { + let source = inject(key); + if (defaultSource) + source = inject(key, defaultSource); + if (treatDefaultAsFactory) + source = inject(key, defaultSource, treatDefaultAsFactory); + if (typeof options === "function") { + return computed((ctx) => options(source, ctx)); + } else { + return computed({ + get: (ctx) => options.get(source, ctx), + set: options.set + }); + } +} +function createReusableTemplate(options = {}) { + const { + inheritAttrs = true + } = options; + const render = shallowRef(); + const define = /* @__PURE__ */ defineComponent({ + setup(_, { slots }) { + return () => { + render.value = slots.default; + }; + } + }); + const reuse = /* @__PURE__ */ defineComponent({ + inheritAttrs, + props: options.props, + setup(props, { attrs, slots }) { + return () => { + var _a; + if (!render.value && false) + throw new Error("[VueUse] Failed to find the definition of reusable template"); + const vnode = (_a = render.value) == null ? void 0 : _a.call(render, { + ...options.props == null ? keysToCamelKebabCase(attrs) : props, + $slots: slots + }); + return inheritAttrs && (vnode == null ? void 0 : vnode.length) === 1 ? vnode[0] : vnode; + }; + } + }); + return makeDestructurable( + { define, reuse }, + [define, reuse] + ); +} +function keysToCamelKebabCase(obj) { + const newObj = {}; + for (const key in obj) + newObj[camelize(key)] = obj[key]; + return newObj; +} +function createTemplatePromise(options = {}) { + let index = 0; + const instances = ref([]); + function create(...args) { + const props = shallowReactive({ + key: index++, + args, + promise: void 0, + resolve: () => { + }, + reject: () => { + }, + isResolving: false, + options + }); + instances.value.push(props); + props.promise = new Promise((_resolve, _reject) => { + props.resolve = (v) => { + props.isResolving = true; + return _resolve(v); + }; + props.reject = _reject; + }).finally(() => { + props.promise = void 0; + const index2 = instances.value.indexOf(props); + if (index2 !== -1) + instances.value.splice(index2, 1); + }); + return props.promise; + } + function start(...args) { + if (options.singleton && instances.value.length > 0) + return instances.value[0].promise; + return create(...args); + } + const component = /* @__PURE__ */ defineComponent((_, { slots }) => { + const renderList = () => instances.value.map((props) => { + var _a; + return h(Fragment, { key: props.key }, (_a = slots.default) == null ? void 0 : _a.call(slots, props)); + }); + if (options.transition) + return () => h(TransitionGroup, options.transition, renderList); + return renderList; + }); + component.start = start; + return component; +} +function createUnrefFn(fn) { + return function(...args) { + return fn.apply(this, args.map((i) => toValue$1(i))); + }; +} +const defaultWindow = isClient ? window : void 0; +const defaultDocument = isClient ? window.document : void 0; +const defaultNavigator = isClient ? window.navigator : void 0; +const defaultLocation = isClient ? window.location : void 0; +function unrefElement(elRef) { + var _a; + const plain = toValue$1(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 = computed(() => { + const test = toArray$1(toValue$1(args[0])).filter((e) => e != null); + return test.every((e) => typeof e !== "string") ? test : void 0; + }); + const stopWatch = watchImmediate( + () => { + var _a, _b; + return [ + (_b = (_a = firstParamTargets.value) == null ? void 0 : _a.map((e) => unrefElement(e))) != null ? _b : [defaultWindow].filter((e) => e != null), + toArray$1(toValue$1(firstParamTargets.value ? args[1] : args[0])), + toArray$1(unref(firstParamTargets.value ? args[2] : args[1])), + // @ts-expect-error - TypeScript gets the correct types, but somehow still complains + toValue$1(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 = isObject$2(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; +} +let _iOSWorkaround = false; +function onClickOutside(target, handler, options = {}) { + const { window: window2 = defaultWindow, ignore = [], capture = true, detectIframe = false, controls = false } = options; + if (!window2) { + return controls ? { stop: noop$3, cancel: noop$3, trigger: noop$3 } : noop$3; + } + if (isIOS && !_iOSWorkaround) { + _iOSWorkaround = true; + const listenerOptions = { passive: true }; + Array.from(window2.document.body.children).forEach((el) => useEventListener(el, "click", noop$3, listenerOptions)); + useEventListener(window2.document.documentElement, "click", noop$3, listenerOptions); + } + let shouldListen = true; + const shouldIgnore = (event) => { + return toValue$1(ignore).some((target2) => { + if (typeof target2 === "string") { + return Array.from(window2.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 = toValue$1(target2); + return vm && vm.$.subTree.shapeFlag === 16; + } + function checkMultipleRoots(target2, event) { + const vm = toValue$1(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(window2, "click", (event) => { + if (!isProcessingClick) { + isProcessingClick = true; + setTimeout(() => { + isProcessingClick = false; + }, 0); + listener(event); + } + }, { passive: true, capture }), + useEventListener(window2, "pointerdown", (e) => { + const el = unrefElement(target); + shouldListen = !shouldIgnore(e) && !!(el && !e.composedPath().includes(el)); + }, { passive: true }), + detectIframe && useEventListener(window2, "blur", (event) => { + setTimeout(() => { + var _a; + const el = unrefElement(target); + if (((_a = window2.document.activeElement) == null ? void 0 : _a.tagName) === "IFRAME" && !(el == null ? void 0 : el.contains(window2.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; +} +function useMounted() { + const isMounted = shallowRef(false); + const instance = getCurrentInstance(); + if (instance) { + onMounted(() => { + isMounted.value = true; + }, instance); + } + return isMounted; +} +function useSupported(callback) { + const isMounted = useMounted(); + return computed(() => { + isMounted.value; + return Boolean(callback()); + }); +} +function useMutationObserver(target, callback, options = {}) { + const { window: window2 = defaultWindow, ...mutationOptions } = options; + let observer; + const isSupported = useSupported(() => window2 && "MutationObserver" in window2); + const cleanup = () => { + if (observer) { + observer.disconnect(); + observer = void 0; + } + }; + const targets = computed(() => { + const value = toValue$1(target); + const items = toArray$1(value).map(unrefElement).filter(notNullish); + return new Set(items); + }); + const stopWatch = watch( + () => targets.value, + (targets2) => { + cleanup(); + if (isSupported.value && targets2.size) { + observer = new MutationObserver(callback); + targets2.forEach((el) => observer.observe(el, mutationOptions)); + } + }, + { immediate: true, flush: "post" } + ); + const takeRecords = () => { + return observer == null ? void 0 : observer.takeRecords(); + }; + const stop = () => { + stopWatch(); + cleanup(); + }; + tryOnScopeDispose(stop); + return { + isSupported, + stop, + takeRecords + }; +} +function onElementRemoval(target, callback, options = {}) { + const { + window: window2 = defaultWindow, + document: document2 = window2 == null ? void 0 : window2.document, + flush = "sync" + } = options; + if (!window2 || !document2) + return noop$3; + let stopFn; + const cleanupAndUpdate = (fn) => { + stopFn == null ? void 0 : stopFn(); + stopFn = fn; + }; + const stopWatch = watchEffect(() => { + const el = unrefElement(target); + if (el) { + const { stop } = useMutationObserver( + document2, + (mutationsList) => { + const targetRemoved = mutationsList.map((mutation) => [...mutation.removedNodes]).flat().some((node) => node === el || node.contains(el)); + if (targetRemoved) { + callback(mutationsList); + } + }, + { + window: window2, + childList: true, + subtree: true + } + ); + cleanupAndUpdate(stop); + } + }, { flush }); + const stopHandle = () => { + stopWatch(); + cleanupAndUpdate(); + }; + tryOnScopeDispose(stopHandle); + return stopHandle; +} +function createKeyPredicate(keyFilter) { + if (typeof keyFilter === "function") + return keyFilter; + else if (typeof keyFilter === "string") + return (event) => event.key === keyFilter; + else if (Array.isArray(keyFilter)) + return (event) => keyFilter.includes(event.key); + return () => true; +} +function onKeyStroke(...args) { + let key; + let handler; + let options = {}; + if (args.length === 3) { + key = args[0]; + handler = args[1]; + options = args[2]; + } else if (args.length === 2) { + if (typeof args[1] === "object") { + key = true; + handler = args[0]; + options = args[1]; + } else { + key = args[0]; + handler = args[1]; + } + } else { + key = true; + handler = args[0]; + } + const { + target = defaultWindow, + eventName = "keydown", + passive = false, + dedupe = false + } = options; + const predicate = createKeyPredicate(key); + const listener = (e) => { + if (e.repeat && toValue$1(dedupe)) + return; + if (predicate(e)) + handler(e); + }; + return useEventListener(target, eventName, listener, passive); +} +function onKeyDown(key, handler, options = {}) { + return onKeyStroke(key, handler, { ...options, eventName: "keydown" }); +} +function onKeyPressed(key, handler, options = {}) { + return onKeyStroke(key, handler, { ...options, eventName: "keypress" }); +} +function onKeyUp(key, handler, options = {}) { + return onKeyStroke(key, handler, { ...options, eventName: "keyup" }); +} +const DEFAULT_DELAY = 500; +const DEFAULT_THRESHOLD = 10; +function onLongPress(target, handler, options) { + var _a, _b; + const elementRef = computed(() => unrefElement(target)); + let timeout; + let posStart; + let startTimestamp; + let hasLongPressed = false; + function clear() { + if (timeout) { + clearTimeout(timeout); + timeout = void 0; + } + posStart = void 0; + startTimestamp = void 0; + hasLongPressed = false; + } + function onRelease(ev) { + var _a2, _b2, _c; + const [_startTimestamp, _posStart, _hasLongPressed] = [startTimestamp, posStart, hasLongPressed]; + clear(); + if (!(options == null ? void 0 : options.onMouseUp) || !_posStart || !_startTimestamp) + return; + if (((_a2 = options == null ? void 0 : options.modifiers) == null ? void 0 : _a2.self) && ev.target !== elementRef.value) + return; + if ((_b2 = options == null ? void 0 : options.modifiers) == null ? void 0 : _b2.prevent) + ev.preventDefault(); + if ((_c = options == null ? void 0 : options.modifiers) == null ? void 0 : _c.stop) + ev.stopPropagation(); + const dx = ev.x - _posStart.x; + const dy = ev.y - _posStart.y; + const distance = Math.sqrt(dx * dx + dy * dy); + options.onMouseUp(ev.timeStamp - _startTimestamp, distance, _hasLongPressed); + } + function onDown(ev) { + var _a2, _b2, _c, _d; + if (((_a2 = options == null ? void 0 : options.modifiers) == null ? void 0 : _a2.self) && ev.target !== elementRef.value) + return; + clear(); + if ((_b2 = options == null ? void 0 : options.modifiers) == null ? void 0 : _b2.prevent) + ev.preventDefault(); + if ((_c = options == null ? void 0 : options.modifiers) == null ? void 0 : _c.stop) + ev.stopPropagation(); + posStart = { + x: ev.x, + y: ev.y + }; + startTimestamp = ev.timeStamp; + timeout = setTimeout( + () => { + hasLongPressed = true; + handler(ev); + }, + (_d = options == null ? void 0 : options.delay) != null ? _d : DEFAULT_DELAY + ); + } + function onMove(ev) { + var _a2, _b2, _c, _d; + if (((_a2 = options == null ? void 0 : options.modifiers) == null ? void 0 : _a2.self) && ev.target !== elementRef.value) + return; + if (!posStart || (options == null ? void 0 : options.distanceThreshold) === false) + return; + if ((_b2 = options == null ? void 0 : options.modifiers) == null ? void 0 : _b2.prevent) + ev.preventDefault(); + if ((_c = options == null ? void 0 : options.modifiers) == null ? void 0 : _c.stop) + ev.stopPropagation(); + const dx = ev.x - posStart.x; + const dy = ev.y - posStart.y; + const distance = Math.sqrt(dx * dx + dy * dy); + if (distance >= ((_d = options == null ? void 0 : options.distanceThreshold) != null ? _d : DEFAULT_THRESHOLD)) + clear(); + } + const listenerOptions = { + capture: (_a = options == null ? void 0 : options.modifiers) == null ? void 0 : _a.capture, + once: (_b = options == null ? void 0 : options.modifiers) == null ? void 0 : _b.once + }; + const cleanup = [ + useEventListener(elementRef, "pointerdown", onDown, listenerOptions), + useEventListener(elementRef, "pointermove", onMove, listenerOptions), + useEventListener(elementRef, ["pointerup", "pointerleave"], onRelease, listenerOptions) + ]; + const stop = () => cleanup.forEach((fn) => fn()); + return stop; +} +function isFocusedElementEditable() { + const { activeElement, body } = document; + if (!activeElement) + return false; + if (activeElement === body) + return false; + switch (activeElement.tagName) { + case "INPUT": + case "TEXTAREA": + return true; + } + return activeElement.hasAttribute("contenteditable"); +} +function isTypedCharValid({ + keyCode, + metaKey, + ctrlKey, + altKey +}) { + if (metaKey || ctrlKey || altKey) + return false; + if (keyCode >= 48 && keyCode <= 57 || keyCode >= 96 && keyCode <= 105) + return true; + if (keyCode >= 65 && keyCode <= 90) + return true; + return false; +} +function onStartTyping(callback, options = {}) { + const { document: document2 = defaultDocument } = options; + const keydown = (event) => { + if (!isFocusedElementEditable() && isTypedCharValid(event)) { + callback(event); + } + }; + if (document2) + useEventListener(document2, "keydown", keydown, { passive: true }); +} +function templateRef(key, initialValue = null) { + const instance = getCurrentInstance(); + let _trigger = () => { + }; + const element = customRef((track, trigger) => { + _trigger = trigger; + return { + get() { + var _a, _b; + track(); + return (_b = (_a = instance == null ? void 0 : instance.proxy) == null ? void 0 : _a.$refs[key]) != null ? _b : initialValue; + }, + set() { + } + }; + }); + tryOnMounted(_trigger); + onUpdated(_trigger); + return element; +} +function useActiveElement(options = {}) { + var _a; + const { + window: window2 = defaultWindow, + deep = true, + triggerOnRemoval = false + } = options; + const document2 = (_a = options.document) != null ? _a : window2 == null ? void 0 : window2.document; + const getDeepActiveElement = () => { + var _a2; + let element = document2 == null ? void 0 : document2.activeElement; + if (deep) { + while (element == null ? void 0 : element.shadowRoot) + element = (_a2 = element == null ? void 0 : element.shadowRoot) == null ? void 0 : _a2.activeElement; + } + return element; + }; + const activeElement = shallowRef(); + const trigger = () => { + activeElement.value = getDeepActiveElement(); + }; + if (window2) { + const listenerOptions = { + capture: true, + passive: true + }; + useEventListener( + window2, + "blur", + (event) => { + if (event.relatedTarget !== null) + return; + trigger(); + }, + listenerOptions + ); + useEventListener( + window2, + "focus", + trigger, + listenerOptions + ); + } + if (triggerOnRemoval) { + onElementRemoval(activeElement, trigger, { document: document2 }); + } + trigger(); + return activeElement; +} +function useRafFn(fn, options = {}) { + const { + immediate = true, + fpsLimit = void 0, + window: window2 = defaultWindow, + once = false + } = options; + const isActive = shallowRef(false); + const intervalLimit = computed(() => { + return fpsLimit ? 1e3 / toValue$1(fpsLimit) : null; + }); + let previousFrameTimestamp = 0; + let rafId = null; + function loop(timestamp2) { + if (!isActive.value || !window2) + return; + if (!previousFrameTimestamp) + previousFrameTimestamp = timestamp2; + const delta = timestamp2 - previousFrameTimestamp; + if (intervalLimit.value && delta < intervalLimit.value) { + rafId = window2.requestAnimationFrame(loop); + return; + } + previousFrameTimestamp = timestamp2; + fn({ delta, timestamp: timestamp2 }); + if (once) { + isActive.value = false; + rafId = null; + return; + } + rafId = window2.requestAnimationFrame(loop); + } + function resume() { + if (!isActive.value && window2) { + isActive.value = true; + previousFrameTimestamp = 0; + rafId = window2.requestAnimationFrame(loop); + } + } + function pause() { + isActive.value = false; + if (rafId != null && window2) { + window2.cancelAnimationFrame(rafId); + rafId = null; + } + } + if (immediate) + resume(); + tryOnScopeDispose(pause); + return { + isActive: readonly(isActive), + pause, + resume + }; +} +function useAnimate(target, keyframes, options) { + let config; + let animateOptions; + if (isObject$2(options)) { + config = options; + animateOptions = objectOmit(options, ["window", "immediate", "commitStyles", "persist", "onReady", "onError"]); + } else { + config = { duration: options }; + animateOptions = options; + } + const { + window: window2 = defaultWindow, + immediate = true, + commitStyles, + persist, + playbackRate: _playbackRate = 1, + onReady, + onError = (e) => { + console.error(e); + } + } = config; + const isSupported = useSupported(() => window2 && HTMLElement && "animate" in HTMLElement.prototype); + const animate = shallowRef(void 0); + const store = shallowReactive({ + startTime: null, + currentTime: null, + timeline: null, + playbackRate: _playbackRate, + pending: false, + playState: immediate ? "idle" : "paused", + replaceState: "active" + }); + const pending = computed(() => store.pending); + const playState = computed(() => store.playState); + const replaceState = computed(() => store.replaceState); + const startTime = computed({ + get() { + return store.startTime; + }, + set(value) { + store.startTime = value; + if (animate.value) + animate.value.startTime = value; + } + }); + const currentTime = computed({ + get() { + return store.currentTime; + }, + set(value) { + store.currentTime = value; + if (animate.value) { + animate.value.currentTime = value; + syncResume(); + } + } + }); + const timeline = computed({ + get() { + return store.timeline; + }, + set(value) { + store.timeline = value; + if (animate.value) + animate.value.timeline = value; + } + }); + const playbackRate = computed({ + get() { + return store.playbackRate; + }, + set(value) { + store.playbackRate = value; + if (animate.value) + animate.value.playbackRate = value; + } + }); + const play = () => { + if (animate.value) { + try { + animate.value.play(); + syncResume(); + } catch (e) { + syncPause(); + onError(e); + } + } else { + update(); + } + }; + const pause = () => { + var _a; + try { + (_a = animate.value) == null ? void 0 : _a.pause(); + syncPause(); + } catch (e) { + onError(e); + } + }; + const reverse = () => { + var _a; + if (!animate.value) + update(); + try { + (_a = animate.value) == null ? void 0 : _a.reverse(); + syncResume(); + } catch (e) { + syncPause(); + onError(e); + } + }; + const finish = () => { + var _a; + try { + (_a = animate.value) == null ? void 0 : _a.finish(); + syncPause(); + } catch (e) { + onError(e); + } + }; + const cancel = () => { + var _a; + try { + (_a = animate.value) == null ? void 0 : _a.cancel(); + syncPause(); + } catch (e) { + onError(e); + } + }; + watch(() => unrefElement(target), (el) => { + if (el) { + update(); + } else { + animate.value = void 0; + } + }); + watch(() => keyframes, (value) => { + if (animate.value) { + update(); + const targetEl = unrefElement(target); + if (targetEl) { + animate.value.effect = new KeyframeEffect( + targetEl, + toValue$1(value), + animateOptions + ); + } + } + }, { deep: true }); + tryOnMounted(() => update(true), false); + tryOnScopeDispose(cancel); + function update(init) { + const el = unrefElement(target); + if (!isSupported.value || !el) + return; + if (!animate.value) + animate.value = el.animate(toValue$1(keyframes), animateOptions); + if (persist) + animate.value.persist(); + if (_playbackRate !== 1) + animate.value.playbackRate = _playbackRate; + if (init && !immediate) + animate.value.pause(); + else + syncResume(); + onReady == null ? void 0 : onReady(animate.value); + } + const listenerOptions = { passive: true }; + useEventListener(animate, ["cancel", "finish", "remove"], syncPause, listenerOptions); + useEventListener(animate, "finish", () => { + var _a; + if (commitStyles) + (_a = animate.value) == null ? void 0 : _a.commitStyles(); + }, listenerOptions); + const { resume: resumeRef, pause: pauseRef } = useRafFn(() => { + if (!animate.value) + return; + store.pending = animate.value.pending; + store.playState = animate.value.playState; + store.replaceState = animate.value.replaceState; + store.startTime = animate.value.startTime; + store.currentTime = animate.value.currentTime; + store.timeline = animate.value.timeline; + store.playbackRate = animate.value.playbackRate; + }, { immediate: false }); + function syncResume() { + if (isSupported.value) + resumeRef(); + } + function syncPause() { + if (isSupported.value && window2) + window2.requestAnimationFrame(pauseRef); + } + return { + isSupported, + animate, + // actions + play, + pause, + reverse, + finish, + cancel, + // state + pending, + playState, + replaceState, + startTime, + currentTime, + timeline, + playbackRate + }; +} +function useAsyncQueue(tasks, options) { + const { + interrupt = true, + onError = noop$3, + onFinished = noop$3, + signal + } = options || {}; + const promiseState = { + aborted: "aborted", + fulfilled: "fulfilled", + pending: "pending", + rejected: "rejected" + }; + const initialResult = Array.from(Array.from({ length: tasks.length }), () => ({ state: promiseState.pending, data: null })); + const result = reactive(initialResult); + const activeIndex = shallowRef(-1); + if (!tasks || tasks.length === 0) { + onFinished(); + return { + activeIndex, + result + }; + } + function updateResult(state, res) { + activeIndex.value++; + result[activeIndex.value].data = res; + result[activeIndex.value].state = state; + } + tasks.reduce((prev, curr) => { + return prev.then((prevRes) => { + var _a; + if (signal == null ? void 0 : signal.aborted) { + updateResult(promiseState.aborted, new Error("aborted")); + return; + } + if (((_a = result[activeIndex.value]) == null ? void 0 : _a.state) === promiseState.rejected && interrupt) { + onFinished(); + return; + } + const done = curr(prevRes).then((currentRes) => { + updateResult(promiseState.fulfilled, currentRes); + if (activeIndex.value === tasks.length - 1) + onFinished(); + return currentRes; + }); + if (!signal) + return done; + return Promise.race([done, whenAborted(signal)]); + }).catch((e) => { + if (signal == null ? void 0 : signal.aborted) { + updateResult(promiseState.aborted, e); + return e; + } + updateResult(promiseState.rejected, e); + onError(); + return e; + }); + }, Promise.resolve()); + return { + activeIndex, + result + }; +} +function whenAborted(signal) { + return new Promise((resolve, reject) => { + const error = new Error("aborted"); + if (signal.aborted) + reject(error); + else + signal.addEventListener("abort", () => reject(error), { once: true }); + }); +} +function useAsyncState(promise, initialState, options) { + const { + immediate = true, + delay = 0, + onError = noop$3, + onSuccess = noop$3, + resetOnExecute = true, + shallow = true, + throwError + } = options != null ? options : {}; + const state = shallow ? shallowRef(initialState) : ref(initialState); + const isReady = shallowRef(false); + const isLoading = shallowRef(false); + const error = shallowRef(void 0); + async function execute(delay2 = 0, ...args) { + if (resetOnExecute) + state.value = initialState; + error.value = void 0; + isReady.value = false; + isLoading.value = true; + if (delay2 > 0) + await promiseTimeout(delay2); + const _promise = typeof promise === "function" ? promise(...args) : promise; + try { + const data = await _promise; + state.value = data; + isReady.value = true; + onSuccess(data); + } catch (e) { + error.value = e; + onError(e); + if (throwError) + throw e; + } finally { + isLoading.value = false; + } + return state.value; + } + if (immediate) { + execute(delay); + } + const shell = { + state, + isReady, + isLoading, + error, + execute + }; + function waitUntilIsLoaded() { + return new Promise((resolve, reject) => { + until(isLoading).toBe(false).then(() => resolve(shell)).catch(reject); + }); + } + return { + ...shell, + then(onFulfilled, onRejected) { + return waitUntilIsLoaded().then(onFulfilled, onRejected); + } + }; +} +const defaults$2 = { + array: (v) => JSON.stringify(v), + object: (v) => JSON.stringify(v), + set: (v) => JSON.stringify(Array.from(v)), + map: (v) => JSON.stringify(Object.fromEntries(v)), + null: () => "" +}; +function getDefaultSerialization(target) { + if (!target) + return defaults$2.null; + if (target instanceof Map) + return defaults$2.map; + else if (target instanceof Set) + return defaults$2.set; + else if (Array.isArray(target)) + return defaults$2.array; + else + return defaults$2.object; +} +function useBase64(target, options) { + const base64 = shallowRef(""); + const promise = shallowRef(); + function execute() { + if (!isClient) + return; + promise.value = new Promise((resolve, reject) => { + try { + const _target = toValue$1(target); + if (_target == null) { + resolve(""); + } else if (typeof _target === "string") { + resolve(blobToBase64(new Blob([_target], { type: "text/plain" }))); + } else if (_target instanceof Blob) { + resolve(blobToBase64(_target)); + } else if (_target instanceof ArrayBuffer) { + resolve(window.btoa(String.fromCharCode(...new Uint8Array(_target)))); + } else if (_target instanceof HTMLCanvasElement) { + resolve(_target.toDataURL(options == null ? void 0 : options.type, options == null ? void 0 : options.quality)); + } else if (_target instanceof HTMLImageElement) { + const img = _target.cloneNode(false); + img.crossOrigin = "Anonymous"; + imgLoaded(img).then(() => { + const canvas = document.createElement("canvas"); + const ctx = canvas.getContext("2d"); + canvas.width = img.width; + canvas.height = img.height; + ctx.drawImage(img, 0, 0, canvas.width, canvas.height); + resolve(canvas.toDataURL(options == null ? void 0 : options.type, options == null ? void 0 : options.quality)); + }).catch(reject); + } else if (typeof _target === "object") { + const _serializeFn = (options == null ? void 0 : options.serializer) || getDefaultSerialization(_target); + const serialized = _serializeFn(_target); + return resolve(blobToBase64(new Blob([serialized], { type: "application/json" }))); + } else { + reject(new Error("target is unsupported types")); + } + } catch (error) { + reject(error); + } + }); + promise.value.then((res) => { + base64.value = (options == null ? void 0 : options.dataUrl) === false ? res.replace(/^data:.*?;base64,/, "") : res; + }); + return promise.value; + } + if (isRef(target) || typeof target === "function") + watch(target, execute, { immediate: true }); + else + execute(); + return { + base64, + promise, + execute + }; +} +function imgLoaded(img) { + return new Promise((resolve, reject) => { + if (!img.complete) { + img.onload = () => { + resolve(); + }; + img.onerror = reject; + } else { + resolve(); + } + }); +} +function blobToBase64(blob) { + return new Promise((resolve, reject) => { + const fr = new FileReader(); + fr.onload = (e) => { + resolve(e.target.result); + }; + fr.onerror = reject; + fr.readAsDataURL(blob); + }); +} +function useBattery(options = {}) { + const { navigator: navigator2 = defaultNavigator } = options; + const events2 = ["chargingchange", "chargingtimechange", "dischargingtimechange", "levelchange"]; + const isSupported = useSupported(() => navigator2 && "getBattery" in navigator2 && typeof navigator2.getBattery === "function"); + const charging = shallowRef(false); + const chargingTime = shallowRef(0); + const dischargingTime = shallowRef(0); + const level = shallowRef(1); + let battery; + function updateBatteryInfo() { + charging.value = this.charging; + chargingTime.value = this.chargingTime || 0; + dischargingTime.value = this.dischargingTime || 0; + level.value = this.level; + } + if (isSupported.value) { + navigator2.getBattery().then((_battery) => { + battery = _battery; + updateBatteryInfo.call(battery); + useEventListener(battery, events2, updateBatteryInfo, { passive: true }); + }); + } + return { + isSupported, + charging, + chargingTime, + dischargingTime, + level + }; +} +function useBluetooth(options) { + let { + acceptAllDevices = false + } = options || {}; + const { + filters = void 0, + optionalServices = void 0, + navigator: navigator2 = defaultNavigator + } = options || {}; + const isSupported = useSupported(() => navigator2 && "bluetooth" in navigator2); + const device = shallowRef(); + const error = shallowRef(null); + watch(device, () => { + connectToBluetoothGATTServer(); + }); + async function requestDevice() { + if (!isSupported.value) + return; + error.value = null; + if (filters && filters.length > 0) + acceptAllDevices = false; + try { + device.value = await (navigator2 == null ? void 0 : navigator2.bluetooth.requestDevice({ + acceptAllDevices, + filters, + optionalServices + })); + } catch (err) { + error.value = err; + } + } + const server = shallowRef(); + const isConnected = shallowRef(false); + function reset() { + isConnected.value = false; + device.value = void 0; + server.value = void 0; + } + async function connectToBluetoothGATTServer() { + error.value = null; + if (device.value && device.value.gatt) { + useEventListener(device, "gattserverdisconnected", reset, { passive: true }); + try { + server.value = await device.value.gatt.connect(); + isConnected.value = server.value.connected; + } catch (err) { + error.value = err; + } + } + } + tryOnMounted(() => { + var _a; + if (device.value) + (_a = device.value.gatt) == null ? void 0 : _a.connect(); + }); + tryOnScopeDispose(() => { + var _a; + if (device.value) + (_a = device.value.gatt) == null ? void 0 : _a.disconnect(); + }); + return { + isSupported, + isConnected: readonly(isConnected), + // Device: + device, + requestDevice, + // Server: + server, + // Errors: + error + }; +} +const ssrWidthSymbol = Symbol("vueuse-ssr-width"); +function useSSRWidth() { + const ssrWidth = hasInjectionContext() ? injectLocal(ssrWidthSymbol, null) : null; + return typeof ssrWidth === "number" ? ssrWidth : void 0; +} +function provideSSRWidth(width, app) { + if (app !== void 0) { + app.provide(ssrWidthSymbol, width); + } else { + provideLocal(ssrWidthSymbol, width); + } +} +function useMediaQuery(query, options = {}) { + const { window: window2 = defaultWindow, ssrWidth = useSSRWidth() } = options; + const isSupported = useSupported(() => window2 && "matchMedia" in window2 && typeof window2.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; + const queryStrings = toValue$1(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 >= pxValue(minWidth[1]); + } + if (maxWidth && res) { + res = ssrWidth <= pxValue(maxWidth[1]); + } + return not ? !res : res; + }); + return; + } + if (!isSupported.value) + return; + mediaQuery.value = window2.matchMedia(toValue$1(query)); + matches.value = mediaQuery.value.matches; + }); + useEventListener(mediaQuery, "change", handler, { passive: true }); + return computed(() => matches.value); +} +const breakpointsTailwind = { + "sm": 640, + "md": 768, + "lg": 1024, + "xl": 1280, + "2xl": 1536 +}; +const breakpointsBootstrapV5 = { + xs: 0, + sm: 576, + md: 768, + lg: 992, + xl: 1200, + xxl: 1400 +}; +const breakpointsVuetifyV2 = { + xs: 0, + sm: 600, + md: 960, + lg: 1264, + xl: 1904 +}; +const breakpointsVuetifyV3 = { + xs: 0, + sm: 600, + md: 960, + lg: 1280, + xl: 1920, + xxl: 2560 +}; +const breakpointsVuetify = breakpointsVuetifyV2; +const breakpointsAntDesign = { + xs: 480, + sm: 576, + md: 768, + lg: 992, + xl: 1200, + xxl: 1600 +}; +const breakpointsQuasar = { + xs: 0, + sm: 600, + md: 1024, + lg: 1440, + xl: 1920 +}; +const breakpointsSematic = { + mobileS: 320, + mobileM: 375, + mobileL: 425, + tablet: 768, + laptop: 1024, + laptopL: 1440, + desktop4K: 2560 +}; +const breakpointsMasterCss = { + "3xs": 360, + "2xs": 480, + "xs": 600, + "sm": 768, + "md": 1024, + "lg": 1280, + "xl": 1440, + "2xl": 1600, + "3xl": 1920, + "4xl": 2560 +}; +const breakpointsPrimeFlex = { + sm: 576, + md: 768, + lg: 992, + xl: 1200 +}; +const breakpointsElement = { + xs: 0, + sm: 768, + md: 992, + lg: 1200, + xl: 1920 +}; +function useBreakpoints(breakpoints, options = {}) { + function getValue2(k, delta) { + let v = toValue$1(breakpoints[toValue$1(k)]); + if (delta != null) + v = increaseWithUnit(v, delta); + if (typeof v === "number") + v = `${v}px`; + return v; + } + const { window: window2 = defaultWindow, strategy = "min-width", ssrWidth = useSSRWidth() } = options; + const ssrSupport = typeof ssrWidth === "number"; + const mounted = ssrSupport ? shallowRef(false) : { value: true }; + if (ssrSupport) { + tryOnMounted(() => mounted.value = !!window2); + } + function match(query, size) { + if (!mounted.value && ssrSupport) { + return query === "min" ? ssrWidth >= pxValue(size) : ssrWidth <= pxValue(size); + } + if (!window2) + return false; + return window2.matchMedia(`(${query}-width: ${size})`).matches; + } + const greaterOrEqual = (k) => { + return useMediaQuery(() => `(min-width: ${getValue2(k)})`, options); + }; + const smallerOrEqual = (k) => { + return useMediaQuery(() => `(max-width: ${getValue2(k)})`, options); + }; + const shortcutMethods = Object.keys(breakpoints).reduce((shortcuts, k) => { + Object.defineProperty(shortcuts, k, { + get: () => strategy === "min-width" ? greaterOrEqual(k) : smallerOrEqual(k), + enumerable: true, + configurable: true + }); + return shortcuts; + }, {}); + function current() { + const points = Object.keys(breakpoints).map((k) => [k, shortcutMethods[k], pxValue(getValue2(k))]).sort((a, b) => a[2] - b[2]); + return computed(() => points.filter(([, v]) => v.value).map(([k]) => k)); + } + return Object.assign(shortcutMethods, { + greaterOrEqual, + smallerOrEqual, + greater(k) { + return useMediaQuery(() => `(min-width: ${getValue2(k, 0.1)})`, options); + }, + smaller(k) { + return useMediaQuery(() => `(max-width: ${getValue2(k, -0.1)})`, options); + }, + between(a, b) { + return useMediaQuery(() => `(min-width: ${getValue2(a)}) and (max-width: ${getValue2(b, -0.1)})`, options); + }, + isGreater(k) { + return match("min", getValue2(k, 0.1)); + }, + isGreaterOrEqual(k) { + return match("min", getValue2(k)); + }, + isSmaller(k) { + return match("max", getValue2(k, -0.1)); + }, + isSmallerOrEqual(k) { + return match("max", getValue2(k)); + }, + isInBetween(a, b) { + return match("min", getValue2(a)) && match("max", getValue2(b, -0.1)); + }, + current, + active() { + const bps = current(); + return computed(() => bps.value.length === 0 ? "" : bps.value.at(strategy === "min-width" ? -1 : 0)); + } + }); +} +function useBroadcastChannel(options) { + const { + name, + window: window2 = defaultWindow + } = options; + const isSupported = useSupported(() => window2 && "BroadcastChannel" in window2); + const isClosed = shallowRef(false); + const channel = ref(); + const data = ref(); + const error = shallowRef(null); + const post = (data2) => { + if (channel.value) + channel.value.postMessage(data2); + }; + const close = () => { + if (channel.value) + channel.value.close(); + isClosed.value = true; + }; + if (isSupported.value) { + tryOnMounted(() => { + error.value = null; + channel.value = new BroadcastChannel(name); + const listenerOptions = { + passive: true + }; + useEventListener(channel, "message", (e) => { + data.value = e.data; + }, listenerOptions); + useEventListener(channel, "messageerror", (e) => { + error.value = e; + }, listenerOptions); + useEventListener(channel, "close", () => { + isClosed.value = true; + }, listenerOptions); + }); + } + tryOnScopeDispose(() => { + close(); + }); + return { + isSupported, + channel, + data, + post, + close, + error, + isClosed + }; +} +const WRITABLE_PROPERTIES = [ + "hash", + "host", + "hostname", + "href", + "pathname", + "port", + "protocol", + "search" +]; +function useBrowserLocation(options = {}) { + const { window: window2 = defaultWindow } = options; + const refs = Object.fromEntries( + WRITABLE_PROPERTIES.map((key) => [key, ref()]) + ); + for (const [key, ref2] of objectEntries(refs)) { + watch(ref2, (value) => { + if (!(window2 == null ? void 0 : window2.location) || window2.location[key] === value) + return; + window2.location[key] = value; + }); + } + const buildState = (trigger) => { + var _a; + const { state: state2, length } = (window2 == null ? void 0 : window2.history) || {}; + const { origin } = (window2 == null ? void 0 : window2.location) || {}; + for (const key of WRITABLE_PROPERTIES) + refs[key].value = (_a = window2 == null ? void 0 : window2.location) == null ? void 0 : _a[key]; + return reactive({ + trigger, + state: state2, + length, + origin, + ...refs + }); + }; + const state = ref(buildState("load")); + if (window2) { + const listenerOptions = { passive: true }; + useEventListener(window2, "popstate", () => state.value = buildState("popstate"), listenerOptions); + useEventListener(window2, "hashchange", () => state.value = buildState("hashchange"), listenerOptions); + } + return state; +} +function useCached(refValue, comparator = (a, b) => a === b, options) { + const { deepRefs = true, ...watchOptions } = options || {}; + const cachedValue = createRef(refValue.value, deepRefs); + watch(() => refValue.value, (value) => { + if (!comparator(value, cachedValue.value)) + cachedValue.value = value; + }, watchOptions); + return cachedValue; +} +function usePermission(permissionDesc, options = {}) { + const { + controls = false, + navigator: navigator2 = defaultNavigator + } = options; + const isSupported = useSupported(() => navigator2 && "permissions" in navigator2); + const permissionStatus = shallowRef(); + const desc = typeof permissionDesc === "string" ? { name: permissionDesc } : permissionDesc; + const state = shallowRef(); + const update = () => { + var _a, _b; + state.value = (_b = (_a = permissionStatus.value) == null ? void 0 : _a.state) != null ? _b : "prompt"; + }; + useEventListener(permissionStatus, "change", update, { passive: true }); + const query = createSingletonPromise(async () => { + if (!isSupported.value) + return; + if (!permissionStatus.value) { + try { + permissionStatus.value = await navigator2.permissions.query(desc); + } catch (e) { + permissionStatus.value = void 0; + } finally { + update(); + } + } + if (controls) + return toRaw(permissionStatus.value); + }); + query(); + if (controls) { + return { + state, + isSupported, + query + }; + } else { + return state; + } +} +function useClipboard(options = {}) { + const { + navigator: navigator2 = defaultNavigator, + read = false, + source, + copiedDuring = 1500, + legacy = false + } = options; + const isClipboardApiSupported = useSupported(() => navigator2 && "clipboard" in navigator2); + const permissionRead = usePermission("clipboard-read"); + const permissionWrite = usePermission("clipboard-write"); + const isSupported = computed(() => isClipboardApiSupported.value || legacy); + const text = shallowRef(""); + const copied = shallowRef(false); + const timeout = useTimeoutFn(() => copied.value = false, copiedDuring, { immediate: false }); + async function updateText() { + let useLegacy = !(isClipboardApiSupported.value && isAllowed(permissionRead.value)); + if (!useLegacy) { + try { + text.value = await navigator2.clipboard.readText(); + } catch (e) { + useLegacy = true; + } + } + if (useLegacy) { + text.value = legacyRead(); + } + } + if (isSupported.value && read) + useEventListener(["copy", "cut"], updateText, { passive: true }); + async function copy(value = toValue$1(source)) { + if (isSupported.value && value != null) { + let useLegacy = !(isClipboardApiSupported.value && isAllowed(permissionWrite.value)); + if (!useLegacy) { + try { + await navigator2.clipboard.writeText(value); + } catch (e) { + useLegacy = true; + } + } + if (useLegacy) + legacyCopy(value); + text.value = value; + copied.value = true; + timeout.start(); + } + } + function legacyCopy(value) { + const ta = document.createElement("textarea"); + ta.value = value != null ? value : ""; + ta.style.position = "absolute"; + ta.style.opacity = "0"; + document.body.appendChild(ta); + ta.select(); + document.execCommand("copy"); + ta.remove(); + } + function legacyRead() { + var _a, _b, _c; + return (_c = (_b = (_a = document == null ? void 0 : document.getSelection) == null ? void 0 : _a.call(document)) == null ? void 0 : _b.toString()) != null ? _c : ""; + } + function isAllowed(status) { + return status === "granted" || status === "prompt"; + } + return { + isSupported, + text, + copied, + copy + }; +} +function useClipboardItems(options = {}) { + const { + navigator: navigator2 = defaultNavigator, + read = false, + source, + copiedDuring = 1500 + } = options; + const isSupported = useSupported(() => navigator2 && "clipboard" in navigator2); + const content = ref([]); + const copied = shallowRef(false); + const timeout = useTimeoutFn(() => copied.value = false, copiedDuring, { immediate: false }); + function updateContent() { + if (isSupported.value) { + navigator2.clipboard.read().then((items) => { + content.value = items; + }); + } + } + if (isSupported.value && read) + useEventListener(["copy", "cut"], updateContent, { passive: true }); + async function copy(value = toValue$1(source)) { + if (isSupported.value && value != null) { + await navigator2.clipboard.write(value); + content.value = value; + copied.value = true; + timeout.start(); + } + } + return { + isSupported, + content, + copied, + copy + }; +} +function cloneFnJSON(source) { + return JSON.parse(JSON.stringify(source)); +} +function useCloned(source, options = {}) { + const cloned = ref({}); + const isModified = shallowRef(false); + let _lastSync = false; + const { + manual, + clone = cloneFnJSON, + // watch options + deep = true, + immediate = true + } = options; + watch(cloned, () => { + if (_lastSync) { + _lastSync = false; + return; + } + isModified.value = true; + }, { + deep: true, + flush: "sync" + }); + function sync() { + _lastSync = true; + isModified.value = false; + cloned.value = clone(toValue$1(source)); + } + if (!manual && (isRef(source) || typeof source === "function")) { + watch(source, sync, { + ...options, + deep, + immediate + }); + } else { + sync(); + } + return { cloned, isModified, sync }; +} +const _global$1 = 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$1)) + _global$1[globalKey] = _global$1[globalKey] || {}; + return _global$1[globalKey]; +} +function getSSRHandler(key, fallback) { + return handlers[key] || fallback; +} +function setSSRHandler(key, fn) { + handlers[key] = fn; +} +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, defaults2, storage, options = {}) { + var _a; + const { + flush = "pre", + deep = true, + listenToStorageChanges = true, + writeDefaults = true, + mergeDefaults = false, + shallow, + window: window2 = defaultWindow, + eventFilter, + onError = (e) => { + console.error(e); + }, + initOnMounted + } = options; + const data = (shallow ? shallowRef : ref)(typeof defaults2 === "function" ? defaults2() : defaults2); + const keyComputed = computed(() => toValue$1(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 = toValue$1(defaults2); + const type = guessSerializerType(rawInit); + const serializer = (_a = options.serializer) != null ? _a : StorageSerializers[type]; + const { pause: pauseWatch, resume: resumeWatch } = watchPausable( + data, + () => write(data.value), + { flush, deep, eventFilter } + ); + watch(keyComputed, () => update(), { flush }); + if (window2 && listenToStorageChanges) { + tryOnMounted(() => { + if (storage instanceof Storage) + useEventListener(window2, "storage", update, { passive: true }); + else + useEventListener(window2, customStorageEventName, updateFromCustomEvent); + if (initOnMounted) + update(); + }); + } + if (!initOnMounted) + update(); + function dispatchWriteEvent(oldValue, newValue) { + if (window2) { + const payload = { + key: keyComputed.value, + oldValue, + newValue, + storageArea: storage + }; + window2.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 { + if ((event == null ? void 0 : event.newValue) !== serializer.write(data.value)) + data.value = read(event); + } catch (e) { + onError(e); + } finally { + if (event) + 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: window2 = 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: window2 }); + const system = computed(() => preferredDark.value ? "dark" : "light"); + const store = storageRef || (storageKey == null ? toRef(initialValue) : useStorage(storageKey, initialValue, storage, { window: window2, listenToStorageChanges })); + const state = computed(() => store.value === "auto" ? system.value : store.value); + const updateHTMLAttrs = getSSRHandler( + "updateHTMLAttrs", + (selector2, attribute2, value) => { + const el = typeof selector2 === "string" ? window2 == null ? void 0 : window2.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 = window2.document.createElement("style"); + style.appendChild(document.createTextNode(CSS_DISABLE_TRANS)); + window2.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) { + window2.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); + } + watch(state, onChanged, { flush: "post", immediate: true }); + tryOnMounted(() => onChanged(state.value)); + const auto = computed({ + get() { + return emitAuto ? store.value : state.value; + }, + set(v) { + store.value = v; + } + }); + return Object.assign(auto, { store, system, state }); +} +function useConfirmDialog(revealed = shallowRef(false)) { + const confirmHook = createEventHook(); + const cancelHook = createEventHook(); + const revealHook = createEventHook(); + let _resolve = noop$3; + const reveal = (data) => { + revealHook.trigger(data); + revealed.value = true; + return new Promise((resolve) => { + _resolve = resolve; + }); + }; + const confirm = (data) => { + revealed.value = false; + confirmHook.trigger(data); + _resolve({ data, isCanceled: false }); + }; + const cancel = (data) => { + revealed.value = false; + cancelHook.trigger(data); + _resolve({ data, isCanceled: true }); + }; + return { + isRevealed: computed(() => revealed.value), + reveal, + confirm, + cancel, + onReveal: revealHook.on, + onConfirm: confirmHook.on, + onCancel: cancelHook.on + }; +} +function useCountdown(initialCountdown, options) { + var _a, _b; + const remaining = shallowRef(toValue$1(initialCountdown)); + const intervalController = useIntervalFn(() => { + var _a2, _b2; + const value = remaining.value - 1; + remaining.value = value < 0 ? 0 : value; + (_a2 = options == null ? void 0 : options.onTick) == null ? void 0 : _a2.call(options); + if (remaining.value <= 0) { + intervalController.pause(); + (_b2 = options == null ? void 0 : options.onComplete) == null ? void 0 : _b2.call(options); + } + }, (_a = options == null ? void 0 : options.interval) != null ? _a : 1e3, { immediate: (_b = options == null ? void 0 : options.immediate) != null ? _b : false }); + const reset = (countdown) => { + var _a2; + remaining.value = (_a2 = toValue$1(countdown)) != null ? _a2 : toValue$1(initialCountdown); + }; + const stop = () => { + intervalController.pause(); + reset(); + }; + const resume = () => { + if (!intervalController.isActive.value) { + if (remaining.value > 0) { + intervalController.resume(); + } + } + }; + const start = (countdown) => { + reset(countdown); + intervalController.resume(); + }; + return { + remaining, + reset, + stop, + start, + pause: intervalController.pause, + resume, + isActive: intervalController.isActive + }; +} +function useCssVar(prop, target, options = {}) { + const { window: window2 = defaultWindow, initialValue, observe = false } = options; + const variable = shallowRef(initialValue); + const elRef = computed(() => { + var _a; + return unrefElement(target) || ((_a = window2 == null ? void 0 : window2.document) == null ? void 0 : _a.documentElement); + }); + function updateCssVar() { + var _a; + const key = toValue$1(prop); + const el = toValue$1(elRef); + if (el && window2 && key) { + const value = (_a = window2.getComputedStyle(el).getPropertyValue(key)) == null ? void 0 : _a.trim(); + variable.value = value || variable.value || initialValue; + } + } + if (observe) { + useMutationObserver(elRef, updateCssVar, { + attributeFilter: ["style", "class"], + window: window2 + }); + } + watch( + [elRef, () => toValue$1(prop)], + (_, old) => { + if (old[0] && old[1]) + old[0].style.removeProperty(old[1]); + updateCssVar(); + }, + { immediate: true } + ); + watch( + [variable, elRef], + ([val, el]) => { + const raw_prop = toValue$1(prop); + if ((el == null ? void 0 : el.style) && raw_prop) { + if (val == null) + el.style.removeProperty(raw_prop); + else + el.style.setProperty(raw_prop, val); + } + }, + { immediate: true } + ); + return variable; +} +function useCurrentElement(rootComponent) { + const vm = getCurrentInstance(); + const currentElement = computedWithControl( + () => null, + () => rootComponent ? unrefElement(rootComponent) : vm.proxy.$el + ); + onUpdated(currentElement.trigger); + onMounted(currentElement.trigger); + return currentElement; +} +function useCycleList(list, options) { + const state = shallowRef(getInitialValue()); + const listRef = toRef(list); + const index = computed({ + get() { + var _a; + const targetList = listRef.value; + let index2 = (options == null ? void 0 : options.getIndexOf) ? options.getIndexOf(state.value, targetList) : targetList.indexOf(state.value); + if (index2 < 0) + index2 = (_a = options == null ? void 0 : options.fallbackIndex) != null ? _a : 0; + return index2; + }, + set(v) { + set(v); + } + }); + function set(i) { + const targetList = listRef.value; + const length = targetList.length; + const index2 = (i % length + length) % length; + const value = targetList[index2]; + state.value = value; + return value; + } + function shift(delta = 1) { + return set(index.value + delta); + } + function next(n = 1) { + return shift(n); + } + function prev(n = 1) { + return shift(-n); + } + function getInitialValue() { + var _a, _b; + return (_b = toValue$1((_a = options == null ? void 0 : options.initialValue) != null ? _a : toValue$1(list)[0])) != null ? _b : void 0; + } + watch(listRef, () => set(index.value)); + return { + state, + index, + next, + prev, + go: set + }; +} +function useDark(options = {}) { + const { + valueDark = "dark", + valueLight = "" + } = options; + const mode = useColorMode({ + ...options, + onChanged: (mode2, defaultHandler) => { + var _a; + if (options.onChanged) + (_a = options.onChanged) == null ? void 0 : _a.call(options, mode2 === "dark", defaultHandler, mode2); + else + defaultHandler(mode2); + }, + modes: { + dark: valueDark, + light: valueLight + } + }); + const system = computed(() => mode.system.value); + const isDark = computed({ + get() { + return mode.value === "dark"; + }, + set(v) { + const modeVal = v ? "dark" : "light"; + if (system.value === modeVal) + mode.value = "auto"; + else + mode.value = modeVal; + } + }); + return isDark; +} +function fnBypass(v) { + return v; +} +function fnSetSource(source, value) { + return source.value = value; +} +function defaultDump(clone) { + return clone ? typeof clone === "function" ? clone : cloneFnJSON : fnBypass; +} +function defaultParse(clone) { + return clone ? typeof clone === "function" ? clone : cloneFnJSON : fnBypass; +} +function useManualRefHistory(source, options = {}) { + const { + clone = false, + dump = defaultDump(clone), + parse = defaultParse(clone), + setSource = fnSetSource + } = options; + function _createHistoryRecord() { + return markRaw({ + snapshot: dump(source.value), + timestamp: timestamp() + }); + } + const last = ref(_createHistoryRecord()); + const undoStack = ref([]); + const redoStack = ref([]); + const _setSource = (record) => { + setSource(source, parse(record.snapshot)); + last.value = record; + }; + const commit = () => { + undoStack.value.unshift(last.value); + last.value = _createHistoryRecord(); + if (options.capacity && undoStack.value.length > options.capacity) + undoStack.value.splice(options.capacity, Number.POSITIVE_INFINITY); + if (redoStack.value.length) + redoStack.value.splice(0, redoStack.value.length); + }; + const clear = () => { + undoStack.value.splice(0, undoStack.value.length); + redoStack.value.splice(0, redoStack.value.length); + }; + const undo = () => { + const state = undoStack.value.shift(); + if (state) { + redoStack.value.unshift(last.value); + _setSource(state); + } + }; + const redo = () => { + const state = redoStack.value.shift(); + if (state) { + undoStack.value.unshift(last.value); + _setSource(state); + } + }; + const reset = () => { + _setSource(last.value); + }; + const history = computed(() => [last.value, ...undoStack.value]); + const canUndo = computed(() => undoStack.value.length > 0); + const canRedo = computed(() => redoStack.value.length > 0); + return { + source, + undoStack, + redoStack, + last, + history, + canUndo, + canRedo, + clear, + commit, + reset, + undo, + redo + }; +} +function useRefHistory(source, options = {}) { + const { + deep = false, + flush = "pre", + eventFilter + } = options; + const { + eventFilter: composedFilter, + pause, + resume: resumeTracking, + isActive: isTracking + } = pausableFilter(eventFilter); + const { + ignoreUpdates, + ignorePrevAsyncUpdates, + stop + } = watchIgnorable( + source, + commit, + { deep, flush, eventFilter: composedFilter } + ); + function setSource(source2, value) { + ignorePrevAsyncUpdates(); + ignoreUpdates(() => { + source2.value = value; + }); + } + const manualHistory = useManualRefHistory(source, { ...options, clone: options.clone || deep, setSource }); + const { clear, commit: manualCommit } = manualHistory; + function commit() { + ignorePrevAsyncUpdates(); + manualCommit(); + } + function resume(commitNow) { + resumeTracking(); + if (commitNow) + commit(); + } + function batch(fn) { + let canceled = false; + const cancel = () => canceled = true; + ignoreUpdates(() => { + fn(cancel); + }); + if (!canceled) + commit(); + } + function dispose() { + stop(); + clear(); + } + return { + ...manualHistory, + isTracking, + pause, + resume, + commit, + batch, + dispose + }; +} +function useDebouncedRefHistory(source, options = {}) { + const filter = options.debounce ? debounceFilter(options.debounce) : void 0; + const history = useRefHistory(source, { ...options, eventFilter: filter }); + return { + ...history + }; +} +function useDeviceMotion(options = {}) { + const { + window: window2 = defaultWindow, + requestPermissions = false, + eventFilter = bypassFilter + } = options; + const isSupported = useSupported(() => typeof DeviceMotionEvent !== "undefined"); + const requirePermissions = useSupported(() => isSupported.value && "requestPermission" in DeviceMotionEvent && typeof DeviceMotionEvent.requestPermission === "function"); + const permissionGranted = shallowRef(false); + const acceleration = ref({ x: null, y: null, z: null }); + const rotationRate = ref({ alpha: null, beta: null, gamma: null }); + const interval = shallowRef(0); + const accelerationIncludingGravity = ref({ + x: null, + y: null, + z: null + }); + function init() { + if (window2) { + const onDeviceMotion = createFilterWrapper( + eventFilter, + (event) => { + var _a, _b, _c, _d, _e, _f, _g, _h, _i; + acceleration.value = { + x: ((_a = event.acceleration) == null ? void 0 : _a.x) || null, + y: ((_b = event.acceleration) == null ? void 0 : _b.y) || null, + z: ((_c = event.acceleration) == null ? void 0 : _c.z) || null + }; + accelerationIncludingGravity.value = { + x: ((_d = event.accelerationIncludingGravity) == null ? void 0 : _d.x) || null, + y: ((_e = event.accelerationIncludingGravity) == null ? void 0 : _e.y) || null, + z: ((_f = event.accelerationIncludingGravity) == null ? void 0 : _f.z) || null + }; + rotationRate.value = { + alpha: ((_g = event.rotationRate) == null ? void 0 : _g.alpha) || null, + beta: ((_h = event.rotationRate) == null ? void 0 : _h.beta) || null, + gamma: ((_i = event.rotationRate) == null ? void 0 : _i.gamma) || null + }; + interval.value = event.interval; + } + ); + useEventListener(window2, "devicemotion", onDeviceMotion, { passive: true }); + } + } + const ensurePermissions = async () => { + if (!requirePermissions.value) + permissionGranted.value = true; + if (permissionGranted.value) + return; + if (requirePermissions.value) { + const requestPermission = DeviceMotionEvent.requestPermission; + try { + const response = await requestPermission(); + if (response === "granted") { + permissionGranted.value = true; + init(); + } + } catch (error) { + console.error(error); + } + } + }; + if (isSupported.value) { + if (requestPermissions && requirePermissions.value) { + ensurePermissions().then(() => init()); + } else { + init(); + } + } + return { + acceleration, + accelerationIncludingGravity, + rotationRate, + interval, + isSupported, + requirePermissions, + ensurePermissions, + permissionGranted + }; +} +function useDeviceOrientation(options = {}) { + const { window: window2 = defaultWindow } = options; + const isSupported = useSupported(() => window2 && "DeviceOrientationEvent" in window2); + const isAbsolute = shallowRef(false); + const alpha = shallowRef(null); + const beta = shallowRef(null); + const gamma = shallowRef(null); + if (window2 && isSupported.value) { + useEventListener(window2, "deviceorientation", (event) => { + isAbsolute.value = event.absolute; + alpha.value = event.alpha; + beta.value = event.beta; + gamma.value = event.gamma; + }, { passive: true }); + } + return { + isSupported, + isAbsolute, + alpha, + beta, + gamma + }; +} +function useDevicePixelRatio(options = {}) { + const { + window: window2 = defaultWindow + } = options; + const pixelRatio = shallowRef(1); + const query = useMediaQuery(() => `(resolution: ${pixelRatio.value}dppx)`, options); + let stop = noop$3; + if (window2) { + stop = watchImmediate(query, () => pixelRatio.value = window2.devicePixelRatio); + } + return { + pixelRatio: readonly(pixelRatio), + stop + }; +} +function useDevicesList(options = {}) { + const { + navigator: navigator2 = defaultNavigator, + requestPermissions = false, + constraints = { audio: true, video: true }, + onUpdated: onUpdated2 + } = options; + const devices = ref([]); + const videoInputs = computed(() => devices.value.filter((i) => i.kind === "videoinput")); + const audioInputs = computed(() => devices.value.filter((i) => i.kind === "audioinput")); + const audioOutputs = computed(() => devices.value.filter((i) => i.kind === "audiooutput")); + const isSupported = useSupported(() => navigator2 && navigator2.mediaDevices && navigator2.mediaDevices.enumerateDevices); + const permissionGranted = shallowRef(false); + let stream; + async function update() { + if (!isSupported.value) + return; + devices.value = await navigator2.mediaDevices.enumerateDevices(); + onUpdated2 == null ? void 0 : onUpdated2(devices.value); + if (stream) { + stream.getTracks().forEach((t) => t.stop()); + stream = null; + } + } + async function ensurePermissions() { + const deviceName = constraints.video ? "camera" : "microphone"; + if (!isSupported.value) + return false; + if (permissionGranted.value) + return true; + const { state, query } = usePermission(deviceName, { controls: true }); + await query(); + if (state.value !== "granted") { + let granted = true; + try { + stream = await navigator2.mediaDevices.getUserMedia(constraints); + } catch (e) { + stream = null; + granted = false; + } + update(); + permissionGranted.value = granted; + } else { + permissionGranted.value = true; + } + return permissionGranted.value; + } + if (isSupported.value) { + if (requestPermissions) + ensurePermissions(); + useEventListener(navigator2.mediaDevices, "devicechange", update, { passive: true }); + update(); + } + return { + devices, + ensurePermissions, + permissionGranted, + videoInputs, + audioInputs, + audioOutputs, + isSupported + }; +} +function useDisplayMedia(options = {}) { + var _a; + const enabled = shallowRef((_a = options.enabled) != null ? _a : false); + const video = options.video; + const audio = options.audio; + const { navigator: navigator2 = defaultNavigator } = options; + const isSupported = useSupported(() => { + var _a2; + return (_a2 = navigator2 == null ? void 0 : navigator2.mediaDevices) == null ? void 0 : _a2.getDisplayMedia; + }); + const constraint = { audio, video }; + const stream = shallowRef(); + async function _start() { + var _a2; + if (!isSupported.value || stream.value) + return; + stream.value = await navigator2.mediaDevices.getDisplayMedia(constraint); + (_a2 = stream.value) == null ? void 0 : _a2.getTracks().forEach((t) => useEventListener(t, "ended", stop, { passive: true })); + return stream.value; + } + async function _stop() { + var _a2; + (_a2 = stream.value) == null ? void 0 : _a2.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; + } + watch( + enabled, + (v) => { + if (v) + _start(); + else + _stop(); + }, + { immediate: true } + ); + return { + isSupported, + stream, + start, + stop, + enabled + }; +} +function useDocumentVisibility(options = {}) { + const { document: document2 = defaultDocument } = options; + if (!document2) + return shallowRef("visible"); + const visibility = shallowRef(document2.visibilityState); + useEventListener(document2, "visibilitychange", () => { + visibility.value = document2.visibilityState; + }, { passive: true }); + return visibility; +} +function useDraggable(target, options = {}) { + var _a; + const { + pointerTypes, + preventDefault: preventDefault2, + stopPropagation, + exact, + onMove, + onEnd, + onStart, + initialValue, + axis = "both", + draggingElement = defaultWindow, + containerElement, + handle: draggingHandle = target, + buttons = [0] + } = options; + const position = ref( + (_a = toValue$1(initialValue)) != null ? _a : { x: 0, y: 0 } + ); + const pressedDelta = ref(); + const filterEvent = (e) => { + if (pointerTypes) + return pointerTypes.includes(e.pointerType); + return true; + }; + const handleEvent = (e) => { + if (toValue$1(preventDefault2)) + e.preventDefault(); + if (toValue$1(stopPropagation)) + e.stopPropagation(); + }; + const start = (e) => { + var _a2; + if (!toValue$1(buttons).includes(e.button)) + return; + if (toValue$1(options.disabled) || !filterEvent(e)) + return; + if (toValue$1(exact) && e.target !== toValue$1(target)) + return; + const container = toValue$1(containerElement); + const containerRect = (_a2 = container == null ? void 0 : container.getBoundingClientRect) == null ? void 0 : _a2.call(container); + const targetRect = toValue$1(target).getBoundingClientRect(); + const pos = { + x: e.clientX - (container ? targetRect.left - containerRect.left + container.scrollLeft : targetRect.left), + y: e.clientY - (container ? targetRect.top - containerRect.top + container.scrollTop : targetRect.top) + }; + if ((onStart == null ? void 0 : onStart(pos, e)) === false) + return; + pressedDelta.value = pos; + handleEvent(e); + }; + const move = (e) => { + if (toValue$1(options.disabled) || !filterEvent(e)) + return; + if (!pressedDelta.value) + return; + const container = toValue$1(containerElement); + const targetRect = toValue$1(target).getBoundingClientRect(); + let { x, y } = position.value; + if (axis === "x" || axis === "both") { + x = e.clientX - pressedDelta.value.x; + if (container) + x = Math.min(Math.max(0, x), container.scrollWidth - targetRect.width); + } + if (axis === "y" || axis === "both") { + y = e.clientY - pressedDelta.value.y; + if (container) + y = Math.min(Math.max(0, y), container.scrollHeight - targetRect.height); + } + position.value = { + x, + y + }; + onMove == null ? void 0 : onMove(position.value, e); + handleEvent(e); + }; + const end = (e) => { + if (toValue$1(options.disabled) || !filterEvent(e)) + return; + if (!pressedDelta.value) + return; + pressedDelta.value = void 0; + onEnd == null ? void 0 : onEnd(position.value, e); + handleEvent(e); + }; + if (isClient) { + const config = () => { + var _a2; + return { + capture: (_a2 = options.capture) != null ? _a2 : true, + passive: !toValue$1(preventDefault2) + }; + }; + useEventListener(draggingHandle, "pointerdown", start, config); + useEventListener(draggingElement, "pointermove", move, config); + useEventListener(draggingElement, "pointerup", end, config); + } + return { + ...toRefs(position), + position, + isDragging: computed(() => !!pressedDelta.value), + style: computed( + () => `left:${position.value.x}px;top:${position.value.y}px;` + ) + }; +} +function useDropZone(target, options = {}) { + var _a, _b; + const isOverDropZone = shallowRef(false); + const files = shallowRef(null); + let counter = 0; + let isValid = true; + if (isClient) { + const _options = typeof options === "function" ? { onDrop: options } : options; + const multiple = (_a = _options.multiple) != null ? _a : true; + const preventDefaultForUnhandled = (_b = _options.preventDefaultForUnhandled) != null ? _b : false; + const getFiles = (event) => { + var _a2, _b2; + const list = Array.from((_b2 = (_a2 = event.dataTransfer) == null ? void 0 : _a2.files) != null ? _b2 : []); + return list.length === 0 ? null : multiple ? list : [list[0]]; + }; + const checkDataTypes = (types) => { + const dataTypes = unref(_options.dataTypes); + if (typeof dataTypes === "function") + return dataTypes(types); + if (!(dataTypes == null ? void 0 : dataTypes.length)) + return true; + if (types.length === 0) + return false; + return types.every( + (type) => dataTypes.some((allowedType) => type.includes(allowedType)) + ); + }; + const checkValidity = (items) => { + const types = Array.from(items != null ? items : []).map((item) => item.type); + const dataTypesValid = checkDataTypes(types); + const multipleFilesValid = multiple || items.length <= 1; + return dataTypesValid && multipleFilesValid; + }; + const isSafari = () => /^(?:(?!chrome|android).)*safari/i.test(navigator.userAgent) && !("chrome" in window); + const handleDragEvent = (event, eventType) => { + var _a2, _b2, _c, _d, _e, _f; + const dataTransferItemList = (_a2 = event.dataTransfer) == null ? void 0 : _a2.items; + isValid = (_b2 = dataTransferItemList && checkValidity(dataTransferItemList)) != null ? _b2 : false; + if (preventDefaultForUnhandled) { + event.preventDefault(); + } + if (!isSafari() && !isValid) { + if (event.dataTransfer) { + event.dataTransfer.dropEffect = "none"; + } + return; + } + event.preventDefault(); + if (event.dataTransfer) { + event.dataTransfer.dropEffect = "copy"; + } + const currentFiles = getFiles(event); + switch (eventType) { + case "enter": + counter += 1; + isOverDropZone.value = true; + (_c = _options.onEnter) == null ? void 0 : _c.call(_options, null, event); + break; + case "over": + (_d = _options.onOver) == null ? void 0 : _d.call(_options, null, event); + break; + case "leave": + counter -= 1; + if (counter === 0) + isOverDropZone.value = false; + (_e = _options.onLeave) == null ? void 0 : _e.call(_options, null, event); + break; + case "drop": + counter = 0; + isOverDropZone.value = false; + if (isValid) { + files.value = currentFiles; + (_f = _options.onDrop) == null ? void 0 : _f.call(_options, currentFiles, event); + } + break; + } + }; + useEventListener(target, "dragenter", (event) => handleDragEvent(event, "enter")); + useEventListener(target, "dragover", (event) => handleDragEvent(event, "over")); + useEventListener(target, "dragleave", (event) => handleDragEvent(event, "leave")); + useEventListener(target, "drop", (event) => handleDragEvent(event, "drop")); + } + return { + files, + isOverDropZone + }; +} +function useResizeObserver(target, callback, options = {}) { + const { window: window2 = defaultWindow, ...observerOptions } = options; + let observer; + const isSupported = useSupported(() => window2 && "ResizeObserver" in window2); + const cleanup = () => { + if (observer) { + observer.disconnect(); + observer = void 0; + } + }; + const targets = computed(() => { + const _targets = toValue$1(target); + return Array.isArray(_targets) ? _targets.map((el) => unrefElement(el)) : [unrefElement(_targets)]; + }); + const stopWatch = watch( + targets, + (els) => { + cleanup(); + if (isSupported.value && window2) { + 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 + }; +} +function useElementBounding(target, options = {}) { + const { + reset = true, + windowResize = true, + windowScroll = true, + immediate = true, + updateTiming = "sync" + } = options; + const height = shallowRef(0); + const bottom = shallowRef(0); + const left = shallowRef(0); + const right = shallowRef(0); + const top = shallowRef(0); + const width = shallowRef(0); + const x = shallowRef(0); + const y = 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); + 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 }); + tryOnMounted(() => { + if (immediate) + update(); + }); + return { + height, + bottom, + left, + right, + top, + width, + x, + y, + update + }; +} +function useElementByPoint(options) { + const { + x, + y, + document: document2 = defaultDocument, + multiple, + interval = "requestAnimationFrame", + immediate = true + } = options; + const isSupported = useSupported(() => { + if (toValue$1(multiple)) + return document2 && "elementsFromPoint" in document2; + return document2 && "elementFromPoint" in document2; + }); + const element = shallowRef(null); + const cb = () => { + var _a, _b; + element.value = toValue$1(multiple) ? (_a = document2 == null ? void 0 : document2.elementsFromPoint(toValue$1(x), toValue$1(y))) != null ? _a : [] : (_b = document2 == null ? void 0 : document2.elementFromPoint(toValue$1(x), toValue$1(y))) != null ? _b : null; + }; + const controls = interval === "requestAnimationFrame" ? useRafFn(cb, { immediate }) : useIntervalFn(cb, interval, { immediate }); + return { + isSupported, + element, + ...controls + }; +} +function useElementHover(el, options = {}) { + const { + delayEnter = 0, + delayLeave = 0, + triggerOnRemoval = false, + window: window2 = defaultWindow + } = options; + const isHovered = 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 (!window2) + return isHovered; + useEventListener(el, "mouseenter", () => toggle(true), { passive: true }); + useEventListener(el, "mouseleave", () => toggle(false), { passive: true }); + if (triggerOnRemoval) { + onElementRemoval( + computed(() => unrefElement(el)), + () => toggle(false) + ); + } + return isHovered; +} +function useElementSize(target, initialSize = { width: 0, height: 0 }, options = {}) { + const { window: window2 = defaultWindow, box = "content-box" } = options; + const isSVG = computed(() => { + var _a, _b; + return (_b = (_a = unrefElement(target)) == null ? void 0 : _a.namespaceURI) == null ? void 0 : _b.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 (window2 && 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$1(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 + }; +} +function useIntersectionObserver(target, callback, options = {}) { + const { + root, + rootMargin = "0px", + threshold = 0, + window: window2 = defaultWindow, + immediate = true + } = options; + const isSupported = useSupported(() => window2 && "IntersectionObserver" in window2); + const targets = computed(() => { + const _target = toValue$1(target); + return toArray$1(_target).map(unrefElement).filter(notNullish); + }); + let cleanup = noop$3; + const isActive = shallowRef(immediate); + const stopWatch = isSupported.value ? 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 = noop$3; + }; + }, + { immediate, flush: "post" } + ) : noop$3; + const stop = () => { + cleanup(); + stopWatch(); + isActive.value = false; + }; + tryOnScopeDispose(stop); + return { + isSupported, + isActive, + pause() { + cleanup(); + isActive.value = false; + }, + resume() { + isActive.value = true; + }, + stop + }; +} +function useElementVisibility(element, options = {}) { + const { + window: window2 = defaultWindow, + scrollTarget, + threshold = 0, + rootMargin, + once = false + } = options; + const elementIsVisible = 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) { + watchOnce(elementIsVisible, () => { + stop(); + }); + } + }, + { + root: scrollTarget, + window: window2, + threshold, + rootMargin: toValue$1(rootMargin) + } + ); + return elementIsVisible; +} +const events = /* @__PURE__ */ new Map(); +function useEventBus(key) { + const scope = getCurrentScope(); + function on(listener) { + var _a; + const listeners = events.get(key) || /* @__PURE__ */ new Set(); + listeners.add(listener); + events.set(key, listeners); + const _off = () => off(listener); + (_a = scope == null ? void 0 : scope.cleanups) == null ? void 0 : _a.push(_off); + return _off; + } + function once(listener) { + function _listener(...args) { + off(_listener); + listener(...args); + } + return on(_listener); + } + function off(listener) { + const listeners = events.get(key); + if (!listeners) + return; + listeners.delete(listener); + if (!listeners.size) + reset(); + } + function reset() { + events.delete(key); + } + function emit(event, payload) { + var _a; + (_a = events.get(key)) == null ? void 0 : _a.forEach((v) => v(event, payload)); + } + return { on, once, off, emit, reset }; +} +function resolveNestedOptions$1(options) { + if (options === true) + return {}; + return options; +} +function useEventSource(url, events2 = [], options = {}) { + const event = shallowRef(null); + const data = shallowRef(null); + const status = shallowRef("CONNECTING"); + const eventSource = ref(null); + const error = shallowRef(null); + const urlRef = toRef(url); + const lastEventId = shallowRef(null); + let explicitlyClosed = false; + let retried = 0; + const { + withCredentials = false, + immediate = true, + autoConnect = true, + autoReconnect + } = options; + const close = () => { + if (isClient && eventSource.value) { + eventSource.value.close(); + eventSource.value = null; + status.value = "CLOSED"; + explicitlyClosed = true; + } + }; + const _init = () => { + if (explicitlyClosed || typeof urlRef.value === "undefined") + return; + const es = new EventSource(urlRef.value, { withCredentials }); + status.value = "CONNECTING"; + eventSource.value = es; + es.onopen = () => { + status.value = "OPEN"; + error.value = null; + }; + es.onerror = (e) => { + status.value = "CLOSED"; + error.value = e; + if (es.readyState === 2 && !explicitlyClosed && autoReconnect) { + es.close(); + const { + retries = -1, + delay = 1e3, + onFailed + } = resolveNestedOptions$1(autoReconnect); + retried += 1; + if (typeof retries === "number" && (retries < 0 || retried < retries)) + setTimeout(_init, delay); + else if (typeof retries === "function" && retries()) + setTimeout(_init, delay); + else + onFailed == null ? void 0 : onFailed(); + } + }; + es.onmessage = (e) => { + event.value = null; + data.value = e.data; + lastEventId.value = e.lastEventId; + }; + for (const event_name of events2) { + useEventListener(es, event_name, (e) => { + event.value = event_name; + data.value = e.data || null; + }, { passive: true }); + } + }; + const open = () => { + if (!isClient) + return; + close(); + explicitlyClosed = false; + retried = 0; + _init(); + }; + if (immediate) + open(); + if (autoConnect) + watch(urlRef, open); + tryOnScopeDispose(close); + return { + eventSource, + event, + data, + status, + error, + open, + close, + lastEventId + }; +} +function useEyeDropper(options = {}) { + const { initialValue = "" } = options; + const isSupported = useSupported(() => typeof window !== "undefined" && "EyeDropper" in window); + const sRGBHex = shallowRef(initialValue); + async function open(openOptions) { + if (!isSupported.value) + return; + const eyeDropper = new window.EyeDropper(); + const result = await eyeDropper.open(openOptions); + sRGBHex.value = result.sRGBHex; + return result; + } + return { isSupported, sRGBHex, open }; +} +function useFavicon(newIcon = null, options = {}) { + const { + baseUrl = "", + rel = "icon", + document: document2 = defaultDocument + } = options; + const favicon = toRef(newIcon); + const applyIcon = (icon) => { + const elements = document2 == null ? void 0 : document2.head.querySelectorAll(`link[rel*="${rel}"]`); + if (!elements || elements.length === 0) { + const link = document2 == null ? void 0 : document2.createElement("link"); + if (link) { + link.rel = rel; + link.href = `${baseUrl}${icon}`; + link.type = `image/${icon.split(".").pop()}`; + document2 == null ? void 0 : document2.head.append(link); + } + return; + } + elements == null ? void 0 : elements.forEach((el) => el.href = `${baseUrl}${icon}`); + }; + watch( + favicon, + (i, o) => { + if (typeof i === "string" && i !== o) + applyIcon(i); + }, + { immediate: true } + ); + return favicon; +} +const payloadMapping = { + json: "application/json", + text: "text/plain" +}; +function isFetchOptions(obj) { + return obj && containsProp(obj, "immediate", "refetch", "initialData", "timeout", "beforeFetch", "afterFetch", "onFetchError", "fetch", "updateDataOnError"); +} +const reAbsolute = /^(?:[a-z][a-z\d+\-.]*:)?\/\//i; +function isAbsoluteURL$1(url) { + return reAbsolute.test(url); +} +function headersToObject$1(headers) { + if (typeof Headers !== "undefined" && headers instanceof Headers) + return Object.fromEntries(headers.entries()); + return headers; +} +function combineCallbacks(combination, ...callbacks) { + if (combination === "overwrite") { + return async (ctx) => { + let callback; + for (let i = callbacks.length - 1; i >= 0; i--) { + if (callbacks[i] != null) { + callback = callbacks[i]; + break; + } + } + if (callback) + return { ...ctx, ...await callback(ctx) }; + return ctx; + }; + } else { + return async (ctx) => { + for (const callback of callbacks) { + if (callback) + ctx = { ...ctx, ...await callback(ctx) }; + } + return ctx; + }; + } +} +function createFetch(config = {}) { + const _combination = config.combination || "chain"; + const _options = config.options || {}; + const _fetchOptions = config.fetchOptions || {}; + function useFactoryFetch(url, ...args) { + const computedUrl = computed(() => { + const baseUrl = toValue$1(config.baseUrl); + const targetUrl = toValue$1(url); + return baseUrl && !isAbsoluteURL$1(targetUrl) ? joinPaths(baseUrl, targetUrl) : targetUrl; + }); + let options = _options; + let fetchOptions = _fetchOptions; + if (args.length > 0) { + if (isFetchOptions(args[0])) { + options = { + ...options, + ...args[0], + beforeFetch: combineCallbacks(_combination, _options.beforeFetch, args[0].beforeFetch), + afterFetch: combineCallbacks(_combination, _options.afterFetch, args[0].afterFetch), + onFetchError: combineCallbacks(_combination, _options.onFetchError, args[0].onFetchError) + }; + } else { + fetchOptions = { + ...fetchOptions, + ...args[0], + headers: { + ...headersToObject$1(fetchOptions.headers) || {}, + ...headersToObject$1(args[0].headers) || {} + } + }; + } + } + if (args.length > 1 && isFetchOptions(args[1])) { + options = { + ...options, + ...args[1], + beforeFetch: combineCallbacks(_combination, _options.beforeFetch, args[1].beforeFetch), + afterFetch: combineCallbacks(_combination, _options.afterFetch, args[1].afterFetch), + onFetchError: combineCallbacks(_combination, _options.onFetchError, args[1].onFetchError) + }; + } + return useFetch(computedUrl, fetchOptions, options); + } + return useFactoryFetch; +} +function useFetch(url, ...args) { + var _a; + const supportsAbort = typeof AbortController === "function"; + let fetchOptions = {}; + let options = { + immediate: true, + refetch: false, + timeout: 0, + updateDataOnError: false + }; + const config = { + method: "GET", + type: "text", + payload: void 0 + }; + if (args.length > 0) { + if (isFetchOptions(args[0])) + options = { ...options, ...args[0] }; + else + fetchOptions = args[0]; + } + if (args.length > 1) { + if (isFetchOptions(args[1])) + options = { ...options, ...args[1] }; + } + const { + fetch = (_a = defaultWindow) == null ? void 0 : _a.fetch, + initialData, + timeout + } = options; + const responseEvent = createEventHook(); + const errorEvent = createEventHook(); + const finallyEvent = createEventHook(); + const isFinished = shallowRef(false); + const isFetching = shallowRef(false); + const aborted = shallowRef(false); + const statusCode = shallowRef(null); + const response = shallowRef(null); + const error = shallowRef(null); + const data = shallowRef(initialData || null); + const canAbort = computed(() => supportsAbort && isFetching.value); + let controller; + let timer; + const abort = () => { + if (supportsAbort) { + controller == null ? void 0 : controller.abort(); + controller = new AbortController(); + controller.signal.onabort = () => aborted.value = true; + fetchOptions = { + ...fetchOptions, + signal: controller.signal + }; + } + }; + const loading = (isLoading) => { + isFetching.value = isLoading; + isFinished.value = !isLoading; + }; + if (timeout) + timer = useTimeoutFn(abort, timeout, { immediate: false }); + let executeCounter = 0; + const execute = async (throwOnFailed = false) => { + var _a2, _b; + abort(); + loading(true); + error.value = null; + statusCode.value = null; + aborted.value = false; + executeCounter += 1; + const currentExecuteCounter = executeCounter; + const defaultFetchOptions = { + method: config.method, + headers: {} + }; + const payload = toValue$1(config.payload); + if (payload) { + const headers = headersToObject$1(defaultFetchOptions.headers); + const proto = Object.getPrototypeOf(payload); + if (!config.payloadType && payload && (proto === Object.prototype || Array.isArray(proto)) && !(payload instanceof FormData)) + config.payloadType = "json"; + if (config.payloadType) + headers["Content-Type"] = (_a2 = payloadMapping[config.payloadType]) != null ? _a2 : config.payloadType; + defaultFetchOptions.body = config.payloadType === "json" ? JSON.stringify(payload) : payload; + } + let isCanceled = false; + const context = { + url: toValue$1(url), + options: { + ...defaultFetchOptions, + ...fetchOptions + }, + cancel: () => { + isCanceled = true; + } + }; + if (options.beforeFetch) + Object.assign(context, await options.beforeFetch(context)); + if (isCanceled || !fetch) { + loading(false); + return Promise.resolve(null); + } + let responseData = null; + if (timer) + timer.start(); + return fetch( + context.url, + { + ...defaultFetchOptions, + ...context.options, + headers: { + ...headersToObject$1(defaultFetchOptions.headers), + ...headersToObject$1((_b = context.options) == null ? void 0 : _b.headers) + } + } + ).then(async (fetchResponse) => { + response.value = fetchResponse; + statusCode.value = fetchResponse.status; + responseData = await fetchResponse.clone()[config.type](); + if (!fetchResponse.ok) { + data.value = initialData || null; + throw new Error(fetchResponse.statusText); + } + if (options.afterFetch) { + ({ data: responseData } = await options.afterFetch({ + data: responseData, + response: fetchResponse, + context, + execute + })); + } + data.value = responseData; + responseEvent.trigger(fetchResponse); + return fetchResponse; + }).catch(async (fetchError) => { + let errorData = fetchError.message || fetchError.name; + if (options.onFetchError) { + ({ error: errorData, data: responseData } = await options.onFetchError({ + data: responseData, + error: fetchError, + response: response.value, + context, + execute + })); + } + error.value = errorData; + if (options.updateDataOnError) + data.value = responseData; + errorEvent.trigger(fetchError); + if (throwOnFailed) + throw fetchError; + return null; + }).finally(() => { + if (currentExecuteCounter === executeCounter) + loading(false); + if (timer) + timer.stop(); + finallyEvent.trigger(null); + }); + }; + const refetch = toRef(options.refetch); + watch( + [ + refetch, + toRef(url) + ], + ([refetch2]) => refetch2 && execute(), + { deep: true } + ); + const shell = { + isFinished: readonly(isFinished), + isFetching: readonly(isFetching), + statusCode, + response, + error, + data, + canAbort, + aborted, + abort, + execute, + onFetchResponse: responseEvent.on, + onFetchError: errorEvent.on, + onFetchFinally: finallyEvent.on, + // method + get: setMethod("GET"), + put: setMethod("PUT"), + post: setMethod("POST"), + delete: setMethod("DELETE"), + patch: setMethod("PATCH"), + head: setMethod("HEAD"), + options: setMethod("OPTIONS"), + // type + json: setType("json"), + text: setType("text"), + blob: setType("blob"), + arrayBuffer: setType("arrayBuffer"), + formData: setType("formData") + }; + function setMethod(method) { + return (payload, payloadType) => { + if (!isFetching.value) { + config.method = method; + config.payload = payload; + config.payloadType = payloadType; + if (isRef(config.payload)) { + watch( + [ + refetch, + toRef(config.payload) + ], + ([refetch2]) => refetch2 && execute(), + { deep: true } + ); + } + return { + ...shell, + then(onFulfilled, onRejected) { + return waitUntilFinished().then(onFulfilled, onRejected); + } + }; + } + return void 0; + }; + } + function waitUntilFinished() { + return new Promise((resolve, reject) => { + until(isFinished).toBe(true).then(() => resolve(shell)).catch(reject); + }); + } + function setType(type) { + return () => { + if (!isFetching.value) { + config.type = type; + return { + ...shell, + then(onFulfilled, onRejected) { + return waitUntilFinished().then(onFulfilled, onRejected); + } + }; + } + return void 0; + }; + } + if (options.immediate) + Promise.resolve().then(() => execute()); + return { + ...shell, + then(onFulfilled, onRejected) { + return waitUntilFinished().then(onFulfilled, onRejected); + } + }; +} +function joinPaths(start, end) { + if (!start.endsWith("/") && !end.startsWith("/")) { + return `${start}/${end}`; + } + if (start.endsWith("/") && end.startsWith("/")) { + return `${start.slice(0, -1)}${end}`; + } + return `${start}${end}`; +} +const DEFAULT_OPTIONS$1 = { + multiple: true, + accept: "*", + reset: false, + directory: false +}; +function prepareInitialFiles(files) { + if (!files) + return null; + if (files instanceof FileList) + return files; + const dt = new DataTransfer(); + for (const file of files) { + dt.items.add(file); + } + return dt.files; +} +function useFileDialog(options = {}) { + const { + document: document2 = defaultDocument + } = options; + const files = ref(prepareInitialFiles(options.initialFiles)); + const { on: onChange, trigger: changeTrigger } = createEventHook(); + const { on: onCancel, trigger: cancelTrigger } = createEventHook(); + let input; + if (document2) { + input = document2.createElement("input"); + input.type = "file"; + input.onchange = (event) => { + const result = event.target; + files.value = result.files; + changeTrigger(files.value); + }; + input.oncancel = () => { + cancelTrigger(); + }; + } + const reset = () => { + files.value = null; + if (input && input.value) { + input.value = ""; + changeTrigger(null); + } + }; + const open = (localOptions) => { + if (!input) + return; + const _options = { + ...DEFAULT_OPTIONS$1, + ...options, + ...localOptions + }; + input.multiple = _options.multiple; + input.accept = _options.accept; + input.webkitdirectory = _options.directory; + if (hasOwn$2(_options, "capture")) + input.capture = _options.capture; + if (_options.reset) + reset(); + input.click(); + }; + return { + files: readonly(files), + open, + reset, + onCancel, + onChange + }; +} +function useFileSystemAccess(options = {}) { + const { + window: _window = defaultWindow, + dataType = "Text" + } = options; + const window2 = _window; + const isSupported = useSupported(() => window2 && "showSaveFilePicker" in window2 && "showOpenFilePicker" in window2); + const fileHandle = shallowRef(); + const data = shallowRef(); + const file = shallowRef(); + const fileName = computed(() => { + var _a, _b; + return (_b = (_a = file.value) == null ? void 0 : _a.name) != null ? _b : ""; + }); + const fileMIME = computed(() => { + var _a, _b; + return (_b = (_a = file.value) == null ? void 0 : _a.type) != null ? _b : ""; + }); + const fileSize = computed(() => { + var _a, _b; + return (_b = (_a = file.value) == null ? void 0 : _a.size) != null ? _b : 0; + }); + const fileLastModified = computed(() => { + var _a, _b; + return (_b = (_a = file.value) == null ? void 0 : _a.lastModified) != null ? _b : 0; + }); + async function open(_options = {}) { + if (!isSupported.value) + return; + const [handle] = await window2.showOpenFilePicker({ ...toValue$1(options), ..._options }); + fileHandle.value = handle; + await updateData(); + } + async function create(_options = {}) { + if (!isSupported.value) + return; + fileHandle.value = await window2.showSaveFilePicker({ ...options, ..._options }); + data.value = void 0; + await updateData(); + } + async function save(_options = {}) { + if (!isSupported.value) + return; + if (!fileHandle.value) + return saveAs(_options); + if (data.value) { + const writableStream = await fileHandle.value.createWritable(); + await writableStream.write(data.value); + await writableStream.close(); + } + await updateFile(); + } + async function saveAs(_options = {}) { + if (!isSupported.value) + return; + fileHandle.value = await window2.showSaveFilePicker({ ...options, ..._options }); + if (data.value) { + const writableStream = await fileHandle.value.createWritable(); + await writableStream.write(data.value); + await writableStream.close(); + } + await updateFile(); + } + async function updateFile() { + var _a; + file.value = await ((_a = fileHandle.value) == null ? void 0 : _a.getFile()); + } + async function updateData() { + var _a, _b; + await updateFile(); + const type = toValue$1(dataType); + if (type === "Text") + data.value = await ((_a = file.value) == null ? void 0 : _a.text()); + else if (type === "ArrayBuffer") + data.value = await ((_b = file.value) == null ? void 0 : _b.arrayBuffer()); + else if (type === "Blob") + data.value = file.value; + } + watch(() => toValue$1(dataType), updateData); + return { + isSupported, + data, + file, + fileName, + fileMIME, + fileSize, + fileLastModified, + open, + create, + save, + saveAs, + updateData + }; +} +function useFocus(target, options = {}) { + const { initialValue = false, focusVisible = false, preventScroll = false } = options; + const innerFocused = shallowRef(false); + const targetElement = computed(() => unrefElement(target)); + const listenerOptions = { passive: true }; + useEventListener(targetElement, "focus", (event) => { + var _a, _b; + if (!focusVisible || ((_b = (_a = event.target).matches) == null ? void 0 : _b.call(_a, ":focus-visible"))) + innerFocused.value = true; + }, listenerOptions); + useEventListener(targetElement, "blur", () => innerFocused.value = false, listenerOptions); + const focused = computed({ + get: () => innerFocused.value, + set(value) { + var _a, _b; + if (!value && innerFocused.value) + (_a = targetElement.value) == null ? void 0 : _a.blur(); + else if (value && !innerFocused.value) + (_b = targetElement.value) == null ? void 0 : _b.focus({ preventScroll }); + } + }); + watch( + targetElement, + () => { + focused.value = initialValue; + }, + { immediate: true, flush: "post" } + ); + return { focused }; +} +const EVENT_FOCUS_IN = "focusin"; +const EVENT_FOCUS_OUT = "focusout"; +const PSEUDO_CLASS_FOCUS_WITHIN = ":focus-within"; +function useFocusWithin(target, options = {}) { + const { window: window2 = defaultWindow } = options; + const targetElement = computed(() => unrefElement(target)); + const _focused = shallowRef(false); + const focused = computed(() => _focused.value); + const activeElement = useActiveElement(options); + if (!window2 || !activeElement.value) { + return { focused }; + } + const listenerOptions = { passive: true }; + useEventListener(targetElement, EVENT_FOCUS_IN, () => _focused.value = true, listenerOptions); + useEventListener(targetElement, EVENT_FOCUS_OUT, () => { + var _a, _b, _c; + return _focused.value = (_c = (_b = (_a = targetElement.value) == null ? void 0 : _a.matches) == null ? void 0 : _b.call(_a, PSEUDO_CLASS_FOCUS_WITHIN)) != null ? _c : false; + }, listenerOptions); + return { focused }; +} +function useFps(options) { + var _a; + const fps = shallowRef(0); + if (typeof performance === "undefined") + return fps; + const every = (_a = options == null ? void 0 : options.every) != null ? _a : 10; + let last = performance.now(); + let ticks = 0; + useRafFn(() => { + ticks += 1; + if (ticks >= every) { + const now = performance.now(); + const diff = now - last; + fps.value = Math.round(1e3 / (diff / ticks)); + last = now; + ticks = 0; + } + }); + return fps; +} +const eventHandlers = [ + "fullscreenchange", + "webkitfullscreenchange", + "webkitendfullscreen", + "mozfullscreenchange", + "MSFullscreenChange" +]; +function useFullscreen(target, options = {}) { + const { + document: document2 = defaultDocument, + autoExit = false + } = options; + const targetRef = computed(() => { + var _a; + return (_a = unrefElement(target)) != null ? _a : document2 == null ? void 0 : document2.documentElement; + }); + const isFullscreen = shallowRef(false); + const requestMethod = computed(() => { + return [ + "requestFullscreen", + "webkitRequestFullscreen", + "webkitEnterFullscreen", + "webkitEnterFullScreen", + "webkitRequestFullScreen", + "mozRequestFullScreen", + "msRequestFullscreen" + ].find((m) => document2 && m in document2 || targetRef.value && m in targetRef.value); + }); + const exitMethod = computed(() => { + return [ + "exitFullscreen", + "webkitExitFullscreen", + "webkitExitFullScreen", + "webkitCancelFullScreen", + "mozCancelFullScreen", + "msExitFullscreen" + ].find((m) => document2 && m in document2 || targetRef.value && m in targetRef.value); + }); + const fullscreenEnabled = computed(() => { + return [ + "fullScreen", + "webkitIsFullScreen", + "webkitDisplayingFullscreen", + "mozFullScreen", + "msFullscreenElement" + ].find((m) => document2 && m in document2 || targetRef.value && m in targetRef.value); + }); + const fullscreenElementMethod = [ + "fullscreenElement", + "webkitFullscreenElement", + "mozFullScreenElement", + "msFullscreenElement" + ].find((m) => document2 && m in document2); + const isSupported = useSupported(() => targetRef.value && document2 && requestMethod.value !== void 0 && exitMethod.value !== void 0 && fullscreenEnabled.value !== void 0); + const isCurrentElementFullScreen = () => { + if (fullscreenElementMethod) + return (document2 == null ? void 0 : document2[fullscreenElementMethod]) === targetRef.value; + return false; + }; + const isElementFullScreen = () => { + if (fullscreenEnabled.value) { + if (document2 && document2[fullscreenEnabled.value] != null) { + return document2[fullscreenEnabled.value]; + } else { + const target2 = targetRef.value; + if ((target2 == null ? void 0 : target2[fullscreenEnabled.value]) != null) { + return Boolean(target2[fullscreenEnabled.value]); + } + } + } + return false; + }; + async function exit() { + if (!isSupported.value || !isFullscreen.value) + return; + if (exitMethod.value) { + if ((document2 == null ? void 0 : document2[exitMethod.value]) != null) { + await document2[exitMethod.value](); + } else { + const target2 = targetRef.value; + if ((target2 == null ? void 0 : target2[exitMethod.value]) != null) + await target2[exitMethod.value](); + } + } + isFullscreen.value = false; + } + async function enter() { + if (!isSupported.value || isFullscreen.value) + return; + if (isElementFullScreen()) + await exit(); + const target2 = targetRef.value; + if (requestMethod.value && (target2 == null ? void 0 : target2[requestMethod.value]) != null) { + await target2[requestMethod.value](); + isFullscreen.value = true; + } + } + async function toggle() { + await (isFullscreen.value ? exit() : enter()); + } + const handlerCallback = () => { + const isElementFullScreenValue = isElementFullScreen(); + if (!isElementFullScreenValue || isElementFullScreenValue && isCurrentElementFullScreen()) + isFullscreen.value = isElementFullScreenValue; + }; + const listenerOptions = { capture: false, passive: true }; + useEventListener(document2, eventHandlers, handlerCallback, listenerOptions); + useEventListener(() => unrefElement(targetRef), eventHandlers, handlerCallback, listenerOptions); + if (autoExit) + tryOnScopeDispose(exit); + return { + isSupported, + isFullscreen, + enter, + exit, + toggle + }; +} +function mapGamepadToXbox360Controller(gamepad) { + return computed(() => { + if (gamepad.value) { + return { + buttons: { + a: gamepad.value.buttons[0], + b: gamepad.value.buttons[1], + x: gamepad.value.buttons[2], + y: gamepad.value.buttons[3] + }, + bumper: { + left: gamepad.value.buttons[4], + right: gamepad.value.buttons[5] + }, + triggers: { + left: gamepad.value.buttons[6], + right: gamepad.value.buttons[7] + }, + stick: { + left: { + horizontal: gamepad.value.axes[0], + vertical: gamepad.value.axes[1], + button: gamepad.value.buttons[10] + }, + right: { + horizontal: gamepad.value.axes[2], + vertical: gamepad.value.axes[3], + button: gamepad.value.buttons[11] + } + }, + dpad: { + up: gamepad.value.buttons[12], + down: gamepad.value.buttons[13], + left: gamepad.value.buttons[14], + right: gamepad.value.buttons[15] + }, + back: gamepad.value.buttons[8], + start: gamepad.value.buttons[9] + }; + } + return null; + }); +} +function useGamepad(options = {}) { + const { + navigator: navigator2 = defaultNavigator + } = options; + const isSupported = useSupported(() => navigator2 && "getGamepads" in navigator2); + const gamepads = ref([]); + const onConnectedHook = createEventHook(); + const onDisconnectedHook = createEventHook(); + const stateFromGamepad = (gamepad) => { + const hapticActuators = []; + const vibrationActuator = "vibrationActuator" in gamepad ? gamepad.vibrationActuator : null; + if (vibrationActuator) + hapticActuators.push(vibrationActuator); + if (gamepad.hapticActuators) + hapticActuators.push(...gamepad.hapticActuators); + return { + id: gamepad.id, + index: gamepad.index, + connected: gamepad.connected, + mapping: gamepad.mapping, + timestamp: gamepad.timestamp, + vibrationActuator: gamepad.vibrationActuator, + hapticActuators, + axes: gamepad.axes.map((axes) => axes), + buttons: gamepad.buttons.map((button) => ({ pressed: button.pressed, touched: button.touched, value: button.value })) + }; + }; + const updateGamepadState = () => { + const _gamepads = (navigator2 == null ? void 0 : navigator2.getGamepads()) || []; + for (const gamepad of _gamepads) { + if (gamepad && gamepads.value[gamepad.index]) + gamepads.value[gamepad.index] = stateFromGamepad(gamepad); + } + }; + const { isActive, pause, resume } = useRafFn(updateGamepadState); + const onGamepadConnected = (gamepad) => { + if (!gamepads.value.some(({ index }) => index === gamepad.index)) { + gamepads.value.push(stateFromGamepad(gamepad)); + onConnectedHook.trigger(gamepad.index); + } + resume(); + }; + const onGamepadDisconnected = (gamepad) => { + gamepads.value = gamepads.value.filter((x) => x.index !== gamepad.index); + onDisconnectedHook.trigger(gamepad.index); + }; + const listenerOptions = { passive: true }; + useEventListener("gamepadconnected", (e) => onGamepadConnected(e.gamepad), listenerOptions); + useEventListener("gamepaddisconnected", (e) => onGamepadDisconnected(e.gamepad), listenerOptions); + tryOnMounted(() => { + const _gamepads = (navigator2 == null ? void 0 : navigator2.getGamepads()) || []; + for (const gamepad of _gamepads) { + if (gamepad && gamepads.value[gamepad.index]) + onGamepadConnected(gamepad); + } + }); + pause(); + return { + isSupported, + onConnected: onConnectedHook.on, + onDisconnected: onDisconnectedHook.on, + gamepads, + pause, + resume, + isActive + }; +} +function useGeolocation(options = {}) { + const { + enableHighAccuracy = true, + maximumAge = 3e4, + timeout = 27e3, + navigator: navigator2 = defaultNavigator, + immediate = true + } = options; + const isSupported = useSupported(() => navigator2 && "geolocation" in navigator2); + const locatedAt = shallowRef(null); + const error = shallowRef(null); + const coords = ref({ + accuracy: 0, + latitude: Number.POSITIVE_INFINITY, + longitude: Number.POSITIVE_INFINITY, + altitude: null, + altitudeAccuracy: null, + heading: null, + speed: null + }); + function updatePosition(position) { + locatedAt.value = position.timestamp; + coords.value = position.coords; + error.value = null; + } + let watcher; + function resume() { + if (isSupported.value) { + watcher = navigator2.geolocation.watchPosition( + updatePosition, + (err) => error.value = err, + { + enableHighAccuracy, + maximumAge, + timeout + } + ); + } + } + if (immediate) + resume(); + function pause() { + if (watcher && navigator2) + navigator2.geolocation.clearWatch(watcher); + } + tryOnScopeDispose(() => { + pause(); + }); + return { + isSupported, + coords, + locatedAt, + error, + resume, + pause + }; +} +const defaultEvents$1 = ["mousemove", "mousedown", "resize", "keydown", "touchstart", "wheel"]; +const oneMinute = 6e4; +function useIdle(timeout = oneMinute, options = {}) { + const { + initialState = false, + listenForVisibilityChange = true, + events: events2 = defaultEvents$1, + window: window2 = defaultWindow, + eventFilter = throttleFilter(50) + } = options; + const idle = shallowRef(initialState); + const lastActive = shallowRef(timestamp()); + let timer; + const reset = () => { + idle.value = false; + clearTimeout(timer); + timer = setTimeout(() => idle.value = true, timeout); + }; + const onEvent = createFilterWrapper( + eventFilter, + () => { + lastActive.value = timestamp(); + reset(); + } + ); + if (window2) { + const document2 = window2.document; + const listenerOptions = { passive: true }; + for (const event of events2) + useEventListener(window2, event, onEvent, listenerOptions); + if (listenForVisibilityChange) { + useEventListener(document2, "visibilitychange", () => { + if (!document2.hidden) + onEvent(); + }, listenerOptions); + } + reset(); + } + return { + idle, + lastActive, + reset + }; +} +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(toValue$1(options)), + void 0, + { + resetOnExecute: true, + ...asyncStateOptions + } + ); + watch( + () => toValue$1(options), + () => state.execute(asyncStateOptions.delay), + { deep: true } + ); + return state; +} +function resolveElement(el) { + if (typeof Window !== "undefined" && el instanceof Window) + return el.document.documentElement; + if (typeof Document !== "undefined" && el instanceof Document) + return el.documentElement; + return el; +} +const ARRIVED_STATE_THRESHOLD_PIXELS = 1; +function useScroll(element, options = {}) { + const { + throttle = 0, + idle = 200, + onStop = noop$3, + onScroll = noop$3, + offset = { + left: 0, + right: 0, + top: 0, + bottom: 0 + }, + eventListenerOptions = { + capture: false, + passive: true + }, + behavior = "auto", + window: window2 = defaultWindow, + onError = (e) => { + console.error(e); + } + } = options; + const internalX = shallowRef(0); + const internalY = shallowRef(0); + const x = computed({ + get() { + return internalX.value; + }, + set(x2) { + scrollTo(x2, void 0); + } + }); + const y = computed({ + get() { + return internalY.value; + }, + set(y2) { + scrollTo(void 0, y2); + } + }); + function scrollTo(_x, _y) { + var _a, _b, _c, _d; + if (!window2) + return; + const _element = toValue$1(element); + if (!_element) + return; + (_c = _element instanceof Document ? window2.document.body : _element) == null ? void 0 : _c.scrollTo({ + top: (_a = toValue$1(_y)) != null ? _a : y.value, + left: (_b = toValue$1(_x)) != null ? _b : x.value, + behavior: toValue$1(behavior) + }); + const scrollContainer = ((_d = _element == null ? void 0 : _element.document) == null ? void 0 : _d.documentElement) || (_element == null ? void 0 : _element.documentElement) || _element; + if (x != null) + internalX.value = scrollContainer.scrollLeft; + if (y != null) + internalY.value = scrollContainer.scrollTop; + } + const isScrolling = shallowRef(false); + const arrivedState = reactive({ + left: true, + right: false, + top: true, + bottom: false + }); + const directions = reactive({ + left: false, + right: false, + top: false, + bottom: false + }); + const onScrollEnd = (e) => { + if (!isScrolling.value) + return; + isScrolling.value = false; + directions.left = false; + directions.right = false; + directions.top = false; + directions.bottom = false; + onStop(e); + }; + const onScrollEndDebounced = useDebounceFn(onScrollEnd, throttle + idle); + const setArrivedState = (target) => { + var _a; + if (!window2) + return; + const el = ((_a = target == null ? void 0 : target.document) == null ? void 0 : _a.documentElement) || (target == null ? void 0 : target.documentElement) || unrefElement(target); + const { display, flexDirection, direction } = getComputedStyle(el); + const directionMultipler = direction === "rtl" ? -1 : 1; + const scrollLeft = el.scrollLeft; + directions.left = scrollLeft < internalX.value; + directions.right = scrollLeft > internalX.value; + const left = Math.abs(scrollLeft * directionMultipler) <= (offset.left || 0); + const right = Math.abs(scrollLeft * directionMultipler) + el.clientWidth >= el.scrollWidth - (offset.right || 0) - ARRIVED_STATE_THRESHOLD_PIXELS; + if (display === "flex" && flexDirection === "row-reverse") { + arrivedState.left = right; + arrivedState.right = left; + } else { + arrivedState.left = left; + arrivedState.right = right; + } + internalX.value = scrollLeft; + let scrollTop = el.scrollTop; + if (target === window2.document && !scrollTop) + scrollTop = window2.document.body.scrollTop; + directions.top = scrollTop < internalY.value; + directions.bottom = scrollTop > internalY.value; + const top = Math.abs(scrollTop) <= (offset.top || 0); + const bottom = Math.abs(scrollTop) + el.clientHeight >= el.scrollHeight - (offset.bottom || 0) - ARRIVED_STATE_THRESHOLD_PIXELS; + if (display === "flex" && flexDirection === "column-reverse") { + arrivedState.top = bottom; + arrivedState.bottom = top; + } else { + arrivedState.top = top; + arrivedState.bottom = bottom; + } + internalY.value = scrollTop; + }; + const onScrollHandler = (e) => { + var _a; + if (!window2) + return; + const eventTarget = (_a = e.target.documentElement) != null ? _a : e.target; + setArrivedState(eventTarget); + isScrolling.value = true; + onScrollEndDebounced(e); + onScroll(e); + }; + useEventListener( + element, + "scroll", + throttle ? useThrottleFn(onScrollHandler, throttle, true, false) : onScrollHandler, + eventListenerOptions + ); + tryOnMounted(() => { + try { + const _element = toValue$1(element); + if (!_element) + return; + setArrivedState(_element); + } catch (e) { + onError(e); + } + }); + useEventListener( + element, + "scrollend", + onScrollEnd, + eventListenerOptions + ); + return { + x, + y, + isScrolling, + arrivedState, + directions, + measure() { + const _element = toValue$1(element); + if (window2 && _element) + setArrivedState(_element); + } + }; +} +function useInfiniteScroll(element, onLoadMore, options = {}) { + var _a; + const { + direction = "bottom", + interval = 100, + canLoadMore = () => true + } = options; + const state = reactive(useScroll( + element, + { + ...options, + offset: { + [direction]: (_a = options.distance) != null ? _a : 0, + ...options.offset + } + } + )); + const promise = ref(); + const isLoading = computed(() => !!promise.value); + const observedElement = computed(() => { + return resolveElement(toValue$1(element)); + }); + const isElementVisible = useElementVisibility(observedElement); + function checkAndLoad() { + state.measure(); + if (!observedElement.value || !isElementVisible.value || !canLoadMore(observedElement.value)) + return; + const { scrollHeight, clientHeight, scrollWidth, clientWidth } = observedElement.value; + const isNarrower = direction === "bottom" || direction === "top" ? scrollHeight <= clientHeight : scrollWidth <= clientWidth; + if (state.arrivedState[direction] || isNarrower) { + if (!promise.value) { + promise.value = Promise.all([ + onLoadMore(state), + new Promise((resolve) => setTimeout(resolve, interval)) + ]).finally(() => { + promise.value = null; + nextTick(() => checkAndLoad()); + }); + } + } + } + const stop = watch( + () => [state.arrivedState[direction], isElementVisible.value], + checkAndLoad, + { immediate: true } + ); + tryOnUnmounted(stop); + return { + isLoading, + reset() { + nextTick(() => checkAndLoad()); + } + }; +} +const defaultEvents = ["mousedown", "mouseup", "keydown", "keyup"]; +function useKeyModifier(modifier, options = {}) { + const { + events: events2 = defaultEvents, + document: document2 = defaultDocument, + initial = null + } = options; + const state = shallowRef(initial); + if (document2) { + events2.forEach((listenerEvent) => { + useEventListener(document2, listenerEvent, (evt) => { + if (typeof evt.getModifierState === "function") + state.value = evt.getModifierState(modifier); + }, { passive: true }); + }); + } + return state; +} +function useLocalStorage(key, initialValue, options = {}) { + const { window: window2 = defaultWindow } = options; + return useStorage(key, initialValue, window2 == null ? void 0 : window2.localStorage, options); +} +const DefaultMagicKeysAliasMap = { + ctrl: "control", + command: "meta", + cmd: "meta", + option: "alt", + up: "arrowup", + down: "arrowdown", + left: "arrowleft", + right: "arrowright" +}; +function useMagicKeys(options = {}) { + const { + reactive: useReactive = false, + target = defaultWindow, + aliasMap = DefaultMagicKeysAliasMap, + passive = true, + onEventFired = noop$3 + } = options; + const current = reactive(/* @__PURE__ */ new Set()); + const obj = { + toJSON() { + return {}; + }, + current + }; + const refs = useReactive ? reactive(obj) : obj; + const metaDeps = /* @__PURE__ */ new Set(); + const usedKeys = /* @__PURE__ */ new Set(); + function setRefs(key, value) { + if (key in refs) { + if (useReactive) + refs[key] = value; + else + refs[key].value = value; + } + } + function reset() { + current.clear(); + for (const key of usedKeys) + setRefs(key, false); + } + function updateRefs(e, value) { + var _a, _b; + const key = (_a = e.key) == null ? void 0 : _a.toLowerCase(); + const code = (_b = e.code) == null ? void 0 : _b.toLowerCase(); + const values = [code, key].filter(Boolean); + if (key) { + if (value) + current.add(key); + else + current.delete(key); + } + for (const key2 of values) { + usedKeys.add(key2); + setRefs(key2, value); + } + if (key === "meta" && !value) { + metaDeps.forEach((key2) => { + current.delete(key2); + setRefs(key2, false); + }); + metaDeps.clear(); + } else if (typeof e.getModifierState === "function" && e.getModifierState("Meta") && value) { + [...current, ...values].forEach((key2) => metaDeps.add(key2)); + } + } + useEventListener(target, "keydown", (e) => { + updateRefs(e, true); + return onEventFired(e); + }, { passive }); + useEventListener(target, "keyup", (e) => { + updateRefs(e, false); + return onEventFired(e); + }, { passive }); + useEventListener("blur", reset, { passive }); + useEventListener("focus", reset, { passive }); + const proxy = new Proxy( + refs, + { + get(target2, prop, rec) { + if (typeof prop !== "string") + return Reflect.get(target2, prop, rec); + prop = prop.toLowerCase(); + if (prop in aliasMap) + prop = aliasMap[prop]; + if (!(prop in refs)) { + if (/[+_-]/.test(prop)) { + const keys2 = prop.split(/[+_-]/g).map((i) => i.trim()); + refs[prop] = computed(() => keys2.map((key) => toValue$1(proxy[key])).every(Boolean)); + } else { + refs[prop] = shallowRef(false); + } + } + const r = Reflect.get(target2, prop, rec); + return useReactive ? toValue$1(r) : r; + } + } + ); + return proxy; +} +function usingElRef(source, cb) { + if (toValue$1(source)) + cb(toValue$1(source)); +} +function timeRangeToArray(timeRanges) { + let ranges = []; + for (let i = 0; i < timeRanges.length; ++i) + ranges = [...ranges, [timeRanges.start(i), timeRanges.end(i)]]; + return ranges; +} +function tracksToArray(tracks) { + return Array.from(tracks).map(({ label, kind, language, mode, activeCues, cues, inBandMetadataTrackDispatchType }, id) => ({ id, label, kind, language, mode, activeCues, cues, inBandMetadataTrackDispatchType })); +} +const defaultOptions = { + src: "", + tracks: [] +}; +function useMediaControls(target, options = {}) { + target = toRef(target); + options = { + ...defaultOptions, + ...options + }; + const { + document: document2 = defaultDocument + } = options; + const listenerOptions = { passive: true }; + const currentTime = shallowRef(0); + const duration = shallowRef(0); + const seeking = shallowRef(false); + const volume = shallowRef(1); + const waiting = shallowRef(false); + const ended = shallowRef(false); + const playing = shallowRef(false); + const rate = shallowRef(1); + const stalled = shallowRef(false); + const buffered = ref([]); + const tracks = ref([]); + const selectedTrack = shallowRef(-1); + const isPictureInPicture = shallowRef(false); + const muted = shallowRef(false); + const supportsPictureInPicture = document2 && "pictureInPictureEnabled" in document2; + const sourceErrorEvent = createEventHook(); + const playbackErrorEvent = createEventHook(); + const disableTrack = (track) => { + usingElRef(target, (el) => { + if (track) { + const id = typeof track === "number" ? track : track.id; + el.textTracks[id].mode = "disabled"; + } else { + for (let i = 0; i < el.textTracks.length; ++i) + el.textTracks[i].mode = "disabled"; + } + selectedTrack.value = -1; + }); + }; + const enableTrack = (track, disableTracks = true) => { + usingElRef(target, (el) => { + const id = typeof track === "number" ? track : track.id; + if (disableTracks) + disableTrack(); + el.textTracks[id].mode = "showing"; + selectedTrack.value = id; + }); + }; + const togglePictureInPicture = () => { + return new Promise((resolve, reject) => { + usingElRef(target, async (el) => { + if (supportsPictureInPicture) { + if (!isPictureInPicture.value) { + el.requestPictureInPicture().then(resolve).catch(reject); + } else { + document2.exitPictureInPicture().then(resolve).catch(reject); + } + } + }); + }); + }; + watchEffect(() => { + if (!document2) + return; + const el = toValue$1(target); + if (!el) + return; + const src = toValue$1(options.src); + let sources = []; + if (!src) + return; + if (typeof src === "string") + sources = [{ src }]; + else if (Array.isArray(src)) + sources = src; + else if (isObject$2(src)) + sources = [src]; + el.querySelectorAll("source").forEach((e) => { + e.remove(); + }); + sources.forEach(({ src: src2, type, media }) => { + const source = document2.createElement("source"); + source.setAttribute("src", src2); + source.setAttribute("type", type || ""); + source.setAttribute("media", media || ""); + useEventListener(source, "error", sourceErrorEvent.trigger, listenerOptions); + el.appendChild(source); + }); + el.load(); + }); + watch([target, volume], () => { + const el = toValue$1(target); + if (!el) + return; + el.volume = volume.value; + }); + watch([target, muted], () => { + const el = toValue$1(target); + if (!el) + return; + el.muted = muted.value; + }); + watch([target, rate], () => { + const el = toValue$1(target); + if (!el) + return; + el.playbackRate = rate.value; + }); + watchEffect(() => { + if (!document2) + return; + const textTracks = toValue$1(options.tracks); + const el = toValue$1(target); + if (!textTracks || !textTracks.length || !el) + return; + el.querySelectorAll("track").forEach((e) => e.remove()); + textTracks.forEach(({ default: isDefault, kind, label, src, srcLang }, i) => { + const track = document2.createElement("track"); + track.default = isDefault || false; + track.kind = kind; + track.label = label; + track.src = src; + track.srclang = srcLang; + if (track.default) + selectedTrack.value = i; + el.appendChild(track); + }); + }); + const { ignoreUpdates: ignoreCurrentTimeUpdates } = watchIgnorable(currentTime, (time) => { + const el = toValue$1(target); + if (!el) + return; + el.currentTime = time; + }); + const { ignoreUpdates: ignorePlayingUpdates } = watchIgnorable(playing, (isPlaying) => { + const el = toValue$1(target); + if (!el) + return; + if (isPlaying) { + el.play().catch((e) => { + playbackErrorEvent.trigger(e); + throw e; + }); + } else { + el.pause(); + } + }); + useEventListener( + target, + "timeupdate", + () => ignoreCurrentTimeUpdates(() => currentTime.value = toValue$1(target).currentTime), + listenerOptions + ); + useEventListener( + target, + "durationchange", + () => duration.value = toValue$1(target).duration, + listenerOptions + ); + useEventListener( + target, + "progress", + () => buffered.value = timeRangeToArray(toValue$1(target).buffered), + listenerOptions + ); + useEventListener( + target, + "seeking", + () => seeking.value = true, + listenerOptions + ); + useEventListener( + target, + "seeked", + () => seeking.value = false, + listenerOptions + ); + useEventListener( + target, + ["waiting", "loadstart"], + () => { + waiting.value = true; + ignorePlayingUpdates(() => playing.value = false); + }, + listenerOptions + ); + useEventListener( + target, + "loadeddata", + () => waiting.value = false, + listenerOptions + ); + useEventListener( + target, + "playing", + () => { + waiting.value = false; + ended.value = false; + ignorePlayingUpdates(() => playing.value = true); + }, + listenerOptions + ); + useEventListener( + target, + "ratechange", + () => rate.value = toValue$1(target).playbackRate, + listenerOptions + ); + useEventListener( + target, + "stalled", + () => stalled.value = true, + listenerOptions + ); + useEventListener( + target, + "ended", + () => ended.value = true, + listenerOptions + ); + useEventListener( + target, + "pause", + () => ignorePlayingUpdates(() => playing.value = false), + listenerOptions + ); + useEventListener( + target, + "play", + () => ignorePlayingUpdates(() => playing.value = true), + listenerOptions + ); + useEventListener( + target, + "enterpictureinpicture", + () => isPictureInPicture.value = true, + listenerOptions + ); + useEventListener( + target, + "leavepictureinpicture", + () => isPictureInPicture.value = false, + listenerOptions + ); + useEventListener( + target, + "volumechange", + () => { + const el = toValue$1(target); + if (!el) + return; + volume.value = el.volume; + muted.value = el.muted; + }, + listenerOptions + ); + const listeners = []; + const stop = watch([target], () => { + const el = toValue$1(target); + if (!el) + return; + stop(); + listeners[0] = useEventListener(el.textTracks, "addtrack", () => tracks.value = tracksToArray(el.textTracks), listenerOptions); + listeners[1] = useEventListener(el.textTracks, "removetrack", () => tracks.value = tracksToArray(el.textTracks), listenerOptions); + listeners[2] = useEventListener(el.textTracks, "change", () => tracks.value = tracksToArray(el.textTracks), listenerOptions); + }); + tryOnScopeDispose(() => listeners.forEach((listener) => listener())); + return { + currentTime, + duration, + waiting, + seeking, + ended, + stalled, + buffered, + playing, + rate, + // Volume + volume, + muted, + // Tracks + tracks, + selectedTrack, + enableTrack, + disableTrack, + // Picture in Picture + supportsPictureInPicture, + togglePictureInPicture, + isPictureInPicture, + // Events + onSourceError: sourceErrorEvent.on, + onPlaybackError: playbackErrorEvent.on + }; +} +function useMemoize(resolver, options) { + const initCache = () => { + if (options == null ? void 0 : options.cache) + return shallowReactive(options.cache); + return shallowReactive(/* @__PURE__ */ new Map()); + }; + const cache = initCache(); + const generateKey = (...args) => (options == null ? void 0 : options.getKey) ? options.getKey(...args) : JSON.stringify(args); + const _loadData = (key, ...args) => { + cache.set(key, resolver(...args)); + return cache.get(key); + }; + const loadData = (...args) => _loadData(generateKey(...args), ...args); + const deleteData = (...args) => { + cache.delete(generateKey(...args)); + }; + const clearData = () => { + cache.clear(); + }; + const memoized = (...args) => { + const key = generateKey(...args); + if (cache.has(key)) + return cache.get(key); + return _loadData(key, ...args); + }; + memoized.load = loadData; + memoized.delete = deleteData; + memoized.clear = clearData; + memoized.generateKey = generateKey; + memoized.cache = cache; + return memoized; +} +function useMemory(options = {}) { + const memory = ref(); + const isSupported = useSupported(() => typeof performance !== "undefined" && "memory" in performance); + if (isSupported.value) { + const { interval = 1e3 } = options; + useIntervalFn(() => { + memory.value = performance.memory; + }, interval, { immediate: options.immediate, immediateCallback: options.immediateCallback }); + } + return { isSupported, memory }; +} +const UseMouseBuiltinExtractors = { + page: (event) => [event.pageX, event.pageY], + client: (event) => [event.clientX, event.clientY], + screen: (event) => [event.screenX, event.screenY], + movement: (event) => event instanceof MouseEvent ? [event.movementX, event.movementY] : null +}; +function useMouse(options = {}) { + const { + type = "page", + touch = true, + resetOnTouchEnds = false, + initialValue = { x: 0, y: 0 }, + window: window2 = defaultWindow, + target = window2, + scroll = true, + eventFilter + } = options; + let _prevMouseEvent = null; + let _prevScrollX = 0; + let _prevScrollY = 0; + const x = shallowRef(initialValue.x); + const y = shallowRef(initialValue.y); + const sourceType = shallowRef(null); + const extractor = typeof type === "function" ? type : UseMouseBuiltinExtractors[type]; + const mouseHandler = (event) => { + const result = extractor(event); + _prevMouseEvent = event; + if (result) { + [x.value, y.value] = result; + sourceType.value = "mouse"; + } + if (window2) { + _prevScrollX = window2.scrollX; + _prevScrollY = window2.scrollY; + } + }; + const touchHandler = (event) => { + if (event.touches.length > 0) { + const result = extractor(event.touches[0]); + if (result) { + [x.value, y.value] = result; + sourceType.value = "touch"; + } + } + }; + const scrollHandler = () => { + if (!_prevMouseEvent || !window2) + return; + const pos = extractor(_prevMouseEvent); + if (_prevMouseEvent instanceof MouseEvent && pos) { + x.value = pos[0] + window2.scrollX - _prevScrollX; + y.value = pos[1] + window2.scrollY - _prevScrollY; + } + }; + const reset = () => { + x.value = initialValue.x; + y.value = initialValue.y; + }; + const mouseHandlerWrapper = eventFilter ? (event) => eventFilter(() => mouseHandler(event), {}) : (event) => mouseHandler(event); + const touchHandlerWrapper = eventFilter ? (event) => eventFilter(() => touchHandler(event), {}) : (event) => touchHandler(event); + const scrollHandlerWrapper = eventFilter ? () => eventFilter(() => scrollHandler(), {}) : () => scrollHandler(); + if (target) { + const listenerOptions = { passive: true }; + useEventListener(target, ["mousemove", "dragover"], mouseHandlerWrapper, listenerOptions); + if (touch && type !== "movement") { + useEventListener(target, ["touchstart", "touchmove"], touchHandlerWrapper, listenerOptions); + if (resetOnTouchEnds) + useEventListener(target, "touchend", reset, listenerOptions); + } + if (scroll && type === "page") + useEventListener(window2, "scroll", scrollHandlerWrapper, listenerOptions); + } + return { + x, + y, + sourceType + }; +} +function useMouseInElement(target, options = {}) { + const { + handleOutside = true, + window: window2 = defaultWindow + } = options; + const type = options.type || "page"; + const { x, y, sourceType } = useMouse(options); + const targetRef = shallowRef(target != null ? target : window2 == null ? void 0 : window2.document.body); + const elementX = shallowRef(0); + const elementY = shallowRef(0); + const elementPositionX = shallowRef(0); + const elementPositionY = shallowRef(0); + const elementHeight = shallowRef(0); + const elementWidth = shallowRef(0); + const isOutside = shallowRef(true); + let stop = () => { + }; + if (window2) { + stop = watch( + [targetRef, x, y], + () => { + const el = unrefElement(targetRef); + if (!el || !(el instanceof Element)) + return; + const { + left, + top, + width, + height + } = el.getBoundingClientRect(); + elementPositionX.value = left + (type === "page" ? window2.pageXOffset : 0); + elementPositionY.value = top + (type === "page" ? window2.pageYOffset : 0); + elementHeight.value = height; + elementWidth.value = width; + const elX = x.value - elementPositionX.value; + const elY = y.value - elementPositionY.value; + isOutside.value = width === 0 || height === 0 || elX < 0 || elY < 0 || elX > width || elY > height; + if (handleOutside || !isOutside.value) { + elementX.value = elX; + elementY.value = elY; + } + }, + { immediate: true } + ); + useEventListener( + document, + "mouseleave", + () => isOutside.value = true, + { passive: true } + ); + } + return { + x, + y, + sourceType, + elementX, + elementY, + elementPositionX, + elementPositionY, + elementHeight, + elementWidth, + isOutside, + stop + }; +} +function useMousePressed(options = {}) { + const { + touch = true, + drag = true, + capture = false, + initialValue = false, + window: window2 = defaultWindow + } = options; + const pressed = shallowRef(initialValue); + const sourceType = shallowRef(null); + if (!window2) { + return { + pressed, + sourceType + }; + } + const onPressed = (srcType) => (event) => { + var _a; + pressed.value = true; + sourceType.value = srcType; + (_a = options.onPressed) == null ? void 0 : _a.call(options, event); + }; + const onReleased = (event) => { + var _a; + pressed.value = false; + sourceType.value = null; + (_a = options.onReleased) == null ? void 0 : _a.call(options, event); + }; + const target = computed(() => unrefElement(options.target) || window2); + const listenerOptions = { passive: true, capture }; + useEventListener(target, "mousedown", onPressed("mouse"), listenerOptions); + useEventListener(window2, "mouseleave", onReleased, listenerOptions); + useEventListener(window2, "mouseup", onReleased, listenerOptions); + if (drag) { + useEventListener(target, "dragstart", onPressed("mouse"), listenerOptions); + useEventListener(window2, "drop", onReleased, listenerOptions); + useEventListener(window2, "dragend", onReleased, listenerOptions); + } + if (touch) { + useEventListener(target, "touchstart", onPressed("touch"), listenerOptions); + useEventListener(window2, "touchend", onReleased, listenerOptions); + useEventListener(window2, "touchcancel", onReleased, listenerOptions); + } + return { + pressed, + sourceType + }; +} +function useNavigatorLanguage(options = {}) { + const { window: window2 = defaultWindow } = options; + const navigator2 = window2 == null ? void 0 : window2.navigator; + const isSupported = useSupported(() => navigator2 && "language" in navigator2); + const language = shallowRef(navigator2 == null ? void 0 : navigator2.language); + useEventListener(window2, "languagechange", () => { + if (navigator2) + language.value = navigator2.language; + }, { passive: true }); + return { + isSupported, + language + }; +} +function useNetwork(options = {}) { + const { window: window2 = defaultWindow } = options; + const navigator2 = window2 == null ? void 0 : window2.navigator; + const isSupported = useSupported(() => navigator2 && "connection" in navigator2); + const isOnline = shallowRef(true); + const saveData = shallowRef(false); + const offlineAt = shallowRef(void 0); + const onlineAt = shallowRef(void 0); + const downlink = shallowRef(void 0); + const downlinkMax = shallowRef(void 0); + const rtt = shallowRef(void 0); + const effectiveType = shallowRef(void 0); + const type = shallowRef("unknown"); + const connection = isSupported.value && navigator2.connection; + function updateNetworkInformation() { + if (!navigator2) + return; + isOnline.value = navigator2.onLine; + offlineAt.value = isOnline.value ? void 0 : Date.now(); + onlineAt.value = isOnline.value ? Date.now() : void 0; + if (connection) { + downlink.value = connection.downlink; + downlinkMax.value = connection.downlinkMax; + effectiveType.value = connection.effectiveType; + rtt.value = connection.rtt; + saveData.value = connection.saveData; + type.value = connection.type; + } + } + const listenerOptions = { passive: true }; + if (window2) { + useEventListener(window2, "offline", () => { + isOnline.value = false; + offlineAt.value = Date.now(); + }, listenerOptions); + useEventListener(window2, "online", () => { + isOnline.value = true; + onlineAt.value = Date.now(); + }, listenerOptions); + } + if (connection) + useEventListener(connection, "change", updateNetworkInformation, listenerOptions); + updateNetworkInformation(); + return { + isSupported, + isOnline: readonly(isOnline), + saveData: readonly(saveData), + offlineAt: readonly(offlineAt), + onlineAt: readonly(onlineAt), + downlink: readonly(downlink), + downlinkMax: readonly(downlinkMax), + effectiveType: readonly(effectiveType), + rtt: readonly(rtt), + type: readonly(type) + }; +} +function useNow(options = {}) { + const { + controls: exposeControls = false, + interval = "requestAnimationFrame" + } = options; + const now = ref(/* @__PURE__ */ new Date()); + const update = () => now.value = /* @__PURE__ */ new Date(); + const controls = interval === "requestAnimationFrame" ? useRafFn(update, { immediate: true }) : useIntervalFn(update, interval, { immediate: true }); + if (exposeControls) { + return { + now, + ...controls + }; + } else { + return now; + } +} +function useObjectUrl(object) { + const url = shallowRef(); + const release = () => { + if (url.value) + URL.revokeObjectURL(url.value); + url.value = void 0; + }; + watch( + () => toValue$1(object), + (newObject) => { + release(); + if (newObject) + url.value = URL.createObjectURL(newObject); + }, + { immediate: true } + ); + tryOnScopeDispose(release); + return readonly(url); +} +function useClamp(value, min, max) { + if (typeof value === "function" || isReadonly(value)) + return computed(() => clamp(toValue$1(value), toValue$1(min), toValue$1(max))); + const _value = ref(value); + return computed({ + get() { + return _value.value = clamp(_value.value, toValue$1(min), toValue$1(max)); + }, + set(value2) { + _value.value = clamp(value2, toValue$1(min), toValue$1(max)); + } + }); +} +function useOffsetPagination(options) { + const { + total = Number.POSITIVE_INFINITY, + pageSize = 10, + page = 1, + onPageChange = noop$3, + onPageSizeChange = noop$3, + onPageCountChange = noop$3 + } = options; + const currentPageSize = useClamp(pageSize, 1, Number.POSITIVE_INFINITY); + const pageCount = computed(() => Math.max( + 1, + Math.ceil(toValue$1(total) / toValue$1(currentPageSize)) + )); + const currentPage = useClamp(page, 1, pageCount); + const isFirstPage = computed(() => currentPage.value === 1); + const isLastPage = computed(() => currentPage.value === pageCount.value); + if (isRef(page)) { + syncRef(page, currentPage, { + direction: isReadonly(page) ? "ltr" : "both" + }); + } + if (isRef(pageSize)) { + syncRef(pageSize, currentPageSize, { + direction: isReadonly(pageSize) ? "ltr" : "both" + }); + } + function prev() { + currentPage.value--; + } + function next() { + currentPage.value++; + } + const returnValue = { + currentPage, + currentPageSize, + pageCount, + isFirstPage, + isLastPage, + prev, + next + }; + watch(currentPage, () => { + onPageChange(reactive(returnValue)); + }); + watch(currentPageSize, () => { + onPageSizeChange(reactive(returnValue)); + }); + watch(pageCount, () => { + onPageCountChange(reactive(returnValue)); + }); + return returnValue; +} +function useOnline(options = {}) { + const { isOnline } = useNetwork(options); + return isOnline; +} +function usePageLeave(options = {}) { + const { window: window2 = defaultWindow } = options; + const isLeft = shallowRef(false); + const handler = (event) => { + if (!window2) + return; + event = event || window2.event; + const from = event.relatedTarget || event.toElement; + isLeft.value = !from; + }; + if (window2) { + const listenerOptions = { passive: true }; + useEventListener(window2, "mouseout", handler, listenerOptions); + useEventListener(window2.document, "mouseleave", handler, listenerOptions); + useEventListener(window2.document, "mouseenter", handler, listenerOptions); + } + return isLeft; +} +function useScreenOrientation(options = {}) { + const { + window: window2 = defaultWindow + } = options; + const isSupported = useSupported(() => window2 && "screen" in window2 && "orientation" in window2.screen); + const screenOrientation = isSupported.value ? window2.screen.orientation : {}; + const orientation = ref(screenOrientation.type); + const angle = shallowRef(screenOrientation.angle || 0); + if (isSupported.value) { + useEventListener(window2, "orientationchange", () => { + orientation.value = screenOrientation.type; + angle.value = screenOrientation.angle; + }, { passive: true }); + } + const lockOrientation = (type) => { + if (isSupported.value && typeof screenOrientation.lock === "function") + return screenOrientation.lock(type); + return Promise.reject(new Error("Not supported")); + }; + const unlockOrientation = () => { + if (isSupported.value && typeof screenOrientation.unlock === "function") + screenOrientation.unlock(); + }; + return { + isSupported, + orientation, + angle, + lockOrientation, + unlockOrientation + }; +} +function useParallax(target, options = {}) { + const { + deviceOrientationTiltAdjust = (i) => i, + deviceOrientationRollAdjust = (i) => i, + mouseTiltAdjust = (i) => i, + mouseRollAdjust = (i) => i, + window: window2 = defaultWindow + } = options; + const orientation = reactive(useDeviceOrientation({ window: window2 })); + const screenOrientation = reactive(useScreenOrientation({ window: window2 })); + const { + elementX: x, + elementY: y, + elementWidth: width, + elementHeight: height + } = useMouseInElement(target, { handleOutside: false, window: window2 }); + const source = computed(() => { + if (orientation.isSupported && (orientation.alpha != null && orientation.alpha !== 0 || orientation.gamma != null && orientation.gamma !== 0)) { + return "deviceOrientation"; + } + return "mouse"; + }); + const roll = computed(() => { + if (source.value === "deviceOrientation") { + let value; + switch (screenOrientation.orientation) { + case "landscape-primary": + value = orientation.gamma / 90; + break; + case "landscape-secondary": + value = -orientation.gamma / 90; + break; + case "portrait-primary": + value = -orientation.beta / 90; + break; + case "portrait-secondary": + value = orientation.beta / 90; + break; + default: + value = -orientation.beta / 90; + } + return deviceOrientationRollAdjust(value); + } else { + const value = -(y.value - height.value / 2) / height.value; + return mouseRollAdjust(value); + } + }); + const tilt = computed(() => { + if (source.value === "deviceOrientation") { + let value; + switch (screenOrientation.orientation) { + case "landscape-primary": + value = orientation.beta / 90; + break; + case "landscape-secondary": + value = -orientation.beta / 90; + break; + case "portrait-primary": + value = orientation.gamma / 90; + break; + case "portrait-secondary": + value = -orientation.gamma / 90; + break; + default: + value = orientation.gamma / 90; + } + return deviceOrientationTiltAdjust(value); + } else { + const value = (x.value - width.value / 2) / width.value; + return mouseTiltAdjust(value); + } + }); + return { roll, tilt, source }; +} +function useParentElement(element = useCurrentElement()) { + const parentElement = shallowRef(); + const update = () => { + const el = unrefElement(element); + if (el) + parentElement.value = el.parentElement; + }; + tryOnMounted(update); + watch(() => toValue$1(element), update); + return parentElement; +} +function usePerformanceObserver(options, callback) { + const { + window: window2 = defaultWindow, + immediate = true, + ...performanceOptions + } = options; + const isSupported = useSupported(() => window2 && "PerformanceObserver" in window2); + let observer; + const stop = () => { + observer == null ? void 0 : observer.disconnect(); + }; + const start = () => { + if (isSupported.value) { + stop(); + observer = new PerformanceObserver(callback); + observer.observe(performanceOptions); + } + }; + tryOnScopeDispose(stop); + if (immediate) + start(); + return { + isSupported, + start, + stop + }; +} +const defaultState = { + x: 0, + y: 0, + pointerId: 0, + pressure: 0, + tiltX: 0, + tiltY: 0, + width: 0, + height: 0, + twist: 0, + pointerType: null +}; +const keys$1 = /* @__PURE__ */ Object.keys(defaultState); +function usePointer(options = {}) { + const { + target = defaultWindow + } = options; + const isInside = shallowRef(false); + const state = ref(options.initialValue || {}); + Object.assign(state.value, defaultState, state.value); + const handler = (event) => { + isInside.value = true; + if (options.pointerTypes && !options.pointerTypes.includes(event.pointerType)) + return; + state.value = objectPick(event, keys$1, false); + }; + if (target) { + const listenerOptions = { passive: true }; + useEventListener(target, ["pointerdown", "pointermove", "pointerup"], handler, listenerOptions); + useEventListener(target, "pointerleave", () => isInside.value = false, listenerOptions); + } + return { + ...toRefs(state), + isInside + }; +} +function usePointerLock(target, options = {}) { + const { document: document2 = defaultDocument } = options; + const isSupported = useSupported(() => document2 && "pointerLockElement" in document2); + const element = shallowRef(); + const triggerElement = shallowRef(); + let targetElement; + if (isSupported.value) { + const listenerOptions = { passive: true }; + useEventListener(document2, "pointerlockchange", () => { + var _a; + const currentElement = (_a = document2.pointerLockElement) != null ? _a : element.value; + if (targetElement && currentElement === targetElement) { + element.value = document2.pointerLockElement; + if (!element.value) + targetElement = triggerElement.value = null; + } + }, listenerOptions); + useEventListener(document2, "pointerlockerror", () => { + var _a; + const currentElement = (_a = document2.pointerLockElement) != null ? _a : element.value; + if (targetElement && currentElement === targetElement) { + const action = document2.pointerLockElement ? "release" : "acquire"; + throw new Error(`Failed to ${action} pointer lock.`); + } + }, listenerOptions); + } + async function lock(e) { + var _a; + if (!isSupported.value) + throw new Error("Pointer Lock API is not supported by your browser."); + triggerElement.value = e instanceof Event ? e.currentTarget : null; + targetElement = e instanceof Event ? (_a = unrefElement(target)) != null ? _a : triggerElement.value : unrefElement(e); + if (!targetElement) + throw new Error("Target element undefined."); + targetElement.requestPointerLock(); + return await until(element).toBe(targetElement); + } + async function unlock() { + if (!element.value) + return false; + document2.exitPointerLock(); + await until(element).toBeNull(); + return true; + } + return { + isSupported, + element, + triggerElement, + lock, + unlock + }; +} +function usePointerSwipe(target, options = {}) { + const targetRef = toRef(target); + const { + threshold = 50, + onSwipe, + onSwipeEnd, + onSwipeStart, + disableTextSelect = false + } = options; + const posStart = reactive({ x: 0, y: 0 }); + const updatePosStart = (x, y) => { + posStart.x = x; + posStart.y = y; + }; + const posEnd = reactive({ x: 0, y: 0 }); + const updatePosEnd = (x, y) => { + posEnd.x = x; + posEnd.y = y; + }; + const distanceX = computed(() => posStart.x - posEnd.x); + const distanceY = computed(() => posStart.y - posEnd.y); + const { max, abs } = Math; + const isThresholdExceeded = computed(() => max(abs(distanceX.value), abs(distanceY.value)) >= threshold); + const isSwiping = shallowRef(false); + const isPointerDown = shallowRef(false); + const direction = computed(() => { + if (!isThresholdExceeded.value) + return "none"; + if (abs(distanceX.value) > abs(distanceY.value)) { + return distanceX.value > 0 ? "left" : "right"; + } else { + return distanceY.value > 0 ? "up" : "down"; + } + }); + const eventIsAllowed = (e) => { + var _a, _b, _c; + const isReleasingButton = e.buttons === 0; + const isPrimaryButton = e.buttons === 1; + return (_c = (_b = (_a = options.pointerTypes) == null ? void 0 : _a.includes(e.pointerType)) != null ? _b : isReleasingButton || isPrimaryButton) != null ? _c : true; + }; + const listenerOptions = { passive: true }; + const stops = [ + useEventListener(target, "pointerdown", (e) => { + if (!eventIsAllowed(e)) + return; + isPointerDown.value = true; + const eventTarget = e.target; + eventTarget == null ? void 0 : eventTarget.setPointerCapture(e.pointerId); + const { clientX: x, clientY: y } = e; + updatePosStart(x, y); + updatePosEnd(x, y); + onSwipeStart == null ? void 0 : onSwipeStart(e); + }, listenerOptions), + useEventListener(target, "pointermove", (e) => { + if (!eventIsAllowed(e)) + return; + if (!isPointerDown.value) + return; + const { clientX: x, clientY: y } = e; + updatePosEnd(x, y); + if (!isSwiping.value && isThresholdExceeded.value) + isSwiping.value = true; + if (isSwiping.value) + onSwipe == null ? void 0 : onSwipe(e); + }, listenerOptions), + useEventListener(target, "pointerup", (e) => { + if (!eventIsAllowed(e)) + return; + if (isSwiping.value) + onSwipeEnd == null ? void 0 : onSwipeEnd(e, direction.value); + isPointerDown.value = false; + isSwiping.value = false; + }, listenerOptions) + ]; + tryOnMounted(() => { + var _a, _b, _c, _d, _e, _f, _g, _h; + (_b = (_a = targetRef.value) == null ? void 0 : _a.style) == null ? void 0 : _b.setProperty("touch-action", "none"); + if (disableTextSelect) { + (_d = (_c = targetRef.value) == null ? void 0 : _c.style) == null ? void 0 : _d.setProperty("-webkit-user-select", "none"); + (_f = (_e = targetRef.value) == null ? void 0 : _e.style) == null ? void 0 : _f.setProperty("-ms-user-select", "none"); + (_h = (_g = targetRef.value) == null ? void 0 : _g.style) == null ? void 0 : _h.setProperty("user-select", "none"); + } + }); + const stop = () => stops.forEach((s) => s()); + return { + isSwiping: readonly(isSwiping), + direction: readonly(direction), + posStart: readonly(posStart), + posEnd: readonly(posEnd), + distanceX, + distanceY, + stop + }; +} +function usePreferredColorScheme(options) { + const isLight = useMediaQuery("(prefers-color-scheme: light)", options); + const isDark = useMediaQuery("(prefers-color-scheme: dark)", options); + return computed(() => { + if (isDark.value) + return "dark"; + if (isLight.value) + return "light"; + return "no-preference"; + }); +} +function usePreferredContrast(options) { + const isMore = useMediaQuery("(prefers-contrast: more)", options); + const isLess = useMediaQuery("(prefers-contrast: less)", options); + const isCustom = useMediaQuery("(prefers-contrast: custom)", options); + return computed(() => { + if (isMore.value) + return "more"; + if (isLess.value) + return "less"; + if (isCustom.value) + return "custom"; + return "no-preference"; + }); +} +function usePreferredLanguages(options = {}) { + const { window: window2 = defaultWindow } = options; + if (!window2) + return ref(["en"]); + const navigator2 = window2.navigator; + const value = ref(navigator2.languages); + useEventListener(window2, "languagechange", () => { + value.value = navigator2.languages; + }, { passive: true }); + return value; +} +function usePreferredReducedMotion(options) { + const isReduced = useMediaQuery("(prefers-reduced-motion: reduce)", options); + return computed(() => { + if (isReduced.value) + return "reduce"; + return "no-preference"; + }); +} +function usePreferredReducedTransparency(options) { + const isReduced = useMediaQuery("(prefers-reduced-transparency: reduce)", options); + return computed(() => { + if (isReduced.value) + return "reduce"; + return "no-preference"; + }); +} +function usePrevious(value, initialValue) { + const previous = shallowRef(initialValue); + watch( + toRef(value), + (_, oldValue) => { + previous.value = oldValue; + }, + { flush: "sync" } + ); + return readonly(previous); +} +const topVarName = "--vueuse-safe-area-top"; +const rightVarName = "--vueuse-safe-area-right"; +const bottomVarName = "--vueuse-safe-area-bottom"; +const leftVarName = "--vueuse-safe-area-left"; +function useScreenSafeArea() { + const top = shallowRef(""); + const right = shallowRef(""); + const bottom = shallowRef(""); + const left = shallowRef(""); + if (isClient) { + const topCssVar = useCssVar(topVarName); + const rightCssVar = useCssVar(rightVarName); + const bottomCssVar = useCssVar(bottomVarName); + const leftCssVar = useCssVar(leftVarName); + topCssVar.value = "env(safe-area-inset-top, 0px)"; + rightCssVar.value = "env(safe-area-inset-right, 0px)"; + bottomCssVar.value = "env(safe-area-inset-bottom, 0px)"; + leftCssVar.value = "env(safe-area-inset-left, 0px)"; + update(); + useEventListener("resize", useDebounceFn(update), { passive: true }); + } + function update() { + top.value = getValue(topVarName); + right.value = getValue(rightVarName); + bottom.value = getValue(bottomVarName); + left.value = getValue(leftVarName); + } + return { + top, + right, + bottom, + left, + update + }; +} +function getValue(position) { + return getComputedStyle(document.documentElement).getPropertyValue(position); +} +function useScriptTag(src, onLoaded = noop$3, options = {}) { + const { + immediate = true, + manual = false, + type = "text/javascript", + async = true, + crossOrigin, + referrerPolicy, + noModule, + defer, + document: document2 = defaultDocument, + attrs = {} + } = options; + const scriptTag = shallowRef(null); + let _promise = null; + const loadScript = (waitForScriptLoad) => new Promise((resolve, reject) => { + const resolveWithElement = (el2) => { + scriptTag.value = el2; + resolve(el2); + return el2; + }; + if (!document2) { + resolve(false); + return; + } + let shouldAppend = false; + let el = document2.querySelector(`script[src="${toValue$1(src)}"]`); + if (!el) { + el = document2.createElement("script"); + el.type = type; + el.async = async; + el.src = toValue$1(src); + if (defer) + el.defer = defer; + if (crossOrigin) + el.crossOrigin = crossOrigin; + if (noModule) + el.noModule = noModule; + if (referrerPolicy) + el.referrerPolicy = referrerPolicy; + Object.entries(attrs).forEach(([name, value]) => el == null ? void 0 : el.setAttribute(name, value)); + shouldAppend = true; + } else if (el.hasAttribute("data-loaded")) { + resolveWithElement(el); + } + const listenerOptions = { + passive: true + }; + useEventListener(el, "error", (event) => reject(event), listenerOptions); + useEventListener(el, "abort", (event) => reject(event), listenerOptions); + useEventListener(el, "load", () => { + el.setAttribute("data-loaded", "true"); + onLoaded(el); + resolveWithElement(el); + }, listenerOptions); + if (shouldAppend) + el = document2.head.appendChild(el); + if (!waitForScriptLoad) + resolveWithElement(el); + }); + const load = (waitForScriptLoad = true) => { + if (!_promise) + _promise = loadScript(waitForScriptLoad); + return _promise; + }; + const unload = () => { + if (!document2) + return; + _promise = null; + if (scriptTag.value) + scriptTag.value = null; + const el = document2.querySelector(`script[src="${toValue$1(src)}"]`); + if (el) + document2.head.removeChild(el); + }; + if (immediate && !manual) + tryOnMounted(load); + if (!manual) + tryOnUnmounted(unload); + return { scriptTag, load, unload }; +} +function checkOverflowScroll(ele) { + const style = window.getComputedStyle(ele); + if (style.overflowX === "scroll" || style.overflowY === "scroll" || style.overflowX === "auto" && ele.clientWidth < ele.scrollWidth || style.overflowY === "auto" && ele.clientHeight < ele.scrollHeight) { + return true; + } else { + const parent = ele.parentNode; + if (!parent || parent.tagName === "BODY") + return false; + return checkOverflowScroll(parent); + } +} +function preventDefault(rawEvent) { + const e = rawEvent || window.event; + const _target = e.target; + if (checkOverflowScroll(_target)) + return false; + if (e.touches.length > 1) + return true; + if (e.preventDefault) + e.preventDefault(); + return false; +} +const elInitialOverflow = /* @__PURE__ */ new WeakMap(); +function useScrollLock(element, initialState = false) { + const isLocked = shallowRef(initialState); + let stopTouchMoveListener = null; + let initialOverflow = ""; + watch(toRef(element), (el) => { + const target = resolveElement(toValue$1(el)); + if (target) { + const ele = target; + if (!elInitialOverflow.get(ele)) + elInitialOverflow.set(ele, ele.style.overflow); + if (ele.style.overflow !== "hidden") + initialOverflow = ele.style.overflow; + if (ele.style.overflow === "hidden") + return isLocked.value = true; + if (isLocked.value) + return ele.style.overflow = "hidden"; + } + }, { + immediate: true + }); + const lock = () => { + const el = resolveElement(toValue$1(element)); + if (!el || isLocked.value) + return; + if (isIOS) { + stopTouchMoveListener = useEventListener( + el, + "touchmove", + (e) => { + preventDefault(e); + }, + { passive: false } + ); + } + el.style.overflow = "hidden"; + isLocked.value = true; + }; + const unlock = () => { + const el = resolveElement(toValue$1(element)); + if (!el || !isLocked.value) + return; + if (isIOS) + stopTouchMoveListener == null ? void 0 : stopTouchMoveListener(); + el.style.overflow = initialOverflow; + elInitialOverflow.delete(el); + isLocked.value = false; + }; + tryOnScopeDispose(unlock); + return computed({ + get() { + return isLocked.value; + }, + set(v) { + if (v) + lock(); + else unlock(); + } + }); +} +function useSessionStorage(key, initialValue, options = {}) { + const { window: window2 = defaultWindow } = options; + return useStorage(key, initialValue, window2 == null ? void 0 : window2.sessionStorage, options); +} +function useShare(shareOptions = {}, options = {}) { + const { navigator: navigator2 = defaultNavigator } = options; + const _navigator = navigator2; + const isSupported = useSupported(() => _navigator && "canShare" in _navigator); + const share = async (overrideOptions = {}) => { + if (isSupported.value) { + const data = { + ...toValue$1(shareOptions), + ...toValue$1(overrideOptions) + }; + let granted = true; + if (data.files && _navigator.canShare) + granted = _navigator.canShare({ files: data.files }); + if (granted) + return _navigator.share(data); + } + }; + return { + isSupported, + share + }; +} +const defaultSortFn = (source, compareFn) => source.sort(compareFn); +const defaultCompare = (a, b) => a - b; +function useSorted(...args) { + var _a, _b, _c, _d; + const [source] = args; + let compareFn = defaultCompare; + let options = {}; + if (args.length === 2) { + if (typeof args[1] === "object") { + options = args[1]; + compareFn = (_a = options.compareFn) != null ? _a : defaultCompare; + } else { + compareFn = (_b = args[1]) != null ? _b : defaultCompare; + } + } else if (args.length > 2) { + compareFn = (_c = args[1]) != null ? _c : defaultCompare; + options = (_d = args[2]) != null ? _d : {}; + } + const { + dirty = false, + sortFn = defaultSortFn + } = options; + if (!dirty) + return computed(() => sortFn([...toValue$1(source)], compareFn)); + watchEffect(() => { + const result = sortFn(toValue$1(source), compareFn); + if (isRef(source)) + source.value = result; + else + source.splice(0, source.length, ...result); + }); + return source; +} +function useSpeechRecognition(options = {}) { + const { + interimResults = true, + continuous = true, + maxAlternatives = 1, + window: window2 = defaultWindow + } = options; + const lang = toRef(options.lang || "en-US"); + const isListening = shallowRef(false); + const isFinal = shallowRef(false); + const result = shallowRef(""); + const error = shallowRef(void 0); + let recognition; + const start = () => { + isListening.value = true; + }; + const stop = () => { + isListening.value = false; + }; + const toggle = (value = !isListening.value) => { + if (value) { + start(); + } else { + stop(); + } + }; + const SpeechRecognition = window2 && (window2.SpeechRecognition || window2.webkitSpeechRecognition); + const isSupported = useSupported(() => SpeechRecognition); + if (isSupported.value) { + recognition = new SpeechRecognition(); + recognition.continuous = continuous; + recognition.interimResults = interimResults; + recognition.lang = toValue$1(lang); + recognition.maxAlternatives = maxAlternatives; + recognition.onstart = () => { + isListening.value = true; + isFinal.value = false; + }; + watch(lang, (lang2) => { + if (recognition && !isListening.value) + recognition.lang = lang2; + }); + recognition.onresult = (event) => { + const currentResult = event.results[event.resultIndex]; + const { transcript } = currentResult[0]; + isFinal.value = currentResult.isFinal; + result.value = transcript; + error.value = void 0; + }; + recognition.onerror = (event) => { + error.value = event; + }; + recognition.onend = () => { + isListening.value = false; + recognition.lang = toValue$1(lang); + }; + watch(isListening, (newValue, oldValue) => { + if (newValue === oldValue) + return; + if (newValue) + recognition.start(); + else + recognition.stop(); + }); + } + tryOnScopeDispose(() => { + stop(); + }); + return { + isSupported, + isListening, + isFinal, + recognition, + result, + error, + toggle, + start, + stop + }; +} +function useSpeechSynthesis(text, options = {}) { + const { + pitch = 1, + rate = 1, + volume = 1, + window: window2 = defaultWindow + } = options; + const synth = window2 && window2.speechSynthesis; + const isSupported = useSupported(() => synth); + const isPlaying = shallowRef(false); + const status = shallowRef("init"); + const spokenText = toRef(text || ""); + const lang = toRef(options.lang || "en-US"); + const error = shallowRef(void 0); + const toggle = (value = !isPlaying.value) => { + isPlaying.value = value; + }; + const bindEventsForUtterance = (utterance2) => { + utterance2.lang = toValue$1(lang); + utterance2.voice = toValue$1(options.voice) || null; + utterance2.pitch = toValue$1(pitch); + utterance2.rate = toValue$1(rate); + utterance2.volume = volume; + utterance2.onstart = () => { + isPlaying.value = true; + status.value = "play"; + }; + utterance2.onpause = () => { + isPlaying.value = false; + status.value = "pause"; + }; + utterance2.onresume = () => { + isPlaying.value = true; + status.value = "play"; + }; + utterance2.onend = () => { + isPlaying.value = false; + status.value = "end"; + }; + utterance2.onerror = (event) => { + error.value = event; + }; + }; + const utterance = computed(() => { + isPlaying.value = false; + status.value = "init"; + const newUtterance = new SpeechSynthesisUtterance(spokenText.value); + bindEventsForUtterance(newUtterance); + return newUtterance; + }); + const speak = () => { + synth.cancel(); + if (utterance) + synth.speak(utterance.value); + }; + const stop = () => { + synth.cancel(); + isPlaying.value = false; + }; + if (isSupported.value) { + bindEventsForUtterance(utterance.value); + watch(lang, (lang2) => { + if (utterance.value && !isPlaying.value) + utterance.value.lang = lang2; + }); + if (options.voice) { + watch(options.voice, () => { + synth.cancel(); + }); + } + watch(isPlaying, () => { + if (isPlaying.value) + synth.resume(); + else + synth.pause(); + }); + } + tryOnScopeDispose(() => { + isPlaying.value = false; + }); + return { + isSupported, + isPlaying, + status, + utterance, + error, + stop, + toggle, + speak + }; +} +function useStepper(steps, initialStep) { + const stepsRef = ref(steps); + const stepNames = computed(() => Array.isArray(stepsRef.value) ? stepsRef.value : Object.keys(stepsRef.value)); + const index = ref(stepNames.value.indexOf(initialStep != null ? initialStep : stepNames.value[0])); + const current = computed(() => at(index.value)); + const isFirst = computed(() => index.value === 0); + const isLast = computed(() => index.value === stepNames.value.length - 1); + const next = computed(() => stepNames.value[index.value + 1]); + const previous = computed(() => stepNames.value[index.value - 1]); + function at(index2) { + if (Array.isArray(stepsRef.value)) + return stepsRef.value[index2]; + return stepsRef.value[stepNames.value[index2]]; + } + function get(step) { + if (!stepNames.value.includes(step)) + return; + return at(stepNames.value.indexOf(step)); + } + function goTo(step) { + if (stepNames.value.includes(step)) + index.value = stepNames.value.indexOf(step); + } + function goToNext() { + if (isLast.value) + return; + index.value++; + } + function goToPrevious() { + if (isFirst.value) + return; + index.value--; + } + function goBackTo(step) { + if (isAfter(step)) + goTo(step); + } + function isNext(step) { + return stepNames.value.indexOf(step) === index.value + 1; + } + function isPrevious(step) { + return stepNames.value.indexOf(step) === index.value - 1; + } + function isCurrent(step) { + return stepNames.value.indexOf(step) === index.value; + } + function isBefore(step) { + return index.value < stepNames.value.indexOf(step); + } + function isAfter(step) { + return index.value > stepNames.value.indexOf(step); + } + return { + steps: stepsRef, + stepNames, + index, + current, + next, + previous, + isFirst, + isLast, + at, + get, + goTo, + goToNext, + goToPrevious, + goBackTo, + isNext, + isPrevious, + isCurrent, + isBefore, + isAfter + }; +} +function useStorageAsync(key, initialValue, storage, options = {}) { + var _a; + const { + flush = "pre", + deep = true, + listenToStorageChanges = true, + writeDefaults = true, + mergeDefaults = false, + shallow, + window: window2 = defaultWindow, + eventFilter, + onError = (e) => { + console.error(e); + } + } = options; + const rawInit = toValue$1(initialValue); + const type = guessSerializerType(rawInit); + const data = (shallow ? shallowRef : ref)(toValue$1(initialValue)); + const serializer = (_a = options.serializer) != null ? _a : StorageSerializers[type]; + if (!storage) { + try { + storage = getSSRHandler("getDefaultStorageAsync", () => { + var _a2; + return (_a2 = defaultWindow) == null ? void 0 : _a2.localStorage; + })(); + } catch (e) { + onError(e); + } + } + async function read(event) { + if (!storage || event && event.key !== key) + return; + try { + const rawValue = event ? event.newValue : await storage.getItem(key); + if (rawValue == null) { + data.value = rawInit; + if (writeDefaults && rawInit !== null) + await storage.setItem(key, await serializer.write(rawInit)); + } else if (mergeDefaults) { + const value = await serializer.read(rawValue); + if (typeof mergeDefaults === "function") + data.value = mergeDefaults(value, rawInit); + else if (type === "object" && !Array.isArray(value)) + data.value = { ...rawInit, ...value }; + else data.value = value; + } else { + data.value = await serializer.read(rawValue); + } + } catch (e) { + onError(e); + } + } + read(); + if (window2 && listenToStorageChanges) + useEventListener(window2, "storage", (e) => Promise.resolve().then(() => read(e)), { passive: true }); + if (storage) { + watchWithFilter( + data, + async () => { + try { + if (data.value == null) + await storage.removeItem(key); + else + await storage.setItem(key, await serializer.write(data.value)); + } catch (e) { + onError(e); + } + }, + { + flush, + deep, + eventFilter + } + ); + } + return data; +} +let _id = 0; +function useStyleTag(css, options = {}) { + const isLoaded = shallowRef(false); + const { + document: document2 = defaultDocument, + immediate = true, + manual = false, + id = `vueuse_styletag_${++_id}` + } = options; + const cssRef = shallowRef(css); + let stop = () => { + }; + const load = () => { + if (!document2) + return; + const el = document2.getElementById(id) || document2.createElement("style"); + if (!el.isConnected) { + el.id = id; + if (options.media) + el.media = options.media; + document2.head.appendChild(el); + } + if (isLoaded.value) + return; + stop = watch( + cssRef, + (value) => { + el.textContent = value; + }, + { immediate: true } + ); + isLoaded.value = true; + }; + const unload = () => { + if (!document2 || !isLoaded.value) + return; + stop(); + document2.head.removeChild(document2.getElementById(id)); + isLoaded.value = false; + }; + if (immediate && !manual) + tryOnMounted(load); + if (!manual) + tryOnScopeDispose(unload); + return { + id, + css: cssRef, + unload, + load, + isLoaded: readonly(isLoaded) + }; +} +function useSwipe(target, options = {}) { + const { + threshold = 50, + onSwipe, + onSwipeEnd, + onSwipeStart, + passive = true + } = options; + const coordsStart = reactive({ x: 0, y: 0 }); + const coordsEnd = reactive({ x: 0, y: 0 }); + const diffX = computed(() => coordsStart.x - coordsEnd.x); + const diffY = computed(() => coordsStart.y - coordsEnd.y); + const { max, abs } = Math; + const isThresholdExceeded = computed(() => max(abs(diffX.value), abs(diffY.value)) >= threshold); + const isSwiping = shallowRef(false); + const direction = computed(() => { + if (!isThresholdExceeded.value) + return "none"; + if (abs(diffX.value) > abs(diffY.value)) { + return diffX.value > 0 ? "left" : "right"; + } else { + return diffY.value > 0 ? "up" : "down"; + } + }); + const getTouchEventCoords = (e) => [e.touches[0].clientX, e.touches[0].clientY]; + const updateCoordsStart = (x, y) => { + coordsStart.x = x; + coordsStart.y = y; + }; + const updateCoordsEnd = (x, y) => { + coordsEnd.x = x; + coordsEnd.y = y; + }; + const listenerOptions = { passive, capture: !passive }; + const onTouchEnd = (e) => { + if (isSwiping.value) + onSwipeEnd == null ? void 0 : onSwipeEnd(e, direction.value); + isSwiping.value = false; + }; + const stops = [ + useEventListener(target, "touchstart", (e) => { + if (e.touches.length !== 1) + return; + const [x, y] = getTouchEventCoords(e); + updateCoordsStart(x, y); + updateCoordsEnd(x, y); + onSwipeStart == null ? void 0 : onSwipeStart(e); + }, listenerOptions), + useEventListener(target, "touchmove", (e) => { + if (e.touches.length !== 1) + return; + const [x, y] = getTouchEventCoords(e); + updateCoordsEnd(x, y); + if (listenerOptions.capture && !listenerOptions.passive && Math.abs(diffX.value) > Math.abs(diffY.value)) + e.preventDefault(); + if (!isSwiping.value && isThresholdExceeded.value) + isSwiping.value = true; + if (isSwiping.value) + onSwipe == null ? void 0 : onSwipe(e); + }, listenerOptions), + useEventListener(target, ["touchend", "touchcancel"], onTouchEnd, listenerOptions) + ]; + const stop = () => stops.forEach((s) => s()); + return { + isSwiping, + direction, + coordsStart, + coordsEnd, + lengthX: diffX, + lengthY: diffY, + stop, + // TODO: Remove in the next major version + isPassiveEventSupported: true + }; +} +function useTemplateRefsList() { + const refs = ref([]); + refs.value.set = (el) => { + if (el) + refs.value.push(el); + }; + onBeforeUpdate(() => { + refs.value.length = 0; + }); + return refs; +} +function useTextDirection(options = {}) { + const { + document: document2 = defaultDocument, + selector = "html", + observe = false, + initialValue = "ltr" + } = options; + function getValue2() { + var _a, _b; + return (_b = (_a = document2 == null ? void 0 : document2.querySelector(selector)) == null ? void 0 : _a.getAttribute("dir")) != null ? _b : initialValue; + } + const dir = ref(getValue2()); + tryOnMounted(() => dir.value = getValue2()); + if (observe && document2) { + useMutationObserver( + document2.querySelector(selector), + () => dir.value = getValue2(), + { attributes: true } + ); + } + return computed({ + get() { + return dir.value; + }, + set(v) { + var _a, _b; + dir.value = v; + if (!document2) + return; + if (dir.value) + (_a = document2.querySelector(selector)) == null ? void 0 : _a.setAttribute("dir", dir.value); + else + (_b = document2.querySelector(selector)) == null ? void 0 : _b.removeAttribute("dir"); + } + }); +} +function getRangesFromSelection(selection) { + var _a; + const rangeCount = (_a = selection.rangeCount) != null ? _a : 0; + return Array.from({ length: rangeCount }, (_, i) => selection.getRangeAt(i)); +} +function useTextSelection(options = {}) { + const { + window: window2 = defaultWindow + } = options; + const selection = ref(null); + const text = computed(() => { + var _a, _b; + return (_b = (_a = selection.value) == null ? void 0 : _a.toString()) != null ? _b : ""; + }); + const ranges = computed(() => selection.value ? getRangesFromSelection(selection.value) : []); + const rects = computed(() => ranges.value.map((range) => range.getBoundingClientRect())); + function onSelectionChange() { + selection.value = null; + if (window2) + selection.value = window2.getSelection(); + } + if (window2) + useEventListener(window2.document, "selectionchange", onSelectionChange, { passive: true }); + return { + text, + rects, + ranges, + selection + }; +} +function tryRequestAnimationFrame(window2 = defaultWindow, fn) { + if (window2 && typeof window2.requestAnimationFrame === "function") { + window2.requestAnimationFrame(fn); + } else { + fn(); + } +} +function useTextareaAutosize(options = {}) { + var _a, _b; + const { window: window2 = defaultWindow } = options; + const textarea = toRef(options == null ? void 0 : options.element); + const input = toRef((_a = options == null ? void 0 : options.input) != null ? _a : ""); + const styleProp = (_b = options == null ? void 0 : options.styleProp) != null ? _b : "height"; + const textareaScrollHeight = shallowRef(1); + const textareaOldWidth = shallowRef(0); + function triggerResize() { + var _a2; + if (!textarea.value) + return; + let height = ""; + textarea.value.style[styleProp] = "1px"; + textareaScrollHeight.value = (_a2 = textarea.value) == null ? void 0 : _a2.scrollHeight; + const _styleTarget = toValue$1(options == null ? void 0 : options.styleTarget); + if (_styleTarget) + _styleTarget.style[styleProp] = `${textareaScrollHeight.value}px`; + else + height = `${textareaScrollHeight.value}px`; + textarea.value.style[styleProp] = height; + } + watch([input, textarea], () => nextTick(triggerResize), { immediate: true }); + watch(textareaScrollHeight, () => { + var _a2; + return (_a2 = options == null ? void 0 : options.onResize) == null ? void 0 : _a2.call(options); + }); + useResizeObserver(textarea, ([{ contentRect }]) => { + if (textareaOldWidth.value === contentRect.width) + return; + tryRequestAnimationFrame(window2, () => { + textareaOldWidth.value = contentRect.width; + triggerResize(); + }); + }); + if (options == null ? void 0 : options.watch) + watch(options.watch, triggerResize, { immediate: true, deep: true }); + return { + textarea, + input, + triggerResize + }; +} +function useThrottledRefHistory(source, options = {}) { + const { throttle = 200, trailing = true } = options; + const filter = throttleFilter(throttle, trailing); + const history = useRefHistory(source, { ...options, eventFilter: filter }); + return { + ...history + }; +} +const DEFAULT_UNITS = [ + { max: 6e4, value: 1e3, name: "second" }, + { max: 276e4, value: 6e4, name: "minute" }, + { max: 72e6, value: 36e5, name: "hour" }, + { max: 5184e5, value: 864e5, name: "day" }, + { max: 24192e5, value: 6048e5, name: "week" }, + { max: 28512e6, value: 2592e6, name: "month" }, + { max: Number.POSITIVE_INFINITY, value: 31536e6, name: "year" } +]; +const DEFAULT_MESSAGES = { + justNow: "just now", + past: (n) => n.match(/\d/) ? `${n} ago` : n, + future: (n) => n.match(/\d/) ? `in ${n}` : n, + month: (n, past) => n === 1 ? past ? "last month" : "next month" : `${n} month${n > 1 ? "s" : ""}`, + year: (n, past) => n === 1 ? past ? "last year" : "next year" : `${n} year${n > 1 ? "s" : ""}`, + day: (n, past) => n === 1 ? past ? "yesterday" : "tomorrow" : `${n} day${n > 1 ? "s" : ""}`, + week: (n, past) => n === 1 ? past ? "last week" : "next week" : `${n} week${n > 1 ? "s" : ""}`, + hour: (n) => `${n} hour${n > 1 ? "s" : ""}`, + minute: (n) => `${n} minute${n > 1 ? "s" : ""}`, + second: (n) => `${n} second${n > 1 ? "s" : ""}`, + invalid: "" +}; +function DEFAULT_FORMATTER(date) { + return date.toISOString().slice(0, 10); +} +function useTimeAgo(time, options = {}) { + const { + controls: exposeControls = false, + updateInterval = 3e4 + } = options; + const { now, ...controls } = useNow({ interval: updateInterval, controls: true }); + const timeAgo = computed(() => formatTimeAgo(new Date(toValue$1(time)), options, toValue$1(now))); + if (exposeControls) { + return { + timeAgo, + ...controls + }; + } else { + return timeAgo; + } +} +function formatTimeAgo(from, options = {}, now = Date.now()) { + var _a; + const { + max, + messages = DEFAULT_MESSAGES, + fullDateFormatter = DEFAULT_FORMATTER, + units = DEFAULT_UNITS, + showSecond = false, + rounding = "round" + } = options; + const roundFn = typeof rounding === "number" ? (n) => +n.toFixed(rounding) : Math[rounding]; + const diff = +now - +from; + const absDiff = Math.abs(diff); + function getValue2(diff2, unit) { + return roundFn(Math.abs(diff2) / unit.value); + } + function format(diff2, unit) { + const val = getValue2(diff2, unit); + const past = diff2 > 0; + const str = applyFormat(unit.name, val, past); + return applyFormat(past ? "past" : "future", str, past); + } + function applyFormat(name, val, isPast) { + const formatter = messages[name]; + if (typeof formatter === "function") + return formatter(val, isPast); + return formatter.replace("{0}", val.toString()); + } + if (absDiff < 6e4 && !showSecond) + return messages.justNow; + if (typeof max === "number" && absDiff > max) + return fullDateFormatter(new Date(from)); + if (typeof max === "string") { + const unitMax = (_a = units.find((i) => i.name === max)) == null ? void 0 : _a.max; + if (unitMax && absDiff > unitMax) + return fullDateFormatter(new Date(from)); + } + for (const [idx, unit] of units.entries()) { + const val = getValue2(diff, unit); + if (val <= 0 && units[idx - 1]) + return format(diff, units[idx - 1]); + if (absDiff < unit.max) + return format(diff, unit); + } + return messages.invalid; +} +function useTimeoutPoll(fn, interval, options = {}) { + const { + immediate = true, + immediateCallback = false + } = options; + const { start } = useTimeoutFn(loop, interval, { immediate }); + const isActive = shallowRef(false); + async function loop() { + if (!isActive.value) + return; + await fn(); + start(); + } + function resume() { + if (!isActive.value) { + isActive.value = true; + if (immediateCallback) + fn(); + start(); + } + } + function pause() { + isActive.value = false; + } + if (immediate && isClient) + resume(); + tryOnScopeDispose(pause); + return { + isActive, + pause, + resume + }; +} +function useTimestamp(options = {}) { + const { + controls: exposeControls = false, + offset = 0, + immediate = true, + interval = "requestAnimationFrame", + callback + } = options; + const ts = shallowRef(timestamp() + offset); + const update = () => ts.value = timestamp() + offset; + const cb = callback ? () => { + update(); + callback(ts.value); + } : update; + const controls = interval === "requestAnimationFrame" ? useRafFn(cb, { immediate }) : useIntervalFn(cb, interval, { immediate }); + if (exposeControls) { + return { + timestamp: ts, + ...controls + }; + } else { + return ts; + } +} +function useTitle(newTitle = null, options = {}) { + var _a, _b, _c; + const { + document: document2 = defaultDocument, + restoreOnUnmount = (t) => t + } = options; + const originalTitle = (_a = document2 == null ? void 0 : document2.title) != null ? _a : ""; + const title = toRef((_b = newTitle != null ? newTitle : document2 == null ? void 0 : document2.title) != null ? _b : null); + const isReadonly2 = !!(newTitle && typeof newTitle === "function"); + function format(t) { + if (!("titleTemplate" in options)) + return t; + const template = options.titleTemplate || "%s"; + return typeof template === "function" ? template(t) : toValue$1(template).replace(/%s/g, t); + } + watch( + title, + (newValue, oldValue) => { + if (newValue !== oldValue && document2) + document2.title = format(newValue != null ? newValue : ""); + }, + { immediate: true } + ); + if (options.observe && !options.titleTemplate && document2 && !isReadonly2) { + useMutationObserver( + (_c = document2.head) == null ? void 0 : _c.querySelector("title"), + () => { + if (document2 && document2.title !== title.value) + title.value = format(document2.title); + }, + { childList: true } + ); + } + tryOnScopeDispose(() => { + if (restoreOnUnmount) { + const restoredTitle = restoreOnUnmount(originalTitle, title.value || ""); + if (restoredTitle != null && document2) + document2.title = restoredTitle; + } + }); + return title; +} +const _TransitionPresets = { + easeInSine: [0.12, 0, 0.39, 0], + easeOutSine: [0.61, 1, 0.88, 1], + easeInOutSine: [0.37, 0, 0.63, 1], + easeInQuad: [0.11, 0, 0.5, 0], + easeOutQuad: [0.5, 1, 0.89, 1], + easeInOutQuad: [0.45, 0, 0.55, 1], + easeInCubic: [0.32, 0, 0.67, 0], + easeOutCubic: [0.33, 1, 0.68, 1], + easeInOutCubic: [0.65, 0, 0.35, 1], + easeInQuart: [0.5, 0, 0.75, 0], + easeOutQuart: [0.25, 1, 0.5, 1], + easeInOutQuart: [0.76, 0, 0.24, 1], + easeInQuint: [0.64, 0, 0.78, 0], + easeOutQuint: [0.22, 1, 0.36, 1], + easeInOutQuint: [0.83, 0, 0.17, 1], + easeInExpo: [0.7, 0, 0.84, 0], + easeOutExpo: [0.16, 1, 0.3, 1], + easeInOutExpo: [0.87, 0, 0.13, 1], + easeInCirc: [0.55, 0, 1, 0.45], + easeOutCirc: [0, 0.55, 0.45, 1], + easeInOutCirc: [0.85, 0, 0.15, 1], + easeInBack: [0.36, 0, 0.66, -0.56], + easeOutBack: [0.34, 1.56, 0.64, 1], + easeInOutBack: [0.68, -0.6, 0.32, 1.6] +}; +const TransitionPresets = /* @__PURE__ */ Object.assign({}, { linear: identity }, _TransitionPresets); +function createEasingFunction([p0, p1, p2, p3]) { + const a = (a1, a2) => 1 - 3 * a2 + 3 * a1; + const b = (a1, a2) => 3 * a2 - 6 * a1; + const c = (a1) => 3 * a1; + const calcBezier = (t, a1, a2) => ((a(a1, a2) * t + b(a1, a2)) * t + c(a1)) * t; + const getSlope = (t, a1, a2) => 3 * a(a1, a2) * t * t + 2 * b(a1, a2) * t + c(a1); + const getTforX = (x) => { + let aGuessT = x; + for (let i = 0; i < 4; ++i) { + const currentSlope = getSlope(aGuessT, p0, p2); + if (currentSlope === 0) + return aGuessT; + const currentX = calcBezier(aGuessT, p0, p2) - x; + aGuessT -= currentX / currentSlope; + } + return aGuessT; + }; + return (x) => p0 === p1 && p2 === p3 ? x : calcBezier(getTforX(x), p1, p3); +} +function lerp(a, b, alpha) { + return a + alpha * (b - a); +} +function toVec(t) { + return (typeof t === "number" ? [t] : t) || []; +} +function executeTransition(source, from, to, options = {}) { + var _a, _b; + const fromVal = toValue$1(from); + const toVal = toValue$1(to); + const v1 = toVec(fromVal); + const v2 = toVec(toVal); + const duration = (_a = toValue$1(options.duration)) != null ? _a : 1e3; + const startedAt = Date.now(); + const endAt = Date.now() + duration; + const trans = typeof options.transition === "function" ? options.transition : (_b = toValue$1(options.transition)) != null ? _b : identity; + const ease = typeof trans === "function" ? trans : createEasingFunction(trans); + return new Promise((resolve) => { + source.value = fromVal; + const tick = () => { + var _a2; + if ((_a2 = options.abort) == null ? void 0 : _a2.call(options)) { + resolve(); + return; + } + const now = Date.now(); + const alpha = ease((now - startedAt) / duration); + const arr = toVec(source.value).map((n, i) => lerp(v1[i], v2[i], alpha)); + if (Array.isArray(source.value)) + source.value = arr.map((n, i) => { + var _a3, _b2; + return lerp((_a3 = v1[i]) != null ? _a3 : 0, (_b2 = v2[i]) != null ? _b2 : 0, alpha); + }); + else if (typeof source.value === "number") + source.value = arr[0]; + if (now < endAt) { + requestAnimationFrame(tick); + } else { + source.value = toVal; + resolve(); + } + }; + tick(); + }); +} +function useTransition(source, options = {}) { + let currentId = 0; + const sourceVal = () => { + const v = toValue$1(source); + return typeof v === "number" ? v : v.map(toValue$1); + }; + const outputRef = ref(sourceVal()); + watch(sourceVal, async (to) => { + var _a, _b; + if (toValue$1(options.disabled)) + return; + const id = ++currentId; + if (options.delay) + await promiseTimeout(toValue$1(options.delay)); + if (id !== currentId) + return; + const toVal = Array.isArray(to) ? to.map(toValue$1) : toValue$1(to); + (_a = options.onStarted) == null ? void 0 : _a.call(options); + await executeTransition(outputRef, outputRef.value, toVal, { + ...options, + abort: () => { + var _a2; + return id !== currentId || ((_a2 = options.abort) == null ? void 0 : _a2.call(options)); + } + }); + (_b = options.onFinished) == null ? void 0 : _b.call(options); + }, { deep: true }); + watch(() => toValue$1(options.disabled), (disabled) => { + if (disabled) { + currentId++; + outputRef.value = sourceVal(); + } + }); + tryOnScopeDispose(() => { + currentId++; + }); + return computed(() => toValue$1(options.disabled) ? sourceVal() : outputRef.value); +} +function useUrlSearchParams(mode = "history", options = {}) { + const { + initialValue = {}, + removeNullishValues = true, + removeFalsyValues = false, + write: enableWrite = true, + writeMode = "replace", + window: window2 = defaultWindow + } = options; + if (!window2) + return reactive(initialValue); + const state = reactive({}); + function getRawParams() { + if (mode === "history") { + return window2.location.search || ""; + } else if (mode === "hash") { + const hash = window2.location.hash || ""; + const index = hash.indexOf("?"); + return index > 0 ? hash.slice(index) : ""; + } else { + return (window2.location.hash || "").replace(/^#/, ""); + } + } + function constructQuery(params) { + const stringified = params.toString(); + if (mode === "history") + return `${stringified ? `?${stringified}` : ""}${window2.location.hash || ""}`; + if (mode === "hash-params") + return `${window2.location.search || ""}${stringified ? `#${stringified}` : ""}`; + const hash = window2.location.hash || "#"; + const index = hash.indexOf("?"); + if (index > 0) + return `${window2.location.search || ""}${hash.slice(0, index)}${stringified ? `?${stringified}` : ""}`; + return `${window2.location.search || ""}${hash}${stringified ? `?${stringified}` : ""}`; + } + function read() { + return new URLSearchParams(getRawParams()); + } + function updateState(params) { + const unusedKeys = new Set(Object.keys(state)); + for (const key of params.keys()) { + const paramsForKey = params.getAll(key); + state[key] = paramsForKey.length > 1 ? paramsForKey : params.get(key) || ""; + unusedKeys.delete(key); + } + Array.from(unusedKeys).forEach((key) => delete state[key]); + } + const { pause, resume } = watchPausable( + state, + () => { + const params = new URLSearchParams(""); + Object.keys(state).forEach((key) => { + const mapEntry = state[key]; + if (Array.isArray(mapEntry)) + mapEntry.forEach((value) => params.append(key, value)); + else if (removeNullishValues && mapEntry == null) + params.delete(key); + else if (removeFalsyValues && !mapEntry) + params.delete(key); + else + params.set(key, mapEntry); + }); + write(params, false); + }, + { deep: true } + ); + function write(params, shouldUpdate) { + pause(); + if (shouldUpdate) + updateState(params); + if (writeMode === "replace") { + window2.history.replaceState( + window2.history.state, + window2.document.title, + window2.location.pathname + constructQuery(params) + ); + } else { + window2.history.pushState( + window2.history.state, + window2.document.title, + window2.location.pathname + constructQuery(params) + ); + } + resume(); + } + function onChanged() { + if (!enableWrite) + return; + write(read(), true); + } + const listenerOptions = { passive: true }; + useEventListener(window2, "popstate", onChanged, listenerOptions); + if (mode !== "history") + useEventListener(window2, "hashchange", onChanged, listenerOptions); + const initial = read(); + if (initial.keys().next().value) + updateState(initial); + else + Object.assign(state, initialValue); + return state; +} +function useUserMedia(options = {}) { + var _a, _b; + const enabled = shallowRef((_a = options.enabled) != null ? _a : false); + const autoSwitch = shallowRef((_b = options.autoSwitch) != null ? _b : true); + const constraints = ref(options.constraints); + const { navigator: navigator2 = defaultNavigator } = options; + const isSupported = useSupported(() => { + var _a2; + return (_a2 = navigator2 == null ? void 0 : navigator2.mediaDevices) == null ? void 0 : _a2.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 navigator2.mediaDevices.getUserMedia({ + video: getDeviceOptions("video"), + audio: getDeviceOptions("audio") + }); + return stream.value; + } + function _stop() { + var _a2; + (_a2 = stream.value) == null ? void 0 : _a2.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 } + ); + tryOnScopeDispose(() => { + stop(); + }); + return { + isSupported, + stream, + start, + stop, + restart, + constraints, + enabled, + autoSwitch + }; +} +function useVModel(props, key, emit, options = {}) { + var _a, _b, _c; + const { + clone = false, + passive = false, + eventName, + deep = false, + defaultValue, + shouldEmit + } = options; + const vm = getCurrentInstance(); + const _emit = emit || (vm == null ? void 0 : vm.emit) || ((_a = vm == null ? void 0 : vm.$emit) == null ? void 0 : _a.bind(vm)) || ((_c = (_b = vm == null ? void 0 : vm.proxy) == null ? void 0 : _b.$emit) == null ? void 0 : _c.bind(vm == null ? void 0 : vm.proxy)); + let event = eventName; + if (!key) { + key = "modelValue"; + } + event = event || `update:${key.toString()}`; + const cloneFn = (val) => !clone ? val : typeof clone === "function" ? clone(val) : cloneFnJSON(val); + const getValue2 = () => 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 initialValue = getValue2(); + const proxy = ref(initialValue); + 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 getValue2(); + }, + set(value) { + triggerEmit(value); + } + }); + } +} +function useVModels(props, emit, options = {}) { + const ret = {}; + for (const key in props) { + ret[key] = useVModel( + props, + key, + emit, + options + ); + } + return ret; +} +function useVibrate(options) { + const { + pattern = [], + interval = 0, + navigator: navigator2 = defaultNavigator + } = options || {}; + const isSupported = useSupported(() => typeof navigator2 !== "undefined" && "vibrate" in navigator2); + const patternRef = toRef(pattern); + let intervalControls; + const vibrate = (pattern2 = patternRef.value) => { + if (isSupported.value) + navigator2.vibrate(pattern2); + }; + const stop = () => { + if (isSupported.value) + navigator2.vibrate(0); + intervalControls == null ? void 0 : intervalControls.pause(); + }; + if (interval > 0) { + intervalControls = useIntervalFn( + vibrate, + interval, + { + immediate: false, + immediateCallback: false + } + ); + } + return { + isSupported, + pattern, + intervalControls, + vibrate, + stop + }; +} +function useVirtualList(list, options) { + const { containerStyle, wrapperProps, scrollTo, calculateRange, currentList, containerRef } = "itemHeight" in options ? useVerticalVirtualList(options, list) : useHorizontalVirtualList(options, list); + return { + list: currentList, + scrollTo, + containerProps: { + ref: containerRef, + onScroll: () => { + calculateRange(); + }, + style: containerStyle + }, + wrapperProps + }; +} +function useVirtualListResources(list) { + const containerRef = shallowRef(null); + const size = useElementSize(containerRef); + const currentList = ref([]); + const source = shallowRef(list); + const state = ref({ start: 0, end: 10 }); + return { state, source, currentList, size, containerRef }; +} +function createGetViewCapacity(state, source, itemSize) { + return (containerSize) => { + if (typeof itemSize === "number") + return Math.ceil(containerSize / itemSize); + const { start = 0 } = state.value; + let sum = 0; + let capacity = 0; + for (let i = start; i < source.value.length; i++) { + const size = itemSize(i); + sum += size; + capacity = i; + if (sum > containerSize) + break; + } + return capacity - start; + }; +} +function createGetOffset(source, itemSize) { + return (scrollDirection) => { + if (typeof itemSize === "number") + return Math.floor(scrollDirection / itemSize) + 1; + let sum = 0; + let offset = 0; + for (let i = 0; i < source.value.length; i++) { + const size = itemSize(i); + sum += size; + if (sum >= scrollDirection) { + offset = i; + break; + } + } + return offset + 1; + }; +} +function createCalculateRange(type, overscan, getOffset, getViewCapacity, { containerRef, state, currentList, source }) { + return () => { + const element = containerRef.value; + if (element) { + const offset = getOffset(type === "vertical" ? element.scrollTop : element.scrollLeft); + const viewCapacity = getViewCapacity(type === "vertical" ? element.clientHeight : element.clientWidth); + const from = offset - overscan; + const to = offset + viewCapacity + overscan; + state.value = { + start: from < 0 ? 0 : from, + end: to > source.value.length ? source.value.length : to + }; + currentList.value = source.value.slice(state.value.start, state.value.end).map((ele, index) => ({ + data: ele, + index: index + state.value.start + })); + } + }; +} +function createGetDistance(itemSize, source) { + return (index) => { + if (typeof itemSize === "number") { + const size2 = index * itemSize; + return size2; + } + const size = source.value.slice(0, index).reduce((sum, _, i) => sum + itemSize(i), 0); + return size; + }; +} +function useWatchForSizes(size, list, containerRef, calculateRange) { + watch([size.width, size.height, list, containerRef], () => { + calculateRange(); + }); +} +function createComputedTotalSize(itemSize, source) { + return computed(() => { + if (typeof itemSize === "number") + return source.value.length * itemSize; + return source.value.reduce((sum, _, index) => sum + itemSize(index), 0); + }); +} +const scrollToDictionaryForElementScrollKey = { + horizontal: "scrollLeft", + vertical: "scrollTop" +}; +function createScrollTo(type, calculateRange, getDistance, containerRef) { + return (index) => { + if (containerRef.value) { + containerRef.value[scrollToDictionaryForElementScrollKey[type]] = getDistance(index); + calculateRange(); + } + }; +} +function useHorizontalVirtualList(options, list) { + const resources = useVirtualListResources(list); + const { state, source, currentList, size, containerRef } = resources; + const containerStyle = { overflowX: "auto" }; + const { itemWidth, overscan = 5 } = options; + const getViewCapacity = createGetViewCapacity(state, source, itemWidth); + const getOffset = createGetOffset(source, itemWidth); + const calculateRange = createCalculateRange("horizontal", overscan, getOffset, getViewCapacity, resources); + const getDistanceLeft = createGetDistance(itemWidth, source); + const offsetLeft = computed(() => getDistanceLeft(state.value.start)); + const totalWidth = createComputedTotalSize(itemWidth, source); + useWatchForSizes(size, list, containerRef, calculateRange); + const scrollTo = createScrollTo("horizontal", calculateRange, getDistanceLeft, containerRef); + const wrapperProps = computed(() => { + return { + style: { + height: "100%", + width: `${totalWidth.value - offsetLeft.value}px`, + marginLeft: `${offsetLeft.value}px`, + display: "flex" + } + }; + }); + return { + scrollTo, + calculateRange, + wrapperProps, + containerStyle, + currentList, + containerRef + }; +} +function useVerticalVirtualList(options, list) { + const resources = useVirtualListResources(list); + const { state, source, currentList, size, containerRef } = resources; + const containerStyle = { overflowY: "auto" }; + const { itemHeight, overscan = 5 } = options; + const getViewCapacity = createGetViewCapacity(state, source, itemHeight); + const getOffset = createGetOffset(source, itemHeight); + const calculateRange = createCalculateRange("vertical", overscan, getOffset, getViewCapacity, resources); + const getDistanceTop = createGetDistance(itemHeight, source); + const offsetTop = computed(() => getDistanceTop(state.value.start)); + const totalHeight = createComputedTotalSize(itemHeight, source); + useWatchForSizes(size, list, containerRef, calculateRange); + const scrollTo = createScrollTo("vertical", calculateRange, getDistanceTop, containerRef); + const wrapperProps = computed(() => { + return { + style: { + width: "100%", + height: `${totalHeight.value - offsetTop.value}px`, + marginTop: `${offsetTop.value}px` + } + }; + }); + return { + calculateRange, + scrollTo, + containerStyle, + wrapperProps, + currentList, + containerRef + }; +} +function useWakeLock(options = {}) { + const { + navigator: navigator2 = defaultNavigator, + document: document2 = defaultDocument + } = options; + const requestedType = shallowRef(false); + const sentinel = shallowRef(null); + const documentVisibility = useDocumentVisibility({ document: document2 }); + const isSupported = useSupported(() => navigator2 && "wakeLock" in navigator2); + const isActive = computed(() => !!sentinel.value && documentVisibility.value === "visible"); + if (isSupported.value) { + useEventListener(sentinel, "release", () => { + var _a, _b; + requestedType.value = (_b = (_a = sentinel.value) == null ? void 0 : _a.type) != null ? _b : false; + }, { passive: true }); + whenever( + () => documentVisibility.value === "visible" && (document2 == null ? void 0 : document2.visibilityState) === "visible" && requestedType.value, + (type) => { + requestedType.value = false; + forceRequest(type); + } + ); + } + async function forceRequest(type) { + var _a; + await ((_a = sentinel.value) == null ? void 0 : _a.release()); + sentinel.value = isSupported.value ? await navigator2.wakeLock.request(type) : null; + } + async function request(type) { + if (documentVisibility.value === "visible") + await forceRequest(type); + else + requestedType.value = type; + } + async function release() { + requestedType.value = false; + const s = sentinel.value; + sentinel.value = null; + await (s == null ? void 0 : s.release()); + } + return { + sentinel, + isSupported, + isActive, + request, + forceRequest, + release + }; +} +function useWebNotification(options = {}) { + const { + window: window2 = defaultWindow, + requestPermissions: _requestForPermissions = true + } = options; + const defaultWebNotificationOptions = options; + const isSupported = useSupported(() => { + if (!window2 || !("Notification" in window2)) + return false; + if (Notification.permission === "granted") + return true; + try { + const notification2 = new Notification(""); + notification2.onshow = () => { + notification2.close(); + }; + } catch (e) { + if (e.name === "TypeError") + return false; + } + return true; + }); + const permissionGranted = shallowRef(isSupported.value && "permission" in Notification && Notification.permission === "granted"); + const notification = ref(null); + const ensurePermissions = async () => { + if (!isSupported.value) + return; + if (!permissionGranted.value && Notification.permission !== "denied") { + const result = await Notification.requestPermission(); + if (result === "granted") + permissionGranted.value = true; + } + return permissionGranted.value; + }; + const { on: onClick, trigger: clickTrigger } = createEventHook(); + const { on: onShow, trigger: showTrigger } = createEventHook(); + const { on: onError, trigger: errorTrigger } = createEventHook(); + const { on: onClose, trigger: closeTrigger } = createEventHook(); + const show = async (overrides) => { + if (!isSupported.value || !permissionGranted.value) + return; + const options2 = Object.assign({}, defaultWebNotificationOptions, overrides); + notification.value = new Notification(options2.title || "", options2); + notification.value.onclick = clickTrigger; + notification.value.onshow = showTrigger; + notification.value.onerror = errorTrigger; + notification.value.onclose = closeTrigger; + return notification.value; + }; + const close = () => { + if (notification.value) + notification.value.close(); + notification.value = null; + }; + if (_requestForPermissions) + tryOnMounted(ensurePermissions); + tryOnScopeDispose(close); + if (isSupported.value && window2) { + const document2 = window2.document; + useEventListener(document2, "visibilitychange", (e) => { + e.preventDefault(); + if (document2.visibilityState === "visible") { + close(); + } + }); + } + return { + isSupported, + notification, + ensurePermissions, + permissionGranted, + show, + close, + onClick, + onShow, + onError, + onClose + }; +} +const DEFAULT_PING_MESSAGE = "ping"; +function resolveNestedOptions(options) { + if (options === true) + return {}; + return options; +} +function useWebSocket(url, options = {}) { + const { + onConnected, + onDisconnected, + onError, + onMessage, + immediate = true, + autoConnect = true, + autoClose = true, + protocols = [] + } = options; + const data = ref(null); + const status = shallowRef("CLOSED"); + const wsRef = ref(); + const urlRef = toRef(url); + let heartbeatPause; + let heartbeatResume; + let explicitlyClosed = false; + let retried = 0; + let bufferedData = []; + let retryTimeout; + let pongTimeoutWait; + const _sendBuffer = () => { + if (bufferedData.length && wsRef.value && status.value === "OPEN") { + for (const buffer of bufferedData) + wsRef.value.send(buffer); + bufferedData = []; + } + }; + const resetRetry = () => { + if (retryTimeout != null) { + clearTimeout(retryTimeout); + retryTimeout = void 0; + } + }; + const resetHeartbeat = () => { + clearTimeout(pongTimeoutWait); + pongTimeoutWait = void 0; + }; + const close = (code = 1e3, reason) => { + resetRetry(); + if (!isClient && !isWorker || !wsRef.value) + return; + explicitlyClosed = true; + resetHeartbeat(); + heartbeatPause == null ? void 0 : heartbeatPause(); + wsRef.value.close(code, reason); + wsRef.value = void 0; + }; + const send = (data2, useBuffer = true) => { + if (!wsRef.value || status.value !== "OPEN") { + if (useBuffer) + bufferedData.push(data2); + return false; + } + _sendBuffer(); + wsRef.value.send(data2); + return true; + }; + const _init = () => { + if (explicitlyClosed || typeof urlRef.value === "undefined") + return; + const ws = new WebSocket(urlRef.value, protocols); + wsRef.value = ws; + status.value = "CONNECTING"; + ws.onopen = () => { + status.value = "OPEN"; + retried = 0; + onConnected == null ? void 0 : onConnected(ws); + heartbeatResume == null ? void 0 : heartbeatResume(); + _sendBuffer(); + }; + ws.onclose = (ev) => { + status.value = "CLOSED"; + resetHeartbeat(); + heartbeatPause == null ? void 0 : heartbeatPause(); + onDisconnected == null ? void 0 : onDisconnected(ws, ev); + if (!explicitlyClosed && options.autoReconnect && (wsRef.value == null || ws === wsRef.value)) { + const { + retries = -1, + delay = 1e3, + onFailed + } = resolveNestedOptions(options.autoReconnect); + const checkRetires = typeof retries === "function" ? retries : () => typeof retries === "number" && (retries < 0 || retried < retries); + if (checkRetires(retried)) { + retried += 1; + retryTimeout = setTimeout(_init, delay); + } else { + onFailed == null ? void 0 : onFailed(); + } + } + }; + ws.onerror = (e) => { + onError == null ? void 0 : onError(ws, e); + }; + ws.onmessage = (e) => { + if (options.heartbeat) { + resetHeartbeat(); + const { + message = DEFAULT_PING_MESSAGE, + responseMessage = message + } = resolveNestedOptions(options.heartbeat); + if (e.data === toValue$1(responseMessage)) + return; + } + data.value = e.data; + onMessage == null ? void 0 : onMessage(ws, e); + }; + }; + if (options.heartbeat) { + const { + message = DEFAULT_PING_MESSAGE, + interval = 1e3, + pongTimeout = 1e3 + } = resolveNestedOptions(options.heartbeat); + const { pause, resume } = useIntervalFn( + () => { + send(toValue$1(message), false); + if (pongTimeoutWait != null) + return; + pongTimeoutWait = setTimeout(() => { + close(); + explicitlyClosed = false; + }, pongTimeout); + }, + interval, + { immediate: false } + ); + heartbeatPause = pause; + heartbeatResume = resume; + } + if (autoClose) { + if (isClient) + useEventListener("beforeunload", () => close(), { passive: true }); + tryOnScopeDispose(close); + } + const open = () => { + if (!isClient && !isWorker) + return; + close(); + explicitlyClosed = false; + retried = 0; + _init(); + }; + if (immediate) + open(); + if (autoConnect) + watch(urlRef, open); + return { + data, + status, + close, + send, + open, + ws: wsRef + }; +} +function useWebWorker(arg0, workerOptions, options) { + const { + window: window2 = defaultWindow + } = options != null ? options : {}; + const data = ref(null); + const worker = shallowRef(); + const post = (...args) => { + if (!worker.value) + return; + worker.value.postMessage(...args); + }; + const terminate = function terminate2() { + if (!worker.value) + return; + worker.value.terminate(); + }; + if (window2) { + if (typeof arg0 === "string") + worker.value = new Worker(arg0, workerOptions); + else if (typeof arg0 === "function") + worker.value = arg0(); + else + worker.value = arg0; + worker.value.onmessage = (e) => { + data.value = e.data; + }; + tryOnScopeDispose(() => { + if (worker.value) + worker.value.terminate(); + }); + } + return { + data, + post, + terminate, + worker + }; +} +function depsParser(deps, localDeps) { + if (deps.length === 0 && localDeps.length === 0) + return ""; + const depsString = deps.map((dep) => `'${dep}'`).toString(); + const depsFunctionString = localDeps.filter((dep) => typeof dep === "function").map((fn) => { + const str = fn.toString(); + if (str.trim().startsWith("function")) { + return str; + } else { + const name = fn.name; + return `const ${name} = ${str}`; + } + }).join(";"); + const importString = `importScripts(${depsString});`; + return `${depsString.trim() === "" ? "" : importString} ${depsFunctionString}`; +} +function jobRunner(userFunc) { + return (e) => { + const userFuncArgs = e.data[0]; + return Promise.resolve(userFunc.apply(void 0, userFuncArgs)).then((result) => { + postMessage(["SUCCESS", result]); + }).catch((error) => { + postMessage(["ERROR", error]); + }); + }; +} +function createWorkerBlobUrl(fn, deps, localDeps) { + const blobCode = `${depsParser(deps, localDeps)}; onmessage=(${jobRunner})(${fn})`; + const blob = new Blob([blobCode], { type: "text/javascript" }); + const url = URL.createObjectURL(blob); + return url; +} +function useWebWorkerFn(fn, options = {}) { + const { + dependencies = [], + localDependencies = [], + timeout, + window: window2 = defaultWindow + } = options; + const worker = ref(); + const workerStatus = shallowRef("PENDING"); + const promise = ref({}); + const timeoutId = shallowRef(); + const workerTerminate = (status = "PENDING") => { + if (worker.value && worker.value._url && window2) { + worker.value.terminate(); + URL.revokeObjectURL(worker.value._url); + promise.value = {}; + worker.value = void 0; + window2.clearTimeout(timeoutId.value); + workerStatus.value = status; + } + }; + workerTerminate(); + tryOnScopeDispose(workerTerminate); + const generateWorker = () => { + const blobUrl = createWorkerBlobUrl(fn, dependencies, localDependencies); + const newWorker = new Worker(blobUrl); + newWorker._url = blobUrl; + newWorker.onmessage = (e) => { + const { resolve = () => { + }, reject = () => { + } } = promise.value; + const [status, result] = e.data; + switch (status) { + case "SUCCESS": + resolve(result); + workerTerminate(status); + break; + default: + reject(result); + workerTerminate("ERROR"); + break; + } + }; + newWorker.onerror = (e) => { + const { reject = () => { + } } = promise.value; + e.preventDefault(); + reject(e); + workerTerminate("ERROR"); + }; + if (timeout) { + timeoutId.value = setTimeout( + () => workerTerminate("TIMEOUT_EXPIRED"), + timeout + ); + } + return newWorker; + }; + const callWorker = (...fnArgs) => new Promise((resolve, reject) => { + var _a; + promise.value = { + resolve, + reject + }; + (_a = worker.value) == null ? void 0 : _a.postMessage([[...fnArgs]]); + workerStatus.value = "RUNNING"; + }); + const workerFn = (...fnArgs) => { + if (workerStatus.value === "RUNNING") { + console.error( + "[useWebWorkerFn] You can only run one instance of the worker at a time." + ); + return Promise.reject(); + } + worker.value = generateWorker(); + return callWorker(...fnArgs); + }; + return { + workerFn, + workerStatus, + workerTerminate + }; +} +function useWindowFocus(options = {}) { + const { window: window2 = defaultWindow } = options; + if (!window2) + return shallowRef(false); + const focused = shallowRef(window2.document.hasFocus()); + const listenerOptions = { passive: true }; + useEventListener(window2, "blur", () => { + focused.value = false; + }, listenerOptions); + useEventListener(window2, "focus", () => { + focused.value = true; + }, listenerOptions); + return focused; +} +function useWindowScroll(options = {}) { + const { window: window2 = defaultWindow, ...rest } = options; + return useScroll(window2, rest); +} +function useWindowSize(options = {}) { + const { + window: window2 = 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 (window2) { + if (type === "outer") { + width.value = window2.outerWidth; + height.value = window2.outerHeight; + } else if (type === "visual" && window2.visualViewport) { + const { width: visualViewportWidth, height: visualViewportHeight, scale } = window2.visualViewport; + width.value = Math.round(visualViewportWidth * scale); + height.value = Math.round(visualViewportHeight * scale); + } else if (includeScrollbar) { + width.value = window2.innerWidth; + height.value = window2.innerHeight; + } else { + width.value = window2.document.documentElement.clientWidth; + height.value = window2.document.documentElement.clientHeight; + } + } + }; + update(); + tryOnMounted(update); + const listenerOptions = { passive: true }; + useEventListener("resize", update, listenerOptions); + if (window2 && type === "visual" && window2.visualViewport) { + useEventListener(window2.visualViewport, "resize", update, listenerOptions); + } + if (listenOrientation) { + const matches = useMediaQuery("(orientation: portrait)"); + watch(matches, () => update()); + } + return { width, height }; +} + +'use strict'; + +/** + * Create a bound version of a function with a specified `this` context + * + * @param {Function} fn - The function to bind + * @param {*} thisArg - The value to be passed as the `this` parameter + * @returns {Function} A new function that will call the original function with the specified `this` context + */ +function bind(fn, thisArg) { + return function wrap() { + return fn.apply(thisArg, arguments); + }; +} + +"use strict"; + +// utils is a library of generic helper functions non-specific to axios + +const { toString } = Object.prototype; +const { getPrototypeOf } = Object; +const { iterator, toStringTag } = Symbol; + +const kindOf = ((cache) => (thing) => { + const str = toString.call(thing); + return cache[str] || (cache[str] = str.slice(8, -1).toLowerCase()); +})(Object.create(null)); + +const kindOfTest = (type) => { + type = type.toLowerCase(); + return (thing) => kindOf(thing) === type; +}; + +const typeOfTest = (type) => (thing) => typeof thing === type; + +/** + * Determine if a value is a non-null object + * + * @param {Object} val The value to test + * + * @returns {boolean} True if value is an Array, otherwise false + */ +const { isArray: isArray$2 } = Array; + +/** + * Determine if a value is undefined + * + * @param {*} val The value to test + * + * @returns {boolean} True if the value is undefined, otherwise false + */ +const isUndefined = typeOfTest("undefined"); + +/** + * Determine if a value is a Buffer + * + * @param {*} val The value to test + * + * @returns {boolean} True if value is a Buffer, otherwise false + */ +function isBuffer(val) { + return ( + val !== null && + !isUndefined(val) && + val.constructor !== null && + !isUndefined(val.constructor) && + isFunction$2(val.constructor.isBuffer) && + val.constructor.isBuffer(val) + ); +} + +/** + * Determine if a value is an ArrayBuffer + * + * @param {*} val The value to test + * + * @returns {boolean} True if value is an ArrayBuffer, otherwise false + */ +const isArrayBuffer = kindOfTest("ArrayBuffer"); + +/** + * Determine if a value is a view on an ArrayBuffer + * + * @param {*} val The value to test + * + * @returns {boolean} True if value is a view on an ArrayBuffer, otherwise false + */ +function isArrayBufferView(val) { + let result; + if (typeof ArrayBuffer !== "undefined" && ArrayBuffer.isView) { + result = ArrayBuffer.isView(val); + } else { + result = val && val.buffer && isArrayBuffer(val.buffer); + } + return result; +} + +/** + * Determine if a value is a String + * + * @param {*} val The value to test + * + * @returns {boolean} True if value is a String, otherwise false + */ +const isString = typeOfTest("string"); + +/** + * Determine if a value is a Function + * + * @param {*} val The value to test + * @returns {boolean} True if value is a Function, otherwise false + */ +const isFunction$2 = typeOfTest("function"); + +/** + * Determine if a value is a Number + * + * @param {*} val The value to test + * + * @returns {boolean} True if value is a Number, otherwise false + */ +const isNumber$1 = typeOfTest("number"); + +/** + * Determine if a value is an Object + * + * @param {*} thing The value to test + * + * @returns {boolean} True if value is an Object, otherwise false + */ +const isObject$1 = (thing) => thing !== null && typeof thing === "object"; + +/** + * Determine if a value is a Boolean + * + * @param {*} thing The value to test + * @returns {boolean} True if value is a Boolean, otherwise false + */ +const isBoolean = (thing) => thing === true || thing === false; + +/** + * Determine if a value is a plain Object + * + * @param {*} val The value to test + * + * @returns {boolean} True if value is a plain Object, otherwise false + */ +const isPlainObject$2 = (val) => { + if (kindOf(val) !== "object") { + return false; + } + + const prototype = getPrototypeOf(val); + return ( + (prototype === null || + prototype === Object.prototype || + Object.getPrototypeOf(prototype) === null) && + !(toStringTag in val) && + !(iterator in val) + ); +}; + +/** + * Determine if a value is an empty object (safely handles Buffers) + * + * @param {*} val The value to test + * + * @returns {boolean} True if value is an empty object, otherwise false + */ +const isEmptyObject = (val) => { + // Early return for non-objects or Buffers to prevent RangeError + if (!isObject$1(val) || isBuffer(val)) { + return false; + } + + try { + return ( + Object.keys(val).length === 0 && + Object.getPrototypeOf(val) === Object.prototype + ); + } catch (e) { + // Fallback for any other objects that might cause RangeError with Object.keys() + return false; + } +}; + +/** + * Determine if a value is a Date + * + * @param {*} val The value to test + * + * @returns {boolean} True if value is a Date, otherwise false + */ +const isDate = kindOfTest("Date"); + +/** + * Determine if a value is a File + * + * @param {*} val The value to test + * + * @returns {boolean} True if value is a File, otherwise false + */ +const isFile = kindOfTest("File"); + +/** + * Determine if a value is a Blob + * + * @param {*} val The value to test + * + * @returns {boolean} True if value is a Blob, otherwise false + */ +const isBlob = kindOfTest("Blob"); + +/** + * Determine if a value is a FileList + * + * @param {*} val The value to test + * + * @returns {boolean} True if value is a File, otherwise false + */ +const isFileList = kindOfTest("FileList"); + +/** + * Determine if a value is a Stream + * + * @param {*} val The value to test + * + * @returns {boolean} True if value is a Stream, otherwise false + */ +const isStream = (val) => isObject$1(val) && isFunction$2(val.pipe); + +/** + * Determine if a value is a FormData + * + * @param {*} thing The value to test + * + * @returns {boolean} True if value is an FormData, otherwise false + */ +const isFormData = (thing) => { + let kind; + return ( + thing && + ((typeof FormData === "function" && thing instanceof FormData) || + (isFunction$2(thing.append) && + ((kind = kindOf(thing)) === "formdata" || + // detect form-data instance + (kind === "object" && + isFunction$2(thing.toString) && + thing.toString() === "[object FormData]")))) + ); +}; + +/** + * Determine if a value is a URLSearchParams object + * + * @param {*} val The value to test + * + * @returns {boolean} True if value is a URLSearchParams object, otherwise false + */ +const isURLSearchParams = kindOfTest("URLSearchParams"); + +const [isReadableStream, isRequest, isResponse, isHeaders] = [ + "ReadableStream", + "Request", + "Response", + "Headers", +].map(kindOfTest); + +/** + * Trim excess whitespace off the beginning and end of a string + * + * @param {String} str The String to trim + * + * @returns {String} The String freed of excess whitespace + */ +const trim = (str) => + str.trim ? str.trim() : str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, ""); + +/** + * Iterate over an Array or an Object invoking a function for each item. + * + * If `obj` is an Array callback will be called passing + * the value, index, and complete array for each item. + * + * If 'obj' is an Object callback will be called passing + * the value, key, and complete object for each property. + * + * @param {Object|Array} obj The object to iterate + * @param {Function} fn The callback to invoke for each item + * + * @param {Object} [options] + * @param {Boolean} [options.allOwnKeys = false] + * @returns {any} + */ +function forEach(obj, fn, { allOwnKeys = false } = {}) { + // Don't bother if no value provided + if (obj === null || typeof obj === "undefined") { + return; + } + + let i; + let l; + + // Force an array if not already something iterable + if (typeof obj !== "object") { + /*eslint no-param-reassign:0*/ + obj = [obj]; + } + + if (isArray$2(obj)) { + // Iterate over array values + for (i = 0, l = obj.length; i < l; i++) { + fn.call(null, obj[i], i, obj); + } + } else { + // Buffer check + if (isBuffer(obj)) { + return; + } + + // Iterate over object keys + const keys = allOwnKeys + ? Object.getOwnPropertyNames(obj) + : Object.keys(obj); + const len = keys.length; + let key; + + for (i = 0; i < len; i++) { + key = keys[i]; + fn.call(null, obj[key], key, obj); + } + } +} + +function findKey(obj, key) { + if (isBuffer(obj)) { + return null; + } + + key = key.toLowerCase(); + const keys = Object.keys(obj); + let i = keys.length; + let _key; + while (i-- > 0) { + _key = keys[i]; + if (key === _key.toLowerCase()) { + return _key; + } + } + return null; +} + +const _global = (() => { + /*eslint no-undef:0*/ + if (typeof globalThis !== "undefined") return globalThis; + return typeof self !== "undefined" + ? self + : typeof window !== "undefined" + ? window + : global; +})(); + +const isContextDefined = (context) => + !isUndefined(context) && context !== _global; + +/** + * Accepts varargs expecting each argument to be an object, then + * immutably merges the properties of each object and returns result. + * + * When multiple objects contain the same key the later object in + * the arguments list will take precedence. + * + * Example: + * + * ```js + * const result = merge({foo: 123}, {foo: 456}); + * console.log(result.foo); // outputs 456 + * ``` + * + * @param {Object} obj1 Object to merge + * + * @returns {Object} Result of all merge properties + */ +function merge$1(/* obj1, obj2, obj3, ... */) { + const { caseless, skipUndefined } = (isContextDefined(this) && this) || {}; + const result = {}; + const assignValue = (val, key) => { + // Skip dangerous property names to prevent prototype pollution + if (key === "__proto__" || key === "constructor" || key === "prototype") { + return; + } + + const targetKey = (caseless && findKey(result, key)) || key; + if (isPlainObject$2(result[targetKey]) && isPlainObject$2(val)) { + result[targetKey] = merge$1(result[targetKey], val); + } else if (isPlainObject$2(val)) { + result[targetKey] = merge$1({}, val); + } else if (isArray$2(val)) { + result[targetKey] = val.slice(); + } else if (!skipUndefined || !isUndefined(val)) { + result[targetKey] = val; + } + }; + + for (let i = 0, l = arguments.length; i < l; i++) { + arguments[i] && forEach(arguments[i], assignValue); + } + return result; +} + +/** + * Extends object a by mutably adding to it the properties of object b. + * + * @param {Object} a The object to be extended + * @param {Object} b The object to copy properties from + * @param {Object} thisArg The object to bind function to + * + * @param {Object} [options] + * @param {Boolean} [options.allOwnKeys] + * @returns {Object} The resulting value of object a + */ +const extend = (a, b, thisArg, { allOwnKeys } = {}) => { + forEach( + b, + (val, key) => { + if (thisArg && isFunction$2(val)) { + Object.defineProperty(a, key, { + value: bind(val, thisArg), + writable: true, + enumerable: true, + configurable: true, + }); + } else { + Object.defineProperty(a, key, { + value: val, + writable: true, + enumerable: true, + configurable: true, + }); + } + }, + { allOwnKeys }, + ); + return a; +}; + +/** + * Remove byte order marker. This catches EF BB BF (the UTF-8 BOM) + * + * @param {string} content with BOM + * + * @returns {string} content value without BOM + */ +const stripBOM = (content) => { + if (content.charCodeAt(0) === 0xfeff) { + content = content.slice(1); + } + return content; +}; + +/** + * Inherit the prototype methods from one constructor into another + * @param {function} constructor + * @param {function} superConstructor + * @param {object} [props] + * @param {object} [descriptors] + * + * @returns {void} + */ +const inherits = (constructor, superConstructor, props, descriptors) => { + constructor.prototype = Object.create( + superConstructor.prototype, + descriptors, + ); + Object.defineProperty(constructor.prototype, "constructor", { + value: constructor, + writable: true, + enumerable: false, + configurable: true, + }); + Object.defineProperty(constructor, "super", { + value: superConstructor.prototype, + }); + props && Object.assign(constructor.prototype, props); +}; + +/** + * Resolve object with deep prototype chain to a flat object + * @param {Object} sourceObj source object + * @param {Object} [destObj] + * @param {Function|Boolean} [filter] + * @param {Function} [propFilter] + * + * @returns {Object} + */ +const toFlatObject = (sourceObj, destObj, filter, propFilter) => { + let props; + let i; + let prop; + const merged = {}; + + destObj = destObj || {}; + // eslint-disable-next-line no-eq-null,eqeqeq + if (sourceObj == null) return destObj; + + do { + props = Object.getOwnPropertyNames(sourceObj); + i = props.length; + while (i-- > 0) { + prop = props[i]; + if ( + (!propFilter || propFilter(prop, sourceObj, destObj)) && + !merged[prop] + ) { + destObj[prop] = sourceObj[prop]; + merged[prop] = true; + } + } + sourceObj = filter !== false && getPrototypeOf(sourceObj); + } while ( + sourceObj && + (!filter || filter(sourceObj, destObj)) && + sourceObj !== Object.prototype + ); + + return destObj; +}; + +/** + * Determines whether a string ends with the characters of a specified string + * + * @param {String} str + * @param {String} searchString + * @param {Number} [position= 0] + * + * @returns {boolean} + */ +const endsWith = (str, searchString, position) => { + str = String(str); + if (position === undefined || position > str.length) { + position = str.length; + } + position -= searchString.length; + const lastIndex = str.indexOf(searchString, position); + return lastIndex !== -1 && lastIndex === position; +}; + +/** + * Returns new array from array like object or null if failed + * + * @param {*} [thing] + * + * @returns {?Array} + */ +const toArray = (thing) => { + if (!thing) return null; + if (isArray$2(thing)) return thing; + let i = thing.length; + if (!isNumber$1(i)) return null; + const arr = new Array(i); + while (i-- > 0) { + arr[i] = thing[i]; + } + return arr; +}; + +/** + * Checking if the Uint8Array exists and if it does, it returns a function that checks if the + * thing passed in is an instance of Uint8Array + * + * @param {TypedArray} + * + * @returns {Array} + */ +// eslint-disable-next-line func-names +const isTypedArray = ((TypedArray) => { + // eslint-disable-next-line func-names + return (thing) => { + return TypedArray && thing instanceof TypedArray; + }; +})(typeof Uint8Array !== "undefined" && getPrototypeOf(Uint8Array)); + +/** + * For each entry in the object, call the function with the key and value. + * + * @param {Object} obj - The object to iterate over. + * @param {Function} fn - The function to call for each entry. + * + * @returns {void} + */ +const forEachEntry = (obj, fn) => { + const generator = obj && obj[iterator]; + + const _iterator = generator.call(obj); + + let result; + + while ((result = _iterator.next()) && !result.done) { + const pair = result.value; + fn.call(obj, pair[0], pair[1]); + } +}; + +/** + * It takes a regular expression and a string, and returns an array of all the matches + * + * @param {string} regExp - The regular expression to match against. + * @param {string} str - The string to search. + * + * @returns {Array} + */ +const matchAll = (regExp, str) => { + let matches; + const arr = []; + + while ((matches = regExp.exec(str)) !== null) { + arr.push(matches); + } + + return arr; +}; + +/* Checking if the kindOfTest function returns true when passed an HTMLFormElement. */ +const isHTMLForm = kindOfTest("HTMLFormElement"); + +const toCamelCase = (str) => { + return str + .toLowerCase() + .replace(/[-_\s]([a-z\d])(\w*)/g, function replacer(m, p1, p2) { + return p1.toUpperCase() + p2; + }); +}; + +/* Creating a function that will check if an object has a property. */ +const hasOwnProperty = ( + ({ hasOwnProperty }) => + (obj, prop) => + hasOwnProperty.call(obj, prop) +)(Object.prototype); + +/** + * Determine if a value is a RegExp object + * + * @param {*} val The value to test + * + * @returns {boolean} True if value is a RegExp object, otherwise false + */ +const isRegExp = kindOfTest("RegExp"); + +const reduceDescriptors = (obj, reducer) => { + const descriptors = Object.getOwnPropertyDescriptors(obj); + const reducedDescriptors = {}; + + forEach(descriptors, (descriptor, name) => { + let ret; + if ((ret = reducer(descriptor, name, obj)) !== false) { + reducedDescriptors[name] = ret || descriptor; + } + }); + + Object.defineProperties(obj, reducedDescriptors); +}; + +/** + * Makes all methods read-only + * @param {Object} obj + */ + +const freezeMethods = (obj) => { + reduceDescriptors(obj, (descriptor, name) => { + // skip restricted props in strict mode + if ( + isFunction$2(obj) && + ["arguments", "caller", "callee"].indexOf(name) !== -1 + ) { + return false; + } + + const value = obj[name]; + + if (!isFunction$2(value)) return; + + descriptor.enumerable = false; + + if ("writable" in descriptor) { + descriptor.writable = false; + return; + } + + if (!descriptor.set) { + descriptor.set = () => { + throw Error("Can not rewrite read-only method '" + name + "'"); + }; + } + }); +}; + +const toObjectSet = (arrayOrString, delimiter) => { + const obj = {}; + + const define = (arr) => { + arr.forEach((value) => { + obj[value] = true; + }); + }; + + isArray$2(arrayOrString) + ? define(arrayOrString) + : define(String(arrayOrString).split(delimiter)); + + return obj; +}; + +const noop$2 = () => {}; + +const toFiniteNumber$2 = (value, defaultValue) => { + return value != null && Number.isFinite((value = +value)) + ? value + : defaultValue; +}; + +/** + * If the thing is a FormData object, return true, otherwise return false. + * + * @param {unknown} thing - The thing to check. + * + * @returns {boolean} + */ +function isSpecCompliantForm(thing) { + return !!( + thing && + isFunction$2(thing.append) && + thing[toStringTag] === "FormData" && + thing[iterator] + ); +} + +const toJSONObject = (obj) => { + const stack = new Array(10); + + const visit = (source, i) => { + if (isObject$1(source)) { + if (stack.indexOf(source) >= 0) { + return; + } + + //Buffer check + if (isBuffer(source)) { + return source; + } + + if (!("toJSON" in source)) { + stack[i] = source; + const target = isArray$2(source) ? [] : {}; + + forEach(source, (value, key) => { + const reducedValue = visit(value, i + 1); + !isUndefined(reducedValue) && (target[key] = reducedValue); + }); + + stack[i] = undefined; + + return target; + } + } + + return source; + }; + + return visit(obj, 0); +}; + +const isAsyncFn = kindOfTest("AsyncFunction"); + +const isThenable = (thing) => + thing && + (isObject$1(thing) || isFunction$2(thing)) && + isFunction$2(thing.then) && + isFunction$2(thing.catch); + +// original code +// https://github.com/DigitalBrainJS/AxiosPromise/blob/16deab13710ec09779922131f3fa5954320f83ab/lib/utils.js#L11-L34 + +const _setImmediate = ((setImmediateSupported, postMessageSupported) => { + if (setImmediateSupported) { + return setImmediate; + } + + return postMessageSupported + ? ((token, callbacks) => { + _global.addEventListener( + "message", + ({ source, data }) => { + if (source === _global && data === token) { + callbacks.length && callbacks.shift()(); + } + }, + false, + ); + + return (cb) => { + callbacks.push(cb); + _global.postMessage(token, "*"); + }; + })(`axios@${Math.random()}`, []) + : (cb) => setTimeout(cb); +})(typeof setImmediate === "function", isFunction$2(_global.postMessage)); + +const asap = + typeof queueMicrotask !== "undefined" + ? queueMicrotask.bind(_global) + : (typeof process !== "undefined" && process.nextTick) || _setImmediate; + +// ********************* + +const isIterable = (thing) => thing != null && isFunction$2(thing[iterator]); + +const utils$2 = { + isArray: isArray$2, + isArrayBuffer, + isBuffer, + isFormData, + isArrayBufferView, + isString, + isNumber: isNumber$1, + isBoolean, + isObject: isObject$1, + isPlainObject: isPlainObject$2, + isEmptyObject, + isReadableStream, + isRequest, + isResponse, + isHeaders, + isUndefined, + isDate, + isFile, + isBlob, + isRegExp, + isFunction: isFunction$2, + isStream, + isURLSearchParams, + isTypedArray, + isFileList, + forEach, + merge: merge$1, + extend, + trim, + stripBOM, + inherits, + toFlatObject, + kindOf, + kindOfTest, + endsWith, + toArray, + forEachEntry, + matchAll, + isHTMLForm, + hasOwnProperty, + hasOwnProp: hasOwnProperty, // an alias to avoid ESLint no-prototype-builtins detection + reduceDescriptors, + freezeMethods, + toObjectSet, + toCamelCase, + noop: noop$2, + toFiniteNumber: toFiniteNumber$2, + findKey, + global: _global, + isContextDefined, + isSpecCompliantForm, + toJSONObject, + isAsyncFn, + isThenable, + setImmediate: _setImmediate, + asap, + isIterable, +}; + +'use strict'; + +let AxiosError$1 = class AxiosError extends Error { + static from(error, code, config, request, response, customProps) { + const axiosError = new AxiosError(error.message, code || error.code, config, request, response); + axiosError.cause = error; + axiosError.name = error.name; + customProps && Object.assign(axiosError, customProps); + return axiosError; + } + + /** + * Create an Error with the specified message, config, error code, request and response. + * + * @param {string} message The error message. + * @param {string} [code] The error code (for example, 'ECONNABORTED'). + * @param {Object} [config] The config. + * @param {Object} [request] The request. + * @param {Object} [response] The response. + * + * @returns {Error} The created error. + */ + constructor(message, code, config, request, response) { + super(message); + this.name = 'AxiosError'; + this.isAxiosError = true; + code && (this.code = code); + config && (this.config = config); + request && (this.request = request); + if (response) { + this.response = response; + this.status = response.status; + } + } + + toJSON() { + return { + // Standard + message: this.message, + name: this.name, + // Microsoft + description: this.description, + number: this.number, + // Mozilla + fileName: this.fileName, + lineNumber: this.lineNumber, + columnNumber: this.columnNumber, + stack: this.stack, + // Axios + config: utils$2.toJSONObject(this.config), + code: this.code, + status: this.status, + }; + } +}; + +// This can be changed to static properties as soon as the parser options in .eslint.cjs are updated. +AxiosError$1.ERR_BAD_OPTION_VALUE = 'ERR_BAD_OPTION_VALUE'; +AxiosError$1.ERR_BAD_OPTION = 'ERR_BAD_OPTION'; +AxiosError$1.ECONNABORTED = 'ECONNABORTED'; +AxiosError$1.ETIMEDOUT = 'ETIMEDOUT'; +AxiosError$1.ERR_NETWORK = 'ERR_NETWORK'; +AxiosError$1.ERR_FR_TOO_MANY_REDIRECTS = 'ERR_FR_TOO_MANY_REDIRECTS'; +AxiosError$1.ERR_DEPRECATED = 'ERR_DEPRECATED'; +AxiosError$1.ERR_BAD_RESPONSE = 'ERR_BAD_RESPONSE'; +AxiosError$1.ERR_BAD_REQUEST = 'ERR_BAD_REQUEST'; +AxiosError$1.ERR_CANCELED = 'ERR_CANCELED'; +AxiosError$1.ERR_NOT_SUPPORT = 'ERR_NOT_SUPPORT'; +AxiosError$1.ERR_INVALID_URL = 'ERR_INVALID_URL'; + +// eslint-disable-next-line strict +const httpAdapter = null; + +'use strict'; + +/** + * Determines if the given thing is a array or js object. + * + * @param {string} thing - The object or array to be visited. + * + * @returns {boolean} + */ +function isVisitable(thing) { + return utils$2.isPlainObject(thing) || utils$2.isArray(thing); +} + +/** + * It removes the brackets from the end of a string + * + * @param {string} key - The key of the parameter. + * + * @returns {string} the key without the brackets. + */ +function removeBrackets(key) { + return utils$2.endsWith(key, '[]') ? key.slice(0, -2) : key; +} + +/** + * It takes a path, a key, and a boolean, and returns a string + * + * @param {string} path - The path to the current key. + * @param {string} key - The key of the current object being iterated over. + * @param {string} dots - If true, the key will be rendered with dots instead of brackets. + * + * @returns {string} The path to the current key. + */ +function renderKey(path, key, dots) { + if (!path) return key; + return path.concat(key).map(function each(token, i) { + // eslint-disable-next-line no-param-reassign + token = removeBrackets(token); + return !dots && i ? '[' + token + ']' : token; + }).join(dots ? '.' : ''); +} + +/** + * If the array is an array and none of its elements are visitable, then it's a flat array. + * + * @param {Array} arr - The array to check + * + * @returns {boolean} + */ +function isFlatArray(arr) { + return utils$2.isArray(arr) && !arr.some(isVisitable); +} + +const predicates = utils$2.toFlatObject(utils$2, {}, null, function filter(prop) { + return /^is[A-Z]/.test(prop); +}); + +/** + * Convert a data object to FormData + * + * @param {Object} obj + * @param {?Object} [formData] + * @param {?Object} [options] + * @param {Function} [options.visitor] + * @param {Boolean} [options.metaTokens = true] + * @param {Boolean} [options.dots = false] + * @param {?Boolean} [options.indexes = false] + * + * @returns {Object} + **/ + +/** + * It converts an object into a FormData object + * + * @param {Object} obj - The object to convert to form data. + * @param {string} formData - The FormData object to append to. + * @param {Object} options + * + * @returns + */ +function toFormData$1(obj, formData, options) { + if (!utils$2.isObject(obj)) { + throw new TypeError('target must be an object'); + } + + // eslint-disable-next-line no-param-reassign + formData = formData || new (httpAdapter || FormData)(); + + // eslint-disable-next-line no-param-reassign + options = utils$2.toFlatObject(options, { + metaTokens: true, + dots: false, + indexes: false + }, false, function defined(option, source) { + // eslint-disable-next-line no-eq-null,eqeqeq + return !utils$2.isUndefined(source[option]); + }); + + const metaTokens = options.metaTokens; + // eslint-disable-next-line no-use-before-define + const visitor = options.visitor || defaultVisitor; + const dots = options.dots; + const indexes = options.indexes; + const _Blob = options.Blob || typeof Blob !== 'undefined' && Blob; + const useBlob = _Blob && utils$2.isSpecCompliantForm(formData); + + if (!utils$2.isFunction(visitor)) { + throw new TypeError('visitor must be a function'); + } + + function convertValue(value) { + if (value === null) return ''; + + if (utils$2.isDate(value)) { + return value.toISOString(); + } + + if (utils$2.isBoolean(value)) { + return value.toString(); + } + + if (!useBlob && utils$2.isBlob(value)) { + throw new AxiosError$1('Blob is not supported. Use a Buffer instead.'); + } + + if (utils$2.isArrayBuffer(value) || utils$2.isTypedArray(value)) { + return useBlob && typeof Blob === 'function' ? new Blob([value]) : Buffer.from(value); + } + + return value; + } + + /** + * Default visitor. + * + * @param {*} value + * @param {String|Number} key + * @param {Array} path + * @this {FormData} + * + * @returns {boolean} return true to visit the each prop of the value recursively + */ + function defaultVisitor(value, key, path) { + let arr = value; + + if (value && !path && typeof value === 'object') { + if (utils$2.endsWith(key, '{}')) { + // eslint-disable-next-line no-param-reassign + key = metaTokens ? key : key.slice(0, -2); + // eslint-disable-next-line no-param-reassign + value = JSON.stringify(value); + } else if ( + (utils$2.isArray(value) && isFlatArray(value)) || + ((utils$2.isFileList(value) || utils$2.endsWith(key, '[]')) && (arr = utils$2.toArray(value)) + )) { + // eslint-disable-next-line no-param-reassign + key = removeBrackets(key); + + arr.forEach(function each(el, index) { + !(utils$2.isUndefined(el) || el === null) && formData.append( + // eslint-disable-next-line no-nested-ternary + indexes === true ? renderKey([key], index, dots) : (indexes === null ? key : key + '[]'), + convertValue(el) + ); + }); + return false; + } + } + + if (isVisitable(value)) { + return true; + } + + formData.append(renderKey(path, key, dots), convertValue(value)); + + return false; + } + + const stack = []; + + const exposedHelpers = Object.assign(predicates, { + defaultVisitor, + convertValue, + isVisitable + }); + + function build(value, path) { + if (utils$2.isUndefined(value)) return; + + if (stack.indexOf(value) !== -1) { + throw Error('Circular reference detected in ' + path.join('.')); + } + + stack.push(value); + + utils$2.forEach(value, function each(el, key) { + const result = !(utils$2.isUndefined(el) || el === null) && visitor.call( + formData, el, utils$2.isString(key) ? key.trim() : key, path, exposedHelpers + ); + + if (result === true) { + build(el, path ? path.concat(key) : [key]); + } + }); + + stack.pop(); + } + + if (!utils$2.isObject(obj)) { + throw new TypeError('data must be an object'); + } + + build(obj); + + return formData; +} + +'use strict'; + +/** + * It encodes a string by replacing all characters that are not in the unreserved set with + * their percent-encoded equivalents + * + * @param {string} str - The string to encode. + * + * @returns {string} The encoded string. + */ +function encode$1(str) { + const charMap = { + '!': '%21', + "'": '%27', + '(': '%28', + ')': '%29', + '~': '%7E', + '%20': '+', + '%00': '\x00' + }; + return encodeURIComponent(str).replace(/[!'()~]|%20|%00/g, function replacer(match) { + return charMap[match]; + }); +} + +/** + * It takes a params object and converts it to a FormData object + * + * @param {Object} params - The parameters to be converted to a FormData object. + * @param {Object} options - The options object passed to the Axios constructor. + * + * @returns {void} + */ +function AxiosURLSearchParams(params, options) { + this._pairs = []; + + params && toFormData$1(params, this, options); +} + +const prototype = AxiosURLSearchParams.prototype; + +prototype.append = function append(name, value) { + this._pairs.push([name, value]); +}; + +prototype.toString = function toString(encoder) { + const _encode = encoder ? function(value) { + return encoder.call(this, value, encode$1); + } : encode$1; + + return this._pairs.map(function each(pair) { + return _encode(pair[0]) + '=' + _encode(pair[1]); + }, '').join('&'); +}; + +'use strict'; + +/** + * It replaces all instances of the characters `:`, `$`, `,`, `+`, `[`, and `]` with their + * URI encoded counterparts + * + * @param {string} val The value to be encoded. + * + * @returns {string} The encoded value. + */ +function encode(val) { + return encodeURIComponent(val). + replace(/%3A/gi, ':'). + replace(/%24/g, '$'). + replace(/%2C/gi, ','). + replace(/%20/g, '+'); +} + +/** + * Build a URL by appending params to the end + * + * @param {string} url The base of the url (e.g., http://www.google.com) + * @param {object} [params] The params to be appended + * @param {?(object|Function)} options + * + * @returns {string} The formatted url + */ +function buildURL(url, params, options) { + if (!params) { + return url; + } + + const _encode = options && options.encode || encode; + + const _options = utils$2.isFunction(options) ? { + serialize: options + } : options; + + const serializeFn = _options && _options.serialize; + + let serializedParams; + + if (serializeFn) { + serializedParams = serializeFn(params, _options); + } else { + serializedParams = utils$2.isURLSearchParams(params) ? + params.toString() : + new AxiosURLSearchParams(params, _options).toString(_encode); + } + + if (serializedParams) { + const hashmarkIndex = url.indexOf("#"); + + if (hashmarkIndex !== -1) { + url = url.slice(0, hashmarkIndex); + } + url += (url.indexOf('?') === -1 ? '?' : '&') + serializedParams; + } + + return url; +} + +'use strict'; + +class InterceptorManager { + constructor() { + this.handlers = []; + } + + /** + * Add a new interceptor to the stack + * + * @param {Function} fulfilled The function to handle `then` for a `Promise` + * @param {Function} rejected The function to handle `reject` for a `Promise` + * @param {Object} options The options for the interceptor, synchronous and runWhen + * + * @return {Number} An ID used to remove interceptor later + */ + use(fulfilled, rejected, options) { + this.handlers.push({ + fulfilled, + rejected, + synchronous: options ? options.synchronous : false, + runWhen: options ? options.runWhen : null + }); + return this.handlers.length - 1; + } + + /** + * Remove an interceptor from the stack + * + * @param {Number} id The ID that was returned by `use` + * + * @returns {void} + */ + eject(id) { + if (this.handlers[id]) { + this.handlers[id] = null; + } + } + + /** + * Clear all interceptors from the stack + * + * @returns {void} + */ + clear() { + if (this.handlers) { + this.handlers = []; + } + } + + /** + * Iterate over all the registered interceptors + * + * This method is particularly useful for skipping over any + * interceptors that may have become `null` calling `eject`. + * + * @param {Function} fn The function to call for each interceptor + * + * @returns {void} + */ + forEach(fn) { + utils$2.forEach(this.handlers, function forEachHandler(h) { + if (h !== null) { + fn(h); + } + }); + } +} + +'use strict'; + +const transitionalDefaults = { + silentJSONParsing: true, + forcedJSONParsing: true, + clarifyTimeoutError: false, + legacyInterceptorReqResOrdering: true +}; + +'use strict'; +const URLSearchParams$1 = typeof URLSearchParams !== 'undefined' ? URLSearchParams : AxiosURLSearchParams; + +'use strict'; + +const FormData$1 = typeof FormData !== 'undefined' ? FormData : null; + +'use strict'; + +const Blob$1 = typeof Blob !== 'undefined' ? Blob : null; + +const platform$1 = { + isBrowser: true, + classes: { + URLSearchParams: URLSearchParams$1, + FormData: FormData$1, + Blob: Blob$1 + }, + protocols: ['http', 'https', 'file', 'blob', 'url', 'data'] +}; + +const hasBrowserEnv = typeof window !== 'undefined' && typeof document !== 'undefined'; + +const _navigator = typeof navigator === 'object' && navigator || undefined; + +/** + * Determine if we're running in a standard browser environment + * + * This allows axios to run in a web worker, and react-native. + * Both environments support XMLHttpRequest, but not fully standard globals. + * + * web workers: + * typeof window -> undefined + * typeof document -> undefined + * + * react-native: + * navigator.product -> 'ReactNative' + * nativescript + * navigator.product -> 'NativeScript' or 'NS' + * + * @returns {boolean} + */ +const hasStandardBrowserEnv = hasBrowserEnv && + (!_navigator || ['ReactNative', 'NativeScript', 'NS'].indexOf(_navigator.product) < 0); + +/** + * Determine if we're running in a standard browser webWorker environment + * + * Although the `isStandardBrowserEnv` method indicates that + * `allows axios to run in a web worker`, the WebWorker will still be + * filtered out due to its judgment standard + * `typeof window !== 'undefined' && typeof document !== 'undefined'`. + * This leads to a problem when axios post `FormData` in webWorker + */ +const hasStandardBrowserWebWorkerEnv = (() => { + return ( + typeof WorkerGlobalScope !== 'undefined' && + // eslint-disable-next-line no-undef + self instanceof WorkerGlobalScope && + typeof self.importScripts === 'function' + ); +})(); + +const origin = hasBrowserEnv && window.location.href || 'http://localhost'; + +const utils$1 = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({ + __proto__: null, + hasBrowserEnv, + hasStandardBrowserEnv, + hasStandardBrowserWebWorkerEnv, + navigator: _navigator, + origin +}, Symbol.toStringTag, { value: 'Module' })); + +const platform = { + ...utils$1, + ...platform$1 +}; + +'use strict'; + +function toURLEncodedForm(data, options) { + return toFormData$1(data, new platform.classes.URLSearchParams(), { + visitor: function(value, key, path, helpers) { + if (platform.isNode && utils$2.isBuffer(value)) { + this.append(key, value.toString('base64')); + return false; + } + + return helpers.defaultVisitor.apply(this, arguments); + }, + ...options + }); +} + +'use strict'; + +/** + * It takes a string like `foo[x][y][z]` and returns an array like `['foo', 'x', 'y', 'z'] + * + * @param {string} name - The name of the property to get. + * + * @returns An array of strings. + */ +function parsePropPath(name) { + // foo[x][y][z] + // foo.x.y.z + // foo-x-y-z + // foo x y z + return utils$2.matchAll(/\w+|\[(\w*)]/g, name).map(match => { + return match[0] === '[]' ? '' : match[1] || match[0]; + }); +} + +/** + * Convert an array to an object. + * + * @param {Array} arr - The array to convert to an object. + * + * @returns An object with the same keys and values as the array. + */ +function arrayToObject(arr) { + const obj = {}; + const keys = Object.keys(arr); + let i; + const len = keys.length; + let key; + for (i = 0; i < len; i++) { + key = keys[i]; + obj[key] = arr[key]; + } + return obj; +} + +/** + * It takes a FormData object and returns a JavaScript object + * + * @param {string} formData The FormData object to convert to JSON. + * + * @returns {Object | null} The converted object. + */ +function formDataToJSON(formData) { + function buildPath(path, value, target, index) { + let name = path[index++]; + + if (name === '__proto__') return true; + + const isNumericKey = Number.isFinite(+name); + const isLast = index >= path.length; + name = !name && utils$2.isArray(target) ? target.length : name; + + if (isLast) { + if (utils$2.hasOwnProp(target, name)) { + target[name] = [target[name], value]; + } else { + target[name] = value; + } + + return !isNumericKey; + } + + if (!target[name] || !utils$2.isObject(target[name])) { + target[name] = []; + } + + const result = buildPath(path, value, target[name], index); + + if (result && utils$2.isArray(target[name])) { + target[name] = arrayToObject(target[name]); + } + + return !isNumericKey; + } + + if (utils$2.isFormData(formData) && utils$2.isFunction(formData.entries)) { + const obj = {}; + + utils$2.forEachEntry(formData, (name, value) => { + buildPath(parsePropPath(name), value, obj, 0); + }); + + return obj; + } + + return null; +} + +'use strict'; + +/** + * It takes a string, tries to parse it, and if it fails, it returns the stringified version + * of the input + * + * @param {any} rawValue - The value to be stringified. + * @param {Function} parser - A function that parses a string into a JavaScript object. + * @param {Function} encoder - A function that takes a value and returns a string. + * + * @returns {string} A stringified version of the rawValue. + */ +function stringifySafely(rawValue, parser, encoder) { + if (utils$2.isString(rawValue)) { + try { + (parser || JSON.parse)(rawValue); + return utils$2.trim(rawValue); + } catch (e) { + if (e.name !== 'SyntaxError') { + throw e; + } + } + } + + return (encoder || JSON.stringify)(rawValue); +} + +const defaults$1 = { + + transitional: transitionalDefaults, + + adapter: ['xhr', 'http', 'fetch'], + + transformRequest: [function transformRequest(data, headers) { + const contentType = headers.getContentType() || ''; + const hasJSONContentType = contentType.indexOf('application/json') > -1; + const isObjectPayload = utils$2.isObject(data); + + if (isObjectPayload && utils$2.isHTMLForm(data)) { + data = new FormData(data); + } + + const isFormData = utils$2.isFormData(data); + + if (isFormData) { + return hasJSONContentType ? JSON.stringify(formDataToJSON(data)) : data; + } + + if (utils$2.isArrayBuffer(data) || + utils$2.isBuffer(data) || + utils$2.isStream(data) || + utils$2.isFile(data) || + utils$2.isBlob(data) || + utils$2.isReadableStream(data) + ) { + return data; + } + if (utils$2.isArrayBufferView(data)) { + return data.buffer; + } + if (utils$2.isURLSearchParams(data)) { + headers.setContentType('application/x-www-form-urlencoded;charset=utf-8', false); + return data.toString(); + } + + let isFileList; + + if (isObjectPayload) { + if (contentType.indexOf('application/x-www-form-urlencoded') > -1) { + return toURLEncodedForm(data, this.formSerializer).toString(); + } + + if ((isFileList = utils$2.isFileList(data)) || contentType.indexOf('multipart/form-data') > -1) { + const _FormData = this.env && this.env.FormData; + + return toFormData$1( + isFileList ? {'files[]': data} : data, + _FormData && new _FormData(), + this.formSerializer + ); + } + } + + if (isObjectPayload || hasJSONContentType ) { + headers.setContentType('application/json', false); + return stringifySafely(data); + } + + return data; + }], + + transformResponse: [function transformResponse(data) { + const transitional = this.transitional || defaults$1.transitional; + const forcedJSONParsing = transitional && transitional.forcedJSONParsing; + const JSONRequested = this.responseType === 'json'; + + if (utils$2.isResponse(data) || utils$2.isReadableStream(data)) { + return data; + } + + if (data && utils$2.isString(data) && ((forcedJSONParsing && !this.responseType) || JSONRequested)) { + const silentJSONParsing = transitional && transitional.silentJSONParsing; + const strictJSONParsing = !silentJSONParsing && JSONRequested; + + try { + return JSON.parse(data, this.parseReviver); + } catch (e) { + if (strictJSONParsing) { + if (e.name === 'SyntaxError') { + throw AxiosError$1.from(e, AxiosError$1.ERR_BAD_RESPONSE, this, null, this.response); + } + throw e; + } + } + } + + return data; + }], + + /** + * A timeout in milliseconds to abort a request. If set to 0 (default) a + * timeout is not created. + */ + timeout: 0, + + xsrfCookieName: 'XSRF-TOKEN', + xsrfHeaderName: 'X-XSRF-TOKEN', + + maxContentLength: -1, + maxBodyLength: -1, + + env: { + FormData: platform.classes.FormData, + Blob: platform.classes.Blob + }, + + validateStatus: function validateStatus(status) { + return status >= 200 && status < 300; + }, + + headers: { + common: { + 'Accept': 'application/json, text/plain, */*', + 'Content-Type': undefined + } + } +}; + +utils$2.forEach(['delete', 'get', 'head', 'post', 'put', 'patch'], (method) => { + defaults$1.headers[method] = {}; +}); + +'use strict'; + +// RawAxiosHeaders whose duplicates are ignored by node +// c.f. https://nodejs.org/api/http.html#http_message_headers +const ignoreDuplicateOf = utils$2.toObjectSet([ + 'age', 'authorization', 'content-length', 'content-type', 'etag', + 'expires', 'from', 'host', 'if-modified-since', 'if-unmodified-since', + 'last-modified', 'location', 'max-forwards', 'proxy-authorization', + 'referer', 'retry-after', 'user-agent' +]); + +/** + * Parse headers into an object + * + * ``` + * Date: Wed, 27 Aug 2014 08:58:49 GMT + * Content-Type: application/json + * Connection: keep-alive + * Transfer-Encoding: chunked + * ``` + * + * @param {String} rawHeaders Headers needing to be parsed + * + * @returns {Object} Headers parsed into an object + */ +const parseHeaders = rawHeaders => { + const parsed = {}; + let key; + let val; + let i; + + rawHeaders && rawHeaders.split('\n').forEach(function parser(line) { + i = line.indexOf(':'); + key = line.substring(0, i).trim().toLowerCase(); + val = line.substring(i + 1).trim(); + + if (!key || (parsed[key] && ignoreDuplicateOf[key])) { + return; + } + + if (key === 'set-cookie') { + if (parsed[key]) { + parsed[key].push(val); + } else { + parsed[key] = [val]; + } + } else { + parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val; + } + }); + + return parsed; +}; + +'use strict'; + +const $internals = Symbol('internals'); + +function normalizeHeader(header) { + return header && String(header).trim().toLowerCase(); +} + +function normalizeValue(value) { + if (value === false || value == null) { + return value; + } + + return utils$2.isArray(value) ? value.map(normalizeValue) : String(value); +} + +function parseTokens(str) { + const tokens = Object.create(null); + const tokensRE = /([^\s,;=]+)\s*(?:=\s*([^,;]+))?/g; + let match; + + while ((match = tokensRE.exec(str))) { + tokens[match[1]] = match[2]; + } + + return tokens; +} + +const isValidHeaderName = (str) => /^[-_a-zA-Z0-9^`|~,!#$%&'*+.]+$/.test(str.trim()); + +function matchHeaderValue(context, value, header, filter, isHeaderNameFilter) { + if (utils$2.isFunction(filter)) { + return filter.call(this, value, header); + } + + if (isHeaderNameFilter) { + value = header; + } + + if (!utils$2.isString(value)) return; + + if (utils$2.isString(filter)) { + return value.indexOf(filter) !== -1; + } + + if (utils$2.isRegExp(filter)) { + return filter.test(value); + } +} + +function formatHeader(header) { + return header.trim() + .toLowerCase().replace(/([a-z\d])(\w*)/g, (w, char, str) => { + return char.toUpperCase() + str; + }); +} + +function buildAccessors(obj, header) { + const accessorName = utils$2.toCamelCase(' ' + header); + + ['get', 'set', 'has'].forEach(methodName => { + Object.defineProperty(obj, methodName + accessorName, { + value: function(arg1, arg2, arg3) { + return this[methodName].call(this, header, arg1, arg2, arg3); + }, + configurable: true + }); + }); +} + +let AxiosHeaders$1 = class AxiosHeaders { + constructor(headers) { + headers && this.set(headers); + } + + set(header, valueOrRewrite, rewrite) { + const self = this; + + function setHeader(_value, _header, _rewrite) { + const lHeader = normalizeHeader(_header); + + if (!lHeader) { + throw new Error('header name must be a non-empty string'); + } + + const key = utils$2.findKey(self, lHeader); + + if(!key || self[key] === undefined || _rewrite === true || (_rewrite === undefined && self[key] !== false)) { + self[key || _header] = normalizeValue(_value); + } + } + + const setHeaders = (headers, _rewrite) => + utils$2.forEach(headers, (_value, _header) => setHeader(_value, _header, _rewrite)); + + if (utils$2.isPlainObject(header) || header instanceof this.constructor) { + setHeaders(header, valueOrRewrite); + } else if(utils$2.isString(header) && (header = header.trim()) && !isValidHeaderName(header)) { + setHeaders(parseHeaders(header), valueOrRewrite); + } else if (utils$2.isObject(header) && utils$2.isIterable(header)) { + let obj = {}, dest, key; + for (const entry of header) { + if (!utils$2.isArray(entry)) { + throw TypeError('Object iterator must return a key-value pair'); + } + + obj[key = entry[0]] = (dest = obj[key]) ? + (utils$2.isArray(dest) ? [...dest, entry[1]] : [dest, entry[1]]) : entry[1]; + } + + setHeaders(obj, valueOrRewrite); + } else { + header != null && setHeader(valueOrRewrite, header, rewrite); + } + + return this; + } + + get(header, parser) { + header = normalizeHeader(header); + + if (header) { + const key = utils$2.findKey(this, header); + + if (key) { + const value = this[key]; + + if (!parser) { + return value; + } + + if (parser === true) { + return parseTokens(value); + } + + if (utils$2.isFunction(parser)) { + return parser.call(this, value, key); + } + + if (utils$2.isRegExp(parser)) { + return parser.exec(value); + } + + throw new TypeError('parser must be boolean|regexp|function'); + } + } + } + + has(header, matcher) { + header = normalizeHeader(header); + + if (header) { + const key = utils$2.findKey(this, header); + + return !!(key && this[key] !== undefined && (!matcher || matchHeaderValue(this, this[key], key, matcher))); + } + + return false; + } + + delete(header, matcher) { + const self = this; + let deleted = false; + + function deleteHeader(_header) { + _header = normalizeHeader(_header); + + if (_header) { + const key = utils$2.findKey(self, _header); + + if (key && (!matcher || matchHeaderValue(self, self[key], key, matcher))) { + delete self[key]; + + deleted = true; + } + } + } + + if (utils$2.isArray(header)) { + header.forEach(deleteHeader); + } else { + deleteHeader(header); + } + + return deleted; + } + + clear(matcher) { + const keys = Object.keys(this); + let i = keys.length; + let deleted = false; + + while (i--) { + const key = keys[i]; + if(!matcher || matchHeaderValue(this, this[key], key, matcher, true)) { + delete this[key]; + deleted = true; + } + } + + return deleted; + } + + normalize(format) { + const self = this; + const headers = {}; + + utils$2.forEach(this, (value, header) => { + const key = utils$2.findKey(headers, header); + + if (key) { + self[key] = normalizeValue(value); + delete self[header]; + return; + } + + const normalized = format ? formatHeader(header) : String(header).trim(); + + if (normalized !== header) { + delete self[header]; + } + + self[normalized] = normalizeValue(value); + + headers[normalized] = true; + }); + + return this; + } + + concat(...targets) { + return this.constructor.concat(this, ...targets); + } + + toJSON(asStrings) { + const obj = Object.create(null); + + utils$2.forEach(this, (value, header) => { + value != null && value !== false && (obj[header] = asStrings && utils$2.isArray(value) ? value.join(', ') : value); + }); + + return obj; + } + + [Symbol.iterator]() { + return Object.entries(this.toJSON())[Symbol.iterator](); + } + + toString() { + return Object.entries(this.toJSON()).map(([header, value]) => header + ': ' + value).join('\n'); + } + + getSetCookie() { + return this.get("set-cookie") || []; + } + + get [Symbol.toStringTag]() { + return 'AxiosHeaders'; + } + + static from(thing) { + return thing instanceof this ? thing : new this(thing); + } + + static concat(first, ...targets) { + const computed = new this(first); + + targets.forEach((target) => computed.set(target)); + + return computed; + } + + static accessor(header) { + const internals = this[$internals] = (this[$internals] = { + accessors: {} + }); + + const accessors = internals.accessors; + const prototype = this.prototype; + + function defineAccessor(_header) { + const lHeader = normalizeHeader(_header); + + if (!accessors[lHeader]) { + buildAccessors(prototype, _header); + accessors[lHeader] = true; + } + } + + utils$2.isArray(header) ? header.forEach(defineAccessor) : defineAccessor(header); + + return this; + } +}; + +AxiosHeaders$1.accessor(['Content-Type', 'Content-Length', 'Accept', 'Accept-Encoding', 'User-Agent', 'Authorization']); + +// reserved names hotfix +utils$2.reduceDescriptors(AxiosHeaders$1.prototype, ({value}, key) => { + let mapped = key[0].toUpperCase() + key.slice(1); // map `set` => `Set` + return { + get: () => value, + set(headerValue) { + this[mapped] = headerValue; + } + } +}); + +utils$2.freezeMethods(AxiosHeaders$1); + +'use strict'; + +/** + * Transform the data for a request or a response + * + * @param {Array|Function} fns A single function or Array of functions + * @param {?Object} response The response object + * + * @returns {*} The resulting transformed data + */ +function transformData(fns, response) { + const config = this || defaults$1; + const context = response || config; + const headers = AxiosHeaders$1.from(context.headers); + let data = context.data; + + utils$2.forEach(fns, function transform(fn) { + data = fn.call(config, data, headers.normalize(), response ? response.status : undefined); + }); + + headers.normalize(); + + return data; +} + +'use strict'; + +function isCancel$1(value) { + return !!(value && value.__CANCEL__); +} + +'use strict'; + +let CanceledError$1 = class CanceledError extends AxiosError$1 { + /** + * A `CanceledError` is an object that is thrown when an operation is canceled. + * + * @param {string=} message The message. + * @param {Object=} config The config. + * @param {Object=} request The request. + * + * @returns {CanceledError} The created error. + */ + constructor(message, config, request) { + super(message == null ? 'canceled' : message, AxiosError$1.ERR_CANCELED, config, request); + this.name = 'CanceledError'; + this.__CANCEL__ = true; + } +}; + +'use strict'; + +/** + * Resolve or reject a Promise based on response status. + * + * @param {Function} resolve A function that resolves the promise. + * @param {Function} reject A function that rejects the promise. + * @param {object} response The response. + * + * @returns {object} The response. + */ +function settle(resolve, reject, response) { + const validateStatus = response.config.validateStatus; + if (!response.status || !validateStatus || validateStatus(response.status)) { + resolve(response); + } else { + reject(new AxiosError$1( + 'Request failed with status code ' + response.status, + [AxiosError$1.ERR_BAD_REQUEST, AxiosError$1.ERR_BAD_RESPONSE][Math.floor(response.status / 100) - 4], + response.config, + response.request, + response + )); + } +} + +'use strict'; + +function parseProtocol(url) { + const match = /^([-+\w]{1,25})(:?\/\/|:)/.exec(url); + return match && match[1] || ''; +} + +'use strict'; + +/** + * Calculate data maxRate + * @param {Number} [samplesCount= 10] + * @param {Number} [min= 1000] + * @returns {Function} + */ +function speedometer(samplesCount, min) { + samplesCount = samplesCount || 10; + const bytes = new Array(samplesCount); + const timestamps = new Array(samplesCount); + let head = 0; + let tail = 0; + let firstSampleTS; + + min = min !== undefined ? min : 1000; + + return function push(chunkLength) { + const now = Date.now(); + + const startedAt = timestamps[tail]; + + if (!firstSampleTS) { + firstSampleTS = now; + } + + bytes[head] = chunkLength; + timestamps[head] = now; + + let i = tail; + let bytesCount = 0; + + while (i !== head) { + bytesCount += bytes[i++]; + i = i % samplesCount; + } + + head = (head + 1) % samplesCount; + + if (head === tail) { + tail = (tail + 1) % samplesCount; + } + + if (now - firstSampleTS < min) { + return; + } + + const passed = startedAt && now - startedAt; + + return passed ? Math.round(bytesCount * 1000 / passed) : undefined; + }; +} + +/** + * Throttle decorator + * @param {Function} fn + * @param {Number} freq + * @return {Function} + */ +function throttle(fn, freq) { + let timestamp = 0; + let threshold = 1000 / freq; + let lastArgs; + let timer; + + const invoke = (args, now = Date.now()) => { + timestamp = now; + lastArgs = null; + if (timer) { + clearTimeout(timer); + timer = null; + } + fn(...args); + }; + + const throttled = (...args) => { + const now = Date.now(); + const passed = now - timestamp; + if ( passed >= threshold) { + invoke(args, now); + } else { + lastArgs = args; + if (!timer) { + timer = setTimeout(() => { + timer = null; + invoke(lastArgs); + }, threshold - passed); + } + } + }; + + const flush = () => lastArgs && invoke(lastArgs); + + return [throttled, flush]; +} + +const progressEventReducer = (listener, isDownloadStream, freq = 3) => { + let bytesNotified = 0; + const _speedometer = speedometer(50, 250); + + return throttle(e => { + const loaded = e.loaded; + const total = e.lengthComputable ? e.total : undefined; + const progressBytes = loaded - bytesNotified; + const rate = _speedometer(progressBytes); + const inRange = loaded <= total; + + bytesNotified = loaded; + + const data = { + loaded, + total, + progress: total ? (loaded / total) : undefined, + bytes: progressBytes, + rate: rate ? rate : undefined, + estimated: rate && total && inRange ? (total - loaded) / rate : undefined, + event: e, + lengthComputable: total != null, + [isDownloadStream ? 'download' : 'upload']: true + }; + + listener(data); + }, freq); +}; + +const progressEventDecorator = (total, throttled) => { + const lengthComputable = total != null; + + return [(loaded) => throttled[0]({ + lengthComputable, + total, + loaded + }), throttled[1]]; +}; + +const asyncDecorator = (fn) => (...args) => utils$2.asap(() => fn(...args)); + +const isURLSameOrigin = platform.hasStandardBrowserEnv ? ((origin, isMSIE) => (url) => { + url = new URL(url, platform.origin); + + return ( + origin.protocol === url.protocol && + origin.host === url.host && + (isMSIE || origin.port === url.port) + ); +})( + new URL(platform.origin), + platform.navigator && /(msie|trident)/i.test(platform.navigator.userAgent) +) : () => true; + +const cookies = platform.hasStandardBrowserEnv ? + + // Standard browser envs support document.cookie + { + write(name, value, expires, path, domain, secure, sameSite) { + if (typeof document === 'undefined') return; + + const cookie = [`${name}=${encodeURIComponent(value)}`]; + + if (utils$2.isNumber(expires)) { + cookie.push(`expires=${new Date(expires).toUTCString()}`); + } + if (utils$2.isString(path)) { + cookie.push(`path=${path}`); + } + if (utils$2.isString(domain)) { + cookie.push(`domain=${domain}`); + } + if (secure === true) { + cookie.push('secure'); + } + if (utils$2.isString(sameSite)) { + cookie.push(`SameSite=${sameSite}`); + } + + document.cookie = cookie.join('; '); + }, + + read(name) { + if (typeof document === 'undefined') return null; + const match = document.cookie.match(new RegExp('(?:^|; )' + name + '=([^;]*)')); + return match ? decodeURIComponent(match[1]) : null; + }, + + remove(name) { + this.write(name, '', Date.now() - 86400000, '/'); + } + } + + : + + // Non-standard browser env (web workers, react-native) lack needed support. + { + write() {}, + read() { + return null; + }, + remove() {} + }; + +'use strict'; + +/** + * Determines whether the specified URL is absolute + * + * @param {string} url The URL to test + * + * @returns {boolean} True if the specified URL is absolute, otherwise false + */ +function isAbsoluteURL(url) { + // A URL is considered absolute if it begins with "://" or "//" (protocol-relative URL). + // RFC 3986 defines scheme name as a sequence of characters beginning with a letter and followed + // by any combination of letters, digits, plus, period, or hyphen. + if (typeof url !== 'string') { + return false; + } + + return /^([a-z][a-z\d+\-.]*:)?\/\//i.test(url); +} + +'use strict'; + +/** + * Creates a new URL by combining the specified URLs + * + * @param {string} baseURL The base URL + * @param {string} relativeURL The relative URL + * + * @returns {string} The combined URL + */ +function combineURLs(baseURL, relativeURL) { + return relativeURL + ? baseURL.replace(/\/?\/$/, '') + '/' + relativeURL.replace(/^\/+/, '') + : baseURL; +} + +'use strict'; + +/** + * Creates a new URL by combining the baseURL with the requestedURL, + * only when the requestedURL is not already an absolute URL. + * If the requestURL is absolute, this function returns the requestedURL untouched. + * + * @param {string} baseURL The base URL + * @param {string} requestedURL Absolute or relative URL to combine + * + * @returns {string} The combined full path + */ +function buildFullPath(baseURL, requestedURL, allowAbsoluteUrls) { + let isRelativeUrl = !isAbsoluteURL(requestedURL); + if (baseURL && (isRelativeUrl || allowAbsoluteUrls == false)) { + return combineURLs(baseURL, requestedURL); + } + return requestedURL; +} + +"use strict"; + +const headersToObject = (thing) => + thing instanceof AxiosHeaders$1 ? { ...thing } : thing; + +/** + * Config-specific merge-function which creates a new config-object + * by merging two configuration objects together. + * + * @param {Object} config1 + * @param {Object} config2 + * + * @returns {Object} New object resulting from merging config2 to config1 + */ +function mergeConfig$1(config1, config2) { + // eslint-disable-next-line no-param-reassign + config2 = config2 || {}; + const config = {}; + + function getMergedValue(target, source, prop, caseless) { + if (utils$2.isPlainObject(target) && utils$2.isPlainObject(source)) { + return utils$2.merge.call({ caseless }, target, source); + } else if (utils$2.isPlainObject(source)) { + return utils$2.merge({}, source); + } else if (utils$2.isArray(source)) { + return source.slice(); + } + return source; + } + + function mergeDeepProperties(a, b, prop, caseless) { + if (!utils$2.isUndefined(b)) { + return getMergedValue(a, b, prop, caseless); + } else if (!utils$2.isUndefined(a)) { + return getMergedValue(undefined, a, prop, caseless); + } + } + + // eslint-disable-next-line consistent-return + function valueFromConfig2(a, b) { + if (!utils$2.isUndefined(b)) { + return getMergedValue(undefined, b); + } + } + + // eslint-disable-next-line consistent-return + function defaultToConfig2(a, b) { + if (!utils$2.isUndefined(b)) { + return getMergedValue(undefined, b); + } else if (!utils$2.isUndefined(a)) { + return getMergedValue(undefined, a); + } + } + + // eslint-disable-next-line consistent-return + function mergeDirectKeys(a, b, prop) { + if (prop in config2) { + return getMergedValue(a, b); + } else if (prop in config1) { + return getMergedValue(undefined, a); + } + } + + const mergeMap = { + url: valueFromConfig2, + method: valueFromConfig2, + data: valueFromConfig2, + baseURL: defaultToConfig2, + transformRequest: defaultToConfig2, + transformResponse: defaultToConfig2, + paramsSerializer: defaultToConfig2, + timeout: defaultToConfig2, + timeoutMessage: defaultToConfig2, + withCredentials: defaultToConfig2, + withXSRFToken: defaultToConfig2, + adapter: defaultToConfig2, + responseType: defaultToConfig2, + xsrfCookieName: defaultToConfig2, + xsrfHeaderName: defaultToConfig2, + onUploadProgress: defaultToConfig2, + onDownloadProgress: defaultToConfig2, + decompress: defaultToConfig2, + maxContentLength: defaultToConfig2, + maxBodyLength: defaultToConfig2, + beforeRedirect: defaultToConfig2, + transport: defaultToConfig2, + httpAgent: defaultToConfig2, + httpsAgent: defaultToConfig2, + cancelToken: defaultToConfig2, + socketPath: defaultToConfig2, + responseEncoding: defaultToConfig2, + validateStatus: mergeDirectKeys, + headers: (a, b, prop) => + mergeDeepProperties(headersToObject(a), headersToObject(b), prop, true), + }; + + utils$2.forEach( + Object.keys({ ...config1, ...config2 }), + function computeConfigValue(prop) { + if ( + prop === "__proto__" || + prop === "constructor" || + prop === "prototype" + ) + return; + const merge = utils$2.hasOwnProp(mergeMap, prop) + ? mergeMap[prop] + : mergeDeepProperties; + const configValue = merge(config1[prop], config2[prop], prop); + (utils$2.isUndefined(configValue) && merge !== mergeDirectKeys) || + (config[prop] = configValue); + }, + ); + + return config; +} + +const resolveConfig = (config) => { + const newConfig = mergeConfig$1({}, config); + + let { data, withXSRFToken, xsrfHeaderName, xsrfCookieName, headers, auth } = newConfig; + + newConfig.headers = headers = AxiosHeaders$1.from(headers); + + newConfig.url = buildURL(buildFullPath(newConfig.baseURL, newConfig.url, newConfig.allowAbsoluteUrls), config.params, config.paramsSerializer); + + // HTTP basic authentication + if (auth) { + headers.set('Authorization', 'Basic ' + + btoa((auth.username || '') + ':' + (auth.password ? unescape(encodeURIComponent(auth.password)) : '')) + ); + } + + if (utils$2.isFormData(data)) { + if (platform.hasStandardBrowserEnv || platform.hasStandardBrowserWebWorkerEnv) { + headers.setContentType(undefined); // browser handles it + } else if (utils$2.isFunction(data.getHeaders)) { + // Node.js FormData (like form-data package) + const formHeaders = data.getHeaders(); + // Only set safe headers to avoid overwriting security headers + const allowedHeaders = ['content-type', 'content-length']; + Object.entries(formHeaders).forEach(([key, val]) => { + if (allowedHeaders.includes(key.toLowerCase())) { + headers.set(key, val); + } + }); + } + } + + // Add xsrf header + // This is only done if running in a standard browser environment. + // Specifically not if we're in a web worker, or react-native. + + if (platform.hasStandardBrowserEnv) { + withXSRFToken && utils$2.isFunction(withXSRFToken) && (withXSRFToken = withXSRFToken(newConfig)); + + if (withXSRFToken || (withXSRFToken !== false && isURLSameOrigin(newConfig.url))) { + // Add xsrf header + const xsrfValue = xsrfHeaderName && xsrfCookieName && cookies.read(xsrfCookieName); + + if (xsrfValue) { + headers.set(xsrfHeaderName, xsrfValue); + } + } + } + + return newConfig; +}; + +const isXHRAdapterSupported = typeof XMLHttpRequest !== 'undefined'; + +const xhrAdapter = isXHRAdapterSupported && function (config) { + return new Promise(function dispatchXhrRequest(resolve, reject) { + const _config = resolveConfig(config); + let requestData = _config.data; + const requestHeaders = AxiosHeaders$1.from(_config.headers).normalize(); + let {responseType, onUploadProgress, onDownloadProgress} = _config; + let onCanceled; + let uploadThrottled, downloadThrottled; + let flushUpload, flushDownload; + + function done() { + flushUpload && flushUpload(); // flush events + flushDownload && flushDownload(); // flush events + + _config.cancelToken && _config.cancelToken.unsubscribe(onCanceled); + + _config.signal && _config.signal.removeEventListener('abort', onCanceled); + } + + let request = new XMLHttpRequest(); + + request.open(_config.method.toUpperCase(), _config.url, true); + + // Set the request timeout in MS + request.timeout = _config.timeout; + + function onloadend() { + if (!request) { + return; + } + // Prepare the response + const responseHeaders = AxiosHeaders$1.from( + 'getAllResponseHeaders' in request && request.getAllResponseHeaders() + ); + const responseData = !responseType || responseType === 'text' || responseType === 'json' ? + request.responseText : request.response; + const response = { + data: responseData, + status: request.status, + statusText: request.statusText, + headers: responseHeaders, + config, + request + }; + + settle(function _resolve(value) { + resolve(value); + done(); + }, function _reject(err) { + reject(err); + done(); + }, response); + + // Clean up request + request = null; + } + + if ('onloadend' in request) { + // Use onloadend if available + request.onloadend = onloadend; + } else { + // Listen for ready state to emulate onloadend + request.onreadystatechange = function handleLoad() { + if (!request || request.readyState !== 4) { + return; + } + + // The request errored out and we didn't get a response, this will be + // handled by onerror instead + // With one exception: request that using file: protocol, most browsers + // will return status as 0 even though it's a successful request + if (request.status === 0 && !(request.responseURL && request.responseURL.indexOf('file:') === 0)) { + return; + } + // readystate handler is calling before onerror or ontimeout handlers, + // so we should call onloadend on the next 'tick' + setTimeout(onloadend); + }; + } + + // Handle browser request cancellation (as opposed to a manual cancellation) + request.onabort = function handleAbort() { + if (!request) { + return; + } + + reject(new AxiosError$1('Request aborted', AxiosError$1.ECONNABORTED, config, request)); + + // Clean up request + request = null; + }; + + // Handle low level network errors + request.onerror = function handleError(event) { + // Browsers deliver a ProgressEvent in XHR onerror + // (message may be empty; when present, surface it) + // See https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/error_event + const msg = event && event.message ? event.message : 'Network Error'; + const err = new AxiosError$1(msg, AxiosError$1.ERR_NETWORK, config, request); + // attach the underlying event for consumers who want details + err.event = event || null; + reject(err); + request = null; + }; + + // Handle timeout + request.ontimeout = function handleTimeout() { + let timeoutErrorMessage = _config.timeout ? 'timeout of ' + _config.timeout + 'ms exceeded' : 'timeout exceeded'; + const transitional = _config.transitional || transitionalDefaults; + if (_config.timeoutErrorMessage) { + timeoutErrorMessage = _config.timeoutErrorMessage; + } + reject(new AxiosError$1( + timeoutErrorMessage, + transitional.clarifyTimeoutError ? AxiosError$1.ETIMEDOUT : AxiosError$1.ECONNABORTED, + config, + request)); + + // Clean up request + request = null; + }; + + // Remove Content-Type if data is undefined + requestData === undefined && requestHeaders.setContentType(null); + + // Add headers to the request + if ('setRequestHeader' in request) { + utils$2.forEach(requestHeaders.toJSON(), function setRequestHeader(val, key) { + request.setRequestHeader(key, val); + }); + } + + // Add withCredentials to request if needed + if (!utils$2.isUndefined(_config.withCredentials)) { + request.withCredentials = !!_config.withCredentials; + } + + // Add responseType to request if needed + if (responseType && responseType !== 'json') { + request.responseType = _config.responseType; + } + + // Handle progress if needed + if (onDownloadProgress) { + ([downloadThrottled, flushDownload] = progressEventReducer(onDownloadProgress, true)); + request.addEventListener('progress', downloadThrottled); + } + + // Not all browsers support upload events + if (onUploadProgress && request.upload) { + ([uploadThrottled, flushUpload] = progressEventReducer(onUploadProgress)); + + request.upload.addEventListener('progress', uploadThrottled); + + request.upload.addEventListener('loadend', flushUpload); + } + + if (_config.cancelToken || _config.signal) { + // Handle cancellation + // eslint-disable-next-line func-names + onCanceled = cancel => { + if (!request) { + return; + } + reject(!cancel || cancel.type ? new CanceledError$1(null, config, request) : cancel); + request.abort(); + request = null; + }; + + _config.cancelToken && _config.cancelToken.subscribe(onCanceled); + if (_config.signal) { + _config.signal.aborted ? onCanceled() : _config.signal.addEventListener('abort', onCanceled); + } + } + + const protocol = parseProtocol(_config.url); + + if (protocol && platform.protocols.indexOf(protocol) === -1) { + reject(new AxiosError$1('Unsupported protocol ' + protocol + ':', AxiosError$1.ERR_BAD_REQUEST, config)); + return; + } + + + // Send the request + request.send(requestData || null); + }); +}; + +const composeSignals = (signals, timeout) => { + const {length} = (signals = signals ? signals.filter(Boolean) : []); + + if (timeout || length) { + let controller = new AbortController(); + + let aborted; + + const onabort = function (reason) { + if (!aborted) { + aborted = true; + unsubscribe(); + const err = reason instanceof Error ? reason : this.reason; + controller.abort(err instanceof AxiosError$1 ? err : new CanceledError$1(err instanceof Error ? err.message : err)); + } + }; + + let timer = timeout && setTimeout(() => { + timer = null; + onabort(new AxiosError$1(`timeout of ${timeout}ms exceeded`, AxiosError$1.ETIMEDOUT)); + }, timeout); + + const unsubscribe = () => { + if (signals) { + timer && clearTimeout(timer); + timer = null; + signals.forEach(signal => { + signal.unsubscribe ? signal.unsubscribe(onabort) : signal.removeEventListener('abort', onabort); + }); + signals = null; + } + }; + + signals.forEach((signal) => signal.addEventListener('abort', onabort)); + + const {signal} = controller; + + signal.unsubscribe = () => utils$2.asap(unsubscribe); + + return signal; + } +}; + +const streamChunk = function* (chunk, chunkSize) { + let len = chunk.byteLength; + + if (!chunkSize || len < chunkSize) { + yield chunk; + return; + } + + let pos = 0; + let end; + + while (pos < len) { + end = pos + chunkSize; + yield chunk.slice(pos, end); + pos = end; + } +}; + +const readBytes = async function* (iterable, chunkSize) { + for await (const chunk of readStream(iterable)) { + yield* streamChunk(chunk, chunkSize); + } +}; + +const readStream = async function* (stream) { + if (stream[Symbol.asyncIterator]) { + yield* stream; + return; + } + + const reader = stream.getReader(); + try { + for (;;) { + const {done, value} = await reader.read(); + if (done) { + break; + } + yield value; + } + } finally { + await reader.cancel(); + } +}; + +const trackStream = (stream, chunkSize, onProgress, onFinish) => { + const iterator = readBytes(stream, chunkSize); + + let bytes = 0; + let done; + let _onFinish = (e) => { + if (!done) { + done = true; + onFinish && onFinish(e); + } + }; + + return new ReadableStream({ + async pull(controller) { + try { + const {done, value} = await iterator.next(); + + if (done) { + _onFinish(); + controller.close(); + return; + } + + let len = value.byteLength; + if (onProgress) { + let loadedBytes = bytes += len; + onProgress(loadedBytes); + } + controller.enqueue(new Uint8Array(value)); + } catch (err) { + _onFinish(err); + throw err; + } + }, + cancel(reason) { + _onFinish(reason); + return iterator.return(); + } + }, { + highWaterMark: 2 + }) +}; + +const DEFAULT_CHUNK_SIZE = 64 * 1024; + +const {isFunction: isFunction$1} = utils$2; + +const globalFetchAPI = (({Request, Response}) => ({ + Request, Response +}))(utils$2.global); + +const { + ReadableStream: ReadableStream$1, TextEncoder: TextEncoder$1 +} = utils$2.global; + + +const test = (fn, ...args) => { + try { + return !!fn(...args); + } catch (e) { + return false + } +}; + +const factory = (env) => { + env = utils$2.merge.call({ + skipUndefined: true + }, globalFetchAPI, env); + + const {fetch: envFetch, Request, Response} = env; + const isFetchSupported = envFetch ? isFunction$1(envFetch) : typeof fetch === 'function'; + const isRequestSupported = isFunction$1(Request); + const isResponseSupported = isFunction$1(Response); + + if (!isFetchSupported) { + return false; + } + + const isReadableStreamSupported = isFetchSupported && isFunction$1(ReadableStream$1); + + const encodeText = isFetchSupported && (typeof TextEncoder$1 === 'function' ? + ((encoder) => (str) => encoder.encode(str))(new TextEncoder$1()) : + async (str) => new Uint8Array(await new Request(str).arrayBuffer()) + ); + + const supportsRequestStream = isRequestSupported && isReadableStreamSupported && test(() => { + let duplexAccessed = false; + + const hasContentType = new Request(platform.origin, { + body: new ReadableStream$1(), + method: 'POST', + get duplex() { + duplexAccessed = true; + return 'half'; + }, + }).headers.has('Content-Type'); + + return duplexAccessed && !hasContentType; + }); + + const supportsResponseStream = isResponseSupported && isReadableStreamSupported && + test(() => utils$2.isReadableStream(new Response('').body)); + + const resolvers = { + stream: supportsResponseStream && ((res) => res.body) + }; + + isFetchSupported && ((() => { + ['text', 'arrayBuffer', 'blob', 'formData', 'stream'].forEach(type => { + !resolvers[type] && (resolvers[type] = (res, config) => { + let method = res && res[type]; + + if (method) { + return method.call(res); + } + + throw new AxiosError$1(`Response type '${type}' is not supported`, AxiosError$1.ERR_NOT_SUPPORT, config); + }); + }); + })()); + + const getBodyLength = async (body) => { + if (body == null) { + return 0; + } + + if (utils$2.isBlob(body)) { + return body.size; + } + + if (utils$2.isSpecCompliantForm(body)) { + const _request = new Request(platform.origin, { + method: 'POST', + body, + }); + return (await _request.arrayBuffer()).byteLength; + } + + if (utils$2.isArrayBufferView(body) || utils$2.isArrayBuffer(body)) { + return body.byteLength; + } + + if (utils$2.isURLSearchParams(body)) { + body = body + ''; + } + + if (utils$2.isString(body)) { + return (await encodeText(body)).byteLength; + } + }; + + const resolveBodyLength = async (headers, body) => { + const length = utils$2.toFiniteNumber(headers.getContentLength()); + + return length == null ? getBodyLength(body) : length; + }; + + return async (config) => { + let { + url, + method, + data, + signal, + cancelToken, + timeout, + onDownloadProgress, + onUploadProgress, + responseType, + headers, + withCredentials = 'same-origin', + fetchOptions + } = resolveConfig(config); + + let _fetch = envFetch || fetch; + + responseType = responseType ? (responseType + '').toLowerCase() : 'text'; + + let composedSignal = composeSignals([signal, cancelToken && cancelToken.toAbortSignal()], timeout); + + let request = null; + + const unsubscribe = composedSignal && composedSignal.unsubscribe && (() => { + composedSignal.unsubscribe(); + }); + + let requestContentLength; + + try { + if ( + onUploadProgress && supportsRequestStream && method !== 'get' && method !== 'head' && + (requestContentLength = await resolveBodyLength(headers, data)) !== 0 + ) { + let _request = new Request(url, { + method: 'POST', + body: data, + duplex: "half" + }); + + let contentTypeHeader; + + if (utils$2.isFormData(data) && (contentTypeHeader = _request.headers.get('content-type'))) { + headers.setContentType(contentTypeHeader); + } + + if (_request.body) { + const [onProgress, flush] = progressEventDecorator( + requestContentLength, + progressEventReducer(asyncDecorator(onUploadProgress)) + ); + + data = trackStream(_request.body, DEFAULT_CHUNK_SIZE, onProgress, flush); + } + } + + if (!utils$2.isString(withCredentials)) { + withCredentials = withCredentials ? 'include' : 'omit'; + } + + // Cloudflare Workers throws when credentials are defined + // see https://github.com/cloudflare/workerd/issues/902 + const isCredentialsSupported = isRequestSupported && "credentials" in Request.prototype; + + const resolvedOptions = { + ...fetchOptions, + signal: composedSignal, + method: method.toUpperCase(), + headers: headers.normalize().toJSON(), + body: data, + duplex: "half", + credentials: isCredentialsSupported ? withCredentials : undefined + }; + + request = isRequestSupported && new Request(url, resolvedOptions); + + let response = await (isRequestSupported ? _fetch(request, fetchOptions) : _fetch(url, resolvedOptions)); + + const isStreamResponse = supportsResponseStream && (responseType === 'stream' || responseType === 'response'); + + if (supportsResponseStream && (onDownloadProgress || (isStreamResponse && unsubscribe))) { + const options = {}; + + ['status', 'statusText', 'headers'].forEach(prop => { + options[prop] = response[prop]; + }); + + const responseContentLength = utils$2.toFiniteNumber(response.headers.get('content-length')); + + const [onProgress, flush] = onDownloadProgress && progressEventDecorator( + responseContentLength, + progressEventReducer(asyncDecorator(onDownloadProgress), true) + ) || []; + + response = new Response( + trackStream(response.body, DEFAULT_CHUNK_SIZE, onProgress, () => { + flush && flush(); + unsubscribe && unsubscribe(); + }), + options + ); + } + + responseType = responseType || 'text'; + + let responseData = await resolvers[utils$2.findKey(resolvers, responseType) || 'text'](response, config); + + !isStreamResponse && unsubscribe && unsubscribe(); + + return await new Promise((resolve, reject) => { + settle(resolve, reject, { + data: responseData, + headers: AxiosHeaders$1.from(response.headers), + status: response.status, + statusText: response.statusText, + config, + request + }); + }) + } catch (err) { + unsubscribe && unsubscribe(); + + if (err && err.name === 'TypeError' && /Load failed|fetch/i.test(err.message)) { + throw Object.assign( + new AxiosError$1('Network Error', AxiosError$1.ERR_NETWORK, config, request, err && err.response), + { + cause: err.cause || err + } + ) + } + + throw AxiosError$1.from(err, err && err.code, config, request, err && err.response); + } + } +}; + +const seedCache = new Map(); + +const getFetch = (config) => { + let env = (config && config.env) || {}; + const {fetch, Request, Response} = env; + const seeds = [ + Request, Response, fetch + ]; + + let len = seeds.length, i = len, + seed, target, map = seedCache; + + while (i--) { + seed = seeds[i]; + target = map.get(seed); + + target === undefined && map.set(seed, target = (i ? new Map() : factory(env))); + + map = target; + } + + return target; +}; + +const adapter = getFetch(); + +/** + * Known adapters mapping. + * Provides environment-specific adapters for Axios: + * - `http` for Node.js + * - `xhr` for browsers + * - `fetch` for fetch API-based requests + * + * @type {Object} + */ +const knownAdapters = { + http: httpAdapter, + xhr: xhrAdapter, + fetch: { + get: getFetch, + } +}; + +// Assign adapter names for easier debugging and identification +utils$2.forEach(knownAdapters, (fn, value) => { + if (fn) { + try { + Object.defineProperty(fn, 'name', { value }); + } catch (e) { + // eslint-disable-next-line no-empty + } + Object.defineProperty(fn, 'adapterName', { value }); + } +}); + +/** + * Render a rejection reason string for unknown or unsupported adapters + * + * @param {string} reason + * @returns {string} + */ +const renderReason = (reason) => `- ${reason}`; + +/** + * Check if the adapter is resolved (function, null, or false) + * + * @param {Function|null|false} adapter + * @returns {boolean} + */ +const isResolvedHandle = (adapter) => utils$2.isFunction(adapter) || adapter === null || adapter === false; + +/** + * Get the first suitable adapter from the provided list. + * Tries each adapter in order until a supported one is found. + * Throws an AxiosError if no adapter is suitable. + * + * @param {Array|string|Function} adapters - Adapter(s) by name or function. + * @param {Object} config - Axios request configuration + * @throws {AxiosError} If no suitable adapter is available + * @returns {Function} The resolved adapter function + */ +function getAdapter$1(adapters, config) { + adapters = utils$2.isArray(adapters) ? adapters : [adapters]; + + const { length } = adapters; + let nameOrAdapter; + let adapter; + + const rejectedReasons = {}; + + for (let i = 0; i < length; i++) { + nameOrAdapter = adapters[i]; + let id; + + adapter = nameOrAdapter; + + if (!isResolvedHandle(nameOrAdapter)) { + adapter = knownAdapters[(id = String(nameOrAdapter)).toLowerCase()]; + + if (adapter === undefined) { + throw new AxiosError$1(`Unknown adapter '${id}'`); + } + } + + if (adapter && (utils$2.isFunction(adapter) || (adapter = adapter.get(config)))) { + break; + } + + rejectedReasons[id || '#' + i] = adapter; + } + + if (!adapter) { + const reasons = Object.entries(rejectedReasons) + .map(([id, state]) => `adapter ${id} ` + + (state === false ? 'is not supported by the environment' : 'is not available in the build') + ); + + let s = length ? + (reasons.length > 1 ? 'since :\n' + reasons.map(renderReason).join('\n') : ' ' + renderReason(reasons[0])) : + 'as no adapter specified'; + + throw new AxiosError$1( + `There is no suitable adapter to dispatch the request ` + s, + 'ERR_NOT_SUPPORT' + ); + } + + return adapter; +} + +/** + * Exports Axios adapters and utility to resolve an adapter + */ +const adapters$1 = { + /** + * Resolve an adapter from a list of adapter names or functions. + * @type {Function} + */ + getAdapter: getAdapter$1, + + /** + * Exposes all known adapters + * @type {Object} + */ + adapters: knownAdapters +}; + +'use strict'; + +/** + * Throws a `CanceledError` if cancellation has been requested. + * + * @param {Object} config The config that is to be used for the request + * + * @returns {void} + */ +function throwIfCancellationRequested(config) { + if (config.cancelToken) { + config.cancelToken.throwIfRequested(); + } + + if (config.signal && config.signal.aborted) { + throw new CanceledError$1(null, config); + } +} + +/** + * Dispatch a request to the server using the configured adapter. + * + * @param {object} config The config that is to be used for the request + * + * @returns {Promise} The Promise to be fulfilled + */ +function dispatchRequest(config) { + throwIfCancellationRequested(config); + + config.headers = AxiosHeaders$1.from(config.headers); + + // Transform request data + config.data = transformData.call( + config, + config.transformRequest + ); + + if (['post', 'put', 'patch'].indexOf(config.method) !== -1) { + config.headers.setContentType('application/x-www-form-urlencoded', false); + } + + const adapter = adapters$1.getAdapter(config.adapter || defaults$1.adapter, config); + + return adapter(config).then(function onAdapterResolution(response) { + throwIfCancellationRequested(config); + + // Transform response data + response.data = transformData.call( + config, + config.transformResponse, + response + ); + + response.headers = AxiosHeaders$1.from(response.headers); + + return response; + }, function onAdapterRejection(reason) { + if (!isCancel$1(reason)) { + throwIfCancellationRequested(config); + + // Transform response data + if (reason && reason.response) { + reason.response.data = transformData.call( + config, + config.transformResponse, + reason.response + ); + reason.response.headers = AxiosHeaders$1.from(reason.response.headers); + } + } + + return Promise.reject(reason); + }); +} + +const VERSION$1 = "1.13.5"; + +'use strict'; + +const validators$1 = {}; + +// eslint-disable-next-line func-names +['object', 'boolean', 'number', 'function', 'string', 'symbol'].forEach((type, i) => { + validators$1[type] = function validator(thing) { + return typeof thing === type || 'a' + (i < 1 ? 'n ' : ' ') + type; + }; +}); + +const deprecatedWarnings = {}; + +/** + * Transitional option validator + * + * @param {function|boolean?} validator - set to false if the transitional option has been removed + * @param {string?} version - deprecated version / removed since version + * @param {string?} message - some message with additional info + * + * @returns {function} + */ +validators$1.transitional = function transitional(validator, version, message) { + function formatMessage(opt, desc) { + return '[Axios v' + VERSION$1 + '] Transitional option \'' + opt + '\'' + desc + (message ? '. ' + message : ''); + } + + // eslint-disable-next-line func-names + return (value, opt, opts) => { + if (validator === false) { + throw new AxiosError$1( + formatMessage(opt, ' has been removed' + (version ? ' in ' + version : '')), + AxiosError$1.ERR_DEPRECATED + ); + } + + if (version && !deprecatedWarnings[opt]) { + deprecatedWarnings[opt] = true; + // eslint-disable-next-line no-console + console.warn( + formatMessage( + opt, + ' has been deprecated since v' + version + ' and will be removed in the near future' + ) + ); + } + + return validator ? validator(value, opt, opts) : true; + }; +}; + +validators$1.spelling = function spelling(correctSpelling) { + return (value, opt) => { + // eslint-disable-next-line no-console + console.warn(`${opt} is likely a misspelling of ${correctSpelling}`); + return true; + } +}; + +/** + * Assert object's properties type + * + * @param {object} options + * @param {object} schema + * @param {boolean?} allowUnknown + * + * @returns {object} + */ + +function assertOptions(options, schema, allowUnknown) { + if (typeof options !== 'object') { + throw new AxiosError$1('options must be an object', AxiosError$1.ERR_BAD_OPTION_VALUE); + } + const keys = Object.keys(options); + let i = keys.length; + while (i-- > 0) { + const opt = keys[i]; + const validator = schema[opt]; + if (validator) { + const value = options[opt]; + const result = value === undefined || validator(value, opt, options); + if (result !== true) { + throw new AxiosError$1('option ' + opt + ' must be ' + result, AxiosError$1.ERR_BAD_OPTION_VALUE); + } + continue; + } + if (allowUnknown !== true) { + throw new AxiosError$1('Unknown option ' + opt, AxiosError$1.ERR_BAD_OPTION); + } + } +} + +const validator = { + assertOptions, + validators: validators$1 +}; + +'use strict'; + +const validators = validator.validators; + +/** + * Create a new instance of Axios + * + * @param {Object} instanceConfig The default config for the instance + * + * @return {Axios} A new instance of Axios + */ +let Axios$1 = class Axios { + constructor(instanceConfig) { + this.defaults = instanceConfig || {}; + this.interceptors = { + request: new InterceptorManager(), + response: new InterceptorManager() + }; + } + + /** + * Dispatch a request + * + * @param {String|Object} configOrUrl The config specific for this request (merged with this.defaults) + * @param {?Object} config + * + * @returns {Promise} The Promise to be fulfilled + */ + async request(configOrUrl, config) { + try { + return await this._request(configOrUrl, config); + } catch (err) { + if (err instanceof Error) { + let dummy = {}; + + Error.captureStackTrace ? Error.captureStackTrace(dummy) : (dummy = new Error()); + + // slice off the Error: ... line + const stack = dummy.stack ? dummy.stack.replace(/^.+\n/, '') : ''; + try { + if (!err.stack) { + err.stack = stack; + // match without the 2 top stack lines + } else if (stack && !String(err.stack).endsWith(stack.replace(/^.+\n.+\n/, ''))) { + err.stack += '\n' + stack; + } + } catch (e) { + // ignore the case where "stack" is an un-writable property + } + } + + throw err; + } + } + + _request(configOrUrl, config) { + /*eslint no-param-reassign:0*/ + // Allow for axios('example/url'[, config]) a la fetch API + if (typeof configOrUrl === 'string') { + config = config || {}; + config.url = configOrUrl; + } else { + config = configOrUrl || {}; + } + + config = mergeConfig$1(this.defaults, config); + + const {transitional, paramsSerializer, headers} = config; + + if (transitional !== undefined) { + validator.assertOptions(transitional, { + silentJSONParsing: validators.transitional(validators.boolean), + forcedJSONParsing: validators.transitional(validators.boolean), + clarifyTimeoutError: validators.transitional(validators.boolean), + legacyInterceptorReqResOrdering: validators.transitional(validators.boolean) + }, false); + } + + if (paramsSerializer != null) { + if (utils$2.isFunction(paramsSerializer)) { + config.paramsSerializer = { + serialize: paramsSerializer + }; + } else { + validator.assertOptions(paramsSerializer, { + encode: validators.function, + serialize: validators.function + }, true); + } + } + + // Set config.allowAbsoluteUrls + if (config.allowAbsoluteUrls !== undefined) { + // do nothing + } else if (this.defaults.allowAbsoluteUrls !== undefined) { + config.allowAbsoluteUrls = this.defaults.allowAbsoluteUrls; + } else { + config.allowAbsoluteUrls = true; + } + + validator.assertOptions(config, { + baseUrl: validators.spelling('baseURL'), + withXsrfToken: validators.spelling('withXSRFToken') + }, true); + + // Set config.method + config.method = (config.method || this.defaults.method || 'get').toLowerCase(); + + // Flatten headers + let contextHeaders = headers && utils$2.merge( + headers.common, + headers[config.method] + ); + + headers && utils$2.forEach( + ['delete', 'get', 'head', 'post', 'put', 'patch', 'common'], + (method) => { + delete headers[method]; + } + ); + + config.headers = AxiosHeaders$1.concat(contextHeaders, headers); + + // filter out skipped interceptors + const requestInterceptorChain = []; + let synchronousRequestInterceptors = true; + this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) { + if (typeof interceptor.runWhen === 'function' && interceptor.runWhen(config) === false) { + return; + } + + synchronousRequestInterceptors = synchronousRequestInterceptors && interceptor.synchronous; + + const transitional = config.transitional || transitionalDefaults; + const legacyInterceptorReqResOrdering = transitional && transitional.legacyInterceptorReqResOrdering; + + if (legacyInterceptorReqResOrdering) { + requestInterceptorChain.unshift(interceptor.fulfilled, interceptor.rejected); + } else { + requestInterceptorChain.push(interceptor.fulfilled, interceptor.rejected); + } + }); + + const responseInterceptorChain = []; + this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) { + responseInterceptorChain.push(interceptor.fulfilled, interceptor.rejected); + }); + + let promise; + let i = 0; + let len; + + if (!synchronousRequestInterceptors) { + const chain = [dispatchRequest.bind(this), undefined]; + chain.unshift(...requestInterceptorChain); + chain.push(...responseInterceptorChain); + len = chain.length; + + promise = Promise.resolve(config); + + while (i < len) { + promise = promise.then(chain[i++], chain[i++]); + } + + return promise; + } + + len = requestInterceptorChain.length; + + let newConfig = config; + + while (i < len) { + const onFulfilled = requestInterceptorChain[i++]; + const onRejected = requestInterceptorChain[i++]; + try { + newConfig = onFulfilled(newConfig); + } catch (error) { + onRejected.call(this, error); + break; + } + } + + try { + promise = dispatchRequest.call(this, newConfig); + } catch (error) { + return Promise.reject(error); + } + + i = 0; + len = responseInterceptorChain.length; + + while (i < len) { + promise = promise.then(responseInterceptorChain[i++], responseInterceptorChain[i++]); + } + + return promise; + } + + getUri(config) { + config = mergeConfig$1(this.defaults, config); + const fullPath = buildFullPath(config.baseURL, config.url, config.allowAbsoluteUrls); + return buildURL(fullPath, config.params, config.paramsSerializer); + } +}; + +// Provide aliases for supported request methods +utils$2.forEach(['delete', 'get', 'head', 'options'], function forEachMethodNoData(method) { + /*eslint func-names:0*/ + Axios$1.prototype[method] = function(url, config) { + return this.request(mergeConfig$1(config || {}, { + method, + url, + data: (config || {}).data + })); + }; +}); + +utils$2.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) { + /*eslint func-names:0*/ + + function generateHTTPMethod(isForm) { + return function httpMethod(url, data, config) { + return this.request(mergeConfig$1(config || {}, { + method, + headers: isForm ? { + 'Content-Type': 'multipart/form-data' + } : {}, + url, + data + })); + }; + } + + Axios$1.prototype[method] = generateHTTPMethod(); + + Axios$1.prototype[method + 'Form'] = generateHTTPMethod(true); +}); + +'use strict'; + +/** + * A `CancelToken` is an object that can be used to request cancellation of an operation. + * + * @param {Function} executor The executor function. + * + * @returns {CancelToken} + */ +let CancelToken$1 = class CancelToken { + constructor(executor) { + if (typeof executor !== 'function') { + throw new TypeError('executor must be a function.'); + } + + let resolvePromise; + + this.promise = new Promise(function promiseExecutor(resolve) { + resolvePromise = resolve; + }); + + const token = this; + + // eslint-disable-next-line func-names + this.promise.then(cancel => { + if (!token._listeners) return; + + let i = token._listeners.length; + + while (i-- > 0) { + token._listeners[i](cancel); + } + token._listeners = null; + }); + + // eslint-disable-next-line func-names + this.promise.then = onfulfilled => { + let _resolve; + // eslint-disable-next-line func-names + const promise = new Promise(resolve => { + token.subscribe(resolve); + _resolve = resolve; + }).then(onfulfilled); + + promise.cancel = function reject() { + token.unsubscribe(_resolve); + }; + + return promise; + }; + + executor(function cancel(message, config, request) { + if (token.reason) { + // Cancellation has already been requested + return; + } + + token.reason = new CanceledError$1(message, config, request); + resolvePromise(token.reason); + }); + } + + /** + * Throws a `CanceledError` if cancellation has been requested. + */ + throwIfRequested() { + if (this.reason) { + throw this.reason; + } + } + + /** + * Subscribe to the cancel signal + */ + + subscribe(listener) { + if (this.reason) { + listener(this.reason); + return; + } + + if (this._listeners) { + this._listeners.push(listener); + } else { + this._listeners = [listener]; + } + } + + /** + * Unsubscribe from the cancel signal + */ + + unsubscribe(listener) { + if (!this._listeners) { + return; + } + const index = this._listeners.indexOf(listener); + if (index !== -1) { + this._listeners.splice(index, 1); + } + } + + toAbortSignal() { + const controller = new AbortController(); + + const abort = (err) => { + controller.abort(err); + }; + + this.subscribe(abort); + + controller.signal.unsubscribe = () => this.unsubscribe(abort); + + return controller.signal; + } + + /** + * Returns an object that contains a new `CancelToken` and a function that, when called, + * cancels the `CancelToken`. + */ + static source() { + let cancel; + const token = new CancelToken(function executor(c) { + cancel = c; + }); + return { + token, + cancel + }; + } +}; + +'use strict'; + +/** + * Syntactic sugar for invoking a function and expanding an array for arguments. + * + * Common use case would be to use `Function.prototype.apply`. + * + * ```js + * function f(x, y, z) {} + * const args = [1, 2, 3]; + * f.apply(null, args); + * ``` + * + * With `spread` this example can be re-written. + * + * ```js + * spread(function(x, y, z) {})([1, 2, 3]); + * ``` + * + * @param {Function} callback + * + * @returns {Function} + */ +function spread$1(callback) { + return function wrap(arr) { + return callback.apply(null, arr); + }; +} + +'use strict'; + +/** + * Determines whether the payload is an error thrown by Axios + * + * @param {*} payload The value to test + * + * @returns {boolean} True if the payload is an error thrown by Axios, otherwise false + */ +function isAxiosError$1(payload) { + return utils$2.isObject(payload) && (payload.isAxiosError === true); +} + +const HttpStatusCode$1 = { + Continue: 100, + SwitchingProtocols: 101, + Processing: 102, + EarlyHints: 103, + Ok: 200, + Created: 201, + Accepted: 202, + NonAuthoritativeInformation: 203, + NoContent: 204, + ResetContent: 205, + PartialContent: 206, + MultiStatus: 207, + AlreadyReported: 208, + ImUsed: 226, + MultipleChoices: 300, + MovedPermanently: 301, + Found: 302, + SeeOther: 303, + NotModified: 304, + UseProxy: 305, + Unused: 306, + TemporaryRedirect: 307, + PermanentRedirect: 308, + BadRequest: 400, + Unauthorized: 401, + PaymentRequired: 402, + Forbidden: 403, + NotFound: 404, + MethodNotAllowed: 405, + NotAcceptable: 406, + ProxyAuthenticationRequired: 407, + RequestTimeout: 408, + Conflict: 409, + Gone: 410, + LengthRequired: 411, + PreconditionFailed: 412, + PayloadTooLarge: 413, + UriTooLong: 414, + UnsupportedMediaType: 415, + RangeNotSatisfiable: 416, + ExpectationFailed: 417, + ImATeapot: 418, + MisdirectedRequest: 421, + UnprocessableEntity: 422, + Locked: 423, + FailedDependency: 424, + TooEarly: 425, + UpgradeRequired: 426, + PreconditionRequired: 428, + TooManyRequests: 429, + RequestHeaderFieldsTooLarge: 431, + UnavailableForLegalReasons: 451, + InternalServerError: 500, + NotImplemented: 501, + BadGateway: 502, + ServiceUnavailable: 503, + GatewayTimeout: 504, + HttpVersionNotSupported: 505, + VariantAlsoNegotiates: 506, + InsufficientStorage: 507, + LoopDetected: 508, + NotExtended: 510, + NetworkAuthenticationRequired: 511, + WebServerIsDown: 521, + ConnectionTimedOut: 522, + OriginIsUnreachable: 523, + TimeoutOccurred: 524, + SslHandshakeFailed: 525, + InvalidSslCertificate: 526, +}; + +Object.entries(HttpStatusCode$1).forEach(([key, value]) => { + HttpStatusCode$1[value] = key; +}); + +'use strict'; + +/** + * Create an instance of Axios + * + * @param {Object} defaultConfig The default config for the instance + * + * @returns {Axios} A new instance of Axios + */ +function createInstance(defaultConfig) { + const context = new Axios$1(defaultConfig); + const instance = bind(Axios$1.prototype.request, context); + + // Copy axios.prototype to instance + utils$2.extend(instance, Axios$1.prototype, context, {allOwnKeys: true}); + + // Copy context to instance + utils$2.extend(instance, context, null, {allOwnKeys: true}); + + // Factory for creating new instances + instance.create = function create(instanceConfig) { + return createInstance(mergeConfig$1(defaultConfig, instanceConfig)); + }; + + return instance; +} + +// Create the default instance to be exported +const axios = createInstance(defaults$1); + +// Expose Axios class to allow class inheritance +axios.Axios = Axios$1; + +// Expose Cancel & CancelToken +axios.CanceledError = CanceledError$1; +axios.CancelToken = CancelToken$1; +axios.isCancel = isCancel$1; +axios.VERSION = VERSION$1; +axios.toFormData = toFormData$1; + +// Expose AxiosError class +axios.AxiosError = AxiosError$1; + +// alias for CanceledError for backward compatibility +axios.Cancel = axios.CanceledError; + +// Expose all/spread +axios.all = function all(promises) { + return Promise.all(promises); +}; + +axios.spread = spread$1; + +// Expose isAxiosError +axios.isAxiosError = isAxiosError$1; + +// Expose mergeConfig +axios.mergeConfig = mergeConfig$1; + +axios.AxiosHeaders = AxiosHeaders$1; + +axios.formToJSON = thing => formDataToJSON(utils$2.isHTMLForm(thing) ? new FormData(thing) : thing); + +axios.getAdapter = adapters$1.getAdapter; + +axios.HttpStatusCode = HttpStatusCode$1; + +axios.default = axios; + +// This module is intended to unwrap Axios default export as named. +// Keep top-level export same with static properties +// so that it can keep same with es module or cjs +const { + Axios, + AxiosError, + CanceledError, + isCancel, + CancelToken, + VERSION, + all, + Cancel, + isAxiosError, + spread, + toFormData, + AxiosHeaders, + HttpStatusCode, + formToJSON, + getAdapter, + mergeConfig +} = axios; + +const CACHE_INVALIDATION_THROTTLE_MS = 30 * 1000; +const CACHE_BUST_PARAM = "force_update"; +const KNOWN_INDEXED_DB_NAMES = ["workbox-expiration", "workbox-background-sync", "pleno", "truckwash"]; + +let lastErrorInvalidationAt = 0; + +const browserWindow = () => (typeof window !== "undefined" ? window : null); +const browserNavigator = () => (typeof navigator !== "undefined" ? navigator : null); + +const clearStorage = (storage) => { + try { + storage?.clear(); + return true; + } catch { + return false; + } +}; + +const clearCacheStorage = async () => { + const win = browserWindow(); + if (!win?.caches) { + return []; + } + + const cacheNames = await win.caches.keys(); + await Promise.all(cacheNames.map((cacheName) => win.caches.delete(cacheName))); + return cacheNames; +}; + +const updateServiceWorkers = async () => { + const nav = browserNavigator(); + if (!nav?.serviceWorker?.getRegistrations) { + return 0; + } + + const registrations = await nav.serviceWorker.getRegistrations(); + await Promise.all( + registrations.map((registration) => (typeof registration.update === "function" ? registration.update() : null)) + ); + return registrations.length; +}; + +const unregisterServiceWorkers = async () => { + const nav = browserNavigator(); + if (!nav?.serviceWorker?.getRegistrations) { + return 0; + } + + const registrations = await nav.serviceWorker.getRegistrations(); + await Promise.all(registrations.map((registration) => registration.unregister())); + return registrations.length; +}; + +const browserIndexedDb = () => { + const win = browserWindow(); + if (win?.indexedDB) { + return win.indexedDB; + } + + return typeof indexedDB !== "undefined" ? indexedDB : null; +}; + +const deleteIndexedDatabase = (indexedDb, databaseName) => + new Promise((resolve) => { + if (!indexedDb || !databaseName) { + resolve(false); + return; + } + + try { + const request = indexedDb.deleteDatabase(databaseName); + request.onsuccess = () => resolve(true); + request.onerror = () => resolve(false); + request.onblocked = () => resolve(false); + } catch { + resolve(false); + } + }); + +const getIndexedDatabaseNames = async (indexedDb) => { + if (typeof indexedDb?.databases !== "function") { + return KNOWN_INDEXED_DB_NAMES; + } + + try { + const databases = await indexedDb.databases(); + return [ + ...new Set( + databases + .map((database) => database?.name) + .filter((databaseName) => typeof databaseName === "string" && databaseName.length > 0) + ), + ]; + } catch { + return KNOWN_INDEXED_DB_NAMES; + } +}; + +const deleteIndexedDatabases = async () => { + const indexedDb = browserIndexedDb(); + if (!indexedDb) { + return []; + } + + const databaseNames = await getIndexedDatabaseNames(indexedDb); + await Promise.all(databaseNames.map((databaseName) => deleteIndexedDatabase(indexedDb, databaseName))); + return databaseNames; +}; + +const reloadWithCacheBust = () => { + const win = browserWindow(); + if (!win?.location) { + return; + } + + const nextUrl = new URL(win.location.href); + nextUrl.searchParams.set(CACHE_BUST_PARAM, String(Date.now())); + win.location.replace(nextUrl.toString()); +}; + +const invalidateFrontendCachesAfterError = async ({ now = Date.now() } = {}) => { + if (lastErrorInvalidationAt > 0 && now - lastErrorInvalidationAt < CACHE_INVALIDATION_THROTTLE_MS) { + return { skipped: true, cacheNames: [], serviceWorkerRegistrations: 0 }; + } + + lastErrorInvalidationAt = now; + const [cacheNames, serviceWorkerRegistrations] = await Promise.all([clearCacheStorage(), updateServiceWorkers()]); + return { skipped: false, cacheNames, serviceWorkerRegistrations }; +}; + +const forceFrontendUpdateAndClearLocal = async ({ reload = reloadWithCacheBust } = {}) => { + const win = browserWindow(); + clearStorage(win?.localStorage); + clearStorage(win?.sessionStorage); + + const [cacheNames, serviceWorkerRegistrations, indexedDatabaseNames] = await Promise.all([ + clearCacheStorage(), + unregisterServiceWorkers(), + deleteIndexedDatabases(), + ]); + + reload(); + return { cacheNames, serviceWorkerRegistrations, indexedDatabaseNames }; +}; + +const __resetFrontendMaintenanceForTests = () => { + lastErrorInvalidationAt = 0; +}; + +const normalizeOrigin = (value) => { + const raw = String(value || "").trim(); + if (!raw) { + return ""; + } + try { + return new URL(raw).origin; + } catch { + return ""; + } +}; + +const browserOrigin$1 = () => { + if (typeof window !== "undefined" && window.location?.origin) { + return window.location.origin; + } + return ""; +}; + +const configuredTrustedOrigins = () => + [ + browserOrigin$1(), + ...ALLOWED_ORIGINS, + ...RELEASE_TRUSTED_ORIGINS, + API_URL, + RELEASE_MANAGER_CONTROL_API_URL, + ...RELEASE_MANAGER_CONTROL_API_FALLBACK_URLS, + RELEASE_PUBLIC_GATEWAY_API_URL, + DEFAULT_LEGACY_API_URL, + DEFAULT_PUBLIC_GATEWAY_API_URL, + DEFAULT_STABLE_API_URL, + ] + .map(normalizeOrigin) + .filter(Boolean); + +const trustedReleaseOrigins = () => Array.from(new Set(configuredTrustedOrigins())); + +const isTrustedReleaseOrigin = (value) => { + const origin = normalizeOrigin(value); + return Boolean(origin) && trustedReleaseOrigins().includes(origin); +}; + +const isRelativeReleaseUrl = (value) => { + const raw = String(value || "").trim(); + return Boolean(raw) && raw.startsWith("/") && !raw.startsWith("//"); +}; + +const isTrustedReleaseUrl = (value, { allowRelative = true } = {}) => { + if (allowRelative && isRelativeReleaseUrl(value)) { + return true; + } + return isTrustedReleaseOrigin(value); +}; + +const sameOriginReleaseUrl = (value, expectedBaseUrl) => { + const resolvedOrigin = normalizeOrigin(value); + const expectedOrigin = normalizeOrigin(expectedBaseUrl); + return Boolean(resolvedOrigin && expectedOrigin && resolvedOrigin === expectedOrigin); +}; + +const RELEASE_TRACE_STORAGE_KEY = "release_trace_id"; +const RELEASE_CHANNEL_SELECTION_STORAGE_KEY$2 = "release_channel_selected_slug"; +const browserStorage$2 = () => { + if (typeof window === "undefined") { + return null; + } + try { + return window.localStorage || null; + } catch { + return null; + } +}; +const normalizeIdentifier = (value, maxLength = 128) => String(value || "").trim().replace(/[^a-zA-Z0-9_.:-]/g, "").slice(0, Math.max(1, maxLength)); +const normalizeReleaseChannelSlug$2 = (value) => String(value || "").trim().toLowerCase().replace(/[^a-z0-9_-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "").slice(0, 64); +const selectedReleaseChannelSlugFromStorage = () => normalizeReleaseChannelSlug$2(browserStorage$2()?.getItem(RELEASE_CHANNEL_SELECTION_STORAGE_KEY$2) || ""); +const releaseTraceIdFromStorage = () => normalizeIdentifier(browserStorage$2()?.getItem(RELEASE_TRACE_STORAGE_KEY) || "", 64); +const fallbackFrontendVersion = () => normalizeIdentifier(undefined || undefined || "unknown", 128); +const buildReleaseHeaders = ({ + traceId = "", + channelSlug = "", + frontendVersion = "" +} = {}) => { + const headers = {}; + const normalizedTraceId = normalizeIdentifier(traceId || releaseTraceIdFromStorage(), 64); + const normalizedChannelSlug = normalizeReleaseChannelSlug$2(channelSlug || selectedReleaseChannelSlugFromStorage()); + const normalizedFrontendVersion = normalizeIdentifier(frontendVersion || fallbackFrontendVersion(), 128); + if (normalizedTraceId) { + headers["X-Release-Trace"] = normalizedTraceId; + } + if (normalizedChannelSlug) { + headers["X-Release-Channel"] = normalizedChannelSlug; + } + if (normalizedFrontendVersion) { + headers["X-Frontend-Version"] = normalizedFrontendVersion; + } + return headers; +}; + +const TRACE_STORAGE_KEY = RELEASE_TRACE_STORAGE_KEY; +const MAX_QUEUE_SIZE = 50; +const MAX_FRONTEND_FAILURE_BUFFER_SIZE = 50; +const FRONTEND_FAILURE_EVENT_TYPES = /* @__PURE__ */ new Set([ + "vue_component_error", + "vue_component_warning", + "window_error", + "unhandled_rejection" +]); +const RELEASE_RUNTIME_SOURCES = /* @__PURE__ */ new Set(["local", "deployment"]); +const RELEASE_RUNTIME_REQUESTED_SOURCES = /* @__PURE__ */ new Set(["local", "deployment", "auto"]); +const normalizeRuntimeSource = (value) => { + const source = String(value || "").trim().toLowerCase(); + return RELEASE_RUNTIME_SOURCES.has(source) ? source : ""; +}; +const normalizeRuntimeRequestedSource = (value) => { + const source = String(value || "").trim().toLowerCase(); + return RELEASE_RUNTIME_REQUESTED_SOURCES.has(source) ? source : ""; +}; +const createTraceId = () => { + if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") { + return crypto.randomUUID().replace(/-/g, ""); + } + return `${Date.now().toString(16)}${Math.random().toString(16).slice(2)}`.slice(0, 32); +}; +const readTraceId = () => { + if (typeof window === "undefined") { + return createTraceId(); + } + try { + const stored = window.localStorage.getItem(TRACE_STORAGE_KEY); + if (stored) { + return stored; + } + const next = createTraceId(); + window.localStorage.setItem(TRACE_STORAGE_KEY, next); + return next; + } catch { + return createTraceId(); + } +}; +const releaseRuntimeStateMutable = reactive({ + source: null, + requestedSource: null, + traceId: readTraceId(), + channel: null, + availableChannels: [], + versions: { + frontend: null, + api: null, + service_set: null, + bundle_id: null, + bundle: null + }, + frontendBaseUrl: null, + apiBaseUrl: null, + availability: { + configured: true, + missing: [], + status: "ready", + explicit: false + }, + capturePolicy: { + enabled: false, + capture_level: "metadata", + all_failure_metadata: true, + retention_days: 14 + }, + generatedAt: null +}); +let pendingEvents = []; +let recentFrontendFailureEvents = []; +let flushTimer = null; +let customTransport = null; +const releaseRuntimeState = readonly(releaseRuntimeStateMutable); +const hasOwn$1 = (value, key) => Boolean(value && Object.prototype.hasOwnProperty.call(value, key)); +const normalizeReadinessMissingValues$1 = (missing = []) => Array.from( + new Set( + (Array.isArray(missing) ? missing : []).map((value) => String(value || "").trim()).filter( + (value) => value && !["release_bundle", "frontend_version", "frontend_base_url", "frontend_entry"].includes(value) + ) + ) +); +const normalizeRuntimeBaseUrl = (value, { allowRelative = true } = {}) => { + const raw = String(value || "").trim().replace(/\/+$/, ""); + if (!raw || !isTrustedReleaseUrl(raw, { allowRelative })) { + return null; + } + if (raw.startsWith("/") && !raw.startsWith("//")) { + return raw; + } + if (/^https?:\/\//i.test(raw)) { + return raw; + } + return null; +}; +const runtimeUrls = (runtime = {}) => { + const urls = runtime?.urls && typeof runtime.urls === "object" ? runtime.urls : {}; + return { + frontendBaseUrl: normalizeRuntimeBaseUrl(runtime.frontend_base_url ?? urls.frontend_base_url, { + allowRelative: false + }), + apiBaseUrl: normalizeRuntimeBaseUrl(runtime.api_base_url ?? urls.api_base_url) + }; +}; +const hasExplicitReleaseRuntime$1 = (runtime) => Boolean( + runtime?.availability && typeof runtime.availability === "object" && runtime.availability.explicit !== false +) || hasOwn$1(runtime, "versions"); +const configureReleaseRuntime = (runtime = {}) => { + if (!runtime || typeof runtime !== "object") { + return releaseRuntimeStateMutable; + } + const runtimeSource = normalizeRuntimeSource(runtime.source); + if (runtimeSource) { + releaseRuntimeStateMutable.source = runtimeSource; + } + const requestedSource = normalizeRuntimeRequestedSource(runtime.requested_source || runtime.requestedSource); + if (requestedSource) { + releaseRuntimeStateMutable.requestedSource = requestedSource; + } else if (runtimeSource) { + releaseRuntimeStateMutable.requestedSource = runtimeSource; + } + if (runtime.trace_id) { + releaseRuntimeStateMutable.traceId = String(runtime.trace_id); + try { + window.localStorage.setItem(TRACE_STORAGE_KEY, releaseRuntimeStateMutable.traceId); + } catch { + } + } + releaseRuntimeStateMutable.channel = runtime.channel || null; + releaseRuntimeStateMutable.availableChannels = Array.isArray(runtime.available_channels) ? runtime.available_channels : Array.isArray(runtime.availableChannels) ? runtime.availableChannels : []; + releaseRuntimeStateMutable.versions = { + frontend: runtime?.versions?.frontend || null, + api: runtime?.versions?.api || null, + service_set: runtime?.versions?.service_set || null, + bundle_id: runtime?.versions?.bundle_id || null, + bundle: runtime?.versions?.bundle || null + }; + const urls = runtimeUrls(runtime); + releaseRuntimeStateMutable.frontendBaseUrl = urls.frontendBaseUrl; + releaseRuntimeStateMutable.apiBaseUrl = urls.apiBaseUrl; + const channel = runtime.channel || null; + const isDefaultChannel = channel?.default_channel === true || channel?.default_channel === 1 || String(channel?.slug || "") === "stable"; + const missingReleaseContent = []; + if (!isDefaultChannel && hasOwn$1(runtime, "versions")) { + if (!runtime?.versions?.api) { + missingReleaseContent.push("api_version"); + } else if (!urls.apiBaseUrl) { + missingReleaseContent.push("api_base_url"); + } + } + releaseRuntimeStateMutable.availability = runtime.availability ? (() => { + const missing = normalizeReadinessMissingValues$1(runtime.availability.missing); + let configured = missing.length === 0; + if (!configured) { + configured = runtime.availability.configured !== false && runtime.availability.status !== "unconfigured"; + } + const status = configured && ["", "unconfigured", "missing_target"].includes(String(runtime.availability.status || "")) ? "ready" : runtime.availability.status || (configured ? "ready" : "unconfigured"); + return { + ...runtime.availability, + configured, + missing, + status, + explicit: true + }; + })() : hasExplicitReleaseRuntime$1(runtime) ? { + configured: missingReleaseContent.length === 0, + missing: missingReleaseContent, + status: missingReleaseContent.length === 0 ? "ready" : "unconfigured", + explicit: true + } : { + configured: true, + missing: [], + status: "ready", + explicit: false + }; + releaseRuntimeStateMutable.capturePolicy = { + enabled: Boolean(runtime?.capture_policy?.enabled), + capture_level: runtime?.capture_policy?.capture_level || "metadata", + all_failure_metadata: runtime?.capture_policy?.all_failure_metadata !== false, + retention_days: Number(runtime?.capture_policy?.retention_days || 14) + }; + releaseRuntimeStateMutable.generatedAt = runtime.generated_at || (/* @__PURE__ */ new Date()).toISOString(); + return releaseRuntimeStateMutable; +}; +const getReleaseRuntimeApiBaseUrl = () => releaseRuntimeStateMutable.apiBaseUrl || API_URL; +const resolveReleaseApiUrl = (url = "") => { + const value = String(url || ""); + if (/^https?:\/\//i.test(value)) { + return rewriteReleaseApiUrl(value); + } + return `${getReleaseRuntimeApiBaseUrl().replace(/\/+$/, "")}/${value.replace(/^\/+/, "")}`; +}; +const rewriteReleaseApiUrl = (url = "") => { + const value = String(url || ""); + const runtimeApiUrl = releaseRuntimeStateMutable.apiBaseUrl; + const defaultApiUrl = API_URL.replace(/\/+$/, ""); + if (!runtimeApiUrl || runtimeApiUrl === defaultApiUrl || !value) { + return value; + } + if (value === defaultApiUrl) { + return runtimeApiUrl; + } + if (value.startsWith(`${defaultApiUrl}/`)) { + return `${runtimeApiUrl}${value.slice(defaultApiUrl.length)}`; + } + return value; +}; +const SENSITIVE_PAYLOAD_KEY_PATTERN = /authorization|cookie|password|passwd|secret|token|api[_-]?key|session|credential|card|cpr|ssn|recaptcha/i; +const CAPTURE_DISABLED_BODY_PLACEHOLDER = "[capture-disabled]"; +const truncateReleasePayloadString = (value) => value.length > 4e3 ? `${value.slice(0, 4e3)} +... [truncated]` : value; +const redactSerializedReleasePayload = (value, depth) => { + const trimmed = value.trim(); + if (trimmed.startsWith("{") || trimmed.startsWith("[")) { + try { + return truncateReleasePayloadString(JSON.stringify(redactReleasePayload(JSON.parse(value), depth + 1))); + } catch { + } + } + if (trimmed.includes("=") && !trimmed.includes("\n")) { + const params = new URLSearchParams(trimmed); + const entries = Array.from(params.entries()); + if (entries.length > 0) { + let changed = false; + const redactedParams = new URLSearchParams(); + for (const [key, item] of entries.slice(0, 80)) { + if (SENSITIVE_PAYLOAD_KEY_PATTERN.test(key)) { + redactedParams.append(key, "[redacted]"); + changed = true; + } else { + redactedParams.append(key, truncateReleasePayloadString(item)); + } + } + if (changed) { + return truncateReleasePayloadString(redactedParams.toString()); + } + } + } + return truncateReleasePayloadString(value); +}; +const redactReleasePayload = (value, depth = 0) => { + if (depth > 8) { + return "[depth-limit]"; + } + if (Array.isArray(value)) { + return value.slice(0, 80).map((item) => redactReleasePayload(item, depth + 1)); + } + if (value && typeof value === "object") { + return Object.fromEntries( + Object.entries(value).slice(0, 80).map(([key, item]) => { + if (SENSITIVE_PAYLOAD_KEY_PATTERN.test(key)) { + return [key, "[redacted]"]; + } + return [key, redactReleasePayload(item, depth + 1)]; + }) + ); + } + if (typeof value === "string") { + return redactSerializedReleasePayload(value, depth); + } + return value; +}; +const isFailureEvent = (type, severity) => { + const normalizedType = String(type || "").toLowerCase(); + const normalizedSeverity = String(severity || "").toLowerCase(); + return normalizedSeverity === "error" || normalizedSeverity === "warning" || normalizedType.includes("error") || normalizedType.includes("failed") || normalizedType.includes("failure"); +}; +const shouldSendEvent = (type, severity) => { + if (isFailureEvent(type, severity)) { + return true; + } + return releaseRuntimeStateMutable.capturePolicy.enabled === true; +}; +const omitCapturedBodiesWhenDisabled = (payload) => { + if (!payload || typeof payload !== "object") { + return payload; + } + const nextPayload = { ...payload }; + for (const key of ["request", "response"]) { + if (nextPayload[key] && typeof nextPayload[key] === "object" && hasOwn$1(nextPayload[key], "data")) { + nextPayload[key] = { + ...nextPayload[key], + data: CAPTURE_DISABLED_BODY_PLACEHOLDER + }; + } + } + return nextPayload; +}; +const sanitizeReleaseTimelinePayload = (type, severity, payload) => { + if (isFailureEvent(type, severity) && !releaseRuntimeStateMutable.capturePolicy.enabled) { + return omitCapturedBodiesWhenDisabled(payload); + } + return payload; +}; +const recordReleaseTimelineEvent = (type, payload = {}, options = {}) => { + const severity = options.severity || payload?.severity || "info"; + if (!shouldSendEvent(type, severity)) { + return false; + } + const event = { + type, + severity, + module_key: options.moduleKey || payload?.module_key || null, + route: options.route || payload?.route || (typeof window !== "undefined" ? window.location.pathname : null), + component: options.component || payload?.component || null, + request_id: options.requestId || payload?.request_id || null, + occurred_at: (/* @__PURE__ */ new Date()).toISOString(), + payload: redactReleasePayload(sanitizeReleaseTimelinePayload(type, severity, payload)) + }; + if (FRONTEND_FAILURE_EVENT_TYPES.has(type)) { + recentFrontendFailureEvents = [event, ...recentFrontendFailureEvents].slice(0, MAX_FRONTEND_FAILURE_BUFFER_SIZE); + } + pendingEvents = [...pendingEvents, event].slice(-MAX_QUEUE_SIZE); + scheduleReleaseTimelineFlush(); + return true; +}; +const getRecentFrontendFailureEvents = () => recentFrontendFailureEvents.map((event) => ({ + ...event, + payload: redactReleasePayload(event.payload) +})); +const browserInfoFromUserAgent = (userAgent = "") => { + const ua = String(userAgent || ""); + const matchers = [ + ["Edge", /Edg\/([\d.]+)/], + ["Chrome", /Chrome\/([\d.]+)/], + ["Firefox", /Firefox\/([\d.]+)/], + ["Safari", /Version\/([\d.]+).*Safari/] + ]; + for (const [name, pattern] of matchers) { + const match = ua.match(pattern); + if (match) { + return { name, version: match[1] || null }; + } + } + return { name: "Unknown", version: null }; +}; +const osInfoFromUserAgent = (userAgent = "") => { + const ua = String(userAgent || ""); + const matchers = [ + ["Windows", /Windows NT ([\d.]+)/], + ["Android", /Android ([\d.]+)/], + ["iOS", /(?:iPhone|iPad).*OS ([\d_]+)/], + ["macOS", /Mac OS X ([\d_]+)/], + ["Linux", /Linux/] + ]; + for (const [name, pattern] of matchers) { + const match = ua.match(pattern); + if (match) { + return { name, version: match[1] ? String(match[1]).replace(/_/g, ".") : null }; + } + } + return { name: "Unknown", version: null }; +}; +const currentDeviceType = () => { + if (typeof window === "undefined") { + return null; + } + const width = Number(window.innerWidth || 0); + if (width > 0 && width < 769) { + return "mobile"; + } + if (width >= 769 && width < 1024) { + return "tablet"; + } + return "desktop"; +}; +const versionLabel = (version) => version?.version_label || version?.label || null; +const commitSha = (version) => version?.commit_sha || version?.commit || null; +const RELEASE_SERVICE_DEFINITIONS = Object.freeze([ + { key: "frontend", label: "Frontend", kind: "app" }, + { key: "api", label: "API", kind: "app" }, + { key: "database", label: "Database", kind: "data" }, + { key: "redis", label: "Redis", kind: "data" }, + { key: "minio", label: "MinIO", kind: "data" } +]); +const RELEASE_MISSING_LABELS = Object.freeze({ + release_bundle: "Release bundle", + frontend_version: "Frontend version", + frontend_base_url: "Frontend URL", + api_version: "API version", + api_base_url: "API URL", + database_service: "Database service", + redis_service: "Redis service", + minio_service: "MinIO service" +}); +const isPlainRecord = (value) => Boolean(value && typeof value === "object" && !Array.isArray(value)); +const firstFilledString = (...values) => { + for (const value of values) { + const normalized = String(value ?? "").trim(); + if (normalized) { + return normalized; + } + } + return ""; +}; +const releaseRuntimeUrlsForDisplay = (runtime = {}) => { + const urls = isPlainRecord(runtime?.urls) ? runtime.urls : {}; + return { + frontend: normalizeRuntimeBaseUrl(runtime.frontendBaseUrl ?? runtime.frontend_base_url ?? urls.frontend_base_url, { + allowRelative: false + }), + api: normalizeRuntimeBaseUrl(runtime.apiBaseUrl ?? runtime.api_base_url ?? urls.api_base_url) + }; +}; +const releaseRuntimeTraceId = (runtime = {}) => firstFilledString(runtime.traceId, runtime.trace_id); +const releaseRuntimeGeneratedAt = (runtime = {}) => firstFilledString(runtime.generatedAt, runtime.generated_at); +const releaseShortText = (value, length = 12) => { + const normalized = firstFilledString(value); + if (!normalized) { + return ""; + } + return normalized.length > length ? normalized.slice(0, length) : normalized; +}; +const releaseCommitValue = (version = null) => { + if (!isPlainRecord(version)) { + return ""; + } + const commit = version.commit; + if (isPlainRecord(commit)) { + return firstFilledString(commit.sha, commit.commit_sha); + } + return firstFilledString(version.commit_sha, commit); +}; +const releaseVersionPrimaryText = (version = null, fallback = "Missing version") => { + if (!isPlainRecord(version)) { + return fallback; + } + return firstFilledString(version.version_label, version.tag, releaseShortText(releaseCommitValue(version)), fallback); +}; +const releaseVersionSecondaryText = (version = null) => { + if (!isPlainRecord(version)) { + return ""; + } + const parts = []; + const commit = releaseShortText(releaseCommitValue(version)); + const repository = firstFilledString(version.repository); + const branch = firstFilledString(version.branch); + if (commit && commit !== firstFilledString(version.version_label, version.tag)) { + parts.push(commit); + } + if (repository || branch) { + parts.push(branch ? `${repository || "repository"}#${branch}` : repository); + } + return parts.join(" - "); +}; +const releaseStatusTone = (status = "") => { + const normalized = String(status || "").trim().toLowerCase(); + if ([ + "failed", + "error", + "critical", + "service_unhealthy", + "unhealthy", + "degraded", + "reconcile_failed", + "restart_failed", + "provision_blocked" + ].includes(normalized)) { + return "danger"; + } + if ([ + "missing", + "missing_value", + "not_configured", + "unconfigured", + "deployment_in_progress", + "warning", + "pending", + "queued", + "running", + "deploying", + "building", + "provisioning", + "unknown" + ].includes(normalized)) { + return "warning"; + } + return "ok"; +}; +const releaseServiceStatus = (service = null, fallback = "connected") => firstFilledString(service?.deployment_status, service?.availability_state, service?.status, service?.state, fallback); +const releaseServicePrimaryText = (service = null) => { + if (!isPlainRecord(service)) { + return ""; + } + const name = firstFilledString( + service.resource_name, + service.label, + service.coolify_service_uuid, + service.health_url, + service.repository + ); + const id = Number(service.id || service.target_id || 0); + return [name, id > 0 ? `#${id}` : ""].filter(Boolean).join(" "); +}; +const releaseServiceSecondaryText = (service = null) => { + if (!isPlainRecord(service)) { + return ""; + } + const parts = []; + const resourceUuid = firstFilledString(service.resource_uuid); + const coolifyServiceUuid = firstFilledString(service.coolify_service_uuid); + const instanceLabel = firstFilledString(service.instance_label, service.coolify_instance_label); + const repository = firstFilledString(service.repository); + const branch = firstFilledString(service.branch); + const replication = isPlainRecord(service.replication) ? service.replication : null; + const replicationStatus = firstFilledString(replication?.last_status?.status, replication?.status); + if (resourceUuid) { + parts.push(`resource ${releaseShortText(resourceUuid)}`); + } + if (coolifyServiceUuid && coolifyServiceUuid !== resourceUuid) { + parts.push(`service ${releaseShortText(coolifyServiceUuid)}`); + } + if (repository || branch) { + parts.push(branch ? `${repository || "repository"}#${branch}` : repository); + } + if (instanceLabel) { + parts.push(instanceLabel); + } + if (replicationStatus) { + parts.push(`replication ${replicationStatus}`); + } + return parts.join(" - "); +}; +const releaseServiceForKey = (serviceSet = null, key = "") => { + if (!isPlainRecord(serviceSet)) { + return null; + } + const stack = isPlainRecord(serviceSet.stack) ? serviceSet.stack : {}; + const dataServices = isPlainRecord(serviceSet.data_services) ? serviceSet.data_services : {}; + const targets = isPlainRecord(serviceSet.targets) ? serviceSet.targets : {}; + const service = stack[key] || dataServices[key] || targets[key] || null; + return isPlainRecord(service) ? service : null; +}; +const buildReleaseSessionSummary = (runtime = releaseRuntimeStateMutable, options = {}) => { + const versions = isPlainRecord(runtime?.versions) ? runtime.versions : {}; + const channel = isPlainRecord(runtime?.channel) ? runtime.channel : null; + const availability = isPlainRecord(runtime?.availability) ? runtime.availability : {}; + const missing = normalizeReadinessMissingValues$1(availability.missing); + const missingLookup = new Set(missing); + const isDefaultChannel = channel?.default_channel === true || channel?.default_channel === 1 || String(channel?.slug || "").toLowerCase() === "stable"; + const includeInfrastructureDetails = options?.includeInfrastructureDetails === true; + const urls = includeInfrastructureDetails ? releaseRuntimeUrlsForDisplay(runtime) : { frontend: "", api: "" }; + const frontendVersion = isPlainRecord(versions.frontend) ? versions.frontend : null; + const apiVersion = isPlainRecord(versions.api) ? versions.api : null; + const bundle = isPlainRecord(versions.bundle) ? versions.bundle : null; + const bundleId = versions.bundle_id || bundle?.id || null; + const rawServiceSet = isPlainRecord(versions.service_set) ? versions.service_set : isPlainRecord(bundle?.service_set) ? bundle.service_set : null; + const serviceSet = includeInfrastructureDetails ? rawServiceSet : null; + const defaultSharedLabel = "Default/shared runtime"; + const missingLabels = missing.map((key) => RELEASE_MISSING_LABELS[key] || key.replace(/_/g, " ")); + const availabilityConfigured = missing.length === 0 ? true : availability.configured !== false && availability.status !== "unconfigured"; + const availabilityStatus = availabilityConfigured && ["", "unconfigured", "missing_target"].includes(String(availability.status || "")) ? "ready" : firstFilledString(availability.status, availabilityConfigured ? "ready" : "unconfigured"); + const buildAppRow = (key, label, version, url) => { + const missingVersionKey = `${key}_version`; + const missingUrlKey = `${key}_base_url`; + const missingKey = missingLookup.has(missingVersionKey) ? missingVersionKey : missingLookup.has(missingUrlKey) ? missingUrlKey : ""; + const usesRegularFrontend = key === "frontend" && !missingKey && !version && !url && !isDefaultChannel; + const fallback = isDefaultChannel ? defaultSharedLabel : usesRegularFrontend ? "Regular frontend" : `Missing ${label} version`; + const status = missingKey ? "missing value" : usesRegularFrontend ? "regular" : isDefaultChannel && !version && !url ? "shared" : firstFilledString(version?.status, url ? "active" : "unknown"); + const primaryText = releaseVersionPrimaryText(version, fallback); + const secondaryText = includeInfrastructureDetails ? releaseVersionSecondaryText(version) : ""; + const displayUrl = includeInfrastructureDetails ? url || "" : ""; + return { + key, + label, + status, + tone: missingKey ? "warning" : releaseStatusTone(status), + primaryText, + secondaryText, + url: displayUrl, + title: [primaryText, secondaryText, displayUrl].filter(Boolean).join(" - "), + missingLabel: missingKey ? RELEASE_MISSING_LABELS[missingKey] || missingKey : "" + }; + }; + const buildServiceRow = ({ key, label }) => { + const service = releaseServiceForKey(serviceSet, key); + const missingKey = missingLookup.has(`${key}_service`) ? `${key}_service` : ""; + if (service) { + const status2 = releaseServiceStatus(service); + return { + key, + label, + status: status2, + tone: releaseStatusTone(status2), + primaryText: releaseServicePrimaryText(service) || "Connected service", + secondaryText: releaseServiceSecondaryText(service), + title: [ + releaseServicePrimaryText(service), + releaseServiceSecondaryText(service), + firstFilledString(service.health_url) + ].filter(Boolean).join(" - "), + missingLabel: "" + }; + } + const fallbackText = missingKey ? `Missing ${label} service` : defaultSharedLabel; + const status = missingKey ? "missing" : "shared"; + return { + key, + label, + status, + tone: missingKey ? "warning" : "ok", + primaryText: fallbackText, + secondaryText: "", + title: fallbackText, + missingLabel: missingKey ? RELEASE_MISSING_LABELS[missingKey] || missingKey : "" + }; + }; + return { + channelLabel: firstFilledString(channel?.name, channel?.slug, isDefaultChannel ? "Stable" : "Unknown channel"), + channelSlug: firstFilledString(channel?.slug), + traceId: releaseRuntimeTraceId(runtime) || "unknown", + generatedAt: releaseRuntimeGeneratedAt(runtime) || "unknown", + availabilityStatus, + availabilityTone: !availabilityConfigured || missing.length > 0 ? "warning" : releaseStatusTone(availabilityStatus), + bundleLabel: bundleId ? `#${bundleId}${firstFilledString(bundle?.version_label) ? ` ${bundle.version_label}` : ""}` : defaultSharedLabel, + bundleStatus: firstFilledString(bundle?.status, bundleId ? "active" : "shared"), + serviceSetLabel: serviceSet ? firstFilledString(serviceSet.name, serviceSet.slug, serviceSet.id ? `#${serviceSet.id}` : "Connected") : rawServiceSet ? "Restricted to release operators" : defaultSharedLabel, + missingLabels, + appRows: [ + buildAppRow("frontend", "Frontend", frontendVersion, urls.frontend), + buildAppRow("api", "API", apiVersion, urls.api) + ], + serviceRows: includeInfrastructureDetails || !rawServiceSet ? RELEASE_SERVICE_DEFINITIONS.map(buildServiceRow) : [] + }; +}; +const buildCurrentReleaseHeaders = () => { + const frontendVersion = releaseRuntimeStateMutable.versions?.frontend || {}; + const fallbackFrontendVersion = undefined || undefined || "unknown"; + return buildReleaseHeaders({ + traceId: releaseRuntimeStateMutable.traceId, + channelSlug: releaseRuntimeStateMutable.channel?.slug || "", + frontendVersion: commitSha(frontendVersion) || versionLabel(frontendVersion) || fallbackFrontendVersion + }); +}; +const buildReleaseTimelineContext = () => { + const userAgent = typeof navigator !== "undefined" ? navigator.userAgent : ""; + const browser = browserInfoFromUserAgent(userAgent); + const os = osInfoFromUserAgent(userAgent); + const frontendVersion = releaseRuntimeStateMutable.versions?.frontend || {}; + const apiVersion = releaseRuntimeStateMutable.versions?.api || {}; + const fallbackFrontendVersion = undefined || "unknown"; + return { + trace_id: releaseRuntimeStateMutable.traceId, + source: releaseRuntimeStateMutable.source, + requested_source: releaseRuntimeStateMutable.requestedSource, + channel_slug: releaseRuntimeStateMutable.channel?.slug || null, + route_path: typeof window !== "undefined" ? window.location.pathname : null, + device: { + type: currentDeviceType() + }, + browser, + os, + viewport: typeof window !== "undefined" ? { + width: window.innerWidth, + height: window.innerHeight, + device_pixel_ratio: window.devicePixelRatio || 1 + } : null, + frontend: { + version_label: versionLabel(frontendVersion) || fallbackFrontendVersion, + commit_sha: commitSha(frontendVersion) || fallbackFrontendVersion + }, + api: { + version_label: versionLabel(apiVersion), + commit_sha: commitSha(apiVersion) + }, + frontend_version: versionLabel(frontendVersion) || fallbackFrontendVersion, + frontend_commit_sha: commitSha(frontendVersion) || fallbackFrontendVersion, + api_version: versionLabel(apiVersion), + api_commit_sha: commitSha(apiVersion) + }; +}; +const scheduleReleaseTimelineFlush = () => { + if (flushTimer !== null || typeof window === "undefined") { + return; + } + flushTimer = window.setTimeout(() => { + flushTimer = null; + void flushReleaseTimelineEvents(); + }, 250); +}; +const flushReleaseTimelineEvents = async () => { + if (pendingEvents.length === 0) { + return { accepted: 0 }; + } + const events = pendingEvents; + pendingEvents = []; + const body = { + events, + context: buildReleaseTimelineContext() + }; + try { + if (typeof customTransport === "function") { + return await customTransport(body); + } + const headers = { + "Content-Type": "application/json", + ...buildCurrentReleaseHeaders() + }; + const token = typeof window !== "undefined" ? window.localStorage.getItem("token") : null; + if (token) { + headers.Authorization = `Bearer ${token}`; + } + const response = await fetch(resolveReleaseApiUrl("/release/timeline/events"), { + method: "POST", + headers, + body: JSON.stringify(body), + keepalive: true + }); + return response.ok ? response.json().catch(() => ({ accepted: events.length })) : { accepted: 0 }; + } catch { + pendingEvents = [...events, ...pendingEvents].slice(-MAX_QUEUE_SIZE); + return { accepted: 0 }; + } +}; +const installReleaseErrorInstrumentation = (app, router) => { + const previousErrorHandler = app?.config?.errorHandler; + const previousWarnHandler = app?.config?.warnHandler; + const invalidateCachesAfterError = (context) => { + invalidateFrontendCachesAfterError().catch((error) => { + console.warn(`Failed to invalidate frontend caches after ${context}:`, error); + }); + }; + if (app?.config) { + app.config.errorHandler = (error, instance, info) => { + invalidateCachesAfterError("Vue component error"); + recordReleaseTimelineEvent( + "vue_component_error", + { + message: error?.message || String(error), + stack: error?.stack || null, + info, + component: instance?.type?.name || instance?.type?.__name || null + }, + { + severity: "error", + moduleKey: "frontend", + component: instance?.type?.name || instance?.type?.__name || null + } + ); + if (typeof previousErrorHandler === "function") { + previousErrorHandler(error, instance, info); + } else { + console.error(error); + } + }; + app.config.warnHandler = (message, instance, trace) => { + if (releaseRuntimeStateMutable.capturePolicy.enabled) { + recordReleaseTimelineEvent( + "vue_component_warning", + { + message, + trace, + component: instance?.type?.name || instance?.type?.__name || null + }, + { + severity: "warning", + moduleKey: "frontend", + component: instance?.type?.name || instance?.type?.__name || null + } + ); + } + if (typeof previousWarnHandler === "function") { + previousWarnHandler(message, instance, trace); + } + }; + } + if (typeof window !== "undefined") { + window.addEventListener("error", (event) => { + invalidateCachesAfterError("window error"); + recordReleaseTimelineEvent( + "window_error", + { + message: event.message, + filename: event.filename, + lineno: event.lineno, + colno: event.colno, + stack: event.error?.stack || null + }, + { severity: "error", moduleKey: "frontend" } + ); + }); + window.addEventListener("unhandledrejection", (event) => { + invalidateCachesAfterError("unhandled rejection"); + recordReleaseTimelineEvent( + "unhandled_rejection", + { + message: event.reason?.message || String(event.reason), + stack: event.reason?.stack || null + }, + { severity: "error", moduleKey: "frontend" } + ); + }); + } + if (router?.afterEach) { + router.afterEach((to, from) => { + if (!releaseRuntimeStateMutable.capturePolicy.enabled) { + return; + } + recordReleaseTimelineEvent( + "route_change", + { + from: from?.fullPath || null, + to: to?.fullPath || null + }, + { severity: "info", moduleKey: "frontend", route: to?.fullPath || null } + ); + }); + } +}; +const __resetReleaseTimelineForTests = () => { + pendingEvents = []; + recentFrontendFailureEvents = []; + if (flushTimer !== null && typeof window !== "undefined") { + window.clearTimeout(flushTimer); + } + flushTimer = null; + customTransport = null; + releaseRuntimeStateMutable.source = null; + releaseRuntimeStateMutable.requestedSource = null; + releaseRuntimeStateMutable.traceId = "test-trace"; + releaseRuntimeStateMutable.channel = null; + releaseRuntimeStateMutable.availableChannels = []; + releaseRuntimeStateMutable.versions = { frontend: null, api: null, service_set: null, bundle_id: null, bundle: null }; + releaseRuntimeStateMutable.frontendBaseUrl = null; + releaseRuntimeStateMutable.apiBaseUrl = null; + releaseRuntimeStateMutable.availability = { + configured: true, + missing: [], + status: "ready", + explicit: false + }; + releaseRuntimeStateMutable.capturePolicy = { + enabled: false, + capture_level: "metadata", + all_failure_metadata: true, + retention_days: 14 + }; + releaseRuntimeStateMutable.generatedAt = null; +}; +const __setReleaseTimelineTransportForTests = (transport) => { + customTransport = transport; +}; + +const cloneObject = (value) => ({ ...(value || {}) }); + +const queueConfig = { + concurrencyByMethod: cloneObject(REQUEST_QUEUE_CONFIG.concurrency), + spacingMs: REQUEST_QUEUE_CONFIG.spacingMs, + retryByStatusCode: cloneObject(REQUEST_QUEUE_CONFIG.retryByStatusCode), + retryDelayBaseMs: REQUEST_QUEUE_CONFIG.retryDelay.baseMs, + retryDelayMaxMs: REQUEST_QUEUE_CONFIG.retryDelay.maxMs, + retryDelayJitterMs: REQUEST_QUEUE_CONFIG.retryDelay.jitterMs, + recentRequestsLimit: REQUEST_QUEUE_CONFIG.inspector.recentRequestsLimit, + errorHistoryLimit: REQUEST_QUEUE_CONFIG.inspector.errorHistoryLimit, + missingPermissionsLimit: REQUEST_QUEUE_CONFIG.inspector.missingPermissionsLimit, + componentPermissionReportWindowMs: REQUEST_QUEUE_CONFIG.inspector.componentPermissionReportWindowMs, + payloadMaxChars: REQUEST_QUEUE_CONFIG.inspector.payloadMaxChars, +}; + +const requestQueueStateMutable = reactive({ + batchId: 0, + pending: 0, + active: 0, + batchTotal: 0, + batchCompleted: 0, + batchFailed: 0, + activeRequests: [], + recentRequests: [], + requestInsights: {}, + errorRequests: [], + missingPermissions: [], + networkTotals: { + outgoingRequests: 0, + ingoingResponses: 0, + outgoingBytes: 0, + ingoingBytes: 0, + }, +}); + +const requestQueue = []; +const activeWorkersByKey = {}; +let activeWorkers = 0; +let trackedActiveWorkers = 0; +let trackedPendingJobs = 0; +let requestIdCounter = 0; +let drainTimer = null; +let lastRequestStartedAt = 0; +const recentComponentPermissionReports = {}; + +const isQueueIdle = () => requestQueue.length === 0 && activeWorkers === 0; + +const startBatchIfNeeded = () => { + if (!isQueueIdle()) { + return; + } + + requestQueueStateMutable.batchId += 1; + requestQueueStateMutable.batchTotal = 0; + requestQueueStateMutable.batchCompleted = 0; + requestQueueStateMutable.batchFailed = 0; + requestQueueStateMutable.recentRequests = []; +}; + +const syncQueueCounters = () => { + requestQueueStateMutable.pending = trackedPendingJobs; + requestQueueStateMutable.active = trackedActiveWorkers; +}; + +const normalizeMethod = (value) => { + if (typeof value !== "string" || value.trim().length === 0) { + return "GET"; + } + return value.trim().toUpperCase(); +}; + +const normalizeQueueGroup = (value) => { + if (typeof value !== "string") { + return ""; + } + + return value.trim().toUpperCase(); +}; + +const normalizeInsightKey = (value) => { + if (typeof value !== "string") { + return ""; + } + + return value.trim().toLowerCase(); +}; + +const normalizeTraceContext = (value) => { + if (typeof value === "string") { + return { component: value.trim(), trace: null }; + } + + if (!value || typeof value !== "object") { + return null; + } + + const component = String(value.component || value.owner || value.source || "").trim(); + const trace = String(value.trace || value.componentTrace || value.stack || "").trim(); + if (!component && !trace) { + return null; + } + + return { + component: component || null, + trace: trace || null, + }; +}; + +const normalizeUrl = (value) => { + if (typeof value !== "string" || value.trim().length === 0) { + return "(unknown endpoint)"; + } + return value.trim(); +}; + +const redactHeaders = (headers) => { + if (!headers || typeof headers !== "object") { + return headers ?? null; + } + + const normalized = {}; + Object.entries(headers).forEach(([key, value]) => { + if (/authorization|x-api-key|token/i.test(String(key))) { + normalized[key] = "***"; + return; + } + normalized[key] = value; + }); + return normalized; +}; + +const toSafeText = (value) => { + if (value === null || value === undefined) { + return ""; + } + + let text; + if (typeof value === "string") { + text = value; + } else { + try { + text = JSON.stringify(value, null, 2); + } catch (_error) { + text = String(value); + } + } + + const maxChars = Math.max(200, Number(queueConfig.payloadMaxChars) || 4000); + if (text.length <= maxChars) { + return text; + } + + return `${text.slice(0, maxChars)}\n... [truncated]`; +}; + +const toRedactedPayload = (value) => redactReleasePayload(value); + +const measureTextBytes = (value) => { + const text = toSafeText(value); + if (!text) { + return 0; + } + + if (typeof TextEncoder === "function") { + return new TextEncoder().encode(text).length; + } + + return text.length; +}; + +const estimateRequestBytes = (job, method, url) => measureTextBytes({ + method, + url, + params: job?.requestData?.params ?? null, + data: job?.requestData?.data ?? null, + headers: redactHeaders(job?.requestData?.headers ?? null), +}); + +const estimateResponseBytes = (response, fallbackMessage = null) => measureTextBytes({ + status: response?.status ?? null, + statusText: response?.statusText ?? null, + data: response?.data ?? fallbackMessage, + headers: redactHeaders(response?.headers ?? null), +}); + +const addNetworkTotals = ({ + outgoingRequests = 0, + ingoingResponses = 0, + outgoingBytes = 0, + ingoingBytes = 0, +} = {}) => { + requestQueueStateMutable.networkTotals = { + outgoingRequests: Number(requestQueueStateMutable.networkTotals?.outgoingRequests || 0) + + Math.max(0, Number(outgoingRequests) || 0), + ingoingResponses: Number(requestQueueStateMutable.networkTotals?.ingoingResponses || 0) + + Math.max(0, Number(ingoingResponses) || 0), + outgoingBytes: Number(requestQueueStateMutable.networkTotals?.outgoingBytes || 0) + + Math.max(0, Number(outgoingBytes) || 0), + ingoingBytes: Number(requestQueueStateMutable.networkTotals?.ingoingBytes || 0) + + Math.max(0, Number(ingoingBytes) || 0), + }; +}; + +const parseJsonIfString = (value) => { + if (typeof value !== "string") { + return value; + } + + const trimmedValue = value.trim(); + if (!trimmedValue.startsWith("{") && !trimmedValue.startsWith("[")) { + return value; + } + + try { + return JSON.parse(trimmedValue); + } catch (_error) { + return value; + } +}; + +const normalizeResponseData = (value) => { + const parsed = parseJsonIfString(value); + if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) { + return parsed; + } + + const parsedData = parseJsonIfString(parsed.data); + if (parsedData === parsed.data) { + return parsed; + } + + return { + ...parsed, + data: parsedData, + }; +}; + +const extractMissingPermissions = (error) => { + const responseData = normalizeResponseData(error?.response?.data); + const messageCandidates = [ + responseData?.data?.message, + responseData?.message, + error?.message, + ]; + const hasMissingPermissionMessage = messageCandidates.some((message) => + typeof message === "string" && message.toLowerCase().includes("missing permission") + ); + + if (!hasMissingPermissionMessage) { + return []; + } + + const permissions = responseData?.data?.permissions ?? responseData?.permissions ?? []; + if (!Array.isArray(permissions)) { + return []; + } + + return permissions + .map((permission) => String(permission || "").trim()) + .filter((permission) => permission.length > 0); +}; + +const getMethodConcurrencyLimit = (method) => { + const normalizedMethod = normalizeMethod(method); + const configuredLimit = queueConfig.concurrencyByMethod[normalizedMethod] + ?? queueConfig.concurrencyByMethod.DEFAULT + ?? 1; + return Math.max(1, Number(configuredLimit) || 1); +}; + +const getJobConcurrencyKey = (job) => { + const queueGroup = normalizeQueueGroup(job.queueGroup); + if (queueGroup) { + return `GROUP:${queueGroup}`; + } + + return `METHOD:${normalizeMethod(job.method)}`; +}; + +const getJobConcurrencyLimit = (job) => { + const configuredLimit = Number.parseInt(String(job.concurrencyLimit ?? ""), 10); + if (Number.isInteger(configuredLimit) && configuredLimit > 0) { + return configuredLimit; + } + + return getMethodConcurrencyLimit(job.method); +}; + +const canRunJob = (job) => { + const concurrencyKey = getJobConcurrencyKey(job); + const activeForKey = Number(activeWorkersByKey[concurrencyKey] || 0); + return activeForKey < getJobConcurrencyLimit(job); +}; + +const getNextRunnableJobIndex = () => { + for (let index = 0; index < requestQueue.length; index += 1) { + if (canRunJob(requestQueue[index])) { + return index; + } + } + return -1; +}; + +const clearDrainTimer = () => { + if (drainTimer !== null) { + clearTimeout(drainTimer); + drainTimer = null; + } +}; + +const scheduleDrain = (delayMs = 0) => { + if (delayMs > 0) { + if (drainTimer !== null) { + return; + } + + drainTimer = setTimeout(() => { + drainTimer = null; + void drainQueue(); + }, delayMs); + return; + } + + Promise.resolve().then(() => { + void drainQueue(); + }); +}; + +const wait$2 = (durationMs) => new Promise((resolve) => { + setTimeout(resolve, Math.max(0, durationMs || 0)); +}); + +const isAbortSignal = (signal) => + signal && typeof signal === "object" && typeof signal.aborted === "boolean"; + +const isRequestAbortError = (error) => + error?.name === "AbortError" || error?.name === "CanceledError" || error?.code === "ERR_CANCELED"; + +const createAbortError = () => { + if (typeof DOMException === "function") { + return new DOMException("Request aborted.", "AbortError"); + } + + const error = new Error("Request aborted."); + error.name = "AbortError"; + error.code = "ERR_CANCELED"; + return error; +}; + +const isJobAborted = (job) => isAbortSignal(job?.signal) && job.signal.aborted === true; + +const decrementBatchTotalForCanceledJob = () => { + const completedOrFailed = Number(requestQueueStateMutable.batchCompleted || 0) + + Number(requestQueueStateMutable.batchFailed || 0); + requestQueueStateMutable.batchTotal = Math.max( + completedOrFailed, + Number(requestQueueStateMutable.batchTotal || 0) - 1 + ); +}; + +const getErrorStatusCode = (error) => { + const code = Number.parseInt(error?.response?.status, 10); + return Number.isFinite(code) ? code : null; +}; + +const getResponseStatusCode = (response) => { + const code = Number.parseInt(response?.status, 10); + return Number.isFinite(code) ? code : null; +}; + +const getHeaderValue = (headers, name) => { + if (!headers || typeof name !== "string") { + return null; + } + + if (typeof headers.get === "function") { + const value = headers.get(name); + return typeof value === "string" && value.length > 0 ? value : null; + } + + const normalizedName = name.toLowerCase(); + const matchingKey = Object.keys(headers).find((key) => String(key).toLowerCase() === normalizedName); + if (!matchingKey) { + return null; + } + + const value = headers[matchingKey]; + return typeof value === "string" && value.length > 0 ? value : null; +}; + +const getServerTimingHeader = (response) => getHeaderValue(response?.headers, "server-timing"); + +const getRetriesForStatusCode = (statusCode, retryByStatusCode) => { + if (statusCode === null) { + return 0; + } + + const retries = Number(retryByStatusCode?.[statusCode] ?? 0); + return Number.isFinite(retries) && retries > 0 ? Math.floor(retries) : 0; +}; + +const computeRetryDelayMs = (attemptNumber) => { + const exponentialDelay = queueConfig.retryDelayBaseMs * (2 ** Math.max(0, attemptNumber)); + const cappedDelay = Math.min(queueConfig.retryDelayMaxMs, exponentialDelay); + const jitter = queueConfig.retryDelayJitterMs > 0 + ? Math.floor(Math.random() * (queueConfig.retryDelayJitterMs + 1)) + : 0; + return Math.max(0, cappedDelay + jitter); +}; + +const shouldRetryAttempt = (error, job, attemptNumber) => { + if (isRequestAbortError(error) || isJobAborted(job)) { + return false; + } + + const statusCode = getErrorStatusCode(error); + const retryByStatusCode = job.retryByStatusCode ?? queueConfig.retryByStatusCode; + const retriesForCode = getRetriesForStatusCode(statusCode, retryByStatusCode); + if (attemptNumber >= retriesForCode) { + return false; + } + + if (typeof job.shouldRetry === "function") { + return job.shouldRetry(error, { attemptNumber, statusCode }) === true; + } + + return true; +}; + +const executeJobWithRetries = async (job) => { + let attemptCount = 0; + const shouldRecordNetworkTotals = job.skipNetworkTotals !== true; + + while (true) { + if (isJobAborted(job)) { + throw createAbortError(); + } + + attemptCount += 1; + const method = normalizeMethod(job.method); + const url = normalizeUrl(job.url); + if (shouldRecordNetworkTotals) { + addNetworkTotals({ + outgoingRequests: 1, + outgoingBytes: job.skipRequestByteAccounting ? 0 : estimateRequestBytes(job, method, url), + }); + } + try { + const response = await job.requestFactory(); + if (shouldRecordNetworkTotals) { + addNetworkTotals({ + ingoingResponses: 1, + ingoingBytes: job.skipResponseByteAccounting ? 0 : estimateResponseBytes(response), + }); + } + return { response, attemptCount }; + } catch (error) { + if (shouldRecordNetworkTotals && error?.response) { + addNetworkTotals({ + ingoingResponses: 1, + ingoingBytes: job.skipResponseByteAccounting + ? 0 + : estimateResponseBytes(error.response, error?.message ?? "Request failed"), + }); + } + const attemptNumber = attemptCount - 1; + if (!shouldRetryAttempt(error, job, attemptNumber)) { + error.__queueAttemptCount = attemptCount; + throw error; + } + + const retryDelayMs = computeRetryDelayMs(attemptNumber); + if (retryDelayMs > 0) { + await wait$2(retryDelayMs); + } + } + } +}; + +const upsertActiveRequest = (job, startedAt) => { + const nextActive = [...requestQueueStateMutable.activeRequests, { + id: job.id, + method: normalizeMethod(job.method), + queueGroup: normalizeQueueGroup(job.queueGroup) || null, + url: job.url, + queuedAt: job.enqueuedAt, + startedAt, + }]; + requestQueueStateMutable.activeRequests = nextActive; +}; + +const removeActiveRequest = (requestId) => { + requestQueueStateMutable.activeRequests = requestQueueStateMutable.activeRequests.filter((item) => item.id !== requestId); +}; + +const pushRecentRequest = (entry) => { + const limit = Math.max(1, Number(queueConfig.recentRequestsLimit) || 8); + const next = [entry, ...requestQueueStateMutable.recentRequests]; + requestQueueStateMutable.recentRequests = next.slice(0, limit); +}; + +const upsertRequestInsight = (key, entry) => { + const normalizedKey = normalizeInsightKey(key); + if (!normalizedKey) { + return; + } + + requestQueueStateMutable.requestInsights[normalizedKey] = entry; +}; + +const pushErrorRequest = (entry) => { + const limit = Math.max(1, Number(queueConfig.errorHistoryLimit) || 10); + const next = [entry, ...requestQueueStateMutable.errorRequests]; + requestQueueStateMutable.errorRequests = next.slice(0, limit); +}; + +const pushMissingPermissions = (permissionEntries) => { + if (!Array.isArray(permissionEntries) || permissionEntries.length === 0) { + return; + } + + const now = Date.now(); + const existing = [...requestQueueStateMutable.missingPermissions]; + permissionEntries.forEach((entry) => { + const permission = String(entry?.permission || "").trim(); + const method = normalizeMethod(entry?.method); + const url = normalizeUrl(entry?.url); + const statusCode = entry?.statusCode ?? null; + const source = entry?.source ?? null; + if (!permission) { + return; + } + + const isComponentEntry = method === "COMPONENT"; + const index = existing.findIndex((item) => { + if (item.permission !== permission) { + return false; + } + if (isComponentEntry) { + return normalizeMethod(item.method) === "COMPONENT"; + } + return normalizeMethod(item.method) !== "COMPONENT"; + }); + if (index >= 0) { + existing[index] = { + ...existing[index], + method, + url, + statusCode, + source, + count: Number(existing[index].count || 0) + 1, + lastSeenAt: now, + }; + return; + } + + existing.push({ + permission, + method, + url, + statusCode, + source, + count: 1, + lastSeenAt: now, + }); + }); + + existing.sort((a, b) => { + const aPriority = normalizeMethod(a?.method) === "COMPONENT" ? 1 : 0; + const bPriority = normalizeMethod(b?.method) === "COMPONENT" ? 1 : 0; + if (aPriority !== bPriority) { + return aPriority - bPriority; + } + return Number(b.lastSeenAt || 0) - Number(a.lastSeenAt || 0); + }); + const limit = Math.max(1, Number(queueConfig.missingPermissionsLimit) || 20); + requestQueueStateMutable.missingPermissions = existing.slice(0, limit); +}; + +const reportComponentMissingPermission = (permission, options = {}) => { + const normalizedPermission = String(permission || "").trim(); + if (!normalizedPermission) { + return; + } + + const source = String(options?.source || "").trim() || "Component"; + const now = Date.now(); + const reportWindowMs = Math.max(0, Number(queueConfig.componentPermissionReportWindowMs) || 0); + const reportKey = `${normalizedPermission}::${source}`; + const lastReportedAt = Number(recentComponentPermissionReports[reportKey] || 0); + if (reportWindowMs > 0 && now - lastReportedAt < reportWindowMs) { + return; + } + + recentComponentPermissionReports[reportKey] = now; + pushMissingPermissions([{ + permission: normalizedPermission, + method: "COMPONENT", + url: source, + statusCode: null, + source, + }]); +}; + +const removePendingAbortListener = (job) => { + if ( + job?.abortPendingListener + && isAbortSignal(job.signal) + && typeof job.signal.removeEventListener === "function" + ) { + job.signal.removeEventListener("abort", job.abortPendingListener); + } + if (job) { + job.abortPendingListener = null; + } +}; + +const rejectCanceledQueuedJob = (job) => { + removePendingAbortListener(job); + if (job.trackProgressCounters !== false) { + trackedPendingJobs = Math.max(0, trackedPendingJobs - 1); + decrementBatchTotalForCanceledJob(); + syncQueueCounters(); + } + job.reject(createAbortError()); +}; + +const runJob = (job) => { + const method = normalizeMethod(job.method); + const concurrencyKey = getJobConcurrencyKey(job); + const queueGroup = normalizeQueueGroup(job.queueGroup) || null; + const startedAt = Date.now(); + + removePendingAbortListener(job); + + activeWorkers += 1; + activeWorkersByKey[concurrencyKey] = Number(activeWorkersByKey[concurrencyKey] || 0) + 1; + if (job.trackProgressCounters !== false) { + trackedActiveWorkers += 1; + } + lastRequestStartedAt = startedAt; + if (job.trackActiveRequest !== false) { + upsertActiveRequest(job, startedAt); + } + if (job.trackProgressCounters !== false) { + syncQueueCounters(); + } + + Promise.resolve() + .then(() => executeJobWithRetries(job)) + .then(({ response, attemptCount }) => { + const completedAt = Date.now(); + if (job.trackProgressCounters !== false) { + requestQueueStateMutable.batchCompleted += 1; + } + const completedEntry = { + id: job.id, + method, + queueGroup, + url: job.url, + success: true, + statusCode: getResponseStatusCode(response), + attemptCount, + queuedAt: job.enqueuedAt, + startedAt, + completedAt, + queueDurationMs: Math.max(0, startedAt - job.enqueuedAt), + requestDurationMs: Math.max(0, completedAt - startedAt), + serverTiming: getServerTimingHeader(response), + }; + upsertRequestInsight(job.insightKey, completedEntry); + if (job.recordRecentOnSuccess !== false) { + pushRecentRequest(completedEntry); + } + job.resolve(response); + }) + .catch((error) => { + const completedAt = Date.now(); + if (isRequestAbortError(error)) { + if (job.trackProgressCounters !== false) { + decrementBatchTotalForCanceledJob(); + } + job.reject(error); + return; + } + + const statusCode = getErrorStatusCode(error); + const attemptCount = Math.max(1, Number(error?.__queueAttemptCount) || 1); + const requestSnapshot = toRedactedPayload({ + method, + url: job.url, + params: job.requestData?.params ?? null, + data: job.requestData?.data ?? null, + headers: redactHeaders(job.requestData?.headers ?? null), + }); + const responseSnapshot = toRedactedPayload({ + status: statusCode, + statusText: error?.response?.statusText ?? null, + code: error?.code ?? null, + message: error?.message ?? "Request failed", + data: error?.response?.data ?? null, + headers: redactHeaders(error?.response?.headers ?? null), + }); + if (job.trackProgressCounters !== false) { + requestQueueStateMutable.batchFailed += 1; + } + const failedEntry = { + id: job.id, + method, + queueGroup, + url: job.url, + success: false, + statusCode, + attemptCount, + queuedAt: job.enqueuedAt, + startedAt, + completedAt, + queueDurationMs: Math.max(0, startedAt - job.enqueuedAt), + requestDurationMs: Math.max(0, completedAt - startedAt), + serverTiming: getServerTimingHeader(error?.response), + }; + upsertRequestInsight(job.insightKey, failedEntry); + pushRecentRequest(failedEntry); + pushErrorRequest({ + id: job.id, + method, + queueGroup, + url: job.url, + statusCode, + attemptCount, + requestDurationMs: Math.max(0, completedAt - startedAt), + serverTiming: getServerTimingHeader(error?.response), + request: requestSnapshot, + response: responseSnapshot, + traceContext: job.traceContext, + requestText: toSafeText(requestSnapshot), + responseText: toSafeText(responseSnapshot), + }); + recordReleaseTimelineEvent("request_failed", { + request_id: String(job.id), + method, + url: job.url, + statusCode, + attemptCount, + requestDurationMs: Math.max(0, completedAt - startedAt), + request: requestSnapshot, + response: responseSnapshot, + trace_context: job.traceContext, + }, { + severity: "error", + moduleKey: "requestqueue", + requestId: String(job.id), + route: job.url, + component: job.traceContext?.component || null, + }); + + const missingPermissions = extractMissingPermissions(error); + pushMissingPermissions( + missingPermissions.map((permission) => ({ + permission, + method, + url: job.url, + statusCode, + })) + ); + job.reject(error); + }) + .finally(() => { + activeWorkers -= 1; + if (job.trackProgressCounters !== false) { + trackedActiveWorkers = Math.max(0, trackedActiveWorkers - 1); + } + activeWorkersByKey[concurrencyKey] = Math.max(0, Number(activeWorkersByKey[concurrencyKey] || 1) - 1); + if (activeWorkersByKey[concurrencyKey] === 0) { + delete activeWorkersByKey[concurrencyKey]; + } + if (job.trackActiveRequest !== false) { + removeActiveRequest(job.id); + } + if (job.trackProgressCounters !== false) { + syncQueueCounters(); + } + scheduleDrain(); + }); +}; + +const drainQueue = async () => { + while (requestQueue.length > 0) { + const nextRunnableJobIndex = getNextRunnableJobIndex(); + if (nextRunnableJobIndex < 0) { + return; + } + + const elapsedSinceLastStart = Date.now() - lastRequestStartedAt; + const waitMs = Math.max(0, queueConfig.spacingMs - elapsedSinceLastStart); + + if (waitMs > 0) { + scheduleDrain(waitMs); + return; + } + + const [nextJob] = requestQueue.splice(nextRunnableJobIndex, 1); + if (isJobAborted(nextJob)) { + rejectCanceledQueuedJob(nextJob); + continue; + } + + if (nextJob.trackProgressCounters !== false) { + trackedPendingJobs = Math.max(0, trackedPendingJobs - 1); + syncQueueCounters(); + } + runJob(nextJob); + } +}; + +const enqueueRequest = (requestFactory, options = {}) => { + if (typeof requestFactory !== "function") { + throw new Error("enqueueRequest requires a function"); + } + + const method = normalizeMethod(options.method); + const url = normalizeUrl(options.url); + const signal = isAbortSignal(options.signal) ? options.signal : null; + if (signal?.aborted) { + return Promise.reject(createAbortError()); + } + + const trackProgressCounters = options.trackProgressCounters !== false; + if (trackProgressCounters) { + startBatchIfNeeded(); + } + + return new Promise((resolve, reject) => { + const job = { + id: ++requestIdCounter, + requestFactory, + resolve, + reject, + method, + url, + enqueuedAt: Date.now(), + requestData: options.requestData || null, + traceContext: normalizeTraceContext(options.traceContext), + retryByStatusCode: options.retryByStatusCode || null, + shouldRetry: typeof options.shouldRetry === "function" ? options.shouldRetry : null, + queueGroup: normalizeQueueGroup(options.queueGroup), + concurrencyLimit: options.concurrencyLimit || null, + skipRequestByteAccounting: options.skipRequestByteAccounting === true, + skipResponseByteAccounting: options.skipResponseByteAccounting === true, + skipNetworkTotals: options.skipNetworkTotals === true, + insightKey: normalizeInsightKey(options.insightKey), + recordRecentOnSuccess: options.recordRecentOnSuccess !== false, + trackActiveRequest: options.trackActiveRequest !== false, + trackProgressCounters, + signal, + abortPendingListener: null, + }; + + if (signal && typeof signal.addEventListener === "function") { + job.abortPendingListener = () => { + const pendingIndex = requestQueue.findIndex((pendingJob) => pendingJob.id === job.id); + if (pendingIndex < 0) { + return; + } + + requestQueue.splice(pendingIndex, 1); + rejectCanceledQueuedJob(job); + scheduleDrain(); + }; + signal.addEventListener("abort", job.abortPendingListener, { once: true }); + } + + requestQueue.push(job); + if (job.trackProgressCounters !== false) { + trackedPendingJobs += 1; + requestQueueStateMutable.batchTotal += 1; + syncQueueCounters(); + } + scheduleDrain(); + }); +}; + +const requestQueueState = readonly(requestQueueStateMutable); + +const clearErrorRequests = () => { + requestQueueStateMutable.errorRequests = []; +}; + +const clearMissingPermissions = () => { + requestQueueStateMutable.missingPermissions = []; + Object.keys(recentComponentPermissionReports).forEach((key) => { + delete recentComponentPermissionReports[key]; + }); +}; + +const __resetRequestQueueForTests = () => { + requestQueue.forEach(removePendingAbortListener); + requestQueue.length = 0; + activeWorkers = 0; + trackedActiveWorkers = 0; + trackedPendingJobs = 0; + requestIdCounter = 0; + Object.keys(activeWorkersByKey).forEach((key) => delete activeWorkersByKey[key]); + lastRequestStartedAt = 0; + clearDrainTimer(); + + requestQueueStateMutable.batchId = 0; + requestQueueStateMutable.pending = 0; + requestQueueStateMutable.active = 0; + requestQueueStateMutable.batchTotal = 0; + requestQueueStateMutable.batchCompleted = 0; + requestQueueStateMutable.batchFailed = 0; + requestQueueStateMutable.activeRequests = []; + requestQueueStateMutable.recentRequests = []; + requestQueueStateMutable.requestInsights = {}; + requestQueueStateMutable.errorRequests = []; + requestQueueStateMutable.missingPermissions = []; + requestQueueStateMutable.networkTotals = { + outgoingRequests: 0, + ingoingResponses: 0, + outgoingBytes: 0, + ingoingBytes: 0, + }; + + queueConfig.concurrencyByMethod = cloneObject(REQUEST_QUEUE_CONFIG.concurrency); + queueConfig.spacingMs = 0; + queueConfig.retryByStatusCode = cloneObject(REQUEST_QUEUE_CONFIG.retryByStatusCode); + queueConfig.retryDelayBaseMs = 0; + queueConfig.retryDelayMaxMs = 0; + queueConfig.retryDelayJitterMs = 0; + queueConfig.recentRequestsLimit = REQUEST_QUEUE_CONFIG.inspector.recentRequestsLimit; + queueConfig.errorHistoryLimit = REQUEST_QUEUE_CONFIG.inspector.errorHistoryLimit; + queueConfig.missingPermissionsLimit = REQUEST_QUEUE_CONFIG.inspector.missingPermissionsLimit; + queueConfig.componentPermissionReportWindowMs = REQUEST_QUEUE_CONFIG.inspector.componentPermissionReportWindowMs; + queueConfig.payloadMaxChars = REQUEST_QUEUE_CONFIG.inspector.payloadMaxChars; + Object.keys(recentComponentPermissionReports).forEach((key) => { + delete recentComponentPermissionReports[key]; + }); +}; + +const __configureRequestQueueForTests = ({ + concurrencyByMethod, + maxConcurrentGet, + maxConcurrentOther, + spacingMs, + retryByStatusCode, + retryDelayBaseMs, + retryDelayMaxMs, + retryDelayJitterMs, + recentRequestsLimit, + errorHistoryLimit, + missingPermissionsLimit, + componentPermissionReportWindowMs, + payloadMaxChars, +} = {}) => { + if (concurrencyByMethod && typeof concurrencyByMethod === "object") { + queueConfig.concurrencyByMethod = { + ...queueConfig.concurrencyByMethod, + ...concurrencyByMethod, + }; + } + + if (typeof maxConcurrentOther === "number" && maxConcurrentOther > 0) { + const normalized = Math.max(1, Math.floor(maxConcurrentOther)); + queueConfig.concurrencyByMethod.DEFAULT = normalized; + queueConfig.concurrencyByMethod.POST = normalized; + queueConfig.concurrencyByMethod.PATCH = normalized; + queueConfig.concurrencyByMethod.PUT = normalized; + queueConfig.concurrencyByMethod.DELETE = normalized; + } + + if (typeof maxConcurrentGet === "number" && maxConcurrentGet > 0) { + queueConfig.concurrencyByMethod.GET = Math.max(1, Math.floor(maxConcurrentGet)); + } + + if (typeof spacingMs === "number" && spacingMs >= 0) { + queueConfig.spacingMs = Math.floor(spacingMs); + } + + if (retryByStatusCode && typeof retryByStatusCode === "object") { + queueConfig.retryByStatusCode = cloneObject(retryByStatusCode); + } + + if (typeof retryDelayBaseMs === "number" && retryDelayBaseMs >= 0) { + queueConfig.retryDelayBaseMs = Math.floor(retryDelayBaseMs); + } + + if (typeof retryDelayMaxMs === "number" && retryDelayMaxMs >= 0) { + queueConfig.retryDelayMaxMs = Math.floor(retryDelayMaxMs); + } + + if (typeof retryDelayJitterMs === "number" && retryDelayJitterMs >= 0) { + queueConfig.retryDelayJitterMs = Math.floor(retryDelayJitterMs); + } + + if (typeof recentRequestsLimit === "number" && recentRequestsLimit > 0) { + queueConfig.recentRequestsLimit = Math.max(1, Math.floor(recentRequestsLimit)); + } + + if (typeof errorHistoryLimit === "number" && errorHistoryLimit > 0) { + queueConfig.errorHistoryLimit = Math.max(1, Math.floor(errorHistoryLimit)); + } + + if (typeof missingPermissionsLimit === "number" && missingPermissionsLimit > 0) { + queueConfig.missingPermissionsLimit = Math.max(1, Math.floor(missingPermissionsLimit)); + } + + if (typeof componentPermissionReportWindowMs === "number" && componentPermissionReportWindowMs >= 0) { + queueConfig.componentPermissionReportWindowMs = Math.floor(componentPermissionReportWindowMs); + } + + if (typeof payloadMaxChars === "number" && payloadMaxChars >= 200) { + queueConfig.payloadMaxChars = Math.floor(payloadMaxChars); + } +}; + +const _export_sfc = (sfc, props) => { + const target = sfc.__vccOpts || sfc; + for (const [key, val] of props) { + target[key] = val; + } + return target; +}; + +/** + * Get the selected customer number for X-Customer-Number header (used by subusers) + * @returns {number|null} + */ +const getSelectedCustomerNumber$2 = () => { + const stored = localStorage.getItem('selected_customer_number'); + return stored ? parseInt(stored) : null; +}; + +const MY_ACTIVE_WASH_ENDPOINT = '/modules/self-serve/lane/wash/my-active-wash'; +const ACTIVE_WASH_STARTED_STATUSES = new Set(['MACHINE_RELAY_ENABLED', 'MACHINE_STARTED']); +const SELF_SERVE_HARDWARE_QUEUE_GROUP = 'SELF_SERVE_HARDWARE'; +const POS_SCANNER_QUEUE_GROUP = 'POS_SCANNER'; +const POS_STRIPE_QUEUE_GROUP = 'POS_STRIPE'; +const FETCH_TRANSPORT = 'fetch'; +const SELF_SERVE_HARDWARE_ENDPOINTS = [ + '/modules/self-serve/lane/command', + '/modules/self-serve/lane/relay/', + '/modules/self-serve/lane/gate/open', + '/modules/self-serve/lane/force/machine', +]; +const POS_LATENCY_QUEUE_RULES = [ + { + endpoints: ['/modules/scanner/lpr'], + queueGroup: POS_SCANNER_QUEUE_GROUP, + concurrencyLimit: 1, + retryByStatusCode: {}, + skipRequestByteAccounting: true, + skipResponseByteAccounting: true, + skipNetworkTotals: true, + insightKey: 'scanner', + recordRecentOnSuccess: false, + trackActiveRequest: false, + trackProgressCounters: false, + }, + { + endpoints: ['/modules/stripe/invoice'], + queueGroup: POS_STRIPE_QUEUE_GROUP, + concurrencyLimit: 2, + retryByStatusCode: {}, + }, +]; + +const normalizeStatus = (status) => String(status || '').trim().toUpperCase(); + +const parseDateTimeMs = (value) => { + if (!value) { + return null; + } + + const timestamp = Date.parse(String(value)); + return Number.isFinite(timestamp) ? timestamp : null; +}; + +const hasActiveWashStartEvidence = (details) => { + const session = details?.session || {}; + const status = normalizeStatus(session?.status ?? details?.status); + + return ( + ACTIVE_WASH_STARTED_STATUSES.has(status) || + session?.machine_relay_enabled === true || + session?.machine_start_triggered === true || + details?.machine_relay_enabled === true || + details?.machine_start_triggered === true || + parseDateTimeMs(session?.wash_started_at) !== null || + parseDateTimeMs(session?.machine_start_triggered_at) !== null || + parseDateTimeMs(session?.machine_relay_enabled_at) !== null + ); +}; + +const normalizeActiveWashResponse = (url, method, response) => { + if (String(method || '').toUpperCase() !== 'GET' || !String(url || '').includes(MY_ACTIVE_WASH_ENDPOINT)) { + return response; + } + + const details = response?.data?.data; + if (!details?.in_progress || hasActiveWashStartEvidence(details)) { + return response; + } + + return { + ...response, + data: { + ...response.data, + data: { + ...details, + in_progress: false, + }, + }, + }; +}; + +const isSelfServeHardwareMutation = (url, method) => { + const normalizedMethod = String(method || '').trim().toUpperCase(); + if (normalizedMethod === 'GET') { + return false; + } + + const normalizedUrl = String(url || ''); + return SELF_SERVE_HARDWARE_ENDPOINTS.some((endpoint) => normalizedUrl.includes(endpoint)); +}; + +const findPosLatencyQueueRule = (url, method) => { + const normalizedMethod = String(method || '').trim().toUpperCase(); + if (normalizedMethod === 'GET') { + return null; + } + + const normalizedUrl = String(url || ''); + return POS_LATENCY_QUEUE_RULES.find((rule) => + rule.endpoints.some((endpoint) => normalizedUrl.includes(endpoint)) + ) || null; +}; + +const hasHeader = (headers, name) => { + const normalizedName = String(name || '').trim().toLowerCase(); + if (!normalizedName || !headers || typeof headers !== 'object') { + return false; + } + + return Object.keys(headers).some((headerName) => String(headerName).toLowerCase() === normalizedName); +}; + +const parseFetchResponseData = async (response) => { + const text = await response.text(); + if (!text) { + return null; + } + + const contentType = response.headers?.get?.('content-type') || ''; + if ( + contentType.toLowerCase().includes('application/json') || + text.trim().startsWith('{') || + text.trim().startsWith('[') + ) { + try { + return JSON.parse(text); + } catch (_error) { + return text; + } + } + + return text; +}; + +const buildFetchBody = (method, data, headers) => { + if (String(method || '').trim().toUpperCase() === 'GET' || data === undefined || data === null) { + return undefined; + } + + if ( + typeof Blob !== 'undefined' && data instanceof Blob || + typeof FormData !== 'undefined' && data instanceof FormData || + typeof URLSearchParams !== 'undefined' && data instanceof URLSearchParams || + typeof ArrayBuffer !== 'undefined' && data instanceof ArrayBuffer || + typeof ReadableStream !== 'undefined' && data instanceof ReadableStream || + typeof data === 'string' + ) { + return data; + } + + if (!hasHeader(headers, 'Content-Type')) { + headers['Content-Type'] = 'application/json'; + } + return JSON.stringify(data); +}; + +const executeFetchRequest = async ({ method, url, data, signal, headers }) => { + const fetchHeaders = { ...headers }; + const body = buildFetchBody(method, data, fetchHeaders); + const response = await fetch(url, { + method, + headers: fetchHeaders, + ...(body !== undefined ? { body } : {}), + ...(signal ? { signal } : {}), + }); + const responseData = await parseFetchResponseData(response); + const axiosLikeResponse = { + data: responseData, + status: response.status, + statusText: response.statusText, + headers: response.headers, + config: { + data, + headers: fetchHeaders, + method, + url, + }, + request: null, + }; + + if (response.ok) { + return axiosLikeResponse; + } + + const error = new Error(`Request failed with status code ${response.status}`); + error.name = 'AxiosError'; + error.response = axiosLikeResponse; + throw error; +}; + +const buildRequestQueueOptions = (url, method, options = {}) => { + const queueOptions = { + retryByStatusCode: options?.retryByStatusCode, + shouldRetry: options?.shouldRetry, + queueGroup: options?.queueGroup, + concurrencyLimit: options?.concurrencyLimit, + skipRequestByteAccounting: options?.skipRequestByteAccounting, + skipResponseByteAccounting: options?.skipResponseByteAccounting, + skipNetworkTotals: options?.skipNetworkTotals, + insightKey: options?.insightKey, + recordRecentOnSuccess: options?.recordRecentOnSuccess, + trackActiveRequest: options?.trackActiveRequest, + trackProgressCounters: options?.trackProgressCounters, + traceContext: options?.traceContext, + }; + + if (isSelfServeHardwareMutation(url, method)) { + queueOptions.retryByStatusCode ??= {}; + queueOptions.queueGroup ??= SELF_SERVE_HARDWARE_QUEUE_GROUP; + queueOptions.concurrencyLimit ??= 1; + } + + const posQueueRule = findPosLatencyQueueRule(url, method); + if (posQueueRule) { + queueOptions.retryByStatusCode ??= posQueueRule.retryByStatusCode; + queueOptions.queueGroup ??= posQueueRule.queueGroup; + queueOptions.concurrencyLimit ??= posQueueRule.concurrencyLimit; + queueOptions.skipRequestByteAccounting ??= posQueueRule.skipRequestByteAccounting; + queueOptions.skipResponseByteAccounting ??= posQueueRule.skipResponseByteAccounting; + queueOptions.skipNetworkTotals ??= posQueueRule.skipNetworkTotals; + queueOptions.insightKey ??= posQueueRule.insightKey; + queueOptions.recordRecentOnSuccess ??= posQueueRule.recordRecentOnSuccess; + queueOptions.trackActiveRequest ??= posQueueRule.trackActiveRequest; + queueOptions.trackProgressCounters ??= posQueueRule.trackProgressCounters; + } + + return queueOptions; +}; + +const authenticatedRequest = (url, method, data, catchCallable = null, thenCallable = null, options = {}) => { + const token = localStorage.getItem('token'); + if (!token) { + //throw new Error('No token was found, unable to make authenticated request'); + } + + const requestUrl = resolveReleaseApiUrl(url); + const canSendCredentials = isTrustedReleaseUrl(requestUrl); + + // Build headers + const headers = { + ...buildCurrentReleaseHeaders(), + ...(options?.headers || {}), + }; + if (canSendCredentials && token && token.length > 0) { + headers.Authorization = `Bearer ${token}`; + } + + // Add X-Customer-Number header if subuser has selected a grant + const isSubuser = localStorage.getItem('is_subuser') === 'true'; + const selectedCustomerNumber = getSelectedCustomerNumber$2(); + if (canSendCredentials && isSubuser && selectedCustomerNumber) { + headers['X-Customer-Number'] = selectedCustomerNumber; + } + + const useFetchTransport = options?.transport === FETCH_TRANSPORT; + + return enqueueRequest( + () => useFetchTransport + ? executeFetchRequest({ + method, + url: requestUrl, + data, + signal: options?.signal, + headers, + }) + : axios({ + method, + url: requestUrl, + ...(method === 'GET' ? { params: data } : { data }), + ...(options?.signal ? { signal: options.signal } : {}), + __skipRequestQueue: true, + headers + }), + { + method, + url: requestUrl, + requestData: { + params: method === 'GET' ? data : null, + data: method === 'GET' ? null : data, + headers, + }, + signal: options?.signal, + ...buildRequestQueueOptions(requestUrl, method, options), + } + ) + .catch((error) => { + if (catchCallable) { + // Call the catch callable + catchCallable(error); + } + throw error; + }) + .then((response) => { + response = normalizeActiveWashResponse(url, method, response); + if (thenCallable) { + // Call the then callable + thenCallable(response); + } + return response; + }); +}; + +const unauthenticatedRequest$1 = (url, method, data, catchCallable = null, thenCallable = null) => { + return axios({ + method, + url: resolveReleaseApiUrl(url), + ...(method === 'GET' ? { params: data } : { data }), + headers: buildCurrentReleaseHeaders(), + }).catch((error) => { + if (catchCallable) { + // Call the catch callable + catchCallable(error); + } + throw error; + }).then((response) => { + if (thenCallable) { + // Call the then callable + thenCallable(response); + } + return response; + }); +}; + +const paginatedGetRequest$1 = (url, currentPage, itemsPerPage) => { + const token = localStorage.getItem('token'); + if (!token) { + return null; + } + const requestUrl = resolveReleaseApiUrl(url); + const canSendCredentials = isTrustedReleaseUrl(requestUrl); + + // Build headers + const headers = { + ...buildCurrentReleaseHeaders(), + }; + if (canSendCredentials) { + headers.Authorization = `Bearer ${token}`; + } + + // Add X-Customer-Number header if subuser has selected a grant + const isSubuser = localStorage.getItem('is_subuser') === 'true'; + const selectedCustomerNumber = getSelectedCustomerNumber$2(); + if (canSendCredentials && isSubuser && selectedCustomerNumber) { + headers['X-Customer-Number'] = selectedCustomerNumber; + } + + return axios.get(requestUrl, { + params: { + page: currentPage, + limit: itemsPerPage + }, + headers + }); +}; + +const _sfc_main$3r = {}; +const authenticatedRequest_default = /*#__PURE__*/_export_sfc(_sfc_main$3r, [['__file',"authenticatedRequest.vue"]]); + +/** Define the errors ref */ +const errors = ref([]); + +/** Define the getError function */ +const getError = (name = null) => { + if (name) { + const result = errors.value.find(error => error.name === name); + return result ? result.error : null; + } + return errors.value; +}; + +/** Define the hasError function */ +const hasError = (name = null) => { + if (name) { + return errors.value.some(error => error.name === name); + } + return errors.value.length > 0; +}; + +/** Define the removeError function */ +const removeError = (name = null) => { + if (name) { + errors.value = errors.value.filter(error => error.name !== name); + return; + } + // If no name is provided, clear all errors + errors.value = []; +}; + +/** Define the clearErrors function */ +const clearErrors = () => { + // Clear all errors if no specific error is provided + errors.value = []; +}; + +/** Define the addError function */ +const addError = (error, name = null) => { + if (name) { + errors.value.push({name, error}); + return; + } + errors.value.push(error); +}; + +/** Define the parseError function */ + +const parseError = (error, name = null) => { + if (error.response) { + // The request was made and the server responded with a status code + // that falls out of the range of 2xx + /** If the response has the custom error message */ + if (error.response.data.data.message) { + addError(error.response.data.data.message, name); + } else { + /** Fall back to the default error message */ + addError(error.response.data.message, name); + } + } else if (error.request) { + // The request was made but no response was received + addError('No response was received', name); + } else { + // Something happened in setting up the request that triggered an Error + addError(error, name); + } +}; + +const _sfc_main$3q = {}; +const HandleGlobalError = /*#__PURE__*/_export_sfc(_sfc_main$3q, [['__file',"HandleGlobalError.vue"]]); + +const EDGE_GATEWAY_WORKSPACE_CACHE_KEY = "truckwash.edgeGatewayWorkspace.cache.v1"; +const EDGE_GATEWAY_WORKSPACE_CACHE_TTL_MS = 15 * 60 * 1000; + +const EDGE_GATEWAY_BASE = "/edge-gateways"; +const EDGE_GATEWAY_CONFIG_BASE = "/edgegateway/config"; + +const listRequestsInFlight = new Map(); +const detailRequestsInFlight = new Map(); +let departmentsRequestInFlight = null; +let edgeGatewayWorkspaceCache = null; +let edgeGatewayWorkspaceCacheStorageKey = null; + +const cloneJson = (value) => (value === null || value === undefined ? value : JSON.parse(JSON.stringify(value))); +const getDataPayload = (response) => (response && response.data ? response.data.data : undefined); +const getMetaPayload = (response) => (response && response.data ? response.data.meta : undefined); +const normalizeDepartmentId = (departmentId) => + departmentId === null || departmentId === undefined || departmentId === "" ? null : Number(departmentId); +const normalizeGatewayId = (gatewayId) => + gatewayId === null || gatewayId === undefined || gatewayId === "" ? null : String(gatewayId); +const listCacheKey = ({ departmentId = null, view = "summary" } = {}) => + JSON.stringify({ departmentId: normalizeDepartmentId(departmentId), view: String(view || "summary") }); + +const normalizeEntries$2 = (entries) => { + if (Array.isArray(entries)) { + return entries; + } + + if (entries && typeof entries === "object") { + return Object.values(entries); + } + + return []; +}; + +const parseJsonObject = (value) => { + if (typeof value !== "string" || !value.trim()) { + return null; + } + + try { + const parsed = JSON.parse(value); + return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null; + } catch (_error) { + return null; + } +}; + +const normalizeRotateCredentialBundle = (bundle) => { + if (!bundle || typeof bundle !== "object" || Array.isArray(bundle)) { + return bundle; + } + + const config = parseJsonObject(bundle.config_json); + const agentToken = + bundle.agent_token || bundle.token || (config && (config.agentToken || config.agent_token)) || null; + const stackServiceName = + bundle.stackServiceName || + bundle.stack_service_name || + (config && config.stackServiceName) || + (config && config.stack_service_name) || + (config && config.serviceName) || + (config && config.service_name) || + null; + const composeFileName = + bundle.composeFileName || + bundle.compose_file_name || + (config && (config.composeFileName || config.compose_file_name)) || + null; + + return { + ...bundle, + token: bundle.token || agentToken, + agent_token: agentToken, + stackServiceName, + stack_service_name: bundle.stack_service_name || stackServiceName, + composeFileName, + compose_file_name: bundle.compose_file_name || composeFileName, + }; +}; + +const normalizeRotateCredentialResponse = (response) => { + const bundle = getDataPayload(response); + if (bundle && typeof bundle === "object" && !Array.isArray(bundle)) { + response.data.data = normalizeRotateCredentialBundle(bundle); + } + return response; +}; + +const toConfigPayload$2 = (entries) => { + const payload = {}; + normalizeEntries$2(entries).forEach((entry) => { + if (!entry || !entry.variable) { + return; + } + payload[entry.variable] = entry.value; + }); + return payload; +}; + +const createEmptyWorkspaceCache = (scope = null) => ({ + scope, + cachedAt: Date.now(), + departments: null, + lists: {}, + details: {}, +}); + +const storage = () => { + if (typeof window === "undefined" || !window.sessionStorage) { + return null; + } + + return window.sessionStorage; +}; + +const removeLegacyWorkspaceCache = () => { + if (typeof window === "undefined" || !window.localStorage) { + return; + } + + try { + window.localStorage.removeItem(EDGE_GATEWAY_WORKSPACE_CACHE_KEY); + } catch (_error) { + // Browser storage can be unavailable in private browsing or tests. + } +}; + +const getStoredValue = (key) => { + if (typeof window === "undefined" || !window.localStorage) { + return null; + } + + try { + return window.localStorage.getItem(key); + } catch (_error) { + return null; + } +}; + +const hashScopePart = (value) => { + let hash = 0; + const input = String(value || ""); + for (let index = 0; index < input.length; index += 1) { + hash = (hash << 5) - hash + input.charCodeAt(index); + hash |= 0; + } + return hash.toString(36); +}; + +const currentWorkspaceCacheScope = () => { + const token = getStoredValue("token"); + if (!token) { + return null; + } + + return JSON.stringify({ + token: hashScopePart(token), + isSubuser: getStoredValue("is_subuser") === "true", + selectedCustomerNumber: getStoredValue("selected_customer_number") || null, + hasSuperuserToken: Boolean(getStoredValue("superuser_token")), + }); +}; + +const isFreshCachedAt = (cachedAt) => Date.now() - Number(cachedAt || 0) <= EDGE_GATEWAY_WORKSPACE_CACHE_TTL_MS; +const isFreshCacheEntry$1 = (entry) => Boolean(entry && typeof entry === "object" && isFreshCachedAt(entry.cachedAt)); +const isSensitiveCacheField = (fieldName) => + /(^|[_-])(token|secret|password|credential|authorization|api[_-]?key|private[_-]?key)($|[_-])/i.test( + String(fieldName || "") + ) || String(fieldName || "").toLowerCase() === "config_json"; + +const sanitizeCacheValue = (value) => { + if (Array.isArray(value)) { + return value.map((item) => sanitizeCacheValue(item)); + } + + if (!value || typeof value !== "object") { + return value; + } + + return Object.entries(value).reduce((sanitized, [key, childValue]) => { + if (!isSensitiveCacheField(key)) { + sanitized[key] = sanitizeCacheValue(childValue); + } + return sanitized; + }, {}); +}; + +const sanitizeGatewayCachePayload = (value) => cloneJson(sanitizeCacheValue(value)); + +const resetWorkspaceCacheMemory = (scope = currentWorkspaceCacheScope()) => { + edgeGatewayWorkspaceCache = createEmptyWorkspaceCache(scope); + edgeGatewayWorkspaceCacheStorageKey = EDGE_GATEWAY_WORKSPACE_CACHE_KEY; + return edgeGatewayWorkspaceCache; +}; + +const loadWorkspaceCache = () => { + removeLegacyWorkspaceCache(); + const scope = currentWorkspaceCacheScope(); + if (!scope) { + return resetWorkspaceCacheMemory(null); + } + + if ( + edgeGatewayWorkspaceCache !== null && + edgeGatewayWorkspaceCache.scope === scope && + isFreshCachedAt(edgeGatewayWorkspaceCache.cachedAt) + ) { + return edgeGatewayWorkspaceCache; + } + + const storageHandle = storage(); + if (!storageHandle) { + return resetWorkspaceCacheMemory(scope); + } + + try { + const decoded = JSON.parse(storageHandle.getItem(EDGE_GATEWAY_WORKSPACE_CACHE_KEY) || "null"); + if (!decoded || typeof decoded !== "object" || decoded.scope !== scope || !isFreshCachedAt(decoded.cachedAt)) { + storageHandle.removeItem(EDGE_GATEWAY_WORKSPACE_CACHE_KEY); + return resetWorkspaceCacheMemory(scope); + } + + edgeGatewayWorkspaceCache = { + ...createEmptyWorkspaceCache(scope), + cachedAt: Number(decoded.cachedAt || Date.now()), + departments: isFreshCacheEntry$1(decoded.departments) ? decoded.departments : null, + lists: + decoded && decoded.lists && typeof decoded.lists === "object" + ? Object.fromEntries(Object.entries(decoded.lists).filter(([, entry]) => isFreshCacheEntry$1(entry))) + : {}, + details: + decoded && decoded.details && typeof decoded.details === "object" + ? Object.fromEntries(Object.entries(decoded.details).filter(([, entry]) => isFreshCacheEntry$1(entry))) + : {}, + }; + edgeGatewayWorkspaceCacheStorageKey = EDGE_GATEWAY_WORKSPACE_CACHE_KEY; + } catch (_error) { + storageHandle.removeItem(EDGE_GATEWAY_WORKSPACE_CACHE_KEY); + resetWorkspaceCacheMemory(scope); + } + + return edgeGatewayWorkspaceCache; +}; + +const persistWorkspaceCache = () => { + const storageHandle = storage(); + const scope = currentWorkspaceCacheScope(); + if (!storageHandle || edgeGatewayWorkspaceCache === null || !scope || edgeGatewayWorkspaceCache.scope !== scope) { + return; + } + + edgeGatewayWorkspaceCache.cachedAt = Date.now(); + edgeGatewayWorkspaceCacheStorageKey = EDGE_GATEWAY_WORKSPACE_CACHE_KEY; + storageHandle.setItem(EDGE_GATEWAY_WORKSPACE_CACHE_KEY, JSON.stringify(edgeGatewayWorkspaceCache)); +}; + +const clearEdgeGatewayWorkspaceCache = () => { + edgeGatewayWorkspaceCache = null; + edgeGatewayWorkspaceCacheStorageKey = null; + removeLegacyWorkspaceCache(); + const storageHandle = storage(); + if (!storageHandle) { + return; + } + + storageHandle.removeItem(EDGE_GATEWAY_WORKSPACE_CACHE_KEY); +}; +const mergeGatewaySnapshots = (currentGateway, nextGateway) => { + if (!currentGateway) { + return cloneJson(nextGateway); + } + + return { + ...cloneJson(currentGateway), + ...cloneJson(nextGateway), + metadata: { + ...((currentGateway && currentGateway.metadata) || {}), + ...((nextGateway && nextGateway.metadata) || {}), + }, + inventory: Array.isArray(nextGateway && nextGateway.inventory) + ? cloneJson(nextGateway.inventory) + : Array.isArray(currentGateway && currentGateway.inventory) + ? cloneJson(currentGateway.inventory) + : undefined, + bindings: Array.isArray(nextGateway && nextGateway.bindings) + ? cloneJson(nextGateway.bindings) + : Array.isArray(currentGateway && currentGateway.bindings) + ? cloneJson(currentGateway.bindings) + : undefined, + operations: Array.isArray(nextGateway && nextGateway.operations) + ? cloneJson(nextGateway.operations) + : Array.isArray(currentGateway && currentGateway.operations) + ? cloneJson(currentGateway.operations) + : undefined, + audit_logs: Array.isArray(nextGateway && nextGateway.audit_logs) + ? cloneJson(nextGateway.audit_logs) + : Array.isArray(currentGateway && currentGateway.audit_logs) + ? cloneJson(currentGateway.audit_logs) + : undefined, + }; +}; + +const cacheGatewaySnapshot = (gateway) => { + if (!gateway || !gateway.id) { + return null; + } + + const cache = loadWorkspaceCache(); + const sanitizedGateway = sanitizeGatewayCachePayload(gateway); + const gatewayId = String(sanitizedGateway.id); + const mergedGateway = mergeGatewaySnapshots( + (cache.details[gatewayId] && cache.details[gatewayId].data) || null, + sanitizedGateway + ); + cache.details[gatewayId] = { + cachedAt: Date.now(), + data: mergedGateway, + }; + + Object.entries(cache.lists || {}).forEach(([cacheKey, entry]) => { + const listEntry = entry && typeof entry === "object" ? entry : { params: null, rows: [] }; + const params = listEntry.params && typeof listEntry.params === "object" ? listEntry.params : {}; + const rows = Array.isArray(listEntry.rows) ? [...listEntry.rows] : []; + const matchesDepartment = + normalizeDepartmentId(params.departmentId) === null || + Number(params.departmentId) === Number(gateway.department_id); + const existingIndex = rows.findIndex((item) => Number((item && item.id) || 0) === Number(gateway.id)); + + if (existingIndex >= 0) { + rows[existingIndex] = mergeGatewaySnapshots(rows[existingIndex], sanitizedGateway); + } else if (matchesDepartment) { + rows.unshift(cloneJson(sanitizedGateway)); + } + + cache.lists[cacheKey] = { + ...listEntry, + rows, + cachedAt: Date.now(), + }; + }); + + persistWorkspaceCache(); + return cloneJson(mergedGateway); +}; + +const cacheFleetSnapshot = ({ departmentId = null, view = "summary", rows = [], meta = {} } = {}) => { + const cache = loadWorkspaceCache(); + const sanitizedRows = sanitizeGatewayCachePayload(Array.isArray(rows) ? rows : []); + const key = listCacheKey({ departmentId, view }); + cache.lists[key] = { + params: { + departmentId: normalizeDepartmentId(departmentId), + view: String(view || "summary"), + }, + rows: sanitizedRows, + meta: sanitizeGatewayCachePayload(meta || {}), + cachedAt: Date.now(), + }; + + sanitizedRows.forEach((gateway) => { + if (!gateway || !gateway.id) { + return; + } + + const gatewayId = String(gateway.id); + if (!cache.details[gatewayId]) { + cache.details[gatewayId] = { + cachedAt: Date.now(), + data: sanitizeGatewayCachePayload(gateway), + }; + return; + } + + cache.details[gatewayId] = { + cachedAt: Date.now(), + data: mergeGatewaySnapshots(cache.details[gatewayId].data, gateway), + }; + }); + + persistWorkspaceCache(); +}; + +const cacheDepartmentsSnapshot = (departments) => { + const cache = loadWorkspaceCache(); + cache.departments = { + cachedAt: Date.now(), + data: sanitizeGatewayCachePayload(Array.isArray(departments) ? departments : []), + }; + persistWorkspaceCache(); +}; + +const cacheGatewayFromResponse = (response) => { + const gateway = getDataPayload(response); + if (gateway && gateway.id) { + cacheGatewaySnapshot(gateway); + } + return response; +}; + +const cacheGatewayFromNestedResponse = (response) => { + const payload = getDataPayload(response); + const gateway = payload && payload.gateway; + if (gateway && gateway.id) { + cacheGatewaySnapshot(gateway); + } + return response; +}; + +const buildOperationPayload = (typeOrPayload, request = {}) => { + if (typeOrPayload && typeof typeOrPayload === "object" && !Array.isArray(typeOrPayload)) { + return { + ...typeOrPayload, + request: + typeOrPayload.request && typeof typeOrPayload.request === "object" && !Array.isArray(typeOrPayload.request) + ? typeOrPayload.request + : {}, + }; + } + + return { + type: String(typeOrPayload || "").toUpperCase(), + request: request && typeof request === "object" && !Array.isArray(request) ? request : {}, + }; +}; + +const unwrapEdgeGatewayResponse = (response, fallback = null) => { + const data = getDataPayload(response); + return data === undefined || data === null ? fallback : data; +}; +const unwrapEdgeGatewayMeta = (response) => getMetaPayload(response) || {}; + +const isEdgeGatewayAuthorizationError = (error) => { + const status = Number( + (error && error.response && error.response.status) || + (error && error.status) || + (error && error.response && error.response.data && error.response.data.status) || + 0 + ); + return status === 401 || status === 403; +}; + +const peekCachedEdgeGatewayDepartments = () => { + const entry = loadWorkspaceCache().departments; + const departments = entry && entry.data; + return isFreshCacheEntry$1(entry) && Array.isArray(departments) ? cloneJson(departments) : null; +}; + +const peekCachedEdgeGatewayList = ({ departmentId = null, view = "summary" } = {}) => { + const entry = loadWorkspaceCache().lists[listCacheKey({ departmentId, view })]; + if (!isFreshCacheEntry$1(entry) || !Array.isArray(entry.rows)) { + return null; + } + + return { + cachedAt: Number(entry.cachedAt || 0), + rows: cloneJson(entry.rows), + meta: cloneJson(entry.meta || {}), + }; +}; + +const peekCachedEdgeGateway = (gatewayId) => { + const normalizedGatewayId = normalizeGatewayId(gatewayId); + if (!normalizedGatewayId) { + return null; + } + + const entry = loadWorkspaceCache().details[normalizedGatewayId]; + return isFreshCacheEntry$1(entry) && entry && entry.data ? cloneJson(entry.data) : null; +}; + +const patchEdgeGatewayCache = (gatewayId, patch) => { + const current = peekCachedEdgeGateway(gatewayId); + if (!current) { + return null; + } + + return cacheGatewaySnapshot(mergeGatewaySnapshots(current, patch)); +}; + +const removeEdgeGatewayCache = (gatewayId) => { + const normalizedGatewayId = normalizeGatewayId(gatewayId); + if (!normalizedGatewayId) { + return; + } + + const cache = loadWorkspaceCache(); + delete cache.details[normalizedGatewayId]; + Object.entries(cache.lists || {}).forEach(([cacheKey, entry]) => { + const rows = Array.isArray(entry && entry.rows) + ? entry.rows.filter((item) => String((item && item.id) || "") !== normalizedGatewayId) + : []; + cache.lists[cacheKey] = { + ...(entry || {}), + rows, + cachedAt: Date.now(), + }; + }); + persistWorkspaceCache(); +}; + +const updateDepartmentGatewayCutoverCache = (departmentId, transportMode) => { + const normalizedDepartmentId = normalizeDepartmentId(departmentId); + if (normalizedDepartmentId === null) { + return; + } + + const cache = loadWorkspaceCache(); + Object.entries(cache.details || {}).forEach(([gatewayId, entry]) => { + if (Number((entry && entry.data && entry.data.department_id) || 0) !== normalizedDepartmentId) { + return; + } + + cache.details[gatewayId] = { + cachedAt: Date.now(), + data: mergeGatewaySnapshots(entry.data, { + department_transport_mode: transportMode, + }), + }; + }); + + Object.entries(cache.lists || {}).forEach(([cacheKey, entry]) => { + const rows = Array.isArray(entry && entry.rows) + ? entry.rows.map((gateway) => + Number((gateway && gateway.department_id) || 0) === normalizedDepartmentId + ? { ...gateway, department_transport_mode: transportMode } + : gateway + ) + : []; + cache.lists[cacheKey] = { + ...(entry || {}), + rows, + cachedAt: Date.now(), + }; + }); + + persistWorkspaceCache(); +}; + +const listEdgeGatewayDepartments = async ({ forceRefresh = false } = {}) => { + if (!forceRefresh && departmentsRequestInFlight) { + return departmentsRequestInFlight; + } + + const request = authenticatedRequest("/departments", "GET", {}).then((response) => { + cacheDepartmentsSnapshot(getDataPayload(response) || []); + return response; + }); + + departmentsRequestInFlight = request.finally(() => { + if (departmentsRequestInFlight === request) { + departmentsRequestInFlight = null; + } + }); + + return departmentsRequestInFlight; +}; + +const listEdgeGatewayDepartmentWorkspaces = async () => + authenticatedRequest("/modules/edge-gateways/workspace/departments", "GET", {}); + +const getEdgeGatewayDepartmentWorkspace = async (departmentId) => + authenticatedRequest( + `/modules/edge-gateways/workspace/departments/${encodeURIComponent(String(departmentId))}`, + "GET", + {} + ); + +const listEdgeGateways = async ({ departmentId = null, view = "summary", forceRefresh = false } = {}) => { + const requestKey = listCacheKey({ departmentId, view }); + if (!forceRefresh && listRequestsInFlight.has(requestKey)) { + return listRequestsInFlight.get(requestKey); + } + + const request = authenticatedRequest(EDGE_GATEWAY_BASE, "GET", { + ...(departmentId ? { department_id: departmentId } : {}), + ...(view ? { view } : {}), + }).then((response) => { + cacheFleetSnapshot({ + departmentId, + view, + rows: getDataPayload(response) || [], + meta: getMetaPayload(response) || {}, + }); + return response; + }); + + const trackedRequest = request.finally(() => { + if (listRequestsInFlight.get(requestKey) === trackedRequest) { + listRequestsInFlight.delete(requestKey); + } + }); + listRequestsInFlight.set(requestKey, trackedRequest); + return trackedRequest; +}; + +const getEdgeGateway = async (gatewayId, { forceRefresh = false } = {}) => { + const normalizedGatewayId = normalizeGatewayId(gatewayId); + if (!normalizedGatewayId) { + throw new Error("A gatewayId is required"); + } + + if (!forceRefresh && detailRequestsInFlight.has(normalizedGatewayId)) { + return detailRequestsInFlight.get(normalizedGatewayId); + } + + const request = authenticatedRequest(`${EDGE_GATEWAY_BASE}/${encodeURIComponent(gatewayId)}`, "GET", {}).then( + (response) => { + const gateway = getDataPayload(response); + if (gateway && gateway.id) { + cacheGatewaySnapshot(gateway); + } + return response; + } + ); + + const trackedRequest = request.finally(() => { + if (detailRequestsInFlight.get(normalizedGatewayId) === trackedRequest) { + detailRequestsInFlight.delete(normalizedGatewayId); + } + }); + detailRequestsInFlight.set(normalizedGatewayId, trackedRequest); + return trackedRequest; +}; + +const listEdgeGatewayOperations = async (gatewayId) => + authenticatedRequest(`${EDGE_GATEWAY_BASE}/${encodeURIComponent(gatewayId)}/operations`, "GET", {}); + +const getEdgeGatewayTasks = async (gatewayId) => + authenticatedRequest(`${EDGE_GATEWAY_BASE}/${encodeURIComponent(gatewayId)}/tasks`, "GET", {}).then( + cacheGatewayFromNestedResponse + ); + +const getEdgeGatewayLogs = async (gatewayId) => + authenticatedRequest(`${EDGE_GATEWAY_BASE}/${encodeURIComponent(gatewayId)}/logs`, "GET", {}).then( + cacheGatewayFromNestedResponse + ); + +const getEdgeGatewayStatistics = async (gatewayId) => + authenticatedRequest(`${EDGE_GATEWAY_BASE}/${encodeURIComponent(gatewayId)}/statistics`, "GET", {}).then( + cacheGatewayFromNestedResponse + ); + +const createEdgeGatewayOperation = async (gatewayId, typeOrPayload, request = {}) => + authenticatedRequest( + `${EDGE_GATEWAY_BASE}/${encodeURIComponent(gatewayId)}/operations`, + "POST", + buildOperationPayload(typeOrPayload, request) + ).then(cacheGatewayFromNestedResponse); + +const cancelEdgeGatewayOperation = async (gatewayId, operationId) => + authenticatedRequest( + `${EDGE_GATEWAY_BASE}/${encodeURIComponent(gatewayId)}/operations/${encodeURIComponent( + String(operationId) + )}/cancel`, + "POST", + {} + ).then(cacheGatewayFromNestedResponse); + +const getEdgeGatewayOperationEvents = async (gatewayId, operationId) => + authenticatedRequest( + `${EDGE_GATEWAY_BASE}/${encodeURIComponent(gatewayId)}/operations/${encodeURIComponent( + String(operationId) + )}/events`, + "GET", + {} + ); + +const listEdgeGatewayOperationEvents = getEdgeGatewayOperationEvents; + +const rotateEdgeGatewayCredentials = async (gatewayId) => + authenticatedRequest(`${EDGE_GATEWAY_BASE}/${encodeURIComponent(gatewayId)}/rotate-credentials`, "POST", {}).then( + normalizeRotateCredentialResponse + ); + +const createEdgeGatewayInstallToken = async ({ department_id, label }) => + authenticatedRequest(`${EDGE_GATEWAY_BASE}/install-token`, "POST", { department_id, label }); + +const getEdgeGatewayInstallTokenStatus = async (claimTokenId) => + authenticatedRequest( + `${EDGE_GATEWAY_BASE}/install-token/${encodeURIComponent(String(claimTokenId))}/status`, + "GET", + {} + ); + +const updateEdgeGateway = async (gatewayId, payload) => + authenticatedRequest(`${EDGE_GATEWAY_BASE}/${encodeURIComponent(gatewayId)}`, "PUT", payload).then( + cacheGatewayFromResponse + ); + +const triggerEdgeGatewayDiscovery = async (gatewayId) => + authenticatedRequest(`${EDGE_GATEWAY_BASE}/${encodeURIComponent(gatewayId)}/discovery`, "POST", {}).then( + cacheGatewayFromResponse + ); + +const saveEdgeGatewayBindings = async (gatewayId, bindings) => + authenticatedRequest(`${EDGE_GATEWAY_BASE}/${encodeURIComponent(gatewayId)}/bindings`, "PUT", { bindings }).then( + cacheGatewayFromResponse + ); + +const deleteEdgeGateway = async (gatewayId) => + authenticatedRequest(`${EDGE_GATEWAY_BASE}/${encodeURIComponent(gatewayId)}`, "DELETE", {}).then((response) => { + removeEdgeGatewayCache(gatewayId); + return response; + }); + +const setDepartmentGatewayCutover = async (departmentId, transport_mode) => + authenticatedRequest(`/departments/${encodeURIComponent(departmentId)}/gateway-cutover`, "POST", { + transport_mode, + }).then((response) => { + updateDepartmentGatewayCutoverCache(departmentId, transport_mode); + return response; + }); + +const updateDepartmentLaneBindings = async (laneId, payload = {}) => + authenticatedRequest("/department/lanes", "PUT", { + id: Number(laneId), + ...payload, + }); + +const SELF_SERVE_RELAY_TEST_ENDPOINTS = Object.freeze({ + MACHINE: "/modules/self-serve/lane/relay/machine/set", + PROGRAM_PICKER: "/modules/self-serve/lane/relay/machine_program_picker/set", + CLEANER: "/modules/self-serve/lane/relay/machine_cleaner/set", +}); + +const normalizeRelayTestTransport = (transport) => { + const normalizedTransport = String(transport || "") + .trim() + .toLowerCase(); + return normalizedTransport === "cloud" ? "cloud" : "local"; +}; + +const normalizeRelayTestTimer = (seconds) => { + const normalizedSeconds = Number.parseInt(String(seconds === null || seconds === undefined ? "" : seconds), 10); + return Number.isInteger(normalizedSeconds) && normalizedSeconds > 0 ? normalizedSeconds : 1; +}; + +const runDepartmentLaneGateTest = async (laneId, gate, { transport = "local", toggleAfter = 1 } = {}) => + authenticatedRequest("/modules/self-serve/lane/gate/open", "POST", { + lane_id: Number(laneId), + gate: String(gate || "").toUpperCase(), + transport: normalizeRelayTestTransport(transport), + toggle_after: normalizeRelayTestTimer(toggleAfter), + }); + +const runDepartmentSelfServeRelayTest = async (laneId, relay, on, { transport = "local" } = {}) => { + const endpoint = SELF_SERVE_RELAY_TEST_ENDPOINTS[String(relay || "").toUpperCase()]; + if (!endpoint) { + throw new Error(`Unsupported self-serve relay test: ${relay}`); + } + + return authenticatedRequest(endpoint, "POST", { + lane_id: Number(laneId), + on: Boolean(on), + transport: normalizeRelayTestTransport(transport), + }); +}; + +const updateNumberPlateScanner = async (scannerId, payload = {}) => + authenticatedRequest("/numberplatescanners", "PUT", { + id: Number(scannerId), + ...payload, + }); + +const rotateNumberPlateScannerKey = async (scannerId) => + authenticatedRequest(`/numberplatescanners/${encodeURIComponent(String(scannerId))}/rotate-key`, "POST", {}); + +const getEdgeGatewayModuleConfig = async (variable = null) => { + const endpoint = variable + ? `${EDGE_GATEWAY_CONFIG_BASE}?variable=${encodeURIComponent(String(variable))}` + : EDGE_GATEWAY_CONFIG_BASE; + + return authenticatedRequest(endpoint, "GET", {}).then((response) => { + const entries = normalizeEntries$2(unwrapEdgeGatewayResponse(response, [])); + response.data.data = entries; + response.data.config = toConfigPayload$2(entries); + return response; + }); +}; + +const setEdgeGatewayModuleConfig = async (payload) => + authenticatedRequest(EDGE_GATEWAY_CONFIG_BASE, "POST", payload); + +const testEdgeGatewayBrokerConfig = async (payload = {}) => + authenticatedRequest(`${EDGE_GATEWAY_CONFIG_BASE}/broker-diagnostics`, "POST", payload); + +const EDGE_GATEWAY_OPERATIONS = { + discovery(request = {}) { + return { + type: "DISCOVERY", + request, + }; + }, + update(targetVersion, releaseChannel = "stable") { + return { + type: "UPDATE", + request: { + target_version: targetVersion, + release_channel: releaseChannel, + }, + }; + }, + uninstall() { + return { + type: "UNINSTALL", + request: {}, + }; + }, +}; + +const pendingRequest = ref(null); + +const SuperUserSystemStatusObject = { + snapshot: ref(null), + loading: ref(false), + error: ref(null), + lastLoadedAt: ref(null), + overallStatus: computed(() => SuperUserSystemStatusObject.snapshot.value?.overall_status ?? "down"), + runtime: computed(() => SuperUserSystemStatusObject.snapshot.value?.runtime ?? {}), + dependencies: computed(() => SuperUserSystemStatusObject.snapshot.value?.dependencies ?? {}), + modules: computed(() => SuperUserSystemStatusObject.snapshot.value?.modules ?? []), + sessions: computed( + () => + SuperUserSystemStatusObject.snapshot.value?.sessions ?? { + active_window_minutes: 15, + active_users: 0, + active_sessions: 0, + recent_sessions: [], + } + ), + warnings: computed(() => SuperUserSystemStatusObject.snapshot.value?.warnings ?? []), + refreshAfterSeconds: computed(() => Number(SuperUserSystemStatusObject.snapshot.value?.refresh_after_seconds ?? 30)), +}; + +const getSuperuserSystemStatus = async ({ force = false } = {}) => { + if (pendingRequest.value) { + return pendingRequest.value; + } + + SuperUserSystemStatusObject.loading.value = true; + + pendingRequest.value = authenticatedRequest("/superuser/system/status", "GET", force ? { force: 1 } : {}) + .then((response) => { + SuperUserSystemStatusObject.snapshot.value = response.data.data; + SuperUserSystemStatusObject.error.value = null; + SuperUserSystemStatusObject.lastLoadedAt.value = new Date(); + return SuperUserSystemStatusObject.snapshot.value; + }) + .catch((error) => { + SuperUserSystemStatusObject.error.value = error; + throw error; + }) + .finally(() => { + SuperUserSystemStatusObject.loading.value = false; + pendingRequest.value = null; + }); + + return pendingRequest.value; +}; + +const createDependencySystemObject = (key) => ({ + status: computed(() => SuperUserSystemStatusObject.dependencies.value?.[key] ?? null), + loading: computed(() => SuperUserSystemStatusObject.loading.value), + error: computed(() => SuperUserSystemStatusObject.error.value), + lastLoadedAt: computed(() => SuperUserSystemStatusObject.lastLoadedAt.value), +}); + +const DatabaseSystemObject = createDependencySystemObject("database"); +const RedisSystemObject = createDependencySystemObject("redis"); +const MinioSystemObject = createDependencySystemObject("minio"); + +const getSystemDependencyStatus = async (key, { force = false } = {}) => { + const snapshot = await getSuperuserSystemStatus({ force }); + return snapshot?.dependencies?.[key] ?? null; +}; + +const getSystemDatabaseStatus = (options = {}) => getSystemDependencyStatus("database", options); +const getSystemRedisStatus = (options = {}) => getSystemDependencyStatus("redis", options); +const getSystemMinioStatus = (options = {}) => getSystemDependencyStatus("minio", options); + +const _sfc_main$3p = {}; +const systemStatus = /*#__PURE__*/_export_sfc(_sfc_main$3p, [['__file',"systemStatus.vue"]]); + +const _sfc_main$3o = {}; +const systemDatabase = /*#__PURE__*/_export_sfc(_sfc_main$3o, [['__file',"systemDatabase.vue"]]); + +/*! +* sweetalert2 v11.22.4 +* Released under the MIT License. +*/ +function _assertClassBrand(e, t, n) { + if ("function" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n; + throw new TypeError("Private element is not present on this object"); +} +function _checkPrivateRedeclaration(e, t) { + if (t.has(e)) throw new TypeError("Cannot initialize the same private elements twice on an object"); +} +function _classPrivateFieldGet2(s, a) { + return s.get(_assertClassBrand(s, a)); +} +function _classPrivateFieldInitSpec(e, t, a) { + _checkPrivateRedeclaration(e, t), t.set(e, a); +} +function _classPrivateFieldSet2(s, a, r) { + return s.set(_assertClassBrand(s, a), r), r; +} + +const RESTORE_FOCUS_TIMEOUT = 100; + +/** @type {GlobalState} */ +const globalState = {}; +const focusPreviousActiveElement = () => { + if (globalState.previousActiveElement instanceof HTMLElement) { + globalState.previousActiveElement.focus(); + globalState.previousActiveElement = null; + } else if (document.body) { + document.body.focus(); + } +}; + +/** + * Restore previous active (focused) element + * + * @param {boolean} returnFocus + * @returns {Promise} + */ +const restoreActiveElement = returnFocus => { + return new Promise(resolve => { + if (!returnFocus) { + return resolve(); + } + const x = window.scrollX; + const y = window.scrollY; + globalState.restoreFocusTimeout = setTimeout(() => { + focusPreviousActiveElement(); + resolve(); + }, RESTORE_FOCUS_TIMEOUT); // issues/900 + + window.scrollTo(x, y); + }); +}; + +const swalPrefix = 'swal2-'; + +/** + * @typedef {Record} SwalClasses + */ + +/** + * @typedef {'success' | 'warning' | 'info' | 'question' | 'error'} SwalIcon + * @typedef {Record} SwalIcons + */ + +/** @type {SwalClass[]} */ +const classNames = ['container', 'shown', 'height-auto', 'iosfix', 'popup', 'modal', 'no-backdrop', 'no-transition', 'toast', 'toast-shown', 'show', 'hide', 'close', 'title', 'html-container', 'actions', 'confirm', 'deny', 'cancel', 'footer', 'icon', 'icon-content', 'image', 'input', 'file', 'range', 'select', 'radio', 'checkbox', 'label', 'textarea', 'inputerror', 'input-label', 'validation-message', 'progress-steps', 'active-progress-step', 'progress-step', 'progress-step-line', 'loader', 'loading', 'styled', 'top', 'top-start', 'top-end', 'top-left', 'top-right', 'center', 'center-start', 'center-end', 'center-left', 'center-right', 'bottom', 'bottom-start', 'bottom-end', 'bottom-left', 'bottom-right', 'grow-row', 'grow-column', 'grow-fullscreen', 'rtl', 'timer-progress-bar', 'timer-progress-bar-container', 'scrollbar-measure', 'icon-success', 'icon-warning', 'icon-info', 'icon-question', 'icon-error', 'draggable', 'dragging']; +const swalClasses = classNames.reduce((acc, className) => { + acc[className] = swalPrefix + className; + return acc; +}, /** @type {SwalClasses} */{}); + +/** @type {SwalIcon[]} */ +const icons = ['success', 'warning', 'info', 'question', 'error']; +const iconTypes = icons.reduce((acc, icon) => { + acc[icon] = swalPrefix + icon; + return acc; +}, /** @type {SwalIcons} */{}); + +const consolePrefix = 'SweetAlert2:'; + +/** + * Capitalize the first letter of a string + * + * @param {string} str + * @returns {string} + */ +const capitalizeFirstLetter = str => str.charAt(0).toUpperCase() + str.slice(1); + +/** + * Standardize console warnings + * + * @param {string | string[]} message + */ +const warn = message => { + console.warn(`${consolePrefix} ${typeof message === 'object' ? message.join(' ') : message}`); +}; + +/** + * Standardize console errors + * + * @param {string} message + */ +const error = message => { + console.error(`${consolePrefix} ${message}`); +}; + +/** + * Private global state for `warnOnce` + * + * @type {string[]} + * @private + */ +const previousWarnOnceMessages = []; + +/** + * Show a console warning, but only if it hasn't already been shown + * + * @param {string} message + */ +const warnOnce = message => { + if (!previousWarnOnceMessages.includes(message)) { + previousWarnOnceMessages.push(message); + warn(message); + } +}; + +/** + * Show a one-time console warning about deprecated params/methods + * + * @param {string} deprecatedParam + * @param {string?} useInstead + */ +const warnAboutDeprecation = (deprecatedParam, useInstead = null) => { + warnOnce(`"${deprecatedParam}" is deprecated and will be removed in the next major release.${useInstead ? ` Use "${useInstead}" instead.` : ''}`); +}; + +/** + * If `arg` is a function, call it (with no arguments or context) and return the result. + * Otherwise, just pass the value through + * + * @param {Function | any} arg + * @returns {any} + */ +const callIfFunction = arg => typeof arg === 'function' ? arg() : arg; + +/** + * @param {any} arg + * @returns {boolean} + */ +const hasToPromiseFn = arg => arg && typeof arg.toPromise === 'function'; + +/** + * @param {any} arg + * @returns {Promise} + */ +const asPromise = arg => hasToPromiseFn(arg) ? arg.toPromise() : Promise.resolve(arg); + +/** + * @param {any} arg + * @returns {boolean} + */ +const isPromise = arg => arg && Promise.resolve(arg) === arg; + +/** + * Gets the popup container which contains the backdrop and the popup itself. + * + * @returns {HTMLElement | null} + */ +const getContainer = () => document.body.querySelector(`.${swalClasses.container}`); + +/** + * @param {string} selectorString + * @returns {HTMLElement | null} + */ +const elementBySelector = selectorString => { + const container = getContainer(); + return container ? container.querySelector(selectorString) : null; +}; + +/** + * @param {string} className + * @returns {HTMLElement | null} + */ +const elementByClass = className => { + return elementBySelector(`.${className}`); +}; + +/** + * @returns {HTMLElement | null} + */ +const getPopup = () => elementByClass(swalClasses.popup); + +/** + * @returns {HTMLElement | null} + */ +const getIcon = () => elementByClass(swalClasses.icon); + +/** + * @returns {HTMLElement | null} + */ +const getIconContent = () => elementByClass(swalClasses['icon-content']); + +/** + * @returns {HTMLElement | null} + */ +const getTitle$1 = () => elementByClass(swalClasses.title); + +/** + * @returns {HTMLElement | null} + */ +const getHtmlContainer = () => elementByClass(swalClasses['html-container']); + +/** + * @returns {HTMLElement | null} + */ +const getImage = () => elementByClass(swalClasses.image); + +/** + * @returns {HTMLElement | null} + */ +const getProgressSteps = () => elementByClass(swalClasses['progress-steps']); + +/** + * @returns {HTMLElement | null} + */ +const getValidationMessage = () => elementByClass(swalClasses['validation-message']); + +/** + * @returns {HTMLButtonElement | null} + */ +const getConfirmButton = () => (/** @type {HTMLButtonElement} */elementBySelector(`.${swalClasses.actions} .${swalClasses.confirm}`)); + +/** + * @returns {HTMLButtonElement | null} + */ +const getCancelButton = () => (/** @type {HTMLButtonElement} */elementBySelector(`.${swalClasses.actions} .${swalClasses.cancel}`)); + +/** + * @returns {HTMLButtonElement | null} + */ +const getDenyButton = () => (/** @type {HTMLButtonElement} */elementBySelector(`.${swalClasses.actions} .${swalClasses.deny}`)); + +/** + * @returns {HTMLElement | null} + */ +const getInputLabel = () => elementByClass(swalClasses['input-label']); + +/** + * @returns {HTMLElement | null} + */ +const getLoader = () => elementBySelector(`.${swalClasses.loader}`); + +/** + * @returns {HTMLElement | null} + */ +const getActions = () => elementByClass(swalClasses.actions); + +/** + * @returns {HTMLElement | null} + */ +const getFooter = () => elementByClass(swalClasses.footer); + +/** + * @returns {HTMLElement | null} + */ +const getTimerProgressBar = () => elementByClass(swalClasses['timer-progress-bar']); + +/** + * @returns {HTMLElement | null} + */ +const getCloseButton = () => elementByClass(swalClasses.close); + +// https://github.com/jkup/focusable/blob/master/index.js +const focusable = ` + a[href], + area[href], + input:not([disabled]), + select:not([disabled]), + textarea:not([disabled]), + button:not([disabled]), + iframe, + object, + embed, + [tabindex="0"], + [contenteditable], + audio[controls], + video[controls], + summary +`; +/** + * @returns {HTMLElement[]} + */ +const getFocusableElements = () => { + const popup = getPopup(); + if (!popup) { + return []; + } + /** @type {NodeListOf} */ + const focusableElementsWithTabindex = popup.querySelectorAll('[tabindex]:not([tabindex="-1"]):not([tabindex="0"])'); + const focusableElementsWithTabindexSorted = Array.from(focusableElementsWithTabindex) + // sort according to tabindex + .sort((a, b) => { + const tabindexA = parseInt(a.getAttribute('tabindex') || '0'); + const tabindexB = parseInt(b.getAttribute('tabindex') || '0'); + if (tabindexA > tabindexB) { + return 1; + } else if (tabindexA < tabindexB) { + return -1; + } + return 0; + }); + + /** @type {NodeListOf} */ + const otherFocusableElements = popup.querySelectorAll(focusable); + const otherFocusableElementsFiltered = Array.from(otherFocusableElements).filter(el => el.getAttribute('tabindex') !== '-1'); + return [...new Set(focusableElementsWithTabindexSorted.concat(otherFocusableElementsFiltered))].filter(el => isVisible$1(el)); +}; + +/** + * @returns {boolean} + */ +const isModal = () => { + return hasClass(document.body, swalClasses.shown) && !hasClass(document.body, swalClasses['toast-shown']) && !hasClass(document.body, swalClasses['no-backdrop']); +}; + +/** + * @returns {boolean} + */ +const isToast = () => { + const popup = getPopup(); + if (!popup) { + return false; + } + return hasClass(popup, swalClasses.toast); +}; + +/** + * @returns {boolean} + */ +const isLoading$2 = () => { + const popup = getPopup(); + if (!popup) { + return false; + } + return popup.hasAttribute('data-loading'); +}; + +/** + * Securely set innerHTML of an element + * https://github.com/sweetalert2/sweetalert2/issues/1926 + * + * @param {HTMLElement} elem + * @param {string} html + */ +const setInnerHtml = (elem, html) => { + elem.textContent = ''; + if (html) { + const parser = new DOMParser(); + const parsed = parser.parseFromString(html, `text/html`); + const head = parsed.querySelector('head'); + if (head) { + Array.from(head.childNodes).forEach(child => { + elem.appendChild(child); + }); + } + const body = parsed.querySelector('body'); + if (body) { + Array.from(body.childNodes).forEach(child => { + if (child instanceof HTMLVideoElement || child instanceof HTMLAudioElement) { + elem.appendChild(child.cloneNode(true)); // https://github.com/sweetalert2/sweetalert2/issues/2507 + } else { + elem.appendChild(child); + } + }); + } + } +}; + +/** + * @param {HTMLElement} elem + * @param {string} className + * @returns {boolean} + */ +const hasClass = (elem, className) => { + if (!className) { + return false; + } + const classList = className.split(/\s+/); + for (let i = 0; i < classList.length; i++) { + if (!elem.classList.contains(classList[i])) { + return false; + } + } + return true; +}; + +/** + * @param {HTMLElement} elem + * @param {SweetAlertOptions} params + */ +const removeCustomClasses = (elem, params) => { + Array.from(elem.classList).forEach(className => { + if (!Object.values(swalClasses).includes(className) && !Object.values(iconTypes).includes(className) && !Object.values(params.showClass || {}).includes(className)) { + elem.classList.remove(className); + } + }); +}; + +/** + * @param {HTMLElement} elem + * @param {SweetAlertOptions} params + * @param {string} className + */ +const applyCustomClass = (elem, params, className) => { + removeCustomClasses(elem, params); + if (!params.customClass) { + return; + } + const customClass = params.customClass[(/** @type {keyof SweetAlertCustomClass} */className)]; + if (!customClass) { + return; + } + if (typeof customClass !== 'string' && !customClass.forEach) { + warn(`Invalid type of customClass.${className}! Expected string or iterable object, got "${typeof customClass}"`); + return; + } + addClass(elem, customClass); +}; + +/** + * @param {HTMLElement} popup + * @param {import('./renderers/renderInput').InputClass | SweetAlertInput} inputClass + * @returns {HTMLInputElement | null} + */ +const getInput$1 = (popup, inputClass) => { + if (!inputClass) { + return null; + } + switch (inputClass) { + case 'select': + case 'textarea': + case 'file': + return popup.querySelector(`.${swalClasses.popup} > .${swalClasses[inputClass]}`); + case 'checkbox': + return popup.querySelector(`.${swalClasses.popup} > .${swalClasses.checkbox} input`); + case 'radio': + return popup.querySelector(`.${swalClasses.popup} > .${swalClasses.radio} input:checked`) || popup.querySelector(`.${swalClasses.popup} > .${swalClasses.radio} input:first-child`); + case 'range': + return popup.querySelector(`.${swalClasses.popup} > .${swalClasses.range} input`); + default: + return popup.querySelector(`.${swalClasses.popup} > .${swalClasses.input}`); + } +}; + +/** + * @param {HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement} input + */ +const focusInput = input => { + input.focus(); + + // place cursor at end of text in text input + if (input.type !== 'file') { + // http://stackoverflow.com/a/2345915 + const val = input.value; + input.value = ''; + input.value = val; + } +}; + +/** + * @param {HTMLElement | HTMLElement[] | null} target + * @param {string | string[] | readonly string[] | undefined} classList + * @param {boolean} condition + */ +const toggleClass = (target, classList, condition) => { + if (!target || !classList) { + return; + } + if (typeof classList === 'string') { + classList = classList.split(/\s+/).filter(Boolean); + } + classList.forEach(className => { + if (Array.isArray(target)) { + target.forEach(elem => { + if (condition) { + elem.classList.add(className); + } else { + elem.classList.remove(className); + } + }); + } else { + if (condition) { + target.classList.add(className); + } else { + target.classList.remove(className); + } + } + }); +}; + +/** + * @param {HTMLElement | HTMLElement[] | null} target + * @param {string | string[] | readonly string[] | undefined} classList + */ +const addClass = (target, classList) => { + toggleClass(target, classList, true); +}; + +/** + * @param {HTMLElement | HTMLElement[] | null} target + * @param {string | string[] | readonly string[] | undefined} classList + */ +const removeClass = (target, classList) => { + toggleClass(target, classList, false); +}; + +/** + * Get direct child of an element by class name + * + * @param {HTMLElement} elem + * @param {string} className + * @returns {HTMLElement | undefined} + */ +const getDirectChildByClass = (elem, className) => { + const children = Array.from(elem.children); + for (let i = 0; i < children.length; i++) { + const child = children[i]; + if (child instanceof HTMLElement && hasClass(child, className)) { + return child; + } + } +}; + +/** + * @param {HTMLElement} elem + * @param {string} property + * @param {*} value + */ +const applyNumericalStyle = (elem, property, value) => { + if (value === `${parseInt(value)}`) { + value = parseInt(value); + } + if (value || parseInt(value) === 0) { + elem.style.setProperty(property, typeof value === 'number' ? `${value}px` : value); + } else { + elem.style.removeProperty(property); + } +}; + +/** + * @param {HTMLElement | null} elem + * @param {string} display + */ +const show = (elem, display = 'flex') => { + if (!elem) { + return; + } + elem.style.display = display; +}; + +/** + * @param {HTMLElement | null} elem + */ +const hide$2 = elem => { + if (!elem) { + return; + } + elem.style.display = 'none'; +}; + +/** + * @param {HTMLElement | null} elem + * @param {string} display + */ +const showWhenInnerHtmlPresent = (elem, display = 'block') => { + if (!elem) { + return; + } + new MutationObserver(() => { + toggle(elem, elem.innerHTML, display); + }).observe(elem, { + childList: true, + subtree: true + }); +}; + +/** + * @param {HTMLElement} parent + * @param {string} selector + * @param {string} property + * @param {string} value + */ +const setStyle$1 = (parent, selector, property, value) => { + /** @type {HTMLElement | null} */ + const el = parent.querySelector(selector); + if (el) { + el.style.setProperty(property, value); + } +}; + +/** + * @param {HTMLElement} elem + * @param {any} condition + * @param {string} display + */ +const toggle = (elem, condition, display = 'flex') => { + if (condition) { + show(elem, display); + } else { + hide$2(elem); + } +}; + +/** + * borrowed from jquery $(elem).is(':visible') implementation + * + * @param {HTMLElement | null} elem + * @returns {boolean} + */ +const isVisible$1 = elem => !!(elem && (elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length)); + +/** + * @returns {boolean} + */ +const allButtonsAreHidden = () => !isVisible$1(getConfirmButton()) && !isVisible$1(getDenyButton()) && !isVisible$1(getCancelButton()); + +/** + * @param {HTMLElement} elem + * @returns {boolean} + */ +const isScrollable = elem => !!(elem.scrollHeight > elem.clientHeight); + +/** + * @param {HTMLElement} element + * @param {HTMLElement} stopElement + * @returns {boolean} + */ +const selfOrParentIsScrollable = (element, stopElement) => { + let parent = element; + while (parent && parent !== stopElement) { + if (isScrollable(parent)) { + return true; + } + parent = parent.parentElement; + } + return false; +}; + +/** + * borrowed from https://stackoverflow.com/a/46352119 + * + * @param {HTMLElement} elem + * @returns {boolean} + */ +const hasCssAnimation = elem => { + const style = window.getComputedStyle(elem); + const animDuration = parseFloat(style.getPropertyValue('animation-duration') || '0'); + const transDuration = parseFloat(style.getPropertyValue('transition-duration') || '0'); + return animDuration > 0 || transDuration > 0; +}; + +/** + * @param {number} timer + * @param {boolean} reset + */ +const animateTimerProgressBar = (timer, reset = false) => { + const timerProgressBar = getTimerProgressBar(); + if (!timerProgressBar) { + return; + } + if (isVisible$1(timerProgressBar)) { + if (reset) { + timerProgressBar.style.transition = 'none'; + timerProgressBar.style.width = '100%'; + } + setTimeout(() => { + timerProgressBar.style.transition = `width ${timer / 1000}s linear`; + timerProgressBar.style.width = '0%'; + }, 10); + } +}; +const stopTimerProgressBar = () => { + const timerProgressBar = getTimerProgressBar(); + if (!timerProgressBar) { + return; + } + const timerProgressBarWidth = parseInt(window.getComputedStyle(timerProgressBar).width); + timerProgressBar.style.removeProperty('transition'); + timerProgressBar.style.width = '100%'; + const timerProgressBarFullWidth = parseInt(window.getComputedStyle(timerProgressBar).width); + const timerProgressBarPercent = timerProgressBarWidth / timerProgressBarFullWidth * 100; + timerProgressBar.style.width = `${timerProgressBarPercent}%`; +}; + +/** + * Detect Node env + * + * @returns {boolean} + */ +const isNodeEnv = () => typeof window === 'undefined' || typeof document === 'undefined'; + +const sweetHTML = ` +
+ +
    +
    + +

    +
    + + +
    + + +
    + +
    + + +
    +
    +
    + + + +
    +
    +
    +
    +
    +
    +`.replace(/(^|\n)\s*/g, ''); + +/** + * @returns {boolean} + */ +const resetOldContainer = () => { + const oldContainer = getContainer(); + if (!oldContainer) { + return false; + } + oldContainer.remove(); + removeClass([document.documentElement, document.body], [swalClasses['no-backdrop'], swalClasses['toast-shown'], swalClasses['has-column']]); + return true; +}; +const resetValidationMessage$1 = () => { + globalState.currentInstance.resetValidationMessage(); +}; +const addInputChangeListeners = () => { + const popup = getPopup(); + const input = getDirectChildByClass(popup, swalClasses.input); + const file = getDirectChildByClass(popup, swalClasses.file); + /** @type {HTMLInputElement} */ + const range = popup.querySelector(`.${swalClasses.range} input`); + /** @type {HTMLOutputElement} */ + const rangeOutput = popup.querySelector(`.${swalClasses.range} output`); + const select = getDirectChildByClass(popup, swalClasses.select); + /** @type {HTMLInputElement} */ + const checkbox = popup.querySelector(`.${swalClasses.checkbox} input`); + const textarea = getDirectChildByClass(popup, swalClasses.textarea); + input.oninput = resetValidationMessage$1; + file.onchange = resetValidationMessage$1; + select.onchange = resetValidationMessage$1; + checkbox.onchange = resetValidationMessage$1; + textarea.oninput = resetValidationMessage$1; + range.oninput = () => { + resetValidationMessage$1(); + rangeOutput.value = range.value; + }; + range.onchange = () => { + resetValidationMessage$1(); + rangeOutput.value = range.value; + }; +}; + +/** + * @param {string | HTMLElement} target + * @returns {HTMLElement} + */ +const getTarget = target => typeof target === 'string' ? document.querySelector(target) : target; + +/** + * @param {SweetAlertOptions} params + */ +const setupAccessibility = params => { + const popup = getPopup(); + popup.setAttribute('role', params.toast ? 'alert' : 'dialog'); + popup.setAttribute('aria-live', params.toast ? 'polite' : 'assertive'); + if (!params.toast) { + popup.setAttribute('aria-modal', 'true'); + } +}; + +/** + * @param {HTMLElement} targetElement + */ +const setupRTL = targetElement => { + if (window.getComputedStyle(targetElement).direction === 'rtl') { + addClass(getContainer(), swalClasses.rtl); + } +}; + +/** + * Add modal + backdrop + no-war message for Russians to DOM + * + * @param {SweetAlertOptions} params + */ +const init$1 = params => { + // Clean up the old popup container if it exists + const oldContainerExisted = resetOldContainer(); + if (isNodeEnv()) { + error('SweetAlert2 requires document to initialize'); + return; + } + const container = document.createElement('div'); + container.className = swalClasses.container; + if (oldContainerExisted) { + addClass(container, swalClasses['no-transition']); + } + setInnerHtml(container, sweetHTML); + container.dataset['swal2Theme'] = params.theme; + const targetElement = getTarget(params.target); + targetElement.appendChild(container); + if (params.topLayer) { + container.setAttribute('popover', ''); + container.showPopover(); + } + setupAccessibility(params); + setupRTL(targetElement); + addInputChangeListeners(); +}; + +/** + * @param {HTMLElement | object | string} param + * @param {HTMLElement} target + */ +const parseHtmlToContainer = (param, target) => { + // DOM element + if (param instanceof HTMLElement) { + target.appendChild(param); + } + + // Object + else if (typeof param === 'object') { + handleObject(param, target); + } + + // Plain string + else if (param) { + setInnerHtml(target, param); + } +}; + +/** + * @param {any} param + * @param {HTMLElement} target + */ +const handleObject = (param, target) => { + // JQuery element(s) + if (param.jquery) { + handleJqueryElem(target, param); + } + + // For other objects use their string representation + else { + setInnerHtml(target, param.toString()); + } +}; + +/** + * @param {HTMLElement} target + * @param {any} elem + */ +const handleJqueryElem = (target, elem) => { + target.textContent = ''; + if (0 in elem) { + for (let i = 0; i in elem; i++) { + target.appendChild(elem[i].cloneNode(true)); + } + } else { + target.appendChild(elem.cloneNode(true)); + } +}; + +/** + * @param {SweetAlert} instance + * @param {SweetAlertOptions} params + */ +const renderActions = (instance, params) => { + const actions = getActions(); + const loader = getLoader(); + if (!actions || !loader) { + return; + } + + // Actions (buttons) wrapper + if (!params.showConfirmButton && !params.showDenyButton && !params.showCancelButton) { + hide$2(actions); + } else { + show(actions); + } + + // Custom class + applyCustomClass(actions, params, 'actions'); + + // Render all the buttons + renderButtons(actions, loader, params); + + // Loader + setInnerHtml(loader, params.loaderHtml || ''); + applyCustomClass(loader, params, 'loader'); +}; + +/** + * @param {HTMLElement} actions + * @param {HTMLElement} loader + * @param {SweetAlertOptions} params + */ +function renderButtons(actions, loader, params) { + const confirmButton = getConfirmButton(); + const denyButton = getDenyButton(); + const cancelButton = getCancelButton(); + if (!confirmButton || !denyButton || !cancelButton) { + return; + } + + // Render buttons + renderButton(confirmButton, 'confirm', params); + renderButton(denyButton, 'deny', params); + renderButton(cancelButton, 'cancel', params); + handleButtonsStyling(confirmButton, denyButton, cancelButton, params); + if (params.reverseButtons) { + if (params.toast) { + actions.insertBefore(cancelButton, confirmButton); + actions.insertBefore(denyButton, confirmButton); + } else { + actions.insertBefore(cancelButton, loader); + actions.insertBefore(denyButton, loader); + actions.insertBefore(confirmButton, loader); + } + } +} + +/** + * @param {HTMLElement} confirmButton + * @param {HTMLElement} denyButton + * @param {HTMLElement} cancelButton + * @param {SweetAlertOptions} params + */ +function handleButtonsStyling(confirmButton, denyButton, cancelButton, params) { + if (!params.buttonsStyling) { + removeClass([confirmButton, denyButton, cancelButton], swalClasses.styled); + return; + } + addClass([confirmButton, denyButton, cancelButton], swalClasses.styled); + + // Apply custom background colors to action buttons + if (params.confirmButtonColor) { + confirmButton.style.setProperty('--swal2-confirm-button-background-color', params.confirmButtonColor); + } + if (params.denyButtonColor) { + denyButton.style.setProperty('--swal2-deny-button-background-color', params.denyButtonColor); + } + if (params.cancelButtonColor) { + cancelButton.style.setProperty('--swal2-cancel-button-background-color', params.cancelButtonColor); + } + + // Apply the outline color to action buttons + applyOutlineColor(confirmButton); + applyOutlineColor(denyButton); + applyOutlineColor(cancelButton); +} + +/** + * @param {HTMLElement} button + */ +function applyOutlineColor(button) { + const buttonStyle = window.getComputedStyle(button); + if (buttonStyle.getPropertyValue('--swal2-action-button-focus-box-shadow')) { + // If the button already has a custom outline color, no need to change it + return; + } + const outlineColor = buttonStyle.backgroundColor.replace(/rgba?\((\d+), (\d+), (\d+).*/, 'rgba($1, $2, $3, 0.5)'); + button.style.setProperty('--swal2-action-button-focus-box-shadow', buttonStyle.getPropertyValue('--swal2-outline').replace(/ rgba\(.*/, ` ${outlineColor}`)); +} + +/** + * @param {HTMLElement} button + * @param {'confirm' | 'deny' | 'cancel'} buttonType + * @param {SweetAlertOptions} params + */ +function renderButton(button, buttonType, params) { + const buttonName = /** @type {'Confirm' | 'Deny' | 'Cancel'} */capitalizeFirstLetter(buttonType); + toggle(button, params[`show${buttonName}Button`], 'inline-block'); + setInnerHtml(button, params[`${buttonType}ButtonText`] || ''); // Set caption text + button.setAttribute('aria-label', params[`${buttonType}ButtonAriaLabel`] || ''); // ARIA label + + // Add buttons custom classes + button.className = swalClasses[buttonType]; + applyCustomClass(button, params, `${buttonType}Button`); +} + +/** + * @param {SweetAlert} instance + * @param {SweetAlertOptions} params + */ +const renderCloseButton = (instance, params) => { + const closeButton = getCloseButton(); + if (!closeButton) { + return; + } + setInnerHtml(closeButton, params.closeButtonHtml || ''); + + // Custom class + applyCustomClass(closeButton, params, 'closeButton'); + toggle(closeButton, params.showCloseButton); + closeButton.setAttribute('aria-label', params.closeButtonAriaLabel || ''); +}; + +/** + * @param {SweetAlert} instance + * @param {SweetAlertOptions} params + */ +const renderContainer = (instance, params) => { + const container = getContainer(); + if (!container) { + return; + } + handleBackdropParam(container, params.backdrop); + handlePositionParam(container, params.position); + handleGrowParam(container, params.grow); + + // Custom class + applyCustomClass(container, params, 'container'); +}; + +/** + * @param {HTMLElement} container + * @param {SweetAlertOptions['backdrop']} backdrop + */ +function handleBackdropParam(container, backdrop) { + if (typeof backdrop === 'string') { + container.style.background = backdrop; + } else if (!backdrop) { + addClass([document.documentElement, document.body], swalClasses['no-backdrop']); + } +} + +/** + * @param {HTMLElement} container + * @param {SweetAlertOptions['position']} position + */ +function handlePositionParam(container, position) { + if (!position) { + return; + } + if (position in swalClasses) { + addClass(container, swalClasses[position]); + } else { + warn('The "position" parameter is not valid, defaulting to "center"'); + addClass(container, swalClasses.center); + } +} + +/** + * @param {HTMLElement} container + * @param {SweetAlertOptions['grow']} grow + */ +function handleGrowParam(container, grow) { + if (!grow) { + return; + } + addClass(container, swalClasses[`grow-${grow}`]); +} + +/** + * This module contains `WeakMap`s for each effectively-"private property" that a `Swal` has. + * For example, to set the private property "foo" of `this` to "bar", you can `privateProps.foo.set(this, 'bar')` + * This is the approach that Babel will probably take to implement private methods/fields + * https://github.com/tc39/proposal-private-methods + * https://github.com/babel/babel/pull/7555 + * Once we have the changes from that PR in Babel, and our core class fits reasonable in *one module* + * then we can use that language feature. + */ + +var privateProps = { + innerParams: new WeakMap(), + domCache: new WeakMap() +}; + +/// + + +/** @type {InputClass[]} */ +const inputClasses = ['input', 'file', 'range', 'select', 'radio', 'checkbox', 'textarea']; + +/** + * @param {SweetAlert} instance + * @param {SweetAlertOptions} params + */ +const renderInput = (instance, params) => { + const popup = getPopup(); + if (!popup) { + return; + } + const innerParams = privateProps.innerParams.get(instance); + const rerender = !innerParams || params.input !== innerParams.input; + inputClasses.forEach(inputClass => { + const inputContainer = getDirectChildByClass(popup, swalClasses[inputClass]); + if (!inputContainer) { + return; + } + + // set attributes + setAttributes(inputClass, params.inputAttributes); + + // set class + inputContainer.className = swalClasses[inputClass]; + if (rerender) { + hide$2(inputContainer); + } + }); + if (params.input) { + if (rerender) { + showInput(params); + } + // set custom class + setCustomClass(params); + } +}; + +/** + * @param {SweetAlertOptions} params + */ +const showInput = params => { + if (!params.input) { + return; + } + if (!renderInputType[params.input]) { + error(`Unexpected type of input! Expected ${Object.keys(renderInputType).join(' | ')}, got "${params.input}"`); + return; + } + const inputContainer = getInputContainer(params.input); + if (!inputContainer) { + return; + } + const input = renderInputType[params.input](inputContainer, params); + show(inputContainer); + + // input autofocus + if (params.inputAutoFocus) { + setTimeout(() => { + focusInput(input); + }); + } +}; + +/** + * @param {HTMLInputElement} input + */ +const removeAttributes = input => { + for (let i = 0; i < input.attributes.length; i++) { + const attrName = input.attributes[i].name; + if (!['id', 'type', 'value', 'style'].includes(attrName)) { + input.removeAttribute(attrName); + } + } +}; + +/** + * @param {InputClass} inputClass + * @param {SweetAlertOptions['inputAttributes']} inputAttributes + */ +const setAttributes = (inputClass, inputAttributes) => { + const popup = getPopup(); + if (!popup) { + return; + } + const input = getInput$1(popup, inputClass); + if (!input) { + return; + } + removeAttributes(input); + for (const attr in inputAttributes) { + input.setAttribute(attr, inputAttributes[attr]); + } +}; + +/** + * @param {SweetAlertOptions} params + */ +const setCustomClass = params => { + if (!params.input) { + return; + } + const inputContainer = getInputContainer(params.input); + if (inputContainer) { + applyCustomClass(inputContainer, params, 'input'); + } +}; + +/** + * @param {HTMLInputElement | HTMLTextAreaElement} input + * @param {SweetAlertOptions} params + */ +const setInputPlaceholder = (input, params) => { + if (!input.placeholder && params.inputPlaceholder) { + input.placeholder = params.inputPlaceholder; + } +}; + +/** + * @param {Input} input + * @param {Input} prependTo + * @param {SweetAlertOptions} params + */ +const setInputLabel = (input, prependTo, params) => { + if (params.inputLabel) { + const label = document.createElement('label'); + const labelClass = swalClasses['input-label']; + label.setAttribute('for', input.id); + label.className = labelClass; + if (typeof params.customClass === 'object') { + addClass(label, params.customClass.inputLabel); + } + label.innerText = params.inputLabel; + prependTo.insertAdjacentElement('beforebegin', label); + } +}; + +/** + * @param {SweetAlertInput} inputType + * @returns {HTMLElement | undefined} + */ +const getInputContainer = inputType => { + const popup = getPopup(); + if (!popup) { + return; + } + return getDirectChildByClass(popup, swalClasses[(/** @type {SwalClass} */inputType)] || swalClasses.input); +}; + +/** + * @param {HTMLInputElement | HTMLOutputElement | HTMLTextAreaElement} input + * @param {SweetAlertOptions['inputValue']} inputValue + */ +const checkAndSetInputValue = (input, inputValue) => { + if (['string', 'number'].includes(typeof inputValue)) { + input.value = `${inputValue}`; + } else if (!isPromise(inputValue)) { + warn(`Unexpected type of inputValue! Expected "string", "number" or "Promise", got "${typeof inputValue}"`); + } +}; + +/** @type {Record Input>} */ +const renderInputType = {}; + +/** + * @param {HTMLInputElement} input + * @param {SweetAlertOptions} params + * @returns {HTMLInputElement} + */ +renderInputType.text = renderInputType.email = renderInputType.password = renderInputType.number = renderInputType.tel = renderInputType.url = renderInputType.search = renderInputType.date = renderInputType['datetime-local'] = renderInputType.time = renderInputType.week = renderInputType.month = /** @type {(input: Input | HTMLElement, params: SweetAlertOptions) => Input} */ +(input, params) => { + checkAndSetInputValue(input, params.inputValue); + setInputLabel(input, input, params); + setInputPlaceholder(input, params); + input.type = params.input; + return input; +}; + +/** + * @param {HTMLInputElement} input + * @param {SweetAlertOptions} params + * @returns {HTMLInputElement} + */ +renderInputType.file = (input, params) => { + setInputLabel(input, input, params); + setInputPlaceholder(input, params); + return input; +}; + +/** + * @param {HTMLInputElement} range + * @param {SweetAlertOptions} params + * @returns {HTMLInputElement} + */ +renderInputType.range = (range, params) => { + const rangeInput = range.querySelector('input'); + const rangeOutput = range.querySelector('output'); + checkAndSetInputValue(rangeInput, params.inputValue); + rangeInput.type = params.input; + checkAndSetInputValue(rangeOutput, params.inputValue); + setInputLabel(rangeInput, range, params); + return range; +}; + +/** + * @param {HTMLSelectElement} select + * @param {SweetAlertOptions} params + * @returns {HTMLSelectElement} + */ +renderInputType.select = (select, params) => { + select.textContent = ''; + if (params.inputPlaceholder) { + const placeholder = document.createElement('option'); + setInnerHtml(placeholder, params.inputPlaceholder); + placeholder.value = ''; + placeholder.disabled = true; + placeholder.selected = true; + select.appendChild(placeholder); + } + setInputLabel(select, select, params); + return select; +}; + +/** + * @param {HTMLInputElement} radio + * @returns {HTMLInputElement} + */ +renderInputType.radio = radio => { + radio.textContent = ''; + return radio; +}; + +/** + * @param {HTMLLabelElement} checkboxContainer + * @param {SweetAlertOptions} params + * @returns {HTMLInputElement} + */ +renderInputType.checkbox = (checkboxContainer, params) => { + const checkbox = getInput$1(getPopup(), 'checkbox'); + checkbox.value = '1'; + checkbox.checked = Boolean(params.inputValue); + const label = checkboxContainer.querySelector('span'); + setInnerHtml(label, params.inputPlaceholder || params.inputLabel); + return checkbox; +}; + +/** + * @param {HTMLTextAreaElement} textarea + * @param {SweetAlertOptions} params + * @returns {HTMLTextAreaElement} + */ +renderInputType.textarea = (textarea, params) => { + checkAndSetInputValue(textarea, params.inputValue); + setInputPlaceholder(textarea, params); + setInputLabel(textarea, textarea, params); + + /** + * @param {HTMLElement} el + * @returns {number} + */ + const getMargin = el => parseInt(window.getComputedStyle(el).marginLeft) + parseInt(window.getComputedStyle(el).marginRight); + + // https://github.com/sweetalert2/sweetalert2/issues/2291 + setTimeout(() => { + // https://github.com/sweetalert2/sweetalert2/issues/1699 + if ('MutationObserver' in window) { + const initialPopupWidth = parseInt(window.getComputedStyle(getPopup()).width); + const textareaResizeHandler = () => { + // check if texarea is still in document (i.e. popup wasn't closed in the meantime) + if (!document.body.contains(textarea)) { + return; + } + const textareaWidth = textarea.offsetWidth + getMargin(textarea); + if (textareaWidth > initialPopupWidth) { + getPopup().style.width = `${textareaWidth}px`; + } else { + applyNumericalStyle(getPopup(), 'width', params.width); + } + }; + new MutationObserver(textareaResizeHandler).observe(textarea, { + attributes: true, + attributeFilter: ['style'] + }); + } + }); + return textarea; +}; + +/** + * @param {SweetAlert} instance + * @param {SweetAlertOptions} params + */ +const renderContent = (instance, params) => { + const htmlContainer = getHtmlContainer(); + if (!htmlContainer) { + return; + } + showWhenInnerHtmlPresent(htmlContainer); + applyCustomClass(htmlContainer, params, 'htmlContainer'); + + // Content as HTML + if (params.html) { + parseHtmlToContainer(params.html, htmlContainer); + show(htmlContainer, 'block'); + } + + // Content as plain text + else if (params.text) { + htmlContainer.textContent = params.text; + show(htmlContainer, 'block'); + } + + // No content + else { + hide$2(htmlContainer); + } + renderInput(instance, params); +}; + +/** + * @param {SweetAlert} instance + * @param {SweetAlertOptions} params + */ +const renderFooter = (instance, params) => { + const footer = getFooter(); + if (!footer) { + return; + } + showWhenInnerHtmlPresent(footer); + toggle(footer, params.footer, 'block'); + if (params.footer) { + parseHtmlToContainer(params.footer, footer); + } + + // Custom class + applyCustomClass(footer, params, 'footer'); +}; + +/** + * @param {SweetAlert} instance + * @param {SweetAlertOptions} params + */ +const renderIcon = (instance, params) => { + const innerParams = privateProps.innerParams.get(instance); + const icon = getIcon(); + if (!icon) { + return; + } + + // if the given icon already rendered, apply the styling without re-rendering the icon + if (innerParams && params.icon === innerParams.icon) { + // Custom or default content + setContent(icon, params); + applyStyles$2(icon, params); + return; + } + if (!params.icon && !params.iconHtml) { + hide$2(icon); + return; + } + if (params.icon && Object.keys(iconTypes).indexOf(params.icon) === -1) { + error(`Unknown icon! Expected "success", "error", "warning", "info" or "question", got "${params.icon}"`); + hide$2(icon); + return; + } + show(icon); + + // Custom or default content + setContent(icon, params); + applyStyles$2(icon, params); + + // Animate icon + addClass(icon, params.showClass && params.showClass.icon); + + // Re-adjust the success icon on system theme change + const colorSchemeQueryList = window.matchMedia('(prefers-color-scheme: dark)'); + colorSchemeQueryList.addEventListener('change', adjustSuccessIconBackgroundColor); +}; + +/** + * @param {HTMLElement} icon + * @param {SweetAlertOptions} params + */ +const applyStyles$2 = (icon, params) => { + for (const [iconType, iconClassName] of Object.entries(iconTypes)) { + if (params.icon !== iconType) { + removeClass(icon, iconClassName); + } + } + addClass(icon, params.icon && iconTypes[params.icon]); + + // Icon color + setColor(icon, params); + + // Success icon background color + adjustSuccessIconBackgroundColor(); + + // Custom class + applyCustomClass(icon, params, 'icon'); +}; + +// Adjust success icon background color to match the popup background color +const adjustSuccessIconBackgroundColor = () => { + const popup = getPopup(); + if (!popup) { + return; + } + const popupBackgroundColor = window.getComputedStyle(popup).getPropertyValue('background-color'); + /** @type {NodeListOf} */ + const successIconParts = popup.querySelectorAll('[class^=swal2-success-circular-line], .swal2-success-fix'); + for (let i = 0; i < successIconParts.length; i++) { + successIconParts[i].style.backgroundColor = popupBackgroundColor; + } +}; + +/** + * + * @param {SweetAlertOptions} params + * @returns {string} + */ +const successIconHtml = params => ` + ${params.animation ? '
    ' : ''} + +
    + ${params.animation ? '
    ' : ''} + ${params.animation ? '
    ' : ''} +`; +const errorIconHtml = ` + + + + +`; + +/** + * @param {HTMLElement} icon + * @param {SweetAlertOptions} params + */ +const setContent = (icon, params) => { + if (!params.icon && !params.iconHtml) { + return; + } + let oldContent = icon.innerHTML; + let newContent = ''; + if (params.iconHtml) { + newContent = iconContent(params.iconHtml); + } else if (params.icon === 'success') { + newContent = successIconHtml(params); + oldContent = oldContent.replace(/ style=".*?"/g, ''); // undo adjustSuccessIconBackgroundColor() + } else if (params.icon === 'error') { + newContent = errorIconHtml; + } else if (params.icon) { + const defaultIconHtml = { + question: '?', + warning: '!', + info: 'i' + }; + newContent = iconContent(defaultIconHtml[params.icon]); + } + if (oldContent.trim() !== newContent.trim()) { + setInnerHtml(icon, newContent); + } +}; + +/** + * @param {HTMLElement} icon + * @param {SweetAlertOptions} params + */ +const setColor = (icon, params) => { + if (!params.iconColor) { + return; + } + icon.style.color = params.iconColor; + icon.style.borderColor = params.iconColor; + for (const sel of ['.swal2-success-line-tip', '.swal2-success-line-long', '.swal2-x-mark-line-left', '.swal2-x-mark-line-right']) { + setStyle$1(icon, sel, 'background-color', params.iconColor); + } + setStyle$1(icon, '.swal2-success-ring', 'border-color', params.iconColor); +}; + +/** + * @param {string} content + * @returns {string} + */ +const iconContent = content => `
    ${content}
    `; + +/** + * @param {SweetAlert} instance + * @param {SweetAlertOptions} params + */ +const renderImage = (instance, params) => { + const image = getImage(); + if (!image) { + return; + } + if (!params.imageUrl) { + hide$2(image); + return; + } + show(image, ''); + + // Src, alt + image.setAttribute('src', params.imageUrl); + image.setAttribute('alt', params.imageAlt || ''); + + // Width, height + applyNumericalStyle(image, 'width', params.imageWidth); + applyNumericalStyle(image, 'height', params.imageHeight); + + // Class + image.className = swalClasses.image; + applyCustomClass(image, params, 'image'); +}; + +let dragging = false; +let mousedownX = 0; +let mousedownY = 0; +let initialX = 0; +let initialY = 0; + +/** + * @param {HTMLElement} popup + */ +const addDraggableListeners = popup => { + popup.addEventListener('mousedown', down); + document.body.addEventListener('mousemove', move); + popup.addEventListener('mouseup', up); + popup.addEventListener('touchstart', down); + document.body.addEventListener('touchmove', move); + popup.addEventListener('touchend', up); +}; + +/** + * @param {HTMLElement} popup + */ +const removeDraggableListeners = popup => { + popup.removeEventListener('mousedown', down); + document.body.removeEventListener('mousemove', move); + popup.removeEventListener('mouseup', up); + popup.removeEventListener('touchstart', down); + document.body.removeEventListener('touchmove', move); + popup.removeEventListener('touchend', up); +}; + +/** + * @param {MouseEvent | TouchEvent} event + */ +const down = event => { + const popup = getPopup(); + if (event.target === popup || getIcon().contains(/** @type {HTMLElement} */event.target)) { + dragging = true; + const clientXY = getClientXY(event); + mousedownX = clientXY.clientX; + mousedownY = clientXY.clientY; + initialX = parseInt(popup.style.insetInlineStart) || 0; + initialY = parseInt(popup.style.insetBlockStart) || 0; + addClass(popup, 'swal2-dragging'); + } +}; + +/** + * @param {MouseEvent | TouchEvent} event + */ +const move = event => { + const popup = getPopup(); + if (dragging) { + let { + clientX, + clientY + } = getClientXY(event); + popup.style.insetInlineStart = `${initialX + (clientX - mousedownX)}px`; + popup.style.insetBlockStart = `${initialY + (clientY - mousedownY)}px`; + } +}; +const up = () => { + const popup = getPopup(); + dragging = false; + removeClass(popup, 'swal2-dragging'); +}; + +/** + * @param {MouseEvent | TouchEvent} event + * @returns {{ clientX: number, clientY: number }} + */ +const getClientXY = event => { + let clientX = 0, + clientY = 0; + if (event.type.startsWith('mouse')) { + clientX = /** @type {MouseEvent} */event.clientX; + clientY = /** @type {MouseEvent} */event.clientY; + } else if (event.type.startsWith('touch')) { + clientX = /** @type {TouchEvent} */event.touches[0].clientX; + clientY = /** @type {TouchEvent} */event.touches[0].clientY; + } + return { + clientX, + clientY + }; +}; + +/** + * @param {SweetAlert} instance + * @param {SweetAlertOptions} params + */ +const renderPopup = (instance, params) => { + const container = getContainer(); + const popup = getPopup(); + if (!container || !popup) { + return; + } + + // Width + // https://github.com/sweetalert2/sweetalert2/issues/2170 + if (params.toast) { + applyNumericalStyle(container, 'width', params.width); + popup.style.width = '100%'; + const loader = getLoader(); + if (loader) { + popup.insertBefore(loader, getIcon()); + } + } else { + applyNumericalStyle(popup, 'width', params.width); + } + + // Padding + applyNumericalStyle(popup, 'padding', params.padding); + + // Color + if (params.color) { + popup.style.color = params.color; + } + + // Background + if (params.background) { + popup.style.background = params.background; + } + hide$2(getValidationMessage()); + + // Classes + addClasses$1(popup, params); + if (params.draggable && !params.toast) { + addClass(popup, swalClasses.draggable); + addDraggableListeners(popup); + } else { + removeClass(popup, swalClasses.draggable); + removeDraggableListeners(popup); + } +}; + +/** + * @param {HTMLElement} popup + * @param {SweetAlertOptions} params + */ +const addClasses$1 = (popup, params) => { + const showClass = params.showClass || {}; + // Default Class + showClass when updating Swal.update({}) + popup.className = `${swalClasses.popup} ${isVisible$1(popup) ? showClass.popup : ''}`; + if (params.toast) { + addClass([document.documentElement, document.body], swalClasses['toast-shown']); + addClass(popup, swalClasses.toast); + } else { + addClass(popup, swalClasses.modal); + } + + // Custom class + applyCustomClass(popup, params, 'popup'); + // TODO: remove in the next major + if (typeof params.customClass === 'string') { + addClass(popup, params.customClass); + } + + // Icon class (#1842) + if (params.icon) { + addClass(popup, swalClasses[`icon-${params.icon}`]); + } +}; + +/** + * @param {SweetAlert} instance + * @param {SweetAlertOptions} params + */ +const renderProgressSteps = (instance, params) => { + const progressStepsContainer = getProgressSteps(); + if (!progressStepsContainer) { + return; + } + const { + progressSteps, + currentProgressStep + } = params; + if (!progressSteps || progressSteps.length === 0 || currentProgressStep === undefined) { + hide$2(progressStepsContainer); + return; + } + show(progressStepsContainer); + progressStepsContainer.textContent = ''; + if (currentProgressStep >= progressSteps.length) { + warn('Invalid currentProgressStep parameter, it should be less than progressSteps.length ' + '(currentProgressStep like JS arrays starts from 0)'); + } + progressSteps.forEach((step, index) => { + const stepEl = createStepElement(step); + progressStepsContainer.appendChild(stepEl); + if (index === currentProgressStep) { + addClass(stepEl, swalClasses['active-progress-step']); + } + if (index !== progressSteps.length - 1) { + const lineEl = createLineElement(params); + progressStepsContainer.appendChild(lineEl); + } + }); +}; + +/** + * @param {string} step + * @returns {HTMLLIElement} + */ +const createStepElement = step => { + const stepEl = document.createElement('li'); + addClass(stepEl, swalClasses['progress-step']); + setInnerHtml(stepEl, step); + return stepEl; +}; + +/** + * @param {SweetAlertOptions} params + * @returns {HTMLLIElement} + */ +const createLineElement = params => { + const lineEl = document.createElement('li'); + addClass(lineEl, swalClasses['progress-step-line']); + if (params.progressStepsDistance) { + applyNumericalStyle(lineEl, 'width', params.progressStepsDistance); + } + return lineEl; +}; + +/** + * @param {SweetAlert} instance + * @param {SweetAlertOptions} params + */ +const renderTitle = (instance, params) => { + const title = getTitle$1(); + if (!title) { + return; + } + showWhenInnerHtmlPresent(title); + toggle(title, params.title || params.titleText, 'block'); + if (params.title) { + parseHtmlToContainer(params.title, title); + } + if (params.titleText) { + title.innerText = params.titleText; + } + + // Custom class + applyCustomClass(title, params, 'title'); +}; + +/** + * @param {SweetAlert} instance + * @param {SweetAlertOptions} params + */ +const render = (instance, params) => { + renderPopup(instance, params); + renderContainer(instance, params); + renderProgressSteps(instance, params); + renderIcon(instance, params); + renderImage(instance, params); + renderTitle(instance, params); + renderCloseButton(instance, params); + renderContent(instance, params); + renderActions(instance, params); + renderFooter(instance, params); + const popup = getPopup(); + if (typeof params.didRender === 'function' && popup) { + params.didRender(popup); + } + globalState.eventEmitter.emit('didRender', popup); +}; + +/* + * Global function to determine if SweetAlert2 popup is shown + */ +const isVisible = () => { + return isVisible$1(getPopup()); +}; + +/* + * Global function to click 'Confirm' button + */ +const clickConfirm = () => { + var _dom$getConfirmButton; + return (_dom$getConfirmButton = getConfirmButton()) === null || _dom$getConfirmButton === void 0 ? void 0 : _dom$getConfirmButton.click(); +}; + +/* + * Global function to click 'Deny' button + */ +const clickDeny = () => { + var _dom$getDenyButton; + return (_dom$getDenyButton = getDenyButton()) === null || _dom$getDenyButton === void 0 ? void 0 : _dom$getDenyButton.click(); +}; + +/* + * Global function to click 'Cancel' button + */ +const clickCancel = () => { + var _dom$getCancelButton; + return (_dom$getCancelButton = getCancelButton()) === null || _dom$getCancelButton === void 0 ? void 0 : _dom$getCancelButton.click(); +}; + +/** @typedef {'cancel' | 'backdrop' | 'close' | 'esc' | 'timer'} DismissReason */ + +/** @type {Record} */ +const DismissReason = Object.freeze({ + cancel: 'cancel', + backdrop: 'backdrop', + close: 'close', + esc: 'esc', + timer: 'timer' +}); + +/** + * @param {GlobalState} globalState + */ +const removeKeydownHandler = globalState => { + if (globalState.keydownTarget && globalState.keydownHandlerAdded) { + globalState.keydownTarget.removeEventListener('keydown', globalState.keydownHandler, { + capture: globalState.keydownListenerCapture + }); + globalState.keydownHandlerAdded = false; + } +}; + +/** + * @param {GlobalState} globalState + * @param {SweetAlertOptions} innerParams + * @param {*} dismissWith + */ +const addKeydownHandler = (globalState, innerParams, dismissWith) => { + removeKeydownHandler(globalState); + if (!innerParams.toast) { + globalState.keydownHandler = e => keydownHandler(innerParams, e, dismissWith); + globalState.keydownTarget = innerParams.keydownListenerCapture ? window : getPopup(); + globalState.keydownListenerCapture = innerParams.keydownListenerCapture; + globalState.keydownTarget.addEventListener('keydown', globalState.keydownHandler, { + capture: globalState.keydownListenerCapture + }); + globalState.keydownHandlerAdded = true; + } +}; + +/** + * @param {number} index + * @param {number} increment + */ +const setFocus = (index, increment) => { + var _dom$getPopup; + const focusableElements = getFocusableElements(); + // search for visible elements and select the next possible match + if (focusableElements.length) { + index = index + increment; + + // shift + tab when .swal2-popup is focused + if (index === -2) { + index = focusableElements.length - 1; + } + + // rollover to first item + if (index === focusableElements.length) { + index = 0; + + // go to last item + } else if (index === -1) { + index = focusableElements.length - 1; + } + focusableElements[index].focus(); + return; + } + // no visible focusable elements, focus the popup + (_dom$getPopup = getPopup()) === null || _dom$getPopup === void 0 || _dom$getPopup.focus(); +}; +const arrowKeysNextButton = ['ArrowRight', 'ArrowDown']; +const arrowKeysPreviousButton = ['ArrowLeft', 'ArrowUp']; + +/** + * @param {SweetAlertOptions} innerParams + * @param {KeyboardEvent} event + * @param {Function} dismissWith + */ +const keydownHandler = (innerParams, event, dismissWith) => { + if (!innerParams) { + return; // This instance has already been destroyed + } + + // Ignore keydown during IME composition + // https://developer.mozilla.org/en-US/docs/Web/API/Document/keydown_event#ignoring_keydown_during_ime_composition + // https://github.com/sweetalert2/sweetalert2/issues/720 + // https://github.com/sweetalert2/sweetalert2/issues/2406 + if (event.isComposing || event.keyCode === 229) { + return; + } + if (innerParams.stopKeydownPropagation) { + event.stopPropagation(); + } + + // ENTER + if (event.key === 'Enter') { + handleEnter(event, innerParams); + } + + // TAB + else if (event.key === 'Tab') { + handleTab(event); + } + + // ARROWS - switch focus between buttons + else if ([...arrowKeysNextButton, ...arrowKeysPreviousButton].includes(event.key)) { + handleArrows(event.key); + } + + // ESC + else if (event.key === 'Escape') { + handleEsc(event, innerParams, dismissWith); + } +}; + +/** + * @param {KeyboardEvent} event + * @param {SweetAlertOptions} innerParams + */ +const handleEnter = (event, innerParams) => { + // https://github.com/sweetalert2/sweetalert2/issues/2386 + if (!callIfFunction(innerParams.allowEnterKey)) { + return; + } + const input = getInput$1(getPopup(), innerParams.input); + if (event.target && input && event.target instanceof HTMLElement && event.target.outerHTML === input.outerHTML) { + if (['textarea', 'file'].includes(innerParams.input)) { + return; // do not submit + } + clickConfirm(); + event.preventDefault(); + } +}; + +/** + * @param {KeyboardEvent} event + */ +const handleTab = event => { + const targetElement = event.target; + const focusableElements = getFocusableElements(); + let btnIndex = -1; + for (let i = 0; i < focusableElements.length; i++) { + if (targetElement === focusableElements[i]) { + btnIndex = i; + break; + } + } + + // Cycle to the next button + if (!event.shiftKey) { + setFocus(btnIndex, 1); + } + + // Cycle to the prev button + else { + setFocus(btnIndex, -1); + } + event.stopPropagation(); + event.preventDefault(); +}; + +/** + * @param {string} key + */ +const handleArrows = key => { + const actions = getActions(); + const confirmButton = getConfirmButton(); + const denyButton = getDenyButton(); + const cancelButton = getCancelButton(); + if (!actions || !confirmButton || !denyButton || !cancelButton) { + return; + } + /** @type HTMLElement[] */ + const buttons = [confirmButton, denyButton, cancelButton]; + if (document.activeElement instanceof HTMLElement && !buttons.includes(document.activeElement)) { + return; + } + const sibling = arrowKeysNextButton.includes(key) ? 'nextElementSibling' : 'previousElementSibling'; + let buttonToFocus = document.activeElement; + if (!buttonToFocus) { + return; + } + for (let i = 0; i < actions.children.length; i++) { + buttonToFocus = buttonToFocus[sibling]; + if (!buttonToFocus) { + return; + } + if (buttonToFocus instanceof HTMLButtonElement && isVisible$1(buttonToFocus)) { + break; + } + } + if (buttonToFocus instanceof HTMLButtonElement) { + buttonToFocus.focus(); + } +}; + +/** + * @param {KeyboardEvent} event + * @param {SweetAlertOptions} innerParams + * @param {Function} dismissWith + */ +const handleEsc = (event, innerParams, dismissWith) => { + event.preventDefault(); + if (callIfFunction(innerParams.allowEscapeKey)) { + dismissWith(DismissReason.esc); + } +}; + +/** + * This module contains `WeakMap`s for each effectively-"private property" that a `Swal` has. + * For example, to set the private property "foo" of `this` to "bar", you can `privateProps.foo.set(this, 'bar')` + * This is the approach that Babel will probably take to implement private methods/fields + * https://github.com/tc39/proposal-private-methods + * https://github.com/babel/babel/pull/7555 + * Once we have the changes from that PR in Babel, and our core class fits reasonable in *one module* + * then we can use that language feature. + */ + +var privateMethods = { + swalPromiseResolve: new WeakMap(), + swalPromiseReject: new WeakMap() +}; + +// From https://developer.paciellogroup.com/blog/2018/06/the-current-state-of-modal-dialog-accessibility/ +// Adding aria-hidden="true" to elements outside of the active modal dialog ensures that +// elements not within the active modal dialog will not be surfaced if a user opens a screen +// reader’s list of elements (headings, form controls, landmarks, etc.) in the document. + +const setAriaHidden = () => { + const container = getContainer(); + const bodyChildren = Array.from(document.body.children); + bodyChildren.forEach(el => { + if (el.contains(container)) { + return; + } + if (el.hasAttribute('aria-hidden')) { + el.setAttribute('data-previous-aria-hidden', el.getAttribute('aria-hidden') || ''); + } + el.setAttribute('aria-hidden', 'true'); + }); +}; +const unsetAriaHidden = () => { + const bodyChildren = Array.from(document.body.children); + bodyChildren.forEach(el => { + if (el.hasAttribute('data-previous-aria-hidden')) { + el.setAttribute('aria-hidden', el.getAttribute('data-previous-aria-hidden') || ''); + el.removeAttribute('data-previous-aria-hidden'); + } else { + el.removeAttribute('aria-hidden'); + } + }); +}; + +// @ts-ignore +const isSafariOrIOS = typeof window !== 'undefined' && !!window.GestureEvent; // true for Safari desktop + all iOS browsers https://stackoverflow.com/a/70585394 + +/** + * Fix iOS scrolling + * http://stackoverflow.com/q/39626302 + */ +const iOSfix = () => { + if (isSafariOrIOS && !hasClass(document.body, swalClasses.iosfix)) { + const offset = document.body.scrollTop; + document.body.style.top = `${offset * -1}px`; + addClass(document.body, swalClasses.iosfix); + lockBodyScroll(); + } +}; + +/** + * https://github.com/sweetalert2/sweetalert2/issues/1246 + */ +const lockBodyScroll = () => { + const container = getContainer(); + if (!container) { + return; + } + /** @type {boolean} */ + let preventTouchMove; + /** + * @param {TouchEvent} event + */ + container.ontouchstart = event => { + preventTouchMove = shouldPreventTouchMove(event); + }; + /** + * @param {TouchEvent} event + */ + container.ontouchmove = event => { + if (preventTouchMove) { + event.preventDefault(); + event.stopPropagation(); + } + }; +}; + +/** + * @param {TouchEvent} event + * @returns {boolean} + */ +const shouldPreventTouchMove = event => { + const target = event.target; + const container = getContainer(); + const htmlContainer = getHtmlContainer(); + if (!container || !htmlContainer) { + return false; + } + if (isStylus(event) || isZoom(event)) { + return false; + } + if (target === container) { + return true; + } + if (!isScrollable(container) && target instanceof HTMLElement && !selfOrParentIsScrollable(target, htmlContainer) && + // #2823 + target.tagName !== 'INPUT' && + // #1603 + target.tagName !== 'TEXTAREA' && + // #2266 + !(isScrollable(htmlContainer) && + // #1944 + htmlContainer.contains(target))) { + return true; + } + return false; +}; + +/** + * https://github.com/sweetalert2/sweetalert2/issues/1786 + * + * @param {*} event + * @returns {boolean} + */ +const isStylus = event => { + return event.touches && event.touches.length && event.touches[0].touchType === 'stylus'; +}; + +/** + * https://github.com/sweetalert2/sweetalert2/issues/1891 + * + * @param {TouchEvent} event + * @returns {boolean} + */ +const isZoom = event => { + return event.touches && event.touches.length > 1; +}; +const undoIOSfix = () => { + if (hasClass(document.body, swalClasses.iosfix)) { + const offset = parseInt(document.body.style.top, 10); + removeClass(document.body, swalClasses.iosfix); + document.body.style.top = ''; + document.body.scrollTop = offset * -1; + } +}; + +/** + * Measure scrollbar width for padding body during modal show/hide + * https://github.com/twbs/bootstrap/blob/master/js/src/modal.js + * + * @returns {number} + */ +const measureScrollbar = () => { + const scrollDiv = document.createElement('div'); + scrollDiv.className = swalClasses['scrollbar-measure']; + document.body.appendChild(scrollDiv); + const scrollbarWidth = scrollDiv.getBoundingClientRect().width - scrollDiv.clientWidth; + document.body.removeChild(scrollDiv); + return scrollbarWidth; +}; + +/** + * Remember state in cases where opening and handling a modal will fiddle with it. + * @type {number | null} + */ +let previousBodyPadding = null; + +/** + * @param {string} initialBodyOverflow + */ +const replaceScrollbarWithPadding = initialBodyOverflow => { + // for queues, do not do this more than once + if (previousBodyPadding !== null) { + return; + } + // if the body has overflow + if (document.body.scrollHeight > window.innerHeight || initialBodyOverflow === 'scroll' // https://github.com/sweetalert2/sweetalert2/issues/2663 + ) { + // add padding so the content doesn't shift after removal of scrollbar + previousBodyPadding = parseInt(window.getComputedStyle(document.body).getPropertyValue('padding-right')); + document.body.style.paddingRight = `${previousBodyPadding + measureScrollbar()}px`; + } +}; +const undoReplaceScrollbarWithPadding = () => { + if (previousBodyPadding !== null) { + document.body.style.paddingRight = `${previousBodyPadding}px`; + previousBodyPadding = null; + } +}; + +/** + * @param {SweetAlert} instance + * @param {HTMLElement} container + * @param {boolean} returnFocus + * @param {Function} didClose + */ +function removePopupAndResetState(instance, container, returnFocus, didClose) { + if (isToast()) { + triggerDidCloseAndDispose(instance, didClose); + } else { + restoreActiveElement(returnFocus).then(() => triggerDidCloseAndDispose(instance, didClose)); + removeKeydownHandler(globalState); + } + + // workaround for https://github.com/sweetalert2/sweetalert2/issues/2088 + // for some reason removing the container in Safari will scroll the document to bottom + if (isSafariOrIOS) { + container.setAttribute('style', 'display:none !important'); + container.removeAttribute('class'); + container.innerHTML = ''; + } else { + container.remove(); + } + if (isModal()) { + undoReplaceScrollbarWithPadding(); + undoIOSfix(); + unsetAriaHidden(); + } + removeBodyClasses(); +} + +/** + * Remove SweetAlert2 classes from body + */ +function removeBodyClasses() { + removeClass([document.documentElement, document.body], [swalClasses.shown, swalClasses['height-auto'], swalClasses['no-backdrop'], swalClasses['toast-shown']]); +} + +/** + * Instance method to close sweetAlert + * + * @param {any} resolveValue + */ +function close(resolveValue) { + resolveValue = prepareResolveValue(resolveValue); + const swalPromiseResolve = privateMethods.swalPromiseResolve.get(this); + const didClose = triggerClosePopup(this); + if (this.isAwaitingPromise) { + // A swal awaiting for a promise (after a click on Confirm or Deny) cannot be dismissed anymore #2335 + if (!resolveValue.isDismissed) { + handleAwaitingPromise(this); + swalPromiseResolve(resolveValue); + } + } else if (didClose) { + // Resolve Swal promise + swalPromiseResolve(resolveValue); + } +} +const triggerClosePopup = instance => { + const popup = getPopup(); + if (!popup) { + return false; + } + const innerParams = privateProps.innerParams.get(instance); + if (!innerParams || hasClass(popup, innerParams.hideClass.popup)) { + return false; + } + removeClass(popup, innerParams.showClass.popup); + addClass(popup, innerParams.hideClass.popup); + const backdrop = getContainer(); + removeClass(backdrop, innerParams.showClass.backdrop); + addClass(backdrop, innerParams.hideClass.backdrop); + handlePopupAnimation(instance, popup, innerParams); + return true; +}; + +/** + * @param {any} error + */ +function rejectPromise(error) { + const rejectPromise = privateMethods.swalPromiseReject.get(this); + handleAwaitingPromise(this); + if (rejectPromise) { + // Reject Swal promise + rejectPromise(error); + } +} + +/** + * @param {SweetAlert} instance + */ +const handleAwaitingPromise = instance => { + if (instance.isAwaitingPromise) { + delete instance.isAwaitingPromise; + // The instance might have been previously partly destroyed, we must resume the destroy process in this case #2335 + if (!privateProps.innerParams.get(instance)) { + instance._destroy(); + } + } +}; + +/** + * @param {any} resolveValue + * @returns {SweetAlertResult} + */ +const prepareResolveValue = resolveValue => { + // When user calls Swal.close() + if (typeof resolveValue === 'undefined') { + return { + isConfirmed: false, + isDenied: false, + isDismissed: true + }; + } + return Object.assign({ + isConfirmed: false, + isDenied: false, + isDismissed: false + }, resolveValue); +}; + +/** + * @param {SweetAlert} instance + * @param {HTMLElement} popup + * @param {SweetAlertOptions} innerParams + */ +const handlePopupAnimation = (instance, popup, innerParams) => { + var _globalState$eventEmi; + const container = getContainer(); + // If animation is supported, animate + const animationIsSupported = hasCssAnimation(popup); + if (typeof innerParams.willClose === 'function') { + innerParams.willClose(popup); + } + (_globalState$eventEmi = globalState.eventEmitter) === null || _globalState$eventEmi === void 0 || _globalState$eventEmi.emit('willClose', popup); + if (animationIsSupported) { + animatePopup(instance, popup, container, innerParams.returnFocus, innerParams.didClose); + } else { + // Otherwise, remove immediately + removePopupAndResetState(instance, container, innerParams.returnFocus, innerParams.didClose); + } +}; + +/** + * @param {SweetAlert} instance + * @param {HTMLElement} popup + * @param {HTMLElement} container + * @param {boolean} returnFocus + * @param {Function} didClose + */ +const animatePopup = (instance, popup, container, returnFocus, didClose) => { + globalState.swalCloseEventFinishedCallback = removePopupAndResetState.bind(null, instance, container, returnFocus, didClose); + /** + * @param {AnimationEvent | TransitionEvent} e + */ + const swalCloseAnimationFinished = function (e) { + if (e.target === popup) { + var _globalState$swalClos; + (_globalState$swalClos = globalState.swalCloseEventFinishedCallback) === null || _globalState$swalClos === void 0 || _globalState$swalClos.call(globalState); + delete globalState.swalCloseEventFinishedCallback; + popup.removeEventListener('animationend', swalCloseAnimationFinished); + popup.removeEventListener('transitionend', swalCloseAnimationFinished); + } + }; + popup.addEventListener('animationend', swalCloseAnimationFinished); + popup.addEventListener('transitionend', swalCloseAnimationFinished); +}; + +/** + * @param {SweetAlert} instance + * @param {Function} didClose + */ +const triggerDidCloseAndDispose = (instance, didClose) => { + setTimeout(() => { + var _globalState$eventEmi2; + if (typeof didClose === 'function') { + didClose.bind(instance.params)(); + } + (_globalState$eventEmi2 = globalState.eventEmitter) === null || _globalState$eventEmi2 === void 0 || _globalState$eventEmi2.emit('didClose'); + // instance might have been destroyed already + if (instance._destroy) { + instance._destroy(); + } + }); +}; + +/** + * Shows loader (spinner), this is useful with AJAX requests. + * By default the loader be shown instead of the "Confirm" button. + * + * @param {HTMLButtonElement | null} [buttonToReplace] + */ +const showLoading = buttonToReplace => { + let popup = getPopup(); + if (!popup) { + new Swal(); + } + popup = getPopup(); + if (!popup) { + return; + } + const loader = getLoader(); + if (isToast()) { + hide$2(getIcon()); + } else { + replaceButton(popup, buttonToReplace); + } + show(loader); + popup.setAttribute('data-loading', 'true'); + popup.setAttribute('aria-busy', 'true'); + popup.focus(); +}; + +/** + * @param {HTMLElement} popup + * @param {HTMLButtonElement | null} [buttonToReplace] + */ +const replaceButton = (popup, buttonToReplace) => { + const actions = getActions(); + const loader = getLoader(); + if (!actions || !loader) { + return; + } + if (!buttonToReplace && isVisible$1(getConfirmButton())) { + buttonToReplace = getConfirmButton(); + } + show(actions); + if (buttonToReplace) { + hide$2(buttonToReplace); + loader.setAttribute('data-button-to-replace', buttonToReplace.className); + actions.insertBefore(loader, buttonToReplace); + } + addClass([popup, actions], swalClasses.loading); +}; + +/** + * @param {SweetAlert} instance + * @param {SweetAlertOptions} params + */ +const handleInputOptionsAndValue = (instance, params) => { + if (params.input === 'select' || params.input === 'radio') { + handleInputOptions(instance, params); + } else if (['text', 'email', 'number', 'tel', 'textarea'].some(i => i === params.input) && (hasToPromiseFn(params.inputValue) || isPromise(params.inputValue))) { + showLoading(getConfirmButton()); + handleInputValue(instance, params); + } +}; + +/** + * @param {SweetAlert} instance + * @param {SweetAlertOptions} innerParams + * @returns {SweetAlertInputValue} + */ +const getInputValue = (instance, innerParams) => { + const input = instance.getInput(); + if (!input) { + return null; + } + switch (innerParams.input) { + case 'checkbox': + return getCheckboxValue(input); + case 'radio': + return getRadioValue(input); + case 'file': + return getFileValue(input); + default: + return innerParams.inputAutoTrim ? input.value.trim() : input.value; + } +}; + +/** + * @param {HTMLInputElement} input + * @returns {number} + */ +const getCheckboxValue = input => input.checked ? 1 : 0; + +/** + * @param {HTMLInputElement} input + * @returns {string | null} + */ +const getRadioValue = input => input.checked ? input.value : null; + +/** + * @param {HTMLInputElement} input + * @returns {FileList | File | null} + */ +const getFileValue = input => input.files && input.files.length ? input.getAttribute('multiple') !== null ? input.files : input.files[0] : null; + +/** + * @param {SweetAlert} instance + * @param {SweetAlertOptions} params + */ +const handleInputOptions = (instance, params) => { + const popup = getPopup(); + if (!popup) { + return; + } + /** + * @param {Record} inputOptions + */ + const processInputOptions = inputOptions => { + if (params.input === 'select') { + populateSelectOptions(popup, formatInputOptions(inputOptions), params); + } else if (params.input === 'radio') { + populateRadioOptions(popup, formatInputOptions(inputOptions), params); + } + }; + if (hasToPromiseFn(params.inputOptions) || isPromise(params.inputOptions)) { + showLoading(getConfirmButton()); + asPromise(params.inputOptions).then(inputOptions => { + instance.hideLoading(); + processInputOptions(inputOptions); + }); + } else if (typeof params.inputOptions === 'object') { + processInputOptions(params.inputOptions); + } else { + error(`Unexpected type of inputOptions! Expected object, Map or Promise, got ${typeof params.inputOptions}`); + } +}; + +/** + * @param {SweetAlert} instance + * @param {SweetAlertOptions} params + */ +const handleInputValue = (instance, params) => { + const input = instance.getInput(); + if (!input) { + return; + } + hide$2(input); + asPromise(params.inputValue).then(inputValue => { + input.value = params.input === 'number' ? `${parseFloat(inputValue) || 0}` : `${inputValue}`; + show(input); + input.focus(); + instance.hideLoading(); + }).catch(err => { + error(`Error in inputValue promise: ${err}`); + input.value = ''; + show(input); + input.focus(); + instance.hideLoading(); + }); +}; + +/** + * @param {HTMLElement} popup + * @param {InputOptionFlattened[]} inputOptions + * @param {SweetAlertOptions} params + */ +function populateSelectOptions(popup, inputOptions, params) { + const select = getDirectChildByClass(popup, swalClasses.select); + if (!select) { + return; + } + /** + * @param {HTMLElement} parent + * @param {string} optionLabel + * @param {string} optionValue + */ + const renderOption = (parent, optionLabel, optionValue) => { + const option = document.createElement('option'); + option.value = optionValue; + setInnerHtml(option, optionLabel); + option.selected = isSelected(optionValue, params.inputValue); + parent.appendChild(option); + }; + inputOptions.forEach(inputOption => { + const optionValue = inputOption[0]; + const optionLabel = inputOption[1]; + // spec: + // https://www.w3.org/TR/html401/interact/forms.html#h-17.6 + // "...all OPTGROUP elements must be specified directly within a SELECT element (i.e., groups may not be nested)..." + // check whether this is a + if (Array.isArray(optionLabel)) { + // if it is an array, then it is an + const optgroup = document.createElement('optgroup'); + optgroup.label = optionValue; + optgroup.disabled = false; // not configurable for now + select.appendChild(optgroup); + optionLabel.forEach(o => renderOption(optgroup, o[1], o[0])); + } else { + // case of