@vuetify/v0 0.1.7 → 0.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/SKILL.md +95 -0
- package/dist/adapter-CWp5eQ6R.d.mts +17 -0
- package/dist/{adapter-DIx4Rntl.d.mts → adapter-hDuQ9aNN.d.mts} +4 -4
- package/dist/browser/index.js +3168 -929
- package/dist/components/index.d.mts +2 -2
- package/dist/components/index.mjs +23 -23
- package/dist/{components-CACff-Lt.mjs → components-mSy9az8x.mjs} +1358 -242
- package/dist/composables/index.d.mts +16 -15
- package/dist/composables/index.mjs +22 -22
- package/dist/{consola-BVzYzeLH.d.mts → consola-C1OjyZVf.d.mts} +1 -1
- package/dist/constants/index.d.mts +1 -1
- package/dist/constants/index.mjs +1 -1
- package/dist/{createDataTable-CLI4TALE.mjs → createDataTable-DIl09siC.mjs} +5 -5
- package/dist/{createGroup-Cf6lK9BR.mjs → createGroup-PvzsLu9E.mjs} +1 -1
- package/dist/{createPagination-Bu8vE0JW.mjs → createPagination-DZSJ8aO5.mjs} +5 -5
- package/dist/{createSelection-DvOR2tKk.mjs → createSelection-DbWP6c7H.mjs} +1 -1
- package/dist/{createSingle-Bbcwcq4R.mjs → createSingle-CeAJpbXs.mjs} +6 -6
- package/dist/{createTokens-CMRBDlzN.mjs → createTokens-C1gIuKCK.mjs} +27 -5
- package/dist/data-table/adapters/client/index.d.mts +1 -1
- package/dist/data-table/adapters/client/index.mjs +3 -3
- package/dist/data-table/adapters/index.d.mts +4 -4
- package/dist/data-table/adapters/index.mjs +5 -5
- package/dist/data-table/adapters/server/index.d.mts +1 -1
- package/dist/data-table/adapters/server/index.mjs +3 -3
- package/dist/data-table/adapters/virtual/index.d.mts +1 -1
- package/dist/data-table/adapters/virtual/index.mjs +3 -3
- package/dist/data-table/index.d.mts +5 -5
- package/dist/data-table/index.mjs +14 -14
- package/dist/date/index.mjs +1 -1
- package/dist/features/adapters/posthog/index.mjs +2 -2
- package/dist/features/index.d.mts +1 -1
- package/dist/features/index.mjs +8 -8
- package/dist/{globals-BqRH_jdr.mjs → globals-3i9umzyz.mjs} +1 -1
- package/dist/{index-8sflFIN8.d.mts → index-BoK8Ln2f.d.mts} +3 -1
- package/dist/{index-CKbxWC4t.d.mts → index-C5XZRWlO.d.mts} +2691 -1303
- package/dist/{index-CmCMrlt3.d.mts → index-CLDBngUs.d.mts} +1 -1
- package/dist/{index-BE848tZ2.d.mts → index-D0qnkRbl.d.mts} +505 -197
- package/dist/index.d.mts +19 -18
- package/dist/index.mjs +23 -23
- package/dist/json/attributes.json +312 -0
- package/dist/json/importMap.json +84 -0
- package/dist/json/tags.json +168 -0
- package/dist/json/web-types.json +1147 -132
- package/dist/locale/adapters/index.d.mts +3 -2
- package/dist/locale/adapters/index.mjs +2 -2
- package/dist/locale/adapters/v0/index.d.mts +1 -1
- package/dist/locale/adapters/v0/index.mjs +2 -2
- package/dist/locale/adapters/vue-i18n/index.d.mts +22 -0
- package/dist/locale/adapters/vue-i18n/index.mjs +26 -0
- package/dist/locale/index.d.mts +4 -3
- package/dist/locale/index.mjs +8 -9
- package/dist/logger/adapters/consola/index.d.mts +1 -1
- package/dist/logger/adapters/index.d.mts +4 -4
- package/dist/logger/adapters/index.mjs +2 -2
- package/dist/logger/adapters/pino/index.d.mts +1 -1
- package/dist/logger/adapters/pino/index.mjs +1 -1
- package/dist/logger/adapters/v0/index.d.mts +1 -1
- package/dist/logger/adapters/v0/index.mjs +2 -2
- package/dist/logger/index.d.mts +5 -5
- package/dist/logger/index.mjs +3 -3
- package/dist/notifications/index.d.mts +78 -0
- package/dist/notifications/index.mjs +215 -0
- package/dist/palettes/ant/index.d.mts +1 -1
- package/dist/palettes/index.d.mts +2 -2
- package/dist/palettes/material/index.d.mts +1 -1
- package/dist/palettes/md1/index.d.mts +1 -1
- package/dist/palettes/md2/index.d.mts +1 -1
- package/dist/palettes/radix/index.d.mts +1 -1
- package/dist/palettes/tailwind/index.d.mts +1 -1
- package/dist/permissions/adapters/index.d.mts +2 -2
- package/dist/permissions/adapters/index.mjs +1 -1
- package/dist/permissions/adapters/v0/index.d.mts +1 -1
- package/dist/permissions/adapters/v0/index.mjs +1 -1
- package/dist/permissions/index.d.mts +1 -1
- package/dist/permissions/index.mjs +5 -5
- package/dist/{pino-Bzighnkd.d.mts → pino-CM1iLXmi.d.mts} +1 -1
- package/dist/{posthog-DbPqmaAp.mjs → posthog-CCQFQ5XD.mjs} +1 -1
- package/dist/rules/index.d.mts +1 -1
- package/dist/rules/index.mjs +9 -10
- package/dist/{server-Ch9J86tb.d.mts → server-Ct-h4-OA.d.mts} +1 -1
- package/dist/{server-CZ6ahbEH.mjs → server-DHET3KNW.mjs} +1 -1
- package/dist/storage/adapters/index.d.mts +2 -2
- package/dist/storage/adapters/memory/index.d.mts +1 -1
- package/dist/storage/index.d.mts +3 -3
- package/dist/storage/index.mjs +21 -21
- package/dist/theme/adapters/index.d.mts +1 -1
- package/dist/theme/adapters/index.mjs +2 -2
- package/dist/theme/adapters/v0/index.d.mts +1 -1
- package/dist/theme/adapters/v0/index.mjs +2 -2
- package/dist/theme/index.d.mts +1 -1
- package/dist/theme/index.mjs +8 -8
- package/dist/{useClickOutside-YOGwKo7v.mjs → useClickOutside-hOhNk4eS.mjs} +1251 -165
- package/dist/{useFeatures-BGDgUrdr.mjs → useFeatures-CXRQvucQ.mjs} +3 -3
- package/dist/{useLocale-C8I_fNAS.mjs → useLocale-BaufqE5Z.mjs} +16 -30
- package/dist/{useLogger-B70T4SgK.mjs → useLogger-cGK00Ywd.mjs} +2 -2
- package/dist/{usePermissions-afVt2qR7.mjs → usePermissions-CR0HkjsF.mjs} +2 -2
- package/dist/{useRules-7C92Xzyt.mjs → useRules-LD-_-Hxt.mjs} +3 -3
- package/dist/{useTheme-jp2wL2FJ.mjs → useTheme-Cs79AFNR.mjs} +5 -5
- package/dist/utilities/index.d.mts +1 -1
- package/dist/utilities/index.mjs +2 -1
- package/dist/{v0-V-cQsuZD.mjs → v0-BJYwZgtp.mjs} +1 -1
- package/dist/v0-BdD1F6JK.d.mts +19 -0
- package/dist/{v0-YAqbXudL.mjs → v0-BoWQ8RK0.mjs} +1 -1
- package/dist/{v0-CdUL2eOn.d.mts → v0-CMeh39LQ.d.mts} +1 -1
- package/dist/v0-CehUknHv.mjs +62 -0
- package/dist/{v0-1bfmyZ5_.d.mts → v0-DFAgNbvC.d.mts} +1 -1
- package/dist/{v0-1xxC39wf.d.mts → v0-JPf99NKg.d.mts} +1 -1
- package/dist/{v0-CGlkn5u7.mjs → v0-Zu7neOYg.mjs} +1 -1
- package/dist/{virtual-DwBiFA25.d.mts → virtual-B1lRbO7Q.d.mts} +1 -1
- package/dist/{virtual-eDNVH1fz.mjs → virtual-D0_D5gkh.mjs} +1 -1
- package/package.json +12 -4
- package/dist/v0-CAKa6tzG.d.mts +0 -22
- package/dist/v0-CHvU3jQE.mjs +0 -35
- /package/dist/{adapter-JTFG3Jn8.d.mts → adapter-CJQav2JB.d.mts} +0 -0
- /package/dist/{index-MHkcqY_y.d.mts → index-BL4uTXWQ.d.mts} +0 -0
- /package/dist/{index-B5ZDDkXv.d.mts → index-BvTD7kU8.d.mts} +0 -0
- /package/dist/{index-NsE5nARK.d.mts → index-DSao7i57.d.mts} +0 -0
- /package/dist/{memory-BTtRdnNn.d.mts → memory-DyBabFV1.d.mts} +0 -0
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import { a as SUPPORTS_OBSERVER, i as SUPPORTS_MUTATION_OBSERVER, n as SUPPORTS_INTERSECTION_OBSERVER, r as SUPPORTS_MATCH_MEDIA, t as IN_BROWSER } from "./globals-
|
|
1
|
+
import { a as SUPPORTS_OBSERVER, i as SUPPORTS_MUTATION_OBSERVER, n as SUPPORTS_INTERSECTION_OBSERVER, r as SUPPORTS_MATCH_MEDIA, t as IN_BROWSER } from "./globals-3i9umzyz.mjs";
|
|
2
2
|
import { clamp, instanceExists, isElement, isFunction, isNull, isNullOrUndefined, isNumber, isObject, isString, isUndefined, mergeDeep, useId as useId$1 } from "./utilities/index.mjs";
|
|
3
3
|
import { i as useContext, n as createContext, t as createTrinity } from "./createTrinity-C_c8eedz.mjs";
|
|
4
|
-
import { a as createPlugin, i as useLogger, o as createPluginContext } from "./useLogger-
|
|
5
|
-
import { i as createRegistry } from "./createTokens-
|
|
6
|
-
import { i as createModel, t as createSelection } from "./createSelection-
|
|
7
|
-
import { t as createSingle } from "./createSingle-
|
|
8
|
-
import { t as createGroup } from "./createGroup-
|
|
4
|
+
import { a as createPlugin, i as useLogger, o as createPluginContext } from "./useLogger-cGK00Ywd.mjs";
|
|
5
|
+
import { i as createRegistry } from "./createTokens-C1gIuKCK.mjs";
|
|
6
|
+
import { i as createModel, t as createSelection } from "./createSelection-DbWP6c7H.mjs";
|
|
7
|
+
import { t as createSingle } from "./createSingle-CeAJpbXs.mjs";
|
|
8
|
+
import { t as createGroup } from "./createGroup-PvzsLu9E.mjs";
|
|
9
9
|
import { t as toArray } from "./toArray-VdROPpy-.mjs";
|
|
10
|
-
import { a as useLocale } from "./useLocale-
|
|
11
|
-
import { a as useRules, o as isStandardSchema
|
|
10
|
+
import { a as useLocale } from "./useLocale-BaufqE5Z.mjs";
|
|
11
|
+
import { a as useRules, o as isStandardSchema } from "./useRules-LD-_-Hxt.mjs";
|
|
12
12
|
import { t as MemoryAdapter } from "./memory-XCMtkld1.mjs";
|
|
13
|
-
import { computed, effectScope, isRef, nextTick, onScopeDispose, reactive, readonly, ref, shallowReactive, shallowReadonly, shallowRef, toRef, toValue, unref, watch, watchEffect } from "vue";
|
|
13
|
+
import { computed, effectScope, isRef, nextTick, onMounted, onScopeDispose, reactive, readonly, ref, shallowReactive, shallowReadonly, shallowRef, toRef, toValue, unref, watch, watchEffect } from "vue";
|
|
14
14
|
//#region src/composables/createBreadcrumbs/index.ts
|
|
15
15
|
/**
|
|
16
16
|
* @module createBreadcrumbs
|
|
@@ -747,7 +747,8 @@ function useProxyModel(context, model, options) {
|
|
|
747
747
|
const modelAsArray = transformIn(model);
|
|
748
748
|
const pending = new Set(modelAsArray);
|
|
749
749
|
context.apply(modelAsArray, applyOptions);
|
|
750
|
-
|
|
750
|
+
const selected = new Set(context.selectedValues.value);
|
|
751
|
+
for (const value of modelAsArray) if (selected.has(value)) pending.delete(value);
|
|
751
752
|
const contextWatch = watch(context.selectedValues, (val) => {
|
|
752
753
|
modelWatch.pause();
|
|
753
754
|
model.value = transformOut(Array.from(toValue(val)));
|
|
@@ -1010,24 +1011,22 @@ function createBreakpoints(_options = {}) {
|
|
|
1010
1011
|
const mdAndUp = shallowRef(initialIndex >= 2);
|
|
1011
1012
|
const lgAndUp = shallowRef(initialIndex >= 3);
|
|
1012
1013
|
const xlAndUp = shallowRef(initialIndex >= 4);
|
|
1013
|
-
const xxlAndUp = shallowRef(initialIndex >= 5);
|
|
1014
1014
|
const smAndDown = shallowRef(initialIndex <= 1);
|
|
1015
1015
|
const mdAndDown = shallowRef(initialIndex <= 2);
|
|
1016
1016
|
const lgAndDown = shallowRef(initialIndex <= 3);
|
|
1017
1017
|
const xlAndDown = shallowRef(initialIndex <= 4);
|
|
1018
|
-
const xxlAndDown = shallowRef(initialIndex <= 5);
|
|
1019
1018
|
function update() {
|
|
1020
1019
|
if (!IN_BROWSER) return;
|
|
1021
1020
|
width.value = window.innerWidth;
|
|
1022
1021
|
height.value = window.innerHeight;
|
|
1023
1022
|
let current = "xs";
|
|
1024
|
-
for (let i = sorted.length - 1; i >= 0; i--) if (width
|
|
1023
|
+
for (let i = sorted.length - 1; i >= 0; i--) if (window.matchMedia(`(min-width: ${sorted[i][1]}px)`).matches) {
|
|
1025
1024
|
current = sorted[i][0];
|
|
1026
1025
|
break;
|
|
1027
1026
|
}
|
|
1028
1027
|
name.value = current;
|
|
1029
1028
|
const index = names.indexOf(current);
|
|
1030
|
-
isMobile.value = width.
|
|
1029
|
+
isMobile.value = /* @__PURE__ */ isNumber(mb) ? !window.matchMedia(`(min-width: ${mb}px)`).matches : index < names.indexOf(mobileBreakpoint);
|
|
1031
1030
|
xs.value = index === 0;
|
|
1032
1031
|
sm.value = index === 1;
|
|
1033
1032
|
md.value = index === 2;
|
|
@@ -1038,15 +1037,14 @@ function createBreakpoints(_options = {}) {
|
|
|
1038
1037
|
mdAndUp.value = index >= 2;
|
|
1039
1038
|
lgAndUp.value = index >= 3;
|
|
1040
1039
|
xlAndUp.value = index >= 4;
|
|
1041
|
-
xxlAndUp.value = index >= 5;
|
|
1042
1040
|
smAndDown.value = index <= 1;
|
|
1043
1041
|
mdAndDown.value = index <= 2;
|
|
1044
1042
|
lgAndDown.value = index <= 3;
|
|
1045
1043
|
xlAndDown.value = index <= 4;
|
|
1046
|
-
xxlAndDown.value = index <= 5;
|
|
1047
1044
|
}
|
|
1048
1045
|
return {
|
|
1049
1046
|
breakpoints,
|
|
1047
|
+
mobileBreakpoint,
|
|
1050
1048
|
name: readonly(name),
|
|
1051
1049
|
width: readonly(width),
|
|
1052
1050
|
height: readonly(height),
|
|
@@ -1061,25 +1059,25 @@ function createBreakpoints(_options = {}) {
|
|
|
1061
1059
|
mdAndUp: readonly(mdAndUp),
|
|
1062
1060
|
lgAndUp: readonly(lgAndUp),
|
|
1063
1061
|
xlAndUp: readonly(xlAndUp),
|
|
1064
|
-
xxlAndUp: readonly(xxlAndUp),
|
|
1065
1062
|
smAndDown: readonly(smAndDown),
|
|
1066
1063
|
mdAndDown: readonly(mdAndDown),
|
|
1067
1064
|
lgAndDown: readonly(lgAndDown),
|
|
1068
1065
|
xlAndDown: readonly(xlAndDown),
|
|
1069
|
-
xxlAndDown: readonly(xxlAndDown),
|
|
1070
1066
|
ssr: isSSR,
|
|
1071
1067
|
update
|
|
1072
1068
|
};
|
|
1073
1069
|
}
|
|
1074
1070
|
function createBreakpointsFallback(options = {}) {
|
|
1075
1071
|
if (options.ssr) return createBreakpoints(options);
|
|
1072
|
+
const defaults = createDefaultBreakpoints();
|
|
1076
1073
|
return {
|
|
1077
|
-
breakpoints:
|
|
1074
|
+
breakpoints: defaults.breakpoints,
|
|
1075
|
+
mobileBreakpoint: defaults.mobileBreakpoint,
|
|
1078
1076
|
name: readonly(shallowRef("xs")),
|
|
1079
1077
|
width: readonly(shallowRef(0)),
|
|
1080
1078
|
height: readonly(shallowRef(0)),
|
|
1081
|
-
isMobile: readonly(shallowRef(
|
|
1082
|
-
xs: readonly(shallowRef(
|
|
1079
|
+
isMobile: readonly(shallowRef(true)),
|
|
1080
|
+
xs: readonly(shallowRef(true)),
|
|
1083
1081
|
sm: readonly(shallowRef(false)),
|
|
1084
1082
|
md: readonly(shallowRef(false)),
|
|
1085
1083
|
lg: readonly(shallowRef(false)),
|
|
@@ -1089,12 +1087,10 @@ function createBreakpointsFallback(options = {}) {
|
|
|
1089
1087
|
mdAndUp: readonly(shallowRef(false)),
|
|
1090
1088
|
lgAndUp: readonly(shallowRef(false)),
|
|
1091
1089
|
xlAndUp: readonly(shallowRef(false)),
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
xlAndDown: readonly(shallowRef(false)),
|
|
1097
|
-
xxlAndDown: readonly(shallowRef(false)),
|
|
1090
|
+
smAndDown: readonly(shallowRef(true)),
|
|
1091
|
+
mdAndDown: readonly(shallowRef(true)),
|
|
1092
|
+
lgAndDown: readonly(shallowRef(true)),
|
|
1093
|
+
xlAndDown: readonly(shallowRef(true)),
|
|
1098
1094
|
ssr: false,
|
|
1099
1095
|
update: () => {}
|
|
1100
1096
|
};
|
|
@@ -1362,14 +1358,14 @@ function useDate(namespace = "v0:date") {
|
|
|
1362
1358
|
* @example
|
|
1363
1359
|
* ```ts
|
|
1364
1360
|
* import { createForm, createValidation } from '@vuetify/v0'
|
|
1361
|
+
* import { shallowRef } from 'vue'
|
|
1365
1362
|
*
|
|
1366
1363
|
* const form = createForm()
|
|
1367
1364
|
*
|
|
1368
|
-
* //
|
|
1369
|
-
* const
|
|
1370
|
-
* const
|
|
1371
|
-
*
|
|
1372
|
-
* value: '',
|
|
1365
|
+
* // Each validation is one input — form is just the coordinator
|
|
1366
|
+
* const email = shallowRef('')
|
|
1367
|
+
* const validation = createValidation({
|
|
1368
|
+
* value: email,
|
|
1373
1369
|
* rules: ['required', 'email'],
|
|
1374
1370
|
* })
|
|
1375
1371
|
*
|
|
@@ -1379,12 +1375,12 @@ function useDate(namespace = "v0:date") {
|
|
|
1379
1375
|
* form.reset()
|
|
1380
1376
|
* ```
|
|
1381
1377
|
*/
|
|
1382
|
-
function createForm(options) {
|
|
1383
|
-
const
|
|
1384
|
-
const
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1378
|
+
function createForm(options = {}) {
|
|
1379
|
+
const { disabled = false, readonly = false, ..._options } = options;
|
|
1380
|
+
const registry = createRegistry({
|
|
1381
|
+
..._options,
|
|
1382
|
+
reactive: true
|
|
1383
|
+
});
|
|
1388
1384
|
const isValidating = computed(() => {
|
|
1389
1385
|
for (const ticket of registry.values()) if (ticket.value.isValidating.value) return true;
|
|
1390
1386
|
return false;
|
|
@@ -1404,14 +1400,14 @@ function createForm(options) {
|
|
|
1404
1400
|
return registry.register(registration);
|
|
1405
1401
|
}
|
|
1406
1402
|
function reset() {
|
|
1407
|
-
for (const ticket of registry.values())
|
|
1403
|
+
for (const ticket of registry.values()) ticket.value.reset();
|
|
1408
1404
|
}
|
|
1409
1405
|
async function submit(id) {
|
|
1410
1406
|
const ids = id ? toArray(id) : [...registry.keys()];
|
|
1411
|
-
return (await Promise.all(ids.map(async (
|
|
1412
|
-
const ticket = registry.get(
|
|
1407
|
+
return (await Promise.all(ids.map(async (key) => {
|
|
1408
|
+
const ticket = registry.get(key);
|
|
1413
1409
|
if (!ticket) return true;
|
|
1414
|
-
return
|
|
1410
|
+
return ticket.value.validate();
|
|
1415
1411
|
}))).every(Boolean);
|
|
1416
1412
|
}
|
|
1417
1413
|
return {
|
|
@@ -2012,6 +2008,132 @@ function useElementIntersection(target, options = {}) {
|
|
|
2012
2008
|
};
|
|
2013
2009
|
}
|
|
2014
2010
|
//#endregion
|
|
2011
|
+
//#region src/composables/useTimer/index.ts
|
|
2012
|
+
/**
|
|
2013
|
+
* @module useTimer
|
|
2014
|
+
*
|
|
2015
|
+
* @remarks
|
|
2016
|
+
* A reactive timer composable with pause/resume support.
|
|
2017
|
+
*
|
|
2018
|
+
* Key features:
|
|
2019
|
+
* - Start/stop/pause/resume controls
|
|
2020
|
+
* - Reactive remaining time tracking
|
|
2021
|
+
* - One-shot (default) or repeating mode
|
|
2022
|
+
* - Automatic cleanup on scope disposal
|
|
2023
|
+
* - SSR-safe
|
|
2024
|
+
*/
|
|
2025
|
+
/**
|
|
2026
|
+
* Creates a reactive timer with pause/resume support.
|
|
2027
|
+
*
|
|
2028
|
+
* @param handler Callback invoked when the timer fires.
|
|
2029
|
+
* @param options Timer configuration.
|
|
2030
|
+
* @returns Timer controls and reactive state.
|
|
2031
|
+
*
|
|
2032
|
+
* @see https://0.vuetifyjs.com/composables/system/use-timer
|
|
2033
|
+
*
|
|
2034
|
+
* @example
|
|
2035
|
+
* ```ts
|
|
2036
|
+
* const timer = useTimer(() => console.log('fired'), { duration: 5000 })
|
|
2037
|
+
*
|
|
2038
|
+
* timer.start()
|
|
2039
|
+
* timer.pause()
|
|
2040
|
+
* timer.resume()
|
|
2041
|
+
* timer.stop()
|
|
2042
|
+
* ```
|
|
2043
|
+
*/
|
|
2044
|
+
function useTimer(handler, options = {}) {
|
|
2045
|
+
const { duration = 1e3, repeat = false } = options;
|
|
2046
|
+
const remaining = shallowRef(duration);
|
|
2047
|
+
const isActive = shallowRef(false);
|
|
2048
|
+
const isPaused = shallowRef(false);
|
|
2049
|
+
let timeoutId;
|
|
2050
|
+
let trackingId;
|
|
2051
|
+
let startedAt = 0;
|
|
2052
|
+
let budget = duration;
|
|
2053
|
+
function clearTimer() {
|
|
2054
|
+
if (!/* @__PURE__ */ isUndefined(timeoutId)) {
|
|
2055
|
+
globalThis.clearTimeout(timeoutId);
|
|
2056
|
+
timeoutId = void 0;
|
|
2057
|
+
}
|
|
2058
|
+
}
|
|
2059
|
+
function startTracking() {
|
|
2060
|
+
stopTracking();
|
|
2061
|
+
if (!IN_BROWSER) return;
|
|
2062
|
+
trackingId = globalThis.setInterval(() => {
|
|
2063
|
+
if (!isActive.value || isPaused.value) return;
|
|
2064
|
+
const elapsed = Date.now() - startedAt;
|
|
2065
|
+
remaining.value = Math.max(0, budget - elapsed);
|
|
2066
|
+
}, 100);
|
|
2067
|
+
}
|
|
2068
|
+
function stopTracking() {
|
|
2069
|
+
if (!/* @__PURE__ */ isUndefined(trackingId)) {
|
|
2070
|
+
globalThis.clearInterval(trackingId);
|
|
2071
|
+
trackingId = void 0;
|
|
2072
|
+
}
|
|
2073
|
+
}
|
|
2074
|
+
function fire() {
|
|
2075
|
+
clearTimer();
|
|
2076
|
+
stopTracking();
|
|
2077
|
+
handler();
|
|
2078
|
+
if (repeat) begin(duration);
|
|
2079
|
+
else {
|
|
2080
|
+
isActive.value = false;
|
|
2081
|
+
remaining.value = 0;
|
|
2082
|
+
}
|
|
2083
|
+
}
|
|
2084
|
+
function begin(ms) {
|
|
2085
|
+
clearTimer();
|
|
2086
|
+
stopTracking();
|
|
2087
|
+
budget = ms;
|
|
2088
|
+
startedAt = Date.now();
|
|
2089
|
+
remaining.value = ms;
|
|
2090
|
+
isActive.value = true;
|
|
2091
|
+
isPaused.value = false;
|
|
2092
|
+
timeoutId = globalThis.setTimeout(fire, ms);
|
|
2093
|
+
startTracking();
|
|
2094
|
+
}
|
|
2095
|
+
function start() {
|
|
2096
|
+
if (duration < 0) return;
|
|
2097
|
+
begin(duration);
|
|
2098
|
+
}
|
|
2099
|
+
function stop() {
|
|
2100
|
+
clearTimer();
|
|
2101
|
+
stopTracking();
|
|
2102
|
+
isActive.value = false;
|
|
2103
|
+
isPaused.value = false;
|
|
2104
|
+
remaining.value = duration;
|
|
2105
|
+
}
|
|
2106
|
+
function pause() {
|
|
2107
|
+
if (!isActive.value || isPaused.value) return;
|
|
2108
|
+
const elapsed = Date.now() - startedAt;
|
|
2109
|
+
budget = Math.max(0, budget - elapsed);
|
|
2110
|
+
remaining.value = budget;
|
|
2111
|
+
clearTimer();
|
|
2112
|
+
stopTracking();
|
|
2113
|
+
isPaused.value = true;
|
|
2114
|
+
}
|
|
2115
|
+
function resume() {
|
|
2116
|
+
if (!isPaused.value) return;
|
|
2117
|
+
isPaused.value = false;
|
|
2118
|
+
startedAt = Date.now();
|
|
2119
|
+
timeoutId = globalThis.setTimeout(fire, budget);
|
|
2120
|
+
startTracking();
|
|
2121
|
+
}
|
|
2122
|
+
onScopeDispose(() => {
|
|
2123
|
+
clearTimer();
|
|
2124
|
+
stopTracking();
|
|
2125
|
+
}, true);
|
|
2126
|
+
return {
|
|
2127
|
+
start,
|
|
2128
|
+
stop,
|
|
2129
|
+
pause,
|
|
2130
|
+
resume,
|
|
2131
|
+
remaining,
|
|
2132
|
+
isActive,
|
|
2133
|
+
isPaused
|
|
2134
|
+
};
|
|
2135
|
+
}
|
|
2136
|
+
//#endregion
|
|
2015
2137
|
//#region src/composables/useLazy/index.ts
|
|
2016
2138
|
/**
|
|
2017
2139
|
* @module useLazy
|
|
@@ -2075,11 +2197,16 @@ function useElementIntersection(target, options = {}) {
|
|
|
2075
2197
|
* ```
|
|
2076
2198
|
*/
|
|
2077
2199
|
function useLazy(active, options = {}) {
|
|
2078
|
-
const { eager = false } = options;
|
|
2200
|
+
const { eager = false, delay = 0 } = options;
|
|
2079
2201
|
const isBooted = shallowRef(false);
|
|
2080
2202
|
const hasContent = toRef(() => isBooted.value || toValue(eager) || toValue(active));
|
|
2203
|
+
const timer = delay > 0 ? useTimer(() => {
|
|
2204
|
+
isBooted.value = true;
|
|
2205
|
+
}, { duration: delay }) : void 0;
|
|
2081
2206
|
const stop = watch(() => toValue(active), (value) => {
|
|
2082
|
-
if (value)
|
|
2207
|
+
if (value) if (timer) timer.start();
|
|
2208
|
+
else isBooted.value = true;
|
|
2209
|
+
else timer?.stop();
|
|
2083
2210
|
}, { immediate: true });
|
|
2084
2211
|
function reset() {
|
|
2085
2212
|
isBooted.value = false;
|
|
@@ -2140,7 +2267,7 @@ function useLazy(active, options = {}) {
|
|
|
2140
2267
|
function useMediaQuery(query) {
|
|
2141
2268
|
const matches = shallowRef(false);
|
|
2142
2269
|
const mediaQueryList = shallowRef(null);
|
|
2143
|
-
const resolvedQuery =
|
|
2270
|
+
const resolvedQuery = toRef(() => toValue(query));
|
|
2144
2271
|
const hydration = useHydration();
|
|
2145
2272
|
let cleanup = null;
|
|
2146
2273
|
function update() {
|
|
@@ -2985,21 +3112,22 @@ function createQueue(_options = {}) {
|
|
|
2985
3112
|
...options,
|
|
2986
3113
|
events: true
|
|
2987
3114
|
});
|
|
2988
|
-
const
|
|
2989
|
-
function
|
|
3115
|
+
const timers = /* @__PURE__ */ new Map();
|
|
3116
|
+
function createTicketTimer(ticket) {
|
|
2990
3117
|
if (/* @__PURE__ */ isUndefined(ticket.timeout) || ticket.timeout < 0 || ticket.isPaused) return;
|
|
2991
|
-
const
|
|
2992
|
-
|
|
3118
|
+
const timer = useTimer(() => {
|
|
3119
|
+
timers.delete(ticket.id);
|
|
2993
3120
|
registry.unregister(ticket.id);
|
|
2994
3121
|
resume();
|
|
2995
|
-
}, ticket.timeout);
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3122
|
+
}, { duration: ticket.timeout });
|
|
3123
|
+
timers.set(ticket.id, timer);
|
|
3124
|
+
timer.start();
|
|
3125
|
+
}
|
|
3126
|
+
function stopTimer(id) {
|
|
3127
|
+
const timer = timers.get(id);
|
|
3128
|
+
if (timer) {
|
|
3129
|
+
timer.stop();
|
|
3130
|
+
timers.delete(id);
|
|
3003
3131
|
}
|
|
3004
3132
|
}
|
|
3005
3133
|
function register(registration = {}) {
|
|
@@ -3013,14 +3141,14 @@ function createQueue(_options = {}) {
|
|
|
3013
3141
|
dismiss: () => unregister(id)
|
|
3014
3142
|
};
|
|
3015
3143
|
const registered = registry.register(ticket);
|
|
3016
|
-
|
|
3144
|
+
createTicketTimer(registered);
|
|
3017
3145
|
return registered;
|
|
3018
3146
|
}
|
|
3019
3147
|
function unregister(id) {
|
|
3020
3148
|
const ticket = /* @__PURE__ */ isUndefined(id) ? registry.seek("first") : registry.get(id);
|
|
3021
3149
|
if (!ticket) return void 0;
|
|
3022
3150
|
const wasFirst = ticket.index === 0;
|
|
3023
|
-
|
|
3151
|
+
stopTimer(ticket.id);
|
|
3024
3152
|
registry.unregister(ticket.id);
|
|
3025
3153
|
if (wasFirst) resume();
|
|
3026
3154
|
return ticket;
|
|
@@ -3031,7 +3159,7 @@ function createQueue(_options = {}) {
|
|
|
3031
3159
|
const ticket = registry.get(id);
|
|
3032
3160
|
if (!ticket) continue;
|
|
3033
3161
|
if (ticket.index === 0) hadFirst = true;
|
|
3034
|
-
|
|
3162
|
+
stopTimer(ticket.id);
|
|
3035
3163
|
}
|
|
3036
3164
|
registry.offboard(ids);
|
|
3037
3165
|
if (hadFirst) resume();
|
|
@@ -3039,18 +3167,21 @@ function createQueue(_options = {}) {
|
|
|
3039
3167
|
function pause() {
|
|
3040
3168
|
const ticket = registry.seek("first");
|
|
3041
3169
|
if (!ticket || ticket.isPaused) return void 0;
|
|
3042
|
-
|
|
3170
|
+
timers.get(ticket.id)?.pause();
|
|
3043
3171
|
return registry.upsert(ticket.id, { isPaused: true });
|
|
3044
3172
|
}
|
|
3045
3173
|
function resume() {
|
|
3046
3174
|
const ticket = registry.seek("first");
|
|
3047
3175
|
if (!ticket || ticket.index !== 0 || !ticket.isPaused) return void 0;
|
|
3048
3176
|
const updated = registry.upsert(ticket.id, { isPaused: false });
|
|
3049
|
-
|
|
3177
|
+
const timer = timers.get(updated.id);
|
|
3178
|
+
if (timer) timer.start();
|
|
3179
|
+
else createTicketTimer(updated);
|
|
3050
3180
|
return updated;
|
|
3051
3181
|
}
|
|
3052
3182
|
function clear() {
|
|
3053
|
-
for (const
|
|
3183
|
+
for (const timer of timers.values()) timer.stop();
|
|
3184
|
+
timers.clear();
|
|
3054
3185
|
registry.clear();
|
|
3055
3186
|
}
|
|
3056
3187
|
function dispose() {
|
|
@@ -3125,6 +3256,909 @@ function useQueue(namespace = "v0:queue") {
|
|
|
3125
3256
|
return useContext(namespace);
|
|
3126
3257
|
}
|
|
3127
3258
|
//#endregion
|
|
3259
|
+
//#region src/composables/useNotifications/index.ts
|
|
3260
|
+
/**
|
|
3261
|
+
* @module useNotifications
|
|
3262
|
+
* @see https://0.vuetifyjs.com/composables/plugins/use-notifications
|
|
3263
|
+
*
|
|
3264
|
+
* @remarks
|
|
3265
|
+
* Notification management composable built on createRegistry and createQueue.
|
|
3266
|
+
* Registry stores the full notification lifecycle (permanent record).
|
|
3267
|
+
* Queue manages the display surface (toasts) with FIFO ordering and auto-dismiss.
|
|
3268
|
+
*
|
|
3269
|
+
* Supports:
|
|
3270
|
+
* - Push notifications with severity levels and configurable timeouts
|
|
3271
|
+
* - State mutations: read, seen, archived, snoozed
|
|
3272
|
+
* - Bulk operations: readAll, archiveAll, clear
|
|
3273
|
+
* - Toast queue with pause/resume and auto-dismiss
|
|
3274
|
+
* - Adapter integration via event system
|
|
3275
|
+
* - Plugin installation via createNotificationsPlugin
|
|
3276
|
+
*/
|
|
3277
|
+
function createNotifications(options = {}) {
|
|
3278
|
+
const { timeout = 3e3, ...registryOptions } = options;
|
|
3279
|
+
const registry = createRegistry({
|
|
3280
|
+
...registryOptions,
|
|
3281
|
+
events: true,
|
|
3282
|
+
reactive: true
|
|
3283
|
+
});
|
|
3284
|
+
const queue = createQueue({
|
|
3285
|
+
timeout,
|
|
3286
|
+
events: true,
|
|
3287
|
+
reactive: true
|
|
3288
|
+
});
|
|
3289
|
+
registry.on("unregister:ticket", (ticket) => {
|
|
3290
|
+
if (queue.has(ticket.id)) queue.unregister(ticket.id);
|
|
3291
|
+
});
|
|
3292
|
+
/**
|
|
3293
|
+
* Build a full {@link NotificationTicket} from raw input
|
|
3294
|
+
*
|
|
3295
|
+
* @param input The notification input to hydrate.
|
|
3296
|
+
* @returns A partial ticket with timestamps, lifecycle methods, and an ID.
|
|
3297
|
+
* @internal Used by {@link send}, {@link register}, and {@link onboard}.
|
|
3298
|
+
*/
|
|
3299
|
+
function hydrate(input) {
|
|
3300
|
+
const id = input.id ?? /* @__PURE__ */ useId$1();
|
|
3301
|
+
const now = /* @__PURE__ */ new Date();
|
|
3302
|
+
return {
|
|
3303
|
+
...input,
|
|
3304
|
+
id,
|
|
3305
|
+
createdAt: now,
|
|
3306
|
+
readAt: null,
|
|
3307
|
+
seenAt: null,
|
|
3308
|
+
archivedAt: null,
|
|
3309
|
+
snoozedUntil: null,
|
|
3310
|
+
read: () => read(id),
|
|
3311
|
+
unread: () => unread(id),
|
|
3312
|
+
seen: () => seen(id),
|
|
3313
|
+
archive: () => archive(id),
|
|
3314
|
+
unarchive: () => unarchive(id),
|
|
3315
|
+
snooze: (until) => snooze(id, until),
|
|
3316
|
+
wake: () => wake(id),
|
|
3317
|
+
dismiss: () => queue.unregister(id)
|
|
3318
|
+
};
|
|
3319
|
+
}
|
|
3320
|
+
/**
|
|
3321
|
+
* Create a notification and enqueue it for toast display
|
|
3322
|
+
*
|
|
3323
|
+
* @param input The notification input to create.
|
|
3324
|
+
* @returns The hydrated notification ticket.
|
|
3325
|
+
* @remarks Hydrates the input with timestamps and lifecycle methods, registers
|
|
3326
|
+
* it in the registry, adds it to the display queue, and emits
|
|
3327
|
+
* `notification:received`. The ticket auto-dismisses after the configured
|
|
3328
|
+
* timeout unless paused.
|
|
3329
|
+
*
|
|
3330
|
+
* @see https://0.vuetifyjs.com/composables/plugins/use-notifications#send
|
|
3331
|
+
*
|
|
3332
|
+
* @example
|
|
3333
|
+
* ```ts
|
|
3334
|
+
* import { useNotifications } from '@vuetify/v0'
|
|
3335
|
+
*
|
|
3336
|
+
* const notifications = useNotifications()
|
|
3337
|
+
*
|
|
3338
|
+
* // Basic toast
|
|
3339
|
+
* notifications.send({ subject: 'Changes saved', severity: 'success' })
|
|
3340
|
+
*
|
|
3341
|
+
* // With custom timeout
|
|
3342
|
+
* const ticket = notifications.send({ subject: 'Connection lost', severity: 'error', timeout: 10000 })
|
|
3343
|
+
*
|
|
3344
|
+
* console.log(ticket.id) // 'generated-id'
|
|
3345
|
+
* console.log(ticket.createdAt) // Date
|
|
3346
|
+
* console.log(ticket.readAt) // null
|
|
3347
|
+
*
|
|
3348
|
+
* // Ticket convenience methods
|
|
3349
|
+
* ticket.read() // marks as read
|
|
3350
|
+
* ticket.dismiss() // removes from toast queue, keeps in registry
|
|
3351
|
+
* ```
|
|
3352
|
+
*/
|
|
3353
|
+
function send(input) {
|
|
3354
|
+
const ticket = registry.register(hydrate(input));
|
|
3355
|
+
queue.register(/* @__PURE__ */ isUndefined(input.timeout) ? { id: ticket.id } : {
|
|
3356
|
+
id: ticket.id,
|
|
3357
|
+
timeout: input.timeout
|
|
3358
|
+
});
|
|
3359
|
+
registry.emit("notification:received", ticket);
|
|
3360
|
+
return ticket;
|
|
3361
|
+
}
|
|
3362
|
+
/**
|
|
3363
|
+
* Register a notification in the registry without adding it to the toast queue
|
|
3364
|
+
*
|
|
3365
|
+
* @param input The notification input to register.
|
|
3366
|
+
* @returns The hydrated notification ticket.
|
|
3367
|
+
* @remarks Overrides the base registry `register` to hydrate the input with
|
|
3368
|
+
* timestamps and lifecycle methods. Use for historical or pre-existing items
|
|
3369
|
+
* that should appear in an inbox but not pop up as toasts.
|
|
3370
|
+
*
|
|
3371
|
+
* @see https://0.vuetifyjs.com/composables/plugins/use-notifications#register
|
|
3372
|
+
*
|
|
3373
|
+
* @example
|
|
3374
|
+
* ```ts
|
|
3375
|
+
* import { useNotifications } from '@vuetify/v0'
|
|
3376
|
+
*
|
|
3377
|
+
* const notifications = useNotifications()
|
|
3378
|
+
*
|
|
3379
|
+
* // Register a historical item (appears in inbox, not as toast)
|
|
3380
|
+
* const ticket = notifications.register({ id: 'old-1', subject: 'Deployed v2.1' })
|
|
3381
|
+
*
|
|
3382
|
+
* console.log(ticket.createdAt) // Date
|
|
3383
|
+
* console.log(ticket.readAt) // null
|
|
3384
|
+
*
|
|
3385
|
+
* // Lifecycle methods work the same as send()
|
|
3386
|
+
* ticket.read()
|
|
3387
|
+
* ticket.archive()
|
|
3388
|
+
* ```
|
|
3389
|
+
*/
|
|
3390
|
+
function register(input) {
|
|
3391
|
+
return registry.register(hydrate(input));
|
|
3392
|
+
}
|
|
3393
|
+
/**
|
|
3394
|
+
* Bulk version of {@link register}
|
|
3395
|
+
*
|
|
3396
|
+
* @param inputs Array of notification inputs to register.
|
|
3397
|
+
* @returns Array of hydrated notification tickets.
|
|
3398
|
+
* @remarks Registers multiple notifications into the registry without toast
|
|
3399
|
+
* display. Wraps all registrations in a single `registry.batch()` call so
|
|
3400
|
+
* reactive updates are deferred until the entire batch completes.
|
|
3401
|
+
*
|
|
3402
|
+
* @see https://0.vuetifyjs.com/composables/plugins/use-notifications#onboard
|
|
3403
|
+
*
|
|
3404
|
+
* @example
|
|
3405
|
+
* ```ts
|
|
3406
|
+
* import { useNotifications } from '@vuetify/v0'
|
|
3407
|
+
*
|
|
3408
|
+
* const notifications = useNotifications()
|
|
3409
|
+
*
|
|
3410
|
+
* // Load historical items on mount
|
|
3411
|
+
* const tickets = notifications.onboard([
|
|
3412
|
+
* { id: 'n1', subject: 'Welcome to the team' },
|
|
3413
|
+
* { id: 'n2', subject: 'Setup complete', severity: 'success' },
|
|
3414
|
+
* ])
|
|
3415
|
+
*
|
|
3416
|
+
* console.log(tickets.length) // 2
|
|
3417
|
+
* console.log(notifications.queue.values()) // [] (no toasts)
|
|
3418
|
+
* console.log(notifications.values().length) // 2 (in registry)
|
|
3419
|
+
* ```
|
|
3420
|
+
*/
|
|
3421
|
+
function onboard(inputs) {
|
|
3422
|
+
return registry.batch(() => inputs.map((input) => register(input)));
|
|
3423
|
+
}
|
|
3424
|
+
/**
|
|
3425
|
+
* Mark a notification as read
|
|
3426
|
+
*
|
|
3427
|
+
* @param id The ID of the notification to mark as read.
|
|
3428
|
+
* @remarks Sets `readAt` to the current time and emits `notification:read`.
|
|
3429
|
+
* Adapters listen to this event for outbound sync.
|
|
3430
|
+
*
|
|
3431
|
+
* @see https://0.vuetifyjs.com/composables/plugins/use-notifications#read
|
|
3432
|
+
*
|
|
3433
|
+
* @example
|
|
3434
|
+
* ```ts
|
|
3435
|
+
* import { useNotifications } from '@vuetify/v0'
|
|
3436
|
+
*
|
|
3437
|
+
* const notifications = useNotifications()
|
|
3438
|
+
*
|
|
3439
|
+
* const ticket = notifications.send({ subject: 'New message' })
|
|
3440
|
+
*
|
|
3441
|
+
* notifications.read(ticket.id)
|
|
3442
|
+
* console.log(ticket.readAt) // Date
|
|
3443
|
+
*
|
|
3444
|
+
* // Or via ticket convenience method
|
|
3445
|
+
* ticket.read()
|
|
3446
|
+
* ```
|
|
3447
|
+
*/
|
|
3448
|
+
function read(id) {
|
|
3449
|
+
registry.upsert(id, { readAt: /* @__PURE__ */ new Date() }, "notification:read");
|
|
3450
|
+
}
|
|
3451
|
+
/**
|
|
3452
|
+
* Mark a notification as unread
|
|
3453
|
+
*
|
|
3454
|
+
* @param id The ID of the notification to mark as unread.
|
|
3455
|
+
* @remarks Clears `readAt` and emits `notification:unread`.
|
|
3456
|
+
*
|
|
3457
|
+
* @see https://0.vuetifyjs.com/composables/plugins/use-notifications#unread
|
|
3458
|
+
*
|
|
3459
|
+
* @example
|
|
3460
|
+
* ```ts
|
|
3461
|
+
* import { useNotifications } from '@vuetify/v0'
|
|
3462
|
+
*
|
|
3463
|
+
* const notifications = useNotifications()
|
|
3464
|
+
*
|
|
3465
|
+
* notifications.unread('notif-1')
|
|
3466
|
+
* ```
|
|
3467
|
+
*/
|
|
3468
|
+
function unread(id) {
|
|
3469
|
+
registry.upsert(id, { readAt: null }, "notification:unread");
|
|
3470
|
+
}
|
|
3471
|
+
/**
|
|
3472
|
+
* Mark a notification as seen
|
|
3473
|
+
*
|
|
3474
|
+
* @param id The ID of the notification to mark as seen.
|
|
3475
|
+
* @remarks Sets `seenAt` to the current time and emits `notification:seen`.
|
|
3476
|
+
* Distinct from read — seen tracks whether the notification appeared in the
|
|
3477
|
+
* user's viewport, while read indicates the user actively engaged with it.
|
|
3478
|
+
*
|
|
3479
|
+
* @see https://0.vuetifyjs.com/composables/plugins/use-notifications#seen
|
|
3480
|
+
*
|
|
3481
|
+
* @example
|
|
3482
|
+
* ```ts
|
|
3483
|
+
* import { useNotifications } from '@vuetify/v0'
|
|
3484
|
+
*
|
|
3485
|
+
* const notifications = useNotifications()
|
|
3486
|
+
*
|
|
3487
|
+
* // Mark as seen when visible in inbox viewport
|
|
3488
|
+
* notifications.seen('notif-1')
|
|
3489
|
+
* ```
|
|
3490
|
+
*/
|
|
3491
|
+
function seen(id) {
|
|
3492
|
+
registry.upsert(id, { seenAt: /* @__PURE__ */ new Date() }, "notification:seen");
|
|
3493
|
+
}
|
|
3494
|
+
/**
|
|
3495
|
+
* Archive a notification
|
|
3496
|
+
*
|
|
3497
|
+
* @param id The ID of the notification to archive.
|
|
3498
|
+
* @remarks Sets `archivedAt` to the current time and emits `notification:archived`.
|
|
3499
|
+
*
|
|
3500
|
+
* @see https://0.vuetifyjs.com/composables/plugins/use-notifications#archive
|
|
3501
|
+
*
|
|
3502
|
+
* @example
|
|
3503
|
+
* ```ts
|
|
3504
|
+
* import { useNotifications } from '@vuetify/v0'
|
|
3505
|
+
*
|
|
3506
|
+
* const notifications = useNotifications()
|
|
3507
|
+
*
|
|
3508
|
+
* notifications.archive('notif-1')
|
|
3509
|
+
* ```
|
|
3510
|
+
*/
|
|
3511
|
+
function archive(id) {
|
|
3512
|
+
registry.upsert(id, { archivedAt: /* @__PURE__ */ new Date() }, "notification:archived");
|
|
3513
|
+
}
|
|
3514
|
+
/**
|
|
3515
|
+
* Restore an archived notification
|
|
3516
|
+
*
|
|
3517
|
+
* @param id The ID of the notification to unarchive.
|
|
3518
|
+
* @remarks Clears `archivedAt` and emits `notification:unarchived`.
|
|
3519
|
+
*
|
|
3520
|
+
* @see https://0.vuetifyjs.com/composables/plugins/use-notifications#unarchive
|
|
3521
|
+
*
|
|
3522
|
+
* @example
|
|
3523
|
+
* ```ts
|
|
3524
|
+
* import { useNotifications } from '@vuetify/v0'
|
|
3525
|
+
*
|
|
3526
|
+
* const notifications = useNotifications()
|
|
3527
|
+
*
|
|
3528
|
+
* notifications.unarchive('notif-1')
|
|
3529
|
+
* ```
|
|
3530
|
+
*/
|
|
3531
|
+
function unarchive(id) {
|
|
3532
|
+
registry.upsert(id, { archivedAt: null }, "notification:unarchived");
|
|
3533
|
+
}
|
|
3534
|
+
/**
|
|
3535
|
+
* Snooze a notification until a given time
|
|
3536
|
+
*
|
|
3537
|
+
* @param id The ID of the notification to snooze.
|
|
3538
|
+
* @param until The time at which the snooze expires.
|
|
3539
|
+
* @remarks Sets `snoozedUntil` and emits `notification:snoozed`. The composable
|
|
3540
|
+
* does not auto-wake — consumers are responsible for calling {@link wake} when
|
|
3541
|
+
* the snooze expires (e.g., via a timer or server push).
|
|
3542
|
+
*
|
|
3543
|
+
* @see https://0.vuetifyjs.com/composables/plugins/use-notifications#snooze
|
|
3544
|
+
*
|
|
3545
|
+
* @example
|
|
3546
|
+
* ```ts
|
|
3547
|
+
* import { useNotifications } from '@vuetify/v0'
|
|
3548
|
+
*
|
|
3549
|
+
* const notifications = useNotifications()
|
|
3550
|
+
*
|
|
3551
|
+
* const tomorrow = new Date(Date.now() + 86_400_000)
|
|
3552
|
+
* notifications.snooze('notif-1', tomorrow)
|
|
3553
|
+
* ```
|
|
3554
|
+
*/
|
|
3555
|
+
function snooze(id, until) {
|
|
3556
|
+
registry.upsert(id, { snoozedUntil: until }, "notification:snoozed");
|
|
3557
|
+
}
|
|
3558
|
+
/**
|
|
3559
|
+
* Cancel a snooze
|
|
3560
|
+
*
|
|
3561
|
+
* @param id The ID of the notification to wake.
|
|
3562
|
+
* @remarks Clears `snoozedUntil` and emits `notification:unsnoozed`.
|
|
3563
|
+
*
|
|
3564
|
+
* @see https://0.vuetifyjs.com/composables/plugins/use-notifications#wake
|
|
3565
|
+
*
|
|
3566
|
+
* @example
|
|
3567
|
+
* ```ts
|
|
3568
|
+
* import { useNotifications } from '@vuetify/v0'
|
|
3569
|
+
*
|
|
3570
|
+
* const notifications = useNotifications()
|
|
3571
|
+
*
|
|
3572
|
+
* notifications.wake('notif-1')
|
|
3573
|
+
* ```
|
|
3574
|
+
*/
|
|
3575
|
+
function wake(id) {
|
|
3576
|
+
registry.upsert(id, { snoozedUntil: null }, "notification:unsnoozed");
|
|
3577
|
+
}
|
|
3578
|
+
/**
|
|
3579
|
+
* Mark all unread notifications as read
|
|
3580
|
+
*
|
|
3581
|
+
* @remarks Iterates all notifications and marks unread ones as read in a single
|
|
3582
|
+
* batch. Skips already-read notifications to preserve their original `readAt`
|
|
3583
|
+
* timestamp. Emits `notification:read` for each affected notification.
|
|
3584
|
+
*
|
|
3585
|
+
* @see https://0.vuetifyjs.com/composables/plugins/use-notifications#readall
|
|
3586
|
+
*
|
|
3587
|
+
* @example
|
|
3588
|
+
* ```ts
|
|
3589
|
+
* import { useNotifications } from '@vuetify/v0'
|
|
3590
|
+
*
|
|
3591
|
+
* const notifications = useNotifications()
|
|
3592
|
+
*
|
|
3593
|
+
* notifications.send({ subject: 'Message 1' })
|
|
3594
|
+
* notifications.send({ subject: 'Message 2' })
|
|
3595
|
+
*
|
|
3596
|
+
* notifications.readAll()
|
|
3597
|
+
*
|
|
3598
|
+
* console.log(notifications.values().every(t => t.readAt !== null)) // true
|
|
3599
|
+
* ```
|
|
3600
|
+
*/
|
|
3601
|
+
function readAll() {
|
|
3602
|
+
const now = /* @__PURE__ */ new Date();
|
|
3603
|
+
registry.batch(() => {
|
|
3604
|
+
for (const ticket of registry.values()) if (/* @__PURE__ */ isNull(ticket.readAt)) registry.upsert(ticket.id, { readAt: now }, "notification:read");
|
|
3605
|
+
});
|
|
3606
|
+
}
|
|
3607
|
+
/**
|
|
3608
|
+
* Archive all unarchived notifications
|
|
3609
|
+
*
|
|
3610
|
+
* @remarks Iterates all notifications and archives unarchived ones in a single
|
|
3611
|
+
* batch. Skips already-archived notifications to preserve their original
|
|
3612
|
+
* `archivedAt` timestamp. Emits `notification:archived` for each affected notification.
|
|
3613
|
+
*
|
|
3614
|
+
* @see https://0.vuetifyjs.com/composables/plugins/use-notifications#archiveall
|
|
3615
|
+
*
|
|
3616
|
+
* @example
|
|
3617
|
+
* ```ts
|
|
3618
|
+
* import { useNotifications } from '@vuetify/v0'
|
|
3619
|
+
*
|
|
3620
|
+
* const notifications = useNotifications()
|
|
3621
|
+
*
|
|
3622
|
+
* notifications.send({ subject: 'Alert 1' })
|
|
3623
|
+
* notifications.send({ subject: 'Alert 2' })
|
|
3624
|
+
*
|
|
3625
|
+
* notifications.archiveAll()
|
|
3626
|
+
*
|
|
3627
|
+
* console.log(notifications.values().every(t => t.archivedAt !== null)) // true
|
|
3628
|
+
* ```
|
|
3629
|
+
*/
|
|
3630
|
+
function archiveAll() {
|
|
3631
|
+
const now = /* @__PURE__ */ new Date();
|
|
3632
|
+
registry.batch(() => {
|
|
3633
|
+
for (const ticket of registry.values()) if (/* @__PURE__ */ isNull(ticket.archivedAt)) registry.upsert(ticket.id, { archivedAt: now }, "notification:archived");
|
|
3634
|
+
});
|
|
3635
|
+
}
|
|
3636
|
+
return {
|
|
3637
|
+
...registry,
|
|
3638
|
+
send,
|
|
3639
|
+
register,
|
|
3640
|
+
onboard,
|
|
3641
|
+
queue,
|
|
3642
|
+
read,
|
|
3643
|
+
unread,
|
|
3644
|
+
seen,
|
|
3645
|
+
archive,
|
|
3646
|
+
unarchive,
|
|
3647
|
+
snooze,
|
|
3648
|
+
wake,
|
|
3649
|
+
readAll,
|
|
3650
|
+
archiveAll,
|
|
3651
|
+
get size() {
|
|
3652
|
+
return registry.size;
|
|
3653
|
+
}
|
|
3654
|
+
};
|
|
3655
|
+
}
|
|
3656
|
+
function noop() {}
|
|
3657
|
+
const EMPTY = [];
|
|
3658
|
+
function createNotificationsFallback() {
|
|
3659
|
+
const stub = {
|
|
3660
|
+
id: "",
|
|
3661
|
+
index: 0,
|
|
3662
|
+
value: 0,
|
|
3663
|
+
valueIsIndex: true,
|
|
3664
|
+
createdAt: /* @__PURE__ */ new Date(0),
|
|
3665
|
+
readAt: null,
|
|
3666
|
+
seenAt: null,
|
|
3667
|
+
archivedAt: null,
|
|
3668
|
+
snoozedUntil: null,
|
|
3669
|
+
read: noop,
|
|
3670
|
+
unread: noop,
|
|
3671
|
+
seen: noop,
|
|
3672
|
+
archive: noop,
|
|
3673
|
+
unarchive: noop,
|
|
3674
|
+
snooze: noop,
|
|
3675
|
+
wake: noop,
|
|
3676
|
+
dismiss: noop,
|
|
3677
|
+
unregister: noop
|
|
3678
|
+
};
|
|
3679
|
+
return {
|
|
3680
|
+
collection: /* @__PURE__ */ new Map(),
|
|
3681
|
+
size: 0,
|
|
3682
|
+
send: () => stub,
|
|
3683
|
+
queue: {
|
|
3684
|
+
collection: /* @__PURE__ */ new Map(),
|
|
3685
|
+
size: 0,
|
|
3686
|
+
register: () => ({}),
|
|
3687
|
+
unregister: () => void 0,
|
|
3688
|
+
has: () => false,
|
|
3689
|
+
get: () => void 0,
|
|
3690
|
+
keys: () => EMPTY,
|
|
3691
|
+
values: () => EMPTY,
|
|
3692
|
+
entries: () => EMPTY,
|
|
3693
|
+
browse: () => void 0,
|
|
3694
|
+
lookup: () => void 0,
|
|
3695
|
+
upsert: () => ({}),
|
|
3696
|
+
seek: () => void 0,
|
|
3697
|
+
move: () => void 0,
|
|
3698
|
+
on: noop,
|
|
3699
|
+
off: noop,
|
|
3700
|
+
emit: noop,
|
|
3701
|
+
dispose: noop,
|
|
3702
|
+
clear: noop,
|
|
3703
|
+
reindex: noop,
|
|
3704
|
+
batch: (fn) => fn(),
|
|
3705
|
+
onboard: () => EMPTY,
|
|
3706
|
+
offboard: noop,
|
|
3707
|
+
pause: () => void 0,
|
|
3708
|
+
resume: () => void 0
|
|
3709
|
+
},
|
|
3710
|
+
read: noop,
|
|
3711
|
+
unread: noop,
|
|
3712
|
+
seen: noop,
|
|
3713
|
+
archive: noop,
|
|
3714
|
+
unarchive: noop,
|
|
3715
|
+
snooze: noop,
|
|
3716
|
+
wake: noop,
|
|
3717
|
+
readAll: noop,
|
|
3718
|
+
archiveAll: noop,
|
|
3719
|
+
clear: noop,
|
|
3720
|
+
has: () => false,
|
|
3721
|
+
get: () => void 0,
|
|
3722
|
+
keys: () => EMPTY,
|
|
3723
|
+
values: () => EMPTY,
|
|
3724
|
+
entries: () => EMPTY,
|
|
3725
|
+
browse: () => void 0,
|
|
3726
|
+
lookup: () => void 0,
|
|
3727
|
+
upsert: () => stub,
|
|
3728
|
+
register: () => stub,
|
|
3729
|
+
unregister: noop,
|
|
3730
|
+
reindex: noop,
|
|
3731
|
+
move: () => void 0,
|
|
3732
|
+
seek: () => void 0,
|
|
3733
|
+
on: noop,
|
|
3734
|
+
off: noop,
|
|
3735
|
+
emit: noop,
|
|
3736
|
+
dispose: noop,
|
|
3737
|
+
batch: (fn) => fn(),
|
|
3738
|
+
onboard: () => EMPTY,
|
|
3739
|
+
offboard: noop
|
|
3740
|
+
};
|
|
3741
|
+
}
|
|
3742
|
+
/**
|
|
3743
|
+
* Notification management with registry, event system, and optional adapters.
|
|
3744
|
+
*
|
|
3745
|
+
* @see https://0.vuetifyjs.com/composables/plugins/use-notifications
|
|
3746
|
+
*
|
|
3747
|
+
* @example
|
|
3748
|
+
* ```ts
|
|
3749
|
+
* import { createNotificationsPlugin, useNotifications } from '@vuetify/v0'
|
|
3750
|
+
*
|
|
3751
|
+
* // Install as plugin
|
|
3752
|
+
* app.use(createNotificationsPlugin())
|
|
3753
|
+
*
|
|
3754
|
+
* // Use in components
|
|
3755
|
+
* const notifications = useNotifications()
|
|
3756
|
+
* notifications.send({ subject: 'Saved', severity: 'success' })
|
|
3757
|
+
* ```
|
|
3758
|
+
*/
|
|
3759
|
+
const [createNotificationsContext, createNotificationsPlugin, useNotifications] = createPluginContext("v0:notifications", (options) => createNotifications(options), {
|
|
3760
|
+
fallback: () => createNotificationsFallback(),
|
|
3761
|
+
setup: (context, app, options) => {
|
|
3762
|
+
app.onUnmount(() => {
|
|
3763
|
+
context.dispose();
|
|
3764
|
+
context.queue.dispose();
|
|
3765
|
+
});
|
|
3766
|
+
const { adapter } = options;
|
|
3767
|
+
if (!adapter) return;
|
|
3768
|
+
adapter.setup({
|
|
3769
|
+
send: context.send,
|
|
3770
|
+
register: context.register,
|
|
3771
|
+
on: context.on,
|
|
3772
|
+
off: context.off
|
|
3773
|
+
});
|
|
3774
|
+
if (/* @__PURE__ */ isFunction(adapter.dispose)) app.onUnmount(() => adapter.dispose());
|
|
3775
|
+
}
|
|
3776
|
+
});
|
|
3777
|
+
//#endregion
|
|
3778
|
+
//#region src/composables/usePopover/index.ts
|
|
3779
|
+
/**
|
|
3780
|
+
* @module usePopover
|
|
3781
|
+
*
|
|
3782
|
+
* @remarks
|
|
3783
|
+
* Composable for native popover API behavior with CSS anchor positioning.
|
|
3784
|
+
* Manages open/close state, anchor styles, content attributes, and
|
|
3785
|
+
* bidirectional sync between reactive state and native popover events.
|
|
3786
|
+
*
|
|
3787
|
+
* Key features:
|
|
3788
|
+
* - Native popover API (showPopover/hidePopover)
|
|
3789
|
+
* - CSS anchor positioning (position-area, position-try-fallbacks)
|
|
3790
|
+
* - Toggle event sync for native state changes
|
|
3791
|
+
* - SSR-safe (no DOM ops outside browser)
|
|
3792
|
+
* - Optional external isOpen ref for v-model integration
|
|
3793
|
+
*
|
|
3794
|
+
* Perfect for building select, combobox, tooltip, and menu components
|
|
3795
|
+
* without wrapping the Popover compound component.
|
|
3796
|
+
*/
|
|
3797
|
+
function usePopover(options = {}) {
|
|
3798
|
+
const { id: _id, positionArea = "bottom", positionTry = "most-width bottom", showDelay = 0, hideDelay = 0 } = options;
|
|
3799
|
+
const id = _id ?? /* @__PURE__ */ useId$1();
|
|
3800
|
+
const isOpen = options.isOpen ?? shallowRef(false);
|
|
3801
|
+
const showTimer = showDelay > 0 ? useTimer(() => {
|
|
3802
|
+
isOpen.value = true;
|
|
3803
|
+
}, { duration: showDelay }) : void 0;
|
|
3804
|
+
const hideTimer = hideDelay > 0 ? useTimer(() => {
|
|
3805
|
+
isOpen.value = false;
|
|
3806
|
+
}, { duration: hideDelay }) : void 0;
|
|
3807
|
+
function open() {
|
|
3808
|
+
hideTimer?.stop();
|
|
3809
|
+
if (showTimer) showTimer.start();
|
|
3810
|
+
else isOpen.value = true;
|
|
3811
|
+
}
|
|
3812
|
+
function close() {
|
|
3813
|
+
showTimer?.stop();
|
|
3814
|
+
if (hideTimer) hideTimer.start();
|
|
3815
|
+
else isOpen.value = false;
|
|
3816
|
+
}
|
|
3817
|
+
function toggle() {
|
|
3818
|
+
if (isOpen.value) close();
|
|
3819
|
+
else open();
|
|
3820
|
+
}
|
|
3821
|
+
const anchorStyles = toRef(() => ({ anchorName: `--${id}` }));
|
|
3822
|
+
const contentAttrs = toRef(() => ({
|
|
3823
|
+
id,
|
|
3824
|
+
popover: ""
|
|
3825
|
+
}));
|
|
3826
|
+
const contentStyles = toRef(() => ({
|
|
3827
|
+
"position": "fixed",
|
|
3828
|
+
"margin": "unset",
|
|
3829
|
+
"inset-area": positionArea,
|
|
3830
|
+
"position-area": positionArea,
|
|
3831
|
+
"position-anchor": `--${id}`,
|
|
3832
|
+
"position-try-fallbacks": positionTry
|
|
3833
|
+
}));
|
|
3834
|
+
/* v8 ignore start -- browser popover API */
|
|
3835
|
+
function attach(el) {
|
|
3836
|
+
onMounted(() => {
|
|
3837
|
+
const element = toValue(el);
|
|
3838
|
+
if (isOpen.value) element?.showPopover();
|
|
3839
|
+
});
|
|
3840
|
+
watch(isOpen, (value) => {
|
|
3841
|
+
const element = toValue(el);
|
|
3842
|
+
if (!element?.isConnected) return;
|
|
3843
|
+
if (value === element.matches?.(":popover-open")) return;
|
|
3844
|
+
if (value) element.showPopover?.();
|
|
3845
|
+
else element.hidePopover?.();
|
|
3846
|
+
});
|
|
3847
|
+
useEventListener(el, "toggle", (e) => {
|
|
3848
|
+
if (!toValue(el)?.isConnected) return;
|
|
3849
|
+
isOpen.value = e.newState === "open";
|
|
3850
|
+
});
|
|
3851
|
+
}
|
|
3852
|
+
/* v8 ignore stop */
|
|
3853
|
+
return {
|
|
3854
|
+
isOpen,
|
|
3855
|
+
id,
|
|
3856
|
+
open,
|
|
3857
|
+
close,
|
|
3858
|
+
toggle,
|
|
3859
|
+
anchorStyles,
|
|
3860
|
+
contentAttrs,
|
|
3861
|
+
contentStyles,
|
|
3862
|
+
attach
|
|
3863
|
+
};
|
|
3864
|
+
}
|
|
3865
|
+
//#endregion
|
|
3866
|
+
//#region src/composables/useRaf/index.ts
|
|
3867
|
+
/**
|
|
3868
|
+
* @module useRaf
|
|
3869
|
+
*
|
|
3870
|
+
* @see https://0.vuetifyjs.com/composables/system/use-raf
|
|
3871
|
+
*
|
|
3872
|
+
* @remarks
|
|
3873
|
+
* Scope-disposed safe requestAnimationFrame composable.
|
|
3874
|
+
*
|
|
3875
|
+
* Key features:
|
|
3876
|
+
* - Cancel-then-request pattern (deduplicates rapid calls)
|
|
3877
|
+
* - Automatic cleanup on scope disposal
|
|
3878
|
+
* - SSR-safe (no-op in non-browser environments)
|
|
3879
|
+
* - Callable function with cancel method
|
|
3880
|
+
*
|
|
3881
|
+
* Perfect for throttling updates to the next animation frame.
|
|
3882
|
+
*/
|
|
3883
|
+
/**
|
|
3884
|
+
* Scope-disposed safe requestAnimationFrame.
|
|
3885
|
+
*
|
|
3886
|
+
* @param callback Function to call on animation frame.
|
|
3887
|
+
* @returns Callable that requests frame (canceling pending), with cancel method.
|
|
3888
|
+
*
|
|
3889
|
+
* @see https://0.vuetifyjs.com/composables/system/use-raf
|
|
3890
|
+
*
|
|
3891
|
+
* @example
|
|
3892
|
+
* ```ts
|
|
3893
|
+
* // Basic usage
|
|
3894
|
+
* const update = useRaf((timestamp) => {
|
|
3895
|
+
* // Runs on next animation frame
|
|
3896
|
+
* })
|
|
3897
|
+
*
|
|
3898
|
+
* update() // Request frame
|
|
3899
|
+
* update() // Cancels previous, requests new (deduplicated)
|
|
3900
|
+
*
|
|
3901
|
+
* // Manual cancel
|
|
3902
|
+
* update.cancel()
|
|
3903
|
+
*
|
|
3904
|
+
* // Check if pending
|
|
3905
|
+
* if (update.isActive.value) { ... }
|
|
3906
|
+
* ```
|
|
3907
|
+
*/
|
|
3908
|
+
function useRaf(callback) {
|
|
3909
|
+
const id = shallowRef();
|
|
3910
|
+
const isActive = toRef(() => !/* @__PURE__ */ isUndefined(id.value));
|
|
3911
|
+
function cancel() {
|
|
3912
|
+
if (!/* @__PURE__ */ isUndefined(id.value)) {
|
|
3913
|
+
cancelAnimationFrame(id.value);
|
|
3914
|
+
id.value = void 0;
|
|
3915
|
+
}
|
|
3916
|
+
}
|
|
3917
|
+
function request() {
|
|
3918
|
+
if (!IN_BROWSER) return;
|
|
3919
|
+
cancel();
|
|
3920
|
+
id.value = requestAnimationFrame((timestamp) => {
|
|
3921
|
+
id.value = void 0;
|
|
3922
|
+
callback(timestamp);
|
|
3923
|
+
});
|
|
3924
|
+
}
|
|
3925
|
+
onScopeDispose(cancel, true);
|
|
3926
|
+
return Object.assign(request, {
|
|
3927
|
+
cancel,
|
|
3928
|
+
isActive
|
|
3929
|
+
});
|
|
3930
|
+
}
|
|
3931
|
+
//#endregion
|
|
3932
|
+
//#region src/composables/createFocusTraversal/index.ts
|
|
3933
|
+
/**
|
|
3934
|
+
* @module createFocusTraversal
|
|
3935
|
+
*
|
|
3936
|
+
* @remarks
|
|
3937
|
+
* Internal factory for keyboard-driven traversal of ordered item lists.
|
|
3938
|
+
* Encapsulates stride-based navigation, disabled-item skipping, circular/bounded
|
|
3939
|
+
* movement, grid row scoping, and key-to-action mapping shared by
|
|
3940
|
+
* useRovingFocus and useVirtualFocus.
|
|
3941
|
+
*
|
|
3942
|
+
* Not exported from the package barrel — consumed only by sibling composables.
|
|
3943
|
+
*/
|
|
3944
|
+
function mod(length, index) {
|
|
3945
|
+
return (index % length + length) % length;
|
|
3946
|
+
}
|
|
3947
|
+
function isRtl(e) {
|
|
3948
|
+
if (!IN_BROWSER) return false;
|
|
3949
|
+
const el = e.currentTarget;
|
|
3950
|
+
return el ? getComputedStyle(el).direction === "rtl" : false;
|
|
3951
|
+
}
|
|
3952
|
+
function createFocusTraversal(items, activate, options = {}) {
|
|
3953
|
+
const { orientation = "vertical", circular = false, columns: _columns } = options;
|
|
3954
|
+
const activeId = shallowRef();
|
|
3955
|
+
function enabled() {
|
|
3956
|
+
return items().filter((item) => !toValue(item.disabled));
|
|
3957
|
+
}
|
|
3958
|
+
function indexOf(id) {
|
|
3959
|
+
return items().findIndex((item) => item.id === id);
|
|
3960
|
+
}
|
|
3961
|
+
function go(id) {
|
|
3962
|
+
activeId.value = id;
|
|
3963
|
+
activate(id);
|
|
3964
|
+
}
|
|
3965
|
+
function step(stride) {
|
|
3966
|
+
const all = items();
|
|
3967
|
+
const length = all.length;
|
|
3968
|
+
if (!length) return;
|
|
3969
|
+
const current = /* @__PURE__ */ isUndefined(activeId.value) ? -1 : indexOf(activeId.value);
|
|
3970
|
+
const direction = stride > 0 ? 1 : -1;
|
|
3971
|
+
const absStride = Math.abs(stride);
|
|
3972
|
+
let index = current + stride;
|
|
3973
|
+
const maxHops = Math.ceil(length / absStride);
|
|
3974
|
+
let hops = 0;
|
|
3975
|
+
if (circular) index = mod(length, index);
|
|
3976
|
+
else if (index < 0 || index >= length) return;
|
|
3977
|
+
while (hops < maxHops) {
|
|
3978
|
+
const item = all[index];
|
|
3979
|
+
if (item && !toValue(item.disabled)) {
|
|
3980
|
+
go(item.id);
|
|
3981
|
+
return;
|
|
3982
|
+
}
|
|
3983
|
+
hops++;
|
|
3984
|
+
index = circular ? mod(length, index + stride) : index + direction * absStride;
|
|
3985
|
+
if (!circular && (index < 0 || index >= length)) return;
|
|
3986
|
+
}
|
|
3987
|
+
}
|
|
3988
|
+
function next() {
|
|
3989
|
+
step(1);
|
|
3990
|
+
}
|
|
3991
|
+
function prev() {
|
|
3992
|
+
step(-1);
|
|
3993
|
+
}
|
|
3994
|
+
function first() {
|
|
3995
|
+
const list = enabled();
|
|
3996
|
+
if (list.length > 0) go(list[0].id);
|
|
3997
|
+
}
|
|
3998
|
+
function last() {
|
|
3999
|
+
const list = enabled();
|
|
4000
|
+
if (list.length > 0) go(list.at(-1).id);
|
|
4001
|
+
}
|
|
4002
|
+
/** Focus first non-disabled item in the current row (grid mode) */
|
|
4003
|
+
function rowFirst() {
|
|
4004
|
+
const cols = toValue(_columns) ?? 0;
|
|
4005
|
+
if (!cols) return first();
|
|
4006
|
+
const all = items();
|
|
4007
|
+
const current = /* @__PURE__ */ isUndefined(activeId.value) ? 0 : indexOf(activeId.value);
|
|
4008
|
+
const rowStart = current - current % cols;
|
|
4009
|
+
const rowEnd = Math.min(rowStart + cols, all.length);
|
|
4010
|
+
for (let i = rowStart; i < rowEnd; i++) {
|
|
4011
|
+
const item = all[i];
|
|
4012
|
+
if (item && !toValue(item.disabled)) {
|
|
4013
|
+
go(item.id);
|
|
4014
|
+
return;
|
|
4015
|
+
}
|
|
4016
|
+
}
|
|
4017
|
+
}
|
|
4018
|
+
/** Focus last non-disabled item in the current row (grid mode) */
|
|
4019
|
+
function rowLast() {
|
|
4020
|
+
const cols = toValue(_columns) ?? 0;
|
|
4021
|
+
if (!cols) return last();
|
|
4022
|
+
const all = items();
|
|
4023
|
+
const current = /* @__PURE__ */ isUndefined(activeId.value) ? 0 : indexOf(activeId.value);
|
|
4024
|
+
const rowStart = current - current % cols;
|
|
4025
|
+
const rowEnd = Math.min(rowStart + cols, all.length);
|
|
4026
|
+
for (let i = rowEnd - 1; i >= rowStart; i--) {
|
|
4027
|
+
const item = all[i];
|
|
4028
|
+
if (item && !toValue(item.disabled)) {
|
|
4029
|
+
go(item.id);
|
|
4030
|
+
return;
|
|
4031
|
+
}
|
|
4032
|
+
}
|
|
4033
|
+
}
|
|
4034
|
+
function onKeydown(e) {
|
|
4035
|
+
const cols = toValue(_columns);
|
|
4036
|
+
const rtl = isRtl(e);
|
|
4037
|
+
if (cols) {
|
|
4038
|
+
switch (e.key) {
|
|
4039
|
+
case "ArrowRight":
|
|
4040
|
+
e.preventDefault();
|
|
4041
|
+
step(rtl ? -1 : 1);
|
|
4042
|
+
break;
|
|
4043
|
+
case "ArrowLeft":
|
|
4044
|
+
e.preventDefault();
|
|
4045
|
+
step(rtl ? 1 : -1);
|
|
4046
|
+
break;
|
|
4047
|
+
case "ArrowDown":
|
|
4048
|
+
e.preventDefault();
|
|
4049
|
+
step(cols);
|
|
4050
|
+
break;
|
|
4051
|
+
case "ArrowUp":
|
|
4052
|
+
e.preventDefault();
|
|
4053
|
+
step(-cols);
|
|
4054
|
+
break;
|
|
4055
|
+
case "Home":
|
|
4056
|
+
e.preventDefault();
|
|
4057
|
+
if (e.ctrlKey) first();
|
|
4058
|
+
else rowFirst();
|
|
4059
|
+
break;
|
|
4060
|
+
case "End":
|
|
4061
|
+
e.preventDefault();
|
|
4062
|
+
if (e.ctrlKey) last();
|
|
4063
|
+
else rowLast();
|
|
4064
|
+
break;
|
|
4065
|
+
}
|
|
4066
|
+
return;
|
|
4067
|
+
}
|
|
4068
|
+
const prevKeys = [];
|
|
4069
|
+
const nextKeys = [];
|
|
4070
|
+
if (orientation === "vertical" || orientation === "both") {
|
|
4071
|
+
prevKeys.push("ArrowUp");
|
|
4072
|
+
nextKeys.push("ArrowDown");
|
|
4073
|
+
}
|
|
4074
|
+
if (orientation === "horizontal" || orientation === "both") {
|
|
4075
|
+
prevKeys.push(rtl ? "ArrowRight" : "ArrowLeft");
|
|
4076
|
+
nextKeys.push(rtl ? "ArrowLeft" : "ArrowRight");
|
|
4077
|
+
}
|
|
4078
|
+
if (prevKeys.includes(e.key)) {
|
|
4079
|
+
e.preventDefault();
|
|
4080
|
+
prev();
|
|
4081
|
+
} else if (nextKeys.includes(e.key)) {
|
|
4082
|
+
e.preventDefault();
|
|
4083
|
+
next();
|
|
4084
|
+
} else if (e.key === "Home") {
|
|
4085
|
+
e.preventDefault();
|
|
4086
|
+
first();
|
|
4087
|
+
} else if (e.key === "End") {
|
|
4088
|
+
e.preventDefault();
|
|
4089
|
+
last();
|
|
4090
|
+
}
|
|
4091
|
+
}
|
|
4092
|
+
return {
|
|
4093
|
+
activeId,
|
|
4094
|
+
step,
|
|
4095
|
+
next,
|
|
4096
|
+
prev,
|
|
4097
|
+
first,
|
|
4098
|
+
last,
|
|
4099
|
+
onKeydown
|
|
4100
|
+
};
|
|
4101
|
+
}
|
|
4102
|
+
//#endregion
|
|
4103
|
+
//#region src/composables/useRovingFocus/index.ts
|
|
4104
|
+
/**
|
|
4105
|
+
* @module useRovingFocus
|
|
4106
|
+
*
|
|
4107
|
+
* @remarks
|
|
4108
|
+
* Roving tabindex composable for keyboard navigation within composite widgets.
|
|
4109
|
+
*
|
|
4110
|
+
* Key features:
|
|
4111
|
+
* - Arrow key navigation with orientation support
|
|
4112
|
+
* - Grid mode for 2D navigation (data tables, calendars)
|
|
4113
|
+
* - Automatic disabled item skipping
|
|
4114
|
+
* - Optional circular navigation
|
|
4115
|
+
* - Home/End key support (row-scoped in grid mode)
|
|
4116
|
+
* - Auto-attaches keydown listener when target is provided
|
|
4117
|
+
*
|
|
4118
|
+
* Perfect for toolbars, menus, tree items, grids, and other composite widgets.
|
|
4119
|
+
*/
|
|
4120
|
+
function useRovingFocus(items, options = {}) {
|
|
4121
|
+
const { orientation, circular, columns, onFocus, target } = options;
|
|
4122
|
+
function applyFocus(id) {
|
|
4123
|
+
const item = items().find((i) => i.id === id);
|
|
4124
|
+
if (!item?.el) return false;
|
|
4125
|
+
onFocus?.(id);
|
|
4126
|
+
nextTick(() => {
|
|
4127
|
+
toValue(item.el)?.focus();
|
|
4128
|
+
});
|
|
4129
|
+
return true;
|
|
4130
|
+
}
|
|
4131
|
+
const traversal = createFocusTraversal(items, (id) => applyFocus(id), {
|
|
4132
|
+
orientation,
|
|
4133
|
+
circular,
|
|
4134
|
+
columns
|
|
4135
|
+
});
|
|
4136
|
+
function focus(id) {
|
|
4137
|
+
const prev = traversal.activeId.value;
|
|
4138
|
+
traversal.activeId.value = id;
|
|
4139
|
+
if (!applyFocus(id)) traversal.activeId.value = prev;
|
|
4140
|
+
}
|
|
4141
|
+
function enabled() {
|
|
4142
|
+
return items().filter((item) => !toValue(item.disabled));
|
|
4143
|
+
}
|
|
4144
|
+
function isTabbable(id) {
|
|
4145
|
+
if (!/* @__PURE__ */ isUndefined(traversal.activeId.value)) return traversal.activeId.value === id;
|
|
4146
|
+
const list = enabled();
|
|
4147
|
+
return list.length > 0 && list[0]?.id === id;
|
|
4148
|
+
}
|
|
4149
|
+
if (target) useEventListener(target, "keydown", traversal.onKeydown);
|
|
4150
|
+
return {
|
|
4151
|
+
focusedId: traversal.activeId,
|
|
4152
|
+
isTabbable,
|
|
4153
|
+
focus,
|
|
4154
|
+
next: traversal.next,
|
|
4155
|
+
prev: traversal.prev,
|
|
4156
|
+
first: traversal.first,
|
|
4157
|
+
last: traversal.last,
|
|
4158
|
+
onKeydown: traversal.onKeydown
|
|
4159
|
+
};
|
|
4160
|
+
}
|
|
4161
|
+
//#endregion
|
|
3128
4162
|
//#region src/composables/useRtl/adapters/v0.ts
|
|
3129
4163
|
var Vuetify0RtlAdapter = class {
|
|
3130
4164
|
setup(app, context, target) {
|
|
@@ -3343,6 +4377,9 @@ function createSlider(options = {}) {
|
|
|
3343
4377
|
function ceil(index) {
|
|
3344
4378
|
set(index, max);
|
|
3345
4379
|
}
|
|
4380
|
+
function onboard(registrations) {
|
|
4381
|
+
return model.batch(() => registrations.map((r) => register(r)));
|
|
4382
|
+
}
|
|
3346
4383
|
return {
|
|
3347
4384
|
...model,
|
|
3348
4385
|
values,
|
|
@@ -3359,6 +4396,7 @@ function createSlider(options = {}) {
|
|
|
3359
4396
|
orientation,
|
|
3360
4397
|
inverted,
|
|
3361
4398
|
register,
|
|
4399
|
+
onboard,
|
|
3362
4400
|
snap,
|
|
3363
4401
|
fromValue,
|
|
3364
4402
|
fromPercent,
|
|
@@ -3438,12 +4476,12 @@ function createStack(_options = {}) {
|
|
|
3438
4476
|
const id = input.id ?? /* @__PURE__ */ useId$1();
|
|
3439
4477
|
const blocking = input.blocking ?? false;
|
|
3440
4478
|
const onDismiss = input.onDismiss;
|
|
3441
|
-
const zIndex =
|
|
4479
|
+
const zIndex = toRef(() => {
|
|
3442
4480
|
const position = ids().indexOf(id);
|
|
3443
4481
|
if (position === -1) return baseZIndex;
|
|
3444
4482
|
return baseZIndex + position * increment;
|
|
3445
4483
|
});
|
|
3446
|
-
const globalTop =
|
|
4484
|
+
const globalTop = toRef(() => {
|
|
3447
4485
|
const list = ids();
|
|
3448
4486
|
if (list.length === 0) return false;
|
|
3449
4487
|
return list.at(-1) === id;
|
|
@@ -4016,6 +5054,12 @@ function createTimeline(_options = {}) {
|
|
|
4016
5054
|
function redo() {
|
|
4017
5055
|
if (stack.length === 0) return void 0;
|
|
4018
5056
|
const item = stack.pop();
|
|
5057
|
+
if (registry.size >= size) {
|
|
5058
|
+
const oldest = registry.seek("first");
|
|
5059
|
+
if (overflow.length === size) overflow.shift();
|
|
5060
|
+
overflow.push(oldest);
|
|
5061
|
+
registry.unregister(oldest.id);
|
|
5062
|
+
}
|
|
4019
5063
|
const ticket = registry.register(item);
|
|
4020
5064
|
registry.reindex();
|
|
4021
5065
|
return ticket;
|
|
@@ -4093,31 +5137,27 @@ function useTimeline(namespace = "v0:timeline") {
|
|
|
4093
5137
|
* @module createValidation
|
|
4094
5138
|
*
|
|
4095
5139
|
* @remarks
|
|
4096
|
-
* Per-
|
|
5140
|
+
* Per-input validation composable built on createGroup.
|
|
4097
5141
|
*
|
|
4098
5142
|
* Key features:
|
|
5143
|
+
* - Each ticket is a rule — enable/disable via select/unselect
|
|
4099
5144
|
* - Auto-register with parent form via useForm() injection
|
|
4100
5145
|
* - Async rule support with generation-based race safety
|
|
4101
5146
|
* - Silent validation mode
|
|
4102
5147
|
* - Tri-state isValid (null/true/false)
|
|
4103
|
-
* - isPristine tracking
|
|
4104
5148
|
*
|
|
4105
5149
|
* Uses useRules() to resolve alias strings via shared context.
|
|
4106
5150
|
*/
|
|
5151
|
+
const UNSET = Symbol("unset");
|
|
4107
5152
|
/**
|
|
4108
|
-
*
|
|
4109
|
-
*
|
|
4110
|
-
*
|
|
4111
|
-
|
|
4112
|
-
|
|
4113
|
-
if (context) return context.resolve(raw);
|
|
4114
|
-
return raw.filter((r) => /* @__PURE__ */ isFunction(r) || isStandardSchema(r)).map((r) => isStandardSchema(r) ? toRule(r) : r);
|
|
4115
|
-
}
|
|
4116
|
-
/**
|
|
4117
|
-
* Creates a new validation instance.
|
|
5153
|
+
* Creates a per-input validation instance.
|
|
5154
|
+
*
|
|
5155
|
+
* Built on `createGroup` — each registered rule becomes a ticket that can be
|
|
5156
|
+
* enabled/disabled via selection methods (`select`, `unselect`, `toggle`).
|
|
5157
|
+
* Only selected (active) rules run during validation.
|
|
4118
5158
|
*
|
|
4119
5159
|
* @param options The options for the validation instance.
|
|
4120
|
-
* @returns A new validation context
|
|
5160
|
+
* @returns A new validation context.
|
|
4121
5161
|
*
|
|
4122
5162
|
* @see https://0.vuetifyjs.com/composables/forms/create-validation
|
|
4123
5163
|
*
|
|
@@ -4125,111 +5165,83 @@ function resolveRules(raw, context) {
|
|
|
4125
5165
|
* ```ts
|
|
4126
5166
|
* import { createValidation } from '@vuetify/v0'
|
|
4127
5167
|
*
|
|
4128
|
-
* const validation = createValidation(
|
|
4129
|
-
*
|
|
4130
|
-
*
|
|
4131
|
-
*
|
|
4132
|
-
*
|
|
4133
|
-
* rules: [(v) => !!v || 'Required'],
|
|
5168
|
+
* const validation = createValidation({
|
|
5169
|
+
* rules: [
|
|
5170
|
+
* v => !!v || 'Required',
|
|
5171
|
+
* v => /^.+@\S+\.\S+$/.test(String(v)) || 'Invalid email',
|
|
5172
|
+
* ],
|
|
4134
5173
|
* })
|
|
4135
5174
|
*
|
|
4136
|
-
* await
|
|
5175
|
+
* await validation.validate('')
|
|
4137
5176
|
*
|
|
4138
|
-
* console.log(
|
|
5177
|
+
* console.log(validation.errors.value) // ['Required', 'Invalid email']
|
|
4139
5178
|
*
|
|
4140
|
-
*
|
|
5179
|
+
* validation.reset()
|
|
4141
5180
|
* ```
|
|
4142
5181
|
*/
|
|
4143
|
-
function createValidation(
|
|
4144
|
-
const
|
|
4145
|
-
const
|
|
4146
|
-
|
|
4147
|
-
|
|
4148
|
-
|
|
5182
|
+
function createValidation(_options = {}) {
|
|
5183
|
+
const { rules: initialRules = [], value: valueSource, enroll = true, ...options } = _options;
|
|
5184
|
+
const group = createGroup({
|
|
5185
|
+
...options,
|
|
5186
|
+
enroll,
|
|
5187
|
+
multiple: true
|
|
4149
5188
|
});
|
|
4150
|
-
const
|
|
4151
|
-
|
|
4152
|
-
|
|
4153
|
-
|
|
4154
|
-
|
|
4155
|
-
|
|
4156
|
-
|
|
5189
|
+
const rulesContext = useRules();
|
|
5190
|
+
const errors = shallowRef([]);
|
|
5191
|
+
const isValid = shallowRef(null);
|
|
5192
|
+
const isValidating = shallowRef(false);
|
|
5193
|
+
let generation = 0;
|
|
5194
|
+
function register(input) {
|
|
5195
|
+
if (/* @__PURE__ */ isFunction(input) || /* @__PURE__ */ isString(input) || isStandardSchema(input)) {
|
|
5196
|
+
const resolved = rulesContext.resolve([input]);
|
|
5197
|
+
return group.register({ value: resolved[0] ?? (() => true) });
|
|
4157
5198
|
}
|
|
4158
|
-
|
|
4159
|
-
|
|
4160
|
-
|
|
4161
|
-
|
|
4162
|
-
|
|
4163
|
-
|
|
4164
|
-
const
|
|
4165
|
-
const
|
|
4166
|
-
const
|
|
4167
|
-
|
|
4168
|
-
|
|
4169
|
-
|
|
4170
|
-
model.value = initialValue;
|
|
4171
|
-
errors.value = [];
|
|
4172
|
-
isPristine.value = true;
|
|
4173
|
-
isFieldValid.value = null;
|
|
4174
|
-
isFieldValidating.value = false;
|
|
4175
|
-
validationGeneration++;
|
|
5199
|
+
return group.register(input);
|
|
5200
|
+
}
|
|
5201
|
+
function onboard(rules) {
|
|
5202
|
+
return group.batch(() => rules.map((r) => register(r)));
|
|
5203
|
+
}
|
|
5204
|
+
async function validate(_value = UNSET, silent = false) {
|
|
5205
|
+
const val = _value === UNSET ? toValue(valueSource) : _value;
|
|
5206
|
+
const activeRules = [];
|
|
5207
|
+
for (const ticket of group.selectedItems.value) activeRules.push(ticket.value);
|
|
5208
|
+
if (activeRules.length === 0) {
|
|
5209
|
+
if (!silent) isValid.value = true;
|
|
5210
|
+
return true;
|
|
4176
5211
|
}
|
|
4177
|
-
|
|
4178
|
-
|
|
4179
|
-
|
|
4180
|
-
const
|
|
4181
|
-
|
|
4182
|
-
|
|
4183
|
-
|
|
4184
|
-
|
|
4185
|
-
|
|
4186
|
-
if (!silent) {
|
|
4187
|
-
errors.value = errorMessages;
|
|
4188
|
-
isFieldValid.value = errorMessages.length === 0;
|
|
4189
|
-
isPristine.value = model.value === initialValue;
|
|
4190
|
-
}
|
|
4191
|
-
return errorMessages.length === 0;
|
|
4192
|
-
} finally {
|
|
4193
|
-
if (generation === validationGeneration) isFieldValidating.value = false;
|
|
5212
|
+
const gen = ++generation;
|
|
5213
|
+
if (!silent) isValidating.value = true;
|
|
5214
|
+
try {
|
|
5215
|
+
const results = await Promise.all(activeRules.map((rule) => rule(val)));
|
|
5216
|
+
if (gen !== generation) return isValid.value ?? false;
|
|
5217
|
+
const errorMessages = results.filter((result) => /* @__PURE__ */ isString(result) || result === false).map((result) => result === false ? "Validation failed" : result);
|
|
5218
|
+
if (!silent) {
|
|
5219
|
+
errors.value = errorMessages;
|
|
5220
|
+
isValid.value = errorMessages.length === 0;
|
|
4194
5221
|
}
|
|
5222
|
+
return errorMessages.length === 0;
|
|
5223
|
+
} finally {
|
|
5224
|
+
if (gen === generation && !silent) isValidating.value = false;
|
|
4195
5225
|
}
|
|
4196
|
-
const item = {
|
|
4197
|
-
...registration,
|
|
4198
|
-
rules: resolved,
|
|
4199
|
-
errors,
|
|
4200
|
-
disabled: registration.disabled || false,
|
|
4201
|
-
isValidating: isFieldValidating,
|
|
4202
|
-
isPristine,
|
|
4203
|
-
isValid: isFieldValid,
|
|
4204
|
-
reset,
|
|
4205
|
-
validate
|
|
4206
|
-
};
|
|
4207
|
-
const ticket = registry.register(item);
|
|
4208
|
-
Object.defineProperty(ticket, "value", {
|
|
4209
|
-
get() {
|
|
4210
|
-
return model.value;
|
|
4211
|
-
},
|
|
4212
|
-
set(val) {
|
|
4213
|
-
model.value = val;
|
|
4214
|
-
isPristine.value = val === initialValue;
|
|
4215
|
-
isFieldValid.value = null;
|
|
4216
|
-
},
|
|
4217
|
-
enumerable: true,
|
|
4218
|
-
configurable: true
|
|
4219
|
-
});
|
|
4220
|
-
return ticket;
|
|
4221
5226
|
}
|
|
4222
|
-
function
|
|
4223
|
-
|
|
5227
|
+
function reset() {
|
|
5228
|
+
errors.value = [];
|
|
5229
|
+
isValid.value = null;
|
|
5230
|
+
isValidating.value = false;
|
|
5231
|
+
generation++;
|
|
4224
5232
|
}
|
|
5233
|
+
if (initialRules.length > 0) onboard(initialRules);
|
|
4225
5234
|
const context = {
|
|
4226
|
-
...
|
|
5235
|
+
...group,
|
|
4227
5236
|
register,
|
|
4228
5237
|
onboard,
|
|
5238
|
+
validate,
|
|
5239
|
+
reset,
|
|
5240
|
+
errors,
|
|
4229
5241
|
isValid,
|
|
4230
5242
|
isValidating,
|
|
4231
5243
|
get size() {
|
|
4232
|
-
return
|
|
5244
|
+
return group.size;
|
|
4233
5245
|
}
|
|
4234
5246
|
};
|
|
4235
5247
|
const form = useForm();
|
|
@@ -4684,6 +5696,80 @@ function useVirtual(namespace = "v0:virtual") {
|
|
|
4684
5696
|
return useContext(namespace);
|
|
4685
5697
|
}
|
|
4686
5698
|
//#endregion
|
|
5699
|
+
//#region src/composables/useVirtualFocus/index.ts
|
|
5700
|
+
/**
|
|
5701
|
+
* @module useVirtualFocus
|
|
5702
|
+
*
|
|
5703
|
+
* @remarks
|
|
5704
|
+
* Virtual focus composable for aria-activedescendant keyboard navigation.
|
|
5705
|
+
* DOM focus stays on a control element while a virtual cursor highlights
|
|
5706
|
+
* items in a list.
|
|
5707
|
+
*
|
|
5708
|
+
* Key features:
|
|
5709
|
+
* - Arrow key navigation with orientation support
|
|
5710
|
+
* - Grid mode for 2D navigation
|
|
5711
|
+
* - Automatic disabled item skipping
|
|
5712
|
+
* - Optional circular navigation
|
|
5713
|
+
* - Home/End key support (row-scoped in grid mode)
|
|
5714
|
+
* - Auto-attaches keydown listener when target is provided
|
|
5715
|
+
* - Sets aria-activedescendant and data-highlighted attributes
|
|
5716
|
+
*
|
|
5717
|
+
* Perfect for comboboxes, autocompletes, listboxes, and other widgets
|
|
5718
|
+
* where DOM focus must remain on the control element.
|
|
5719
|
+
*/
|
|
5720
|
+
function useVirtualFocus(items, options) {
|
|
5721
|
+
const { control, target, orientation, circular, columns, onHighlight } = options;
|
|
5722
|
+
let previousEl = null;
|
|
5723
|
+
function applyHighlight(id) {
|
|
5724
|
+
const item = items().find((i) => i.id === id);
|
|
5725
|
+
if (!item?.el) return false;
|
|
5726
|
+
const el = toValue(item.el);
|
|
5727
|
+
if (!el) return false;
|
|
5728
|
+
const controlEl = toValue(control);
|
|
5729
|
+
if (controlEl) {
|
|
5730
|
+
const itemId = el.getAttribute("id");
|
|
5731
|
+
if (itemId) controlEl.setAttribute("aria-activedescendant", itemId);
|
|
5732
|
+
}
|
|
5733
|
+
if (previousEl) delete previousEl.dataset.highlighted;
|
|
5734
|
+
el.dataset.highlighted = "";
|
|
5735
|
+
previousEl = el;
|
|
5736
|
+
el.scrollIntoView({ block: "nearest" });
|
|
5737
|
+
onHighlight?.(id);
|
|
5738
|
+
return true;
|
|
5739
|
+
}
|
|
5740
|
+
const traversal = createFocusTraversal(items, (id) => applyHighlight(id), {
|
|
5741
|
+
orientation,
|
|
5742
|
+
circular,
|
|
5743
|
+
columns
|
|
5744
|
+
});
|
|
5745
|
+
function highlight(id) {
|
|
5746
|
+
const prev = traversal.activeId.value;
|
|
5747
|
+
traversal.activeId.value = id;
|
|
5748
|
+
if (!applyHighlight(id)) traversal.activeId.value = prev;
|
|
5749
|
+
}
|
|
5750
|
+
function clear() {
|
|
5751
|
+
traversal.activeId.value = void 0;
|
|
5752
|
+
const controlEl = toValue(control);
|
|
5753
|
+
if (controlEl) controlEl.removeAttribute("aria-activedescendant");
|
|
5754
|
+
if (previousEl) {
|
|
5755
|
+
delete previousEl.dataset.highlighted;
|
|
5756
|
+
previousEl = null;
|
|
5757
|
+
}
|
|
5758
|
+
}
|
|
5759
|
+
const listener = target ?? control;
|
|
5760
|
+
if (listener) useEventListener(listener, "keydown", traversal.onKeydown);
|
|
5761
|
+
return {
|
|
5762
|
+
highlightedId: traversal.activeId,
|
|
5763
|
+
highlight,
|
|
5764
|
+
clear,
|
|
5765
|
+
next: traversal.next,
|
|
5766
|
+
prev: traversal.prev,
|
|
5767
|
+
first: traversal.first,
|
|
5768
|
+
last: traversal.last,
|
|
5769
|
+
onKeydown: traversal.onKeydown
|
|
5770
|
+
};
|
|
5771
|
+
}
|
|
5772
|
+
//#endregion
|
|
4687
5773
|
//#region src/composables/useEventListener/index.ts
|
|
4688
5774
|
/**
|
|
4689
5775
|
* @module useEventListener
|
|
@@ -5029,4 +6115,4 @@ function useClickOutside(target, handler, options = {}) {
|
|
|
5029
6115
|
};
|
|
5030
6116
|
}
|
|
5031
6117
|
//#endregion
|
|
5032
|
-
export {
|
|
6118
|
+
export { useTimer as $, useRtl as A, createQueueContext as B, createStackPlugin as C, createHydration as Ct, createRtlContext as D, createBreadcrumbs as Dt, createRtl as E, useHydration as Et, createNotifications as F, multipleOpenStrategy as G, createNested as H, createNotificationsContext as I, useMediaQuery as J, singleOpenStrategy as K, createNotificationsPlugin as L, useRovingFocus as M, useRaf as N, createRtlFallback as O, createBreadcrumbsContext as Ot, usePopover as P, useLazy as Q, useNotifications as R, createStackContext as S, createFallbackHydration as St, createSlider as T, createHydrationPlugin as Tt, createNestedContext as U, useQueue as V, useNested as W, usePrefersDark as X, usePrefersContrast as Y, usePrefersReducedMotion as Z, useStorage as _, createOverflowContext as _t, useVirtualFocus as a, useForm as at, useStep as b, useResizeObserver as bt, useVirtual as c, createDatePlugin as ct, createTimeline as d, createBreakpointsContext as dt, useElementIntersection as et, createTimelineContext as f, createBreakpointsPlugin as ft, createStoragePlugin as g, createOverflow as gt, createStorageContext as h, useProxyModel as ht, useWindowEventListener as i, createFormContext as it, Vuetify0RtlAdapter as j, createRtlPlugin as k, useBreadcrumbs as kt, useToggleScope as l, useDate as lt, createStorage as m, toReactive as mt, useDocumentEventListener as n, useHotkey as nt, createVirtual as o, createDate as ot, useTimeline as p, useBreakpoints as pt, useMutationObserver as q, useEventListener as r, createForm as rt, createVirtualContext as s, createDateContext as st, useClickOutside as t, useIntersectionObserver as tt, createValidation as u, createBreakpoints as ut, createStep as v, useOverflow as vt, useStack as w, createHydrationContext as wt, createStack as x, toElement as xt, createStepContext as y, useElementSize as yt, createQueue as z };
|