@vuetify/v0 0.0.3 → 0.0.6

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.
Files changed (35) hide show
  1. package/dist/browser/index.js +2698 -1483
  2. package/dist/components/index.d.ts +4 -7
  3. package/dist/components/index.js +6 -7
  4. package/dist/{components-DVuB4lnH.js → components-B5k361i-.js} +164 -8
  5. package/dist/composables/index.d.ts +3 -7
  6. package/dist/composables/index.js +4 -7
  7. package/dist/composables-CAbYjAkR.js +3746 -0
  8. package/dist/constants/index.d.ts +1 -1
  9. package/dist/constants/index.js +3 -3
  10. package/dist/{globals-DZvNEOB4.js → globals-CHVv7nNV.js} +2 -2
  11. package/dist/{htmlElements-SjqYu0am.js → htmlElements-lF7PGahL.js} +1 -1
  12. package/dist/{index-DVKeyWc5.d.ts → index-BKc0YiL1.d.ts} +2 -2
  13. package/dist/index-BQfe0WBZ.d.ts +410 -0
  14. package/dist/index-BhPlroXd.d.ts +2764 -0
  15. package/dist/{index-LBy5OPMu.d.ts → index-C_lAPFXS.d.ts} +1 -1
  16. package/dist/{index-BozA2pze.d.ts → index-DIX3zaZG.d.ts} +3 -10
  17. package/dist/index.d.ts +6 -7
  18. package/dist/index.js +7 -10
  19. package/dist/types/index.d.ts +1 -1
  20. package/dist/utilities/index.d.ts +3 -3
  21. package/dist/utilities/index.js +2 -2
  22. package/dist/{utilities-D9rWEgQK.js → utilities-rsKHgU2m.js} +5 -32
  23. package/package.json +1 -3
  24. package/dist/composables-yeVk-ULz.js +0 -1270
  25. package/dist/factories/index.d.ts +0 -2
  26. package/dist/factories/index.js +0 -3
  27. package/dist/factories-BEpawPUw.js +0 -96
  28. package/dist/index-Ckt12ON6.d.ts +0 -75
  29. package/dist/index-D0L_ydyW.d.ts +0 -1396
  30. package/dist/index-tUyghL98.d.ts +0 -19
  31. package/dist/transformers/index.d.ts +0 -2
  32. package/dist/transformers/index.js +0 -4
  33. package/dist/transformers-CWrxLIkw.js +0 -122
  34. package/dist/useTheme-DCXkw_kv.js +0 -1208
  35. /package/dist/{constants-DiTCgvMU.js → constants-De5c3_aB.js} +0 -0
@@ -0,0 +1,3746 @@
1
+ import { a as isNullOrUndefined, d as mergeDeep, i as isFunction, l as isString, n as isArray, r as isBoolean, s as isObject, t as genId, u as isUndefined } from "./utilities-rsKHgU2m.js";
2
+ import { a as SUPPORTS_OBSERVER, i as SUPPORTS_MUTATION_OBSERVER, n as SUPPORTS_INTERSECTION_OBSERVER, s as __LOGGER_ENABLED__, t as IN_BROWSER } from "./globals-CHVv7nNV.js";
3
+ import { computed, getCurrentInstance, getCurrentScope, inject, isRef, onMounted, onScopeDispose, onUnmounted, provide, reactive, readonly, ref, shallowReactive, shallowReadonly, shallowRef, toRef, toValue, unref, watch } from "vue";
4
+
5
+ //#region src/composables/createContext/index.ts
6
+ /**
7
+ * Injects a context provided by an ancestor component.
8
+ *
9
+ * @param key The key of the context to inject.
10
+ * @template Z The type of the context.
11
+ * @returns The injected context.
12
+ * @throws An error if the context is not found.
13
+ *
14
+ * @see https://vuejs.org/api/composition-api-dependency-injection.html#inject
15
+ * @see https://0.vuetifyjs.com/composables/foundation/create-context
16
+ *
17
+ * @example
18
+ * ```ts
19
+ * const myContext = useContext<MyContext>('my-context')
20
+ * ```
21
+ */
22
+ function useContext(key) {
23
+ const context = inject(key, void 0);
24
+ if (context === void 0) throw new Error(`Context "${String(key)}" not found. Ensure it's provided by an ancestor.`);
25
+ return context;
26
+ }
27
+ /**
28
+ * Provides a context to all descendant components.
29
+ *
30
+ * @param key The key of the context to provide.
31
+ * @param context The context to provide.
32
+ * @param app The Vue app instance to provide the context to.
33
+ * @template Z The type of the context.
34
+ * @returns The provided context.
35
+ *
36
+ * @see https://vuejs.org/api/composition-api-dependency-injection.html#provide
37
+ * @see https://0.vuetifyjs.com/composables/foundation/create-context
38
+ *
39
+ * @example
40
+ * ```ts
41
+ * provideContext<MyContext>('my-context', myContext)
42
+ * ```
43
+ */
44
+ function provideContext(key, context, app) {
45
+ app?.provide(key, context) ?? provide(key, context);
46
+ return context;
47
+ }
48
+ /**
49
+ * Creates a new context for providing and injecting data.
50
+ *
51
+ * @param key The key of the context to create.
52
+ * @template Z The type of the context.
53
+ * @returns A tuple containing the `useContext` and `provideContext` functions.
54
+ *
55
+ * @see https://vuejs.org/api/composition-api-dependency-injection.html
56
+ * @see https://0.vuetifyjs.com/composables/foundation/create-context
57
+ *
58
+ * @example
59
+ * ```ts
60
+ * const [provideMyContext, useMyContext] = createContext<MyContext>('my-context')
61
+ * ```
62
+ */
63
+ function createContext(_key) {
64
+ function _provideContext(context, app) {
65
+ return provideContext(_key, context, app);
66
+ }
67
+ function _useContext(key = _key) {
68
+ return useContext(key);
69
+ }
70
+ return [_useContext, _provideContext];
71
+ }
72
+
73
+ //#endregion
74
+ //#region src/composables/createPlugin/index.ts
75
+ /**
76
+ * Creates a new Vue plugin.
77
+ *
78
+ * @param options The plugin options.
79
+ * @returns A new Vue plugin.
80
+ *
81
+ * @see https://vuejs.org/guide/reusability/plugins.html
82
+ * @see https://0.vuetifyjs.com/composables/foundation/create-plugin
83
+ *
84
+ * @example
85
+ * ```ts
86
+ * export const [useContext, provideContext] = createContext<MyContext>('my-plugin')
87
+ *
88
+ * const context = {}
89
+ *
90
+ * export const MyPlugin = createPlugin({
91
+ * namespace: 'my-plugin',
92
+ * provide: (app) => {
93
+ * provideContext(context, app)
94
+ * },
95
+ * setup: (app) => {
96
+ * // Optional setup logic
97
+ * },
98
+ * })
99
+ */
100
+ function createPlugin(options) {
101
+ return { install(app) {
102
+ app.runWithContext(() => {
103
+ options.provide(app);
104
+ options.setup?.(app);
105
+ });
106
+ } };
107
+ }
108
+
109
+ //#endregion
110
+ //#region src/composables/createTrinity/index.ts
111
+ /**
112
+ * Creates a new trinity for a context composable and its provider.
113
+ *
114
+ * @param createContext The function that creates the context.
115
+ * @param provideContext The function that provides the context.
116
+ * @param context The context to provide.
117
+ * @template Z The type of the context.
118
+ * @returns A new trinity.
119
+ *
120
+ * @see https://0.vuetifyjs.com/composables/foundation/create-trinity
121
+ *
122
+ * @example
123
+ * ```ts
124
+ * interface MyContext {
125
+ * foo: string
126
+ * bar: number
127
+ * }
128
+ *
129
+ * export function createMyFeature<E extends MyContext = MyContext>() {
130
+ * const [useContext, _provideContext] = createContext<E>('my-context')
131
+ *
132
+ * const context = { foo: 'hello', bar: 42 }
133
+ *
134
+ * function provideContext (_context: E = context, app?: App): E {
135
+ * return _provideContext(_context, app)
136
+ * }
137
+ *
138
+ * return createTrinity<E>(useContext, provideContext, context)
139
+ * }
140
+ */
141
+ function createTrinity(createContext$1, provideContext$1, context) {
142
+ return [
143
+ createContext$1,
144
+ (_context = context, app) => provideContext$1(_context, app),
145
+ context
146
+ ];
147
+ }
148
+
149
+ //#endregion
150
+ //#region src/composables/toArray/index.ts
151
+ /**
152
+ * Converts a value to an array.
153
+ *
154
+ * @param value The value to convert.
155
+ * @template Z The type of the value.
156
+ * @returns The converted array.
157
+ *
158
+ * @see https://0.vuetifyjs.com/composables/transformers/to-array
159
+ *
160
+ * @example
161
+ * ```ts
162
+ * import { toArray } from '@vuetify/v0'
163
+ *
164
+ * const value = 'Example Value'
165
+ * const valueAsArray = toArray(value)
166
+ *
167
+ * console.log(valueAsArray) // ['Example Value']
168
+ * ```
169
+ */
170
+ function toArray(value) {
171
+ return /* @__PURE__ */ isNullOrUndefined(value) ? [] : Array.isArray(value) ? value : [value];
172
+ }
173
+
174
+ //#endregion
175
+ //#region src/composables/toReactive/index.ts
176
+ /**
177
+ * Converts a `MaybeRef` to a `UnwrapNestedRefs`.
178
+ *
179
+ * @param objectRef The object to convert.
180
+ * @template Z The type of the object.
181
+ * @returns The converted object.
182
+ *
183
+ * @see https://vuejs.org/api/reactivity-utilities.html#toreactive
184
+ *
185
+ * @example
186
+ * ```ts
187
+ * import { ref } from 'vue'
188
+ * import { toReactive } from '@vuetify/v0'
189
+ *
190
+ * const state = ref({ name: 'John', age: 30 })
191
+ * const rstate = toReactive(state)
192
+ *
193
+ * console.log(rstate.name) // John
194
+ * ```
195
+ */
196
+ function toReactive(objectRef) {
197
+ if (!isRef(objectRef)) return reactive(objectRef);
198
+ const target = objectRef.value;
199
+ if (target instanceof Map) {
200
+ const mapProxy = new Proxy(/* @__PURE__ */ new Map(), { get(_, p) {
201
+ const map = objectRef.value;
202
+ if (p === "get") return (key) => unref(map.get(key));
203
+ if (p === "set") return (key, value) => {
204
+ const existingValue = map.get(key);
205
+ if (isRef(existingValue)) existingValue.value = unref(value);
206
+ else map.set(key, value);
207
+ return mapProxy;
208
+ };
209
+ if (p === "has") return (key) => map.has(key);
210
+ if (p === "delete") return (key) => map.delete(key);
211
+ if (p === "clear") return () => map.clear();
212
+ if (p === "size") return map.size;
213
+ if (p === "keys") return () => map.keys();
214
+ if (p === "values") return function* () {
215
+ for (const value of map.values()) yield unref(value);
216
+ };
217
+ if (p === "entries") return function* () {
218
+ for (const [key, value] of map.entries()) yield [key, unref(value)];
219
+ };
220
+ if (p === "forEach") return (callback, thisArg) => {
221
+ for (const [key, value] of map.entries()) callback.call(thisArg, unref(value), key, mapProxy);
222
+ };
223
+ if (p === Symbol.iterator) return function* () {
224
+ for (const [key, value] of map.entries()) yield [key, unref(value)];
225
+ };
226
+ return Reflect.get(map, p);
227
+ } });
228
+ return reactive(mapProxy);
229
+ }
230
+ if (target instanceof Set) {
231
+ const setProxy = new Proxy(/* @__PURE__ */ new Set(), { get(_, p) {
232
+ const set = objectRef.value;
233
+ if (p === "add") return (value) => {
234
+ set.add(value);
235
+ return setProxy;
236
+ };
237
+ if (p === "has") return (value) => set.has(value);
238
+ if (p === "delete") return (value) => set.delete(value);
239
+ if (p === "clear") return () => set.clear();
240
+ if (p === "size") return set.size;
241
+ if (p === "keys" || p === "values") return function* () {
242
+ for (const value of set.values()) yield unref(value);
243
+ };
244
+ if (p === "entries") return function* () {
245
+ for (const value of set.values()) {
246
+ const unreffedValue = unref(value);
247
+ yield [unreffedValue, unreffedValue];
248
+ }
249
+ };
250
+ if (p === "forEach") return (callback, thisArg) => {
251
+ for (const value of set) {
252
+ const unreffedValue = unref(value);
253
+ callback.call(thisArg, unreffedValue, unreffedValue, setProxy);
254
+ }
255
+ };
256
+ if (p === Symbol.iterator) return function* () {
257
+ for (const value of set.values()) yield unref(value);
258
+ };
259
+ return Reflect.get(set, p);
260
+ } });
261
+ return reactive(setProxy);
262
+ }
263
+ return reactive(new Proxy({}, {
264
+ get(_, p, receiver) {
265
+ return unref(Reflect.get(objectRef.value, p, receiver));
266
+ },
267
+ set(_, p, value) {
268
+ const currentTarget = objectRef.value;
269
+ currentTarget[p] = value;
270
+ return true;
271
+ },
272
+ deleteProperty(_, p) {
273
+ return Reflect.deleteProperty(objectRef.value, p);
274
+ },
275
+ has(_, p) {
276
+ return Reflect.has(objectRef.value, p);
277
+ },
278
+ ownKeys() {
279
+ return Object.keys(objectRef.value);
280
+ },
281
+ getOwnPropertyDescriptor(_, p) {
282
+ const desc = Reflect.getOwnPropertyDescriptor(objectRef.value, p);
283
+ if (!desc) return;
284
+ const newDesc = {
285
+ ...desc,
286
+ configurable: true
287
+ };
288
+ if ("value" in newDesc) newDesc.value = unref(newDesc.value);
289
+ return newDesc;
290
+ }
291
+ }));
292
+ }
293
+
294
+ //#endregion
295
+ //#region src/composables/useHydration/index.ts
296
+ const [useHydrationContext, provideHydrationContext] = createContext("v0:hydration");
297
+ /**
298
+ * Creates a new hydration instance.
299
+ *
300
+ * @returns A new hydration instance.
301
+ *
302
+ * @see https://0.vuetifyjs.com/composables/plugins/use-hydration
303
+ *
304
+ * @example
305
+ * ```ts
306
+ * import { createHydration } from '@vuetify/v0'
307
+ *
308
+ * const [useHydration, provideHydration] = createHydration()
309
+ * ```
310
+ */
311
+ function createHydration() {
312
+ const isHydrated = shallowRef(false);
313
+ function hydrate() {
314
+ isHydrated.value = true;
315
+ }
316
+ return {
317
+ isHydrated: shallowReadonly(isHydrated),
318
+ hydrate
319
+ };
320
+ }
321
+ /**
322
+ * Returns the current hydration instance.
323
+ *
324
+ * @returns The current hydration instance.
325
+ *
326
+ * @see https://0.vuetifyjs.com/composables/plugins/use-hydration
327
+ *
328
+ * @example
329
+ * ```vue
330
+ * <script setup lang="ts">
331
+ * import { useHydration } from '@vuetify/v0'
332
+ *
333
+ * const hydration = useHydration()
334
+ * <\/script>
335
+ *
336
+ * <template>
337
+ * <div>
338
+ * <p>Is hydrated: {{ hydration.isHydrated.value }}</p>
339
+ * </div>
340
+ * </template>
341
+ * ```
342
+ */
343
+ function useHydration() {
344
+ return useHydrationContext();
345
+ }
346
+ /**
347
+ * Creates a new hydration plugin.
348
+ *
349
+ * @returns A new hydration plugin.
350
+ *
351
+ * @see https://0.vuetifyjs.com/composables/plugins/use-hydration
352
+ *
353
+ * @example
354
+ * ```ts
355
+ * import { createApp } from 'vue'
356
+ * import { createHydrationPlugin } from '@vuetify/v0'
357
+ * import App from './App.vue'
358
+ *
359
+ * const plugin = createHydrationPlugin()
360
+ *
361
+ * const app = createApp(App)
362
+ *
363
+ * app.use(plugin)
364
+ *
365
+ * app.mount('#app')
366
+ * ```
367
+ */
368
+ function createHydrationPlugin() {
369
+ const context = createHydration();
370
+ return createPlugin({
371
+ namespace: "v0:hydration",
372
+ provide: (app) => {
373
+ provideHydrationContext(context, app);
374
+ },
375
+ setup: (app) => {
376
+ app.mixin({ mounted() {
377
+ if (this.$parent !== null) return;
378
+ context.hydrate();
379
+ } });
380
+ }
381
+ });
382
+ }
383
+
384
+ //#endregion
385
+ //#region src/composables/useBreakpoints/index.ts
386
+ /**
387
+ * Creates default breakpoint configuration.
388
+ *
389
+ * @returns The default breakpoint configuration object.
390
+ */
391
+ function createDefaultBreakpoints() {
392
+ return {
393
+ mobileBreakpoint: "md",
394
+ breakpoints: {
395
+ xs: 0,
396
+ sm: 600,
397
+ md: 960,
398
+ lg: 1280,
399
+ xl: 1920,
400
+ xxl: 2560
401
+ }
402
+ };
403
+ }
404
+ /**
405
+ * Creates a new breakpoints instance.
406
+ *
407
+ * @param namespace The namespace to use for the breakpoints instance.
408
+ * @param options The options for the breakpoints instance.
409
+ * @template E The type of the breakpoints context.
410
+ * @returns A new breakpoints instance.
411
+ *
412
+ * @see https://0.vuetifyjs.com/composables/plugins/use-breakpoints
413
+ *
414
+ * @example
415
+ * ```ts
416
+ * import { createBreakpoints } from '@vuetify/v0'
417
+ *
418
+ * export const [useBreakpoints, provideBreakpoints] = createBreakpoints('v0:breakpoints', {
419
+ * mobileBreakpoint: 'sm',
420
+ * breakpoints: {
421
+ * xs: 0,
422
+ * sm: 680,
423
+ * md: 1024,
424
+ * lg: 1280,
425
+ * xl: 1920,
426
+ * xxl: 2560,
427
+ * },
428
+ * })
429
+ * ```
430
+ */
431
+ function createBreakpoints(namespace = "v0:breakpoints", options = {}) {
432
+ const [useBreakpointsContext, _provideBreakpointsContext] = createContext(namespace);
433
+ const { mobileBreakpoint, breakpoints } = /* @__PURE__ */ mergeDeep(createDefaultBreakpoints(), options);
434
+ const sorted = Object.entries(breakpoints).sort((a, b) => a[1] - b[1]);
435
+ const names = sorted.map(([n]) => n);
436
+ const mb = typeof mobileBreakpoint === "number" ? mobileBreakpoint : breakpoints[mobileBreakpoint] ?? breakpoints.md;
437
+ const name = shallowRef("xs");
438
+ const width = shallowRef(0);
439
+ const height = shallowRef(0);
440
+ const isMobile = shallowRef(true);
441
+ const xs = shallowRef(true);
442
+ const sm = shallowRef(false);
443
+ const md = shallowRef(false);
444
+ const lg = shallowRef(false);
445
+ const xl = shallowRef(false);
446
+ const xxl = shallowRef(false);
447
+ const smAndUp = shallowRef(false);
448
+ const mdAndUp = shallowRef(false);
449
+ const lgAndUp = shallowRef(false);
450
+ const xlAndUp = shallowRef(false);
451
+ const xxlAndUp = shallowRef(false);
452
+ const smAndDown = shallowRef(true);
453
+ const mdAndDown = shallowRef(true);
454
+ const lgAndDown = shallowRef(true);
455
+ const xlAndDown = shallowRef(true);
456
+ const xxlAndDown = shallowRef(true);
457
+ function update() {
458
+ if (!IN_BROWSER) return;
459
+ width.value = window.innerWidth;
460
+ height.value = window.innerHeight;
461
+ let current = "xs";
462
+ for (let i = sorted.length - 1; i >= 0; i--) if (width.value >= sorted[i][1]) {
463
+ current = sorted[i][0];
464
+ break;
465
+ }
466
+ name.value = current;
467
+ const index = names.indexOf(current);
468
+ isMobile.value = width.value < mb;
469
+ xs.value = index === 0;
470
+ sm.value = index === 1;
471
+ md.value = index === 2;
472
+ lg.value = index === 3;
473
+ xl.value = index === 4;
474
+ xxl.value = index === 5;
475
+ smAndUp.value = index >= 1;
476
+ mdAndUp.value = index >= 2;
477
+ lgAndUp.value = index >= 3;
478
+ xlAndUp.value = index >= 4;
479
+ xxlAndUp.value = index >= 5;
480
+ smAndDown.value = index <= 1;
481
+ mdAndDown.value = index <= 2;
482
+ lgAndDown.value = index <= 3;
483
+ xlAndDown.value = index <= 4;
484
+ xxlAndDown.value = index <= 5;
485
+ }
486
+ if (getCurrentInstance()) onMounted(() => {
487
+ const { isHydrated } = useHydration();
488
+ if (isHydrated.value) update();
489
+ watch(isHydrated, (hydrated) => {
490
+ if (hydrated) update();
491
+ }, { immediate: true });
492
+ });
493
+ if (IN_BROWSER) {
494
+ function listener() {
495
+ update();
496
+ }
497
+ window.addEventListener("resize", listener, { passive: true });
498
+ onScopeDispose(() => window.removeEventListener("resize", listener), true);
499
+ }
500
+ const context = {
501
+ breakpoints,
502
+ name: readonly(name),
503
+ width: readonly(width),
504
+ height: readonly(height),
505
+ isMobile: readonly(isMobile),
506
+ xs: readonly(xs),
507
+ sm: readonly(sm),
508
+ md: readonly(md),
509
+ lg: readonly(lg),
510
+ xl: readonly(xl),
511
+ xxl: readonly(xxl),
512
+ smAndUp: readonly(smAndUp),
513
+ mdAndUp: readonly(mdAndUp),
514
+ lgAndUp: readonly(lgAndUp),
515
+ xlAndUp: readonly(xlAndUp),
516
+ xxlAndUp: readonly(xxlAndUp),
517
+ smAndDown: readonly(smAndDown),
518
+ mdAndDown: readonly(mdAndDown),
519
+ lgAndDown: readonly(lgAndDown),
520
+ xlAndDown: readonly(xlAndDown),
521
+ xxlAndDown: readonly(xxlAndDown),
522
+ update
523
+ };
524
+ function provideBreakpointsContext(_context = context, app) {
525
+ return _provideBreakpointsContext(_context, app);
526
+ }
527
+ return createTrinity(useBreakpointsContext, provideBreakpointsContext, context);
528
+ }
529
+ /**
530
+ * Returns the current breakpoints instance.
531
+ *
532
+ * @returns The current breakpoints instance.
533
+ *
534
+ * @see https://0.vuetifyjs.com/composables/plugins/use-breakpoints
535
+ *
536
+ * @example
537
+ * ```vue
538
+ * <script setup lang="ts">
539
+ * import { useBreakpoints } from '@vuetify/v0'
540
+ *
541
+ * const { isMobile, mdAndUp } = useBreakpoints()
542
+ * <\/script>
543
+ *
544
+ * <template>
545
+ * <div class="pa-4">
546
+ * <p v-if="isMobile.value">Mobile layout active</p>
547
+ * <p v-else-if="mdAndUp.value">Medium and up layout active</p>
548
+ * </div>
549
+ * </template>
550
+ * ```
551
+ */
552
+ function useBreakpoints() {
553
+ return useContext("v0:breakpoints");
554
+ }
555
+ /**
556
+ * Creates a new breakpoints plugin.
557
+ *
558
+ * @param options The options for the breakpoints plugin.
559
+ * @template E The type of the breakpoints context.
560
+ * @returns A new breakpoints plugin.
561
+ *
562
+ * @see https://0.vuetifyjs.com/composables/plugins/use-breakpoints
563
+ *
564
+ * @example
565
+ * ```ts
566
+ * import { createApp } from 'vue'
567
+ * import { createBreakpointsPlugin } from '@vuetify/v0'
568
+ * import App from './App.vue'
569
+ *
570
+ * const app = createApp(App)
571
+ *
572
+ * app.use(
573
+ * createBreakpointsPlugin({
574
+ * mobileBreakpoint: 'sm',
575
+ * breakpoints: {
576
+ * xs: 0,
577
+ * sm: 680,
578
+ * md: 1024,
579
+ * lg: 1280,
580
+ * xl: 1920,
581
+ * xxl: 2560,
582
+ * },
583
+ * })
584
+ * )
585
+ *
586
+ * app.mount('#app')
587
+ * ```
588
+ */
589
+ function createBreakpointsPlugin(options = {}) {
590
+ const [, provideBreakpointsContext, context] = createBreakpoints("v0:breakpoints", options);
591
+ return createPlugin({
592
+ namespace: "v0:breakpoints",
593
+ provide: (app) => {
594
+ provideBreakpointsContext(context, app);
595
+ },
596
+ setup: (app) => {
597
+ app.mixin({ mounted() {
598
+ context.update();
599
+ } });
600
+ }
601
+ });
602
+ }
603
+
604
+ //#endregion
605
+ //#region src/composables/useEventListener/index.ts
606
+ /**
607
+ * Attaches an event listener to a target.
608
+ *
609
+ * @param target The target to attach the event listener to.
610
+ * @param event The event to listen for.
611
+ * @param listener The event listener.
612
+ * @param options The event listener options.
613
+ * @returns A function to remove the event listener.
614
+ *
615
+ * @see https://0.vuetifyjs.com/composables/system/use-event-listener
616
+ */
617
+ function useEventListener(target, event, listener, options) {
618
+ const cleanups = [];
619
+ function cleanup() {
620
+ for (const fn of cleanups) fn();
621
+ cleanups.length = 0;
622
+ }
623
+ function register(el, event$1, listener$1, options$1) {
624
+ el.addEventListener(event$1, listener$1, options$1);
625
+ return () => el.removeEventListener(event$1, listener$1, options$1);
626
+ }
627
+ const stopWatcher = watch(() => [
628
+ toValue(target),
629
+ toValue(event),
630
+ unref(listener),
631
+ toValue(options)
632
+ ], ([el, events, listeners, opts]) => {
633
+ cleanup();
634
+ if (!el) return;
635
+ const eventList = toArray(events);
636
+ const listenerList = toArray(listeners);
637
+ for (const event$1 of eventList) for (const listenerFn of listenerList) cleanups.push(register(el, event$1, listenerFn, opts));
638
+ }, {
639
+ immediate: true,
640
+ flush: "post"
641
+ });
642
+ function stop() {
643
+ stopWatcher();
644
+ cleanup();
645
+ }
646
+ onScopeDispose(stop, true);
647
+ return stop;
648
+ }
649
+ /**
650
+ * Attaches an event listener to the window.
651
+ *
652
+ * @param event The event to listen for.
653
+ * @param listener The event listener.
654
+ * @param options The event listener options.
655
+ * @template E The event type.
656
+ * @returns A function to remove the event listener.
657
+ *
658
+ * @see https://0.vuetifyjs.com/composables/system/use-event-listener
659
+ */
660
+ function useWindowEventListener(event, listener, options) {
661
+ return useEventListener(window, event, listener, options);
662
+ }
663
+ /**
664
+ * Attaches an event listener to the document.
665
+ *
666
+ * @param event The event to listen for.
667
+ * @param listener The event listener.
668
+ * @param options The event listener options.
669
+ * @template E The event type.
670
+ * @returns A function to remove the event listener.
671
+ *
672
+ * @see https://0.vuetifyjs.com/composables/system/use-event-listener
673
+ */
674
+ function useDocumentEventListener(event, listener, options) {
675
+ return useEventListener(document, event, listener, options);
676
+ }
677
+
678
+ //#endregion
679
+ //#region src/composables/useLogger/adapters/consola.ts
680
+ var ConsolaLoggerAdapter = class {
681
+ consola;
682
+ constructor(consolaInstance) {
683
+ if (!consolaInstance) throw new Error("Consola instance is required for ConsolaLoggerAdapter");
684
+ this.consola = consolaInstance;
685
+ }
686
+ debug(message, ...args) {
687
+ this.consola.debug(message, ...args);
688
+ }
689
+ info(message, ...args) {
690
+ this.consola.info(message, ...args);
691
+ }
692
+ warn(message, ...args) {
693
+ this.consola.warn(message, ...args);
694
+ }
695
+ error(message, ...args) {
696
+ this.consola.error(message, ...args);
697
+ }
698
+ trace(message, ...args) {
699
+ if (this.consola.trace) this.consola.trace(message, ...args);
700
+ else this.consola.debug(message, ...args);
701
+ }
702
+ fatal(message, ...args) {
703
+ if (this.consola.fatal) this.consola.fatal(message, ...args);
704
+ else this.consola.error("[FATAL]", message, ...args);
705
+ }
706
+ };
707
+
708
+ //#endregion
709
+ //#region src/composables/useLogger/adapters/pino.ts
710
+ /**
711
+ * Pino logger adapter implementation
712
+ *
713
+ * This adapter integrates with the Pino logging library,
714
+ * providing high-performance structured logging optimized
715
+ * for Node.js applications with minimal overhead.
716
+ */
717
+ var PinoLoggerAdapter = class {
718
+ pino;
719
+ constructor(pinoInstance) {
720
+ if (!pinoInstance) throw new Error("Pino instance is required for PinoLoggerAdapter");
721
+ this.pino = pinoInstance;
722
+ }
723
+ debug(message, ...args) {
724
+ this.pino.debug(this.format(message, ...args));
725
+ }
726
+ info(message, ...args) {
727
+ this.pino.info(this.format(message, ...args));
728
+ }
729
+ warn(message, ...args) {
730
+ this.pino.warn(this.format(message, ...args));
731
+ }
732
+ error(message, ...args) {
733
+ this.pino.error(this.format(message, ...args));
734
+ }
735
+ trace(message, ...args) {
736
+ this.pino.trace(this.format(message, ...args));
737
+ }
738
+ fatal(message, ...args) {
739
+ this.pino.fatal(this.format(message, ...args));
740
+ }
741
+ format(message, ...args) {
742
+ if (args.length === 0) return { msg: message };
743
+ if (args.length === 1 && typeof args[0] === "object" && args[0] !== null) return {
744
+ ...args[0],
745
+ msg: message
746
+ };
747
+ return {
748
+ msg: message,
749
+ args
750
+ };
751
+ }
752
+ };
753
+
754
+ //#endregion
755
+ //#region src/composables/useLogger/adapters/v0.ts
756
+ /**
757
+ * Vuetify0.x logger adapter implementation
758
+ *
759
+ * This adapter provides console-based logging with proper formatting,
760
+ * color coding, timestamps, and log level filtering for development
761
+ * and production environments.
762
+ */
763
+ var Vuetify0LoggerAdapter = class {
764
+ prefix;
765
+ colors;
766
+ timestamps;
767
+ constructor(options = {}) {
768
+ this.prefix = options.prefix || "v0";
769
+ this.colors = options.colors !== false;
770
+ this.timestamps = options.timestamps !== false;
771
+ }
772
+ debug(message, ...args) {
773
+ this.log("debug", "debug", message, ...args);
774
+ }
775
+ info(message, ...args) {
776
+ this.log("info", "info", message, ...args);
777
+ }
778
+ warn(message, ...args) {
779
+ this.log("warn", "warn", message, ...args);
780
+ }
781
+ error(message, ...args) {
782
+ this.log("error", "error", message, ...args);
783
+ }
784
+ trace(message, ...args) {
785
+ this.log("trace", "trace", message, ...args);
786
+ }
787
+ fatal(message, ...args) {
788
+ this.log("fatal", "error", message, ...args);
789
+ }
790
+ format(level, message, ...args) {
791
+ return [[
792
+ this.timestamps ? this.timestamp() : "",
793
+ `[${this.prefix} ${level.toLowerCase()}]`,
794
+ message
795
+ ].filter(Boolean).join(" "), ...args];
796
+ }
797
+ timestamp() {
798
+ if (!IN_BROWSER) return (/* @__PURE__ */ new Date()).toISOString();
799
+ return (/* @__PURE__ */ new Date()).toTimeString().split(" ")[0] ?? "";
800
+ }
801
+ style(level) {
802
+ if (!this.colors || !IN_BROWSER) return "";
803
+ return {
804
+ trace: "color: #64748b",
805
+ debug: "color: #3b82f6",
806
+ info: "color: #10b981",
807
+ warn: "color: #f59e0b",
808
+ error: "color: #ef4444",
809
+ fatal: "color: #dc2626; font-weight: bold",
810
+ silent: ""
811
+ }[level] || "";
812
+ }
813
+ log(level, method, message, ...args) {
814
+ const [formattedMessage, ...restArgs] = this.format(level, message, ...args);
815
+ const style = this.style(level);
816
+ if (IN_BROWSER && style && typeof console[method] === "function") console[method](`%c${formattedMessage}`, style, ...restArgs);
817
+ else if (typeof console[method] === "function") console[method](formattedMessage, ...restArgs);
818
+ }
819
+ };
820
+
821
+ //#endregion
822
+ //#region src/composables/useLogger/index.ts
823
+ const [useLoggerContext, provideLoggerContext] = createContext("v0:logger");
824
+ /**
825
+ * Creates a new logger instance.
826
+ *
827
+ * @param options The options for the logger instance.
828
+ * @returns A new logger instance.
829
+ *
830
+ * @see https://0.vuetifyjs.com/composables/plugins/use-logger
831
+ */
832
+ function createLogger(options = {}) {
833
+ const { adapter = new Vuetify0LoggerAdapter({ prefix: options.prefix }), level: initialLevel = "info", enabled: initialEnabled = __LOGGER_ENABLED__ } = options;
834
+ const currentLevel = shallowRef(initialLevel);
835
+ const isEnabled = shallowRef(initialEnabled);
836
+ function value(level$1) {
837
+ return {
838
+ trace: 0,
839
+ debug: 1,
840
+ info: 2,
841
+ warn: 3,
842
+ error: 4,
843
+ fatal: 5,
844
+ silent: 6
845
+ }[level$1] ?? 2;
846
+ }
847
+ function can(level$1) {
848
+ if (!isEnabled.value) return false;
849
+ return value(level$1) >= value(currentLevel.value);
850
+ }
851
+ function format(message) {
852
+ return message;
853
+ }
854
+ function debug(message, ...args) {
855
+ if (can("debug")) adapter.debug(format(message), ...args);
856
+ }
857
+ function info(message, ...args) {
858
+ if (can("info")) adapter.info(format(message), ...args);
859
+ }
860
+ function warn(message, ...args) {
861
+ if (can("warn")) adapter.warn(format(message), ...args);
862
+ }
863
+ function error(message, ...args) {
864
+ if (can("error")) adapter.error(format(message), ...args);
865
+ }
866
+ function trace(message, ...args) {
867
+ if (can("trace")) adapter.trace?.(format(message), ...args);
868
+ }
869
+ function fatal(message, ...args) {
870
+ if (can("fatal")) adapter.fatal?.(format(message), ...args);
871
+ }
872
+ function level(newLevel) {
873
+ currentLevel.value = newLevel;
874
+ }
875
+ function current() {
876
+ return currentLevel.value;
877
+ }
878
+ function enabled() {
879
+ return isEnabled.value;
880
+ }
881
+ function enable() {
882
+ isEnabled.value = true;
883
+ }
884
+ function disable() {
885
+ isEnabled.value = false;
886
+ }
887
+ return {
888
+ debug,
889
+ info,
890
+ warn,
891
+ error,
892
+ trace,
893
+ fatal,
894
+ level,
895
+ current,
896
+ enabled,
897
+ enable,
898
+ disable
899
+ };
900
+ }
901
+ function createFallbackLogger(namespace = "v0:logger") {
902
+ function format(message, type) {
903
+ return `[${namespace} ${type}] ${message}`;
904
+ }
905
+ return {
906
+ debug: (message, ...args) => console.log(format(message, "debug"), ...args),
907
+ info: (message, ...args) => console.log(format(message, "info"), ...args),
908
+ warn: (message, ...args) => console.log(format(message, "warn"), ...args),
909
+ error: (message, ...args) => console.log(format(message, "error"), ...args),
910
+ trace: (message, ...args) => console.log(format(message, "trace"), ...args),
911
+ fatal: (message, ...args) => console.log(format(message, "fatal"), ...args),
912
+ level: () => {},
913
+ current: () => "info",
914
+ enabled: () => true,
915
+ enable: () => {},
916
+ disable: () => {}
917
+ };
918
+ }
919
+ /**
920
+ * Uses an existing or creates a new logger instance.
921
+ *
922
+ * @param namespace The namespace for the logger context.
923
+ * @returns The logger instance.
924
+ *
925
+ * @see https://0.vuetifyjs.com/composables/plugins/use-logger
926
+ */
927
+ function useLogger(namespace) {
928
+ if (getCurrentInstance()) try {
929
+ return useLoggerContext(namespace);
930
+ } catch (error) {
931
+ if (process.env.NODE_ENV !== "production" && IN_BROWSER && namespace) console.warn(error);
932
+ }
933
+ return createFallbackLogger(namespace);
934
+ }
935
+ /**
936
+ * Creates a new logger plugin.
937
+ *
938
+ * @param options The options for the logger plugin.
939
+ * @returns A new logger plugin.
940
+ *
941
+ * @see https://0.vuetifyjs.com/composables/plugins/use-logger
942
+ */
943
+ function createLoggerPlugin(options = {}) {
944
+ const context = createLogger(options);
945
+ return createPlugin({
946
+ namespace: "v0:logger",
947
+ provide: (app) => {
948
+ provideLoggerContext(context, app);
949
+ },
950
+ setup: (_app) => {
951
+ if (process.env.NODE_ENV !== "production" && IN_BROWSER) window.__v0Logger__ = context;
952
+ }
953
+ });
954
+ }
955
+
956
+ //#endregion
957
+ //#region src/composables/useRegistry/index.ts
958
+ /**
959
+ * Creates a new registry instance.
960
+ *
961
+ * @param options The options for the registry instance.
962
+ * @template Z The type of registry ticket that extends RegistryTicket. Use this to add custom properties to tickets.
963
+ * @template E The type of registry context that extends RegistryContext<Z>. Use this when extending the registry with additional methods.
964
+ * @returns A new registry instance.
965
+ *
966
+ * @see https://0.vuetifyjs.com/composables/registration/use-registry
967
+ *
968
+ * @example
969
+ * ```ts
970
+ * import { useRegistry } from '@vuetify/v0'
971
+ *
972
+ * const registry = useRegistry()
973
+ *
974
+ * const ticket1 = registry.register({ id: 'user-1', value: { name: 'John' } })
975
+ * const ticket2 = registry.register({ id: 'user-2', value: { name: 'Jane' } })
976
+ *
977
+ * console.log(registry.size) // 2
978
+ * console.log(registry.get('user-1')) // { id: 'user-1', index: 0, value: { name: 'John' }, ... }
979
+ * ```
980
+ */
981
+ function useRegistry(options) {
982
+ const logger = useLogger();
983
+ const collection = /* @__PURE__ */ new Map();
984
+ const catalog = /* @__PURE__ */ new Map();
985
+ const directory = /* @__PURE__ */ new Map();
986
+ const cache = /* @__PURE__ */ new Map();
987
+ const listeners = /* @__PURE__ */ new Map();
988
+ const events = options?.events ?? false;
989
+ function emit(event, data = void 0) {
990
+ if (!events) return;
991
+ const cbs = listeners.get(event);
992
+ if (!cbs) return;
993
+ for (const cb of cbs) cb(data);
994
+ }
995
+ function on(event, cb) {
996
+ if (!events) {
997
+ logger.warn(`Attempted to register event listener for "${event}" but events are disabled.`);
998
+ return;
999
+ }
1000
+ if (!listeners.has(event)) listeners.set(event, /* @__PURE__ */ new Set());
1001
+ listeners.get(event).add(cb);
1002
+ }
1003
+ function off(event, cb) {
1004
+ listeners.get(event)?.delete(cb);
1005
+ }
1006
+ function dispose() {
1007
+ if (listeners.size > 0) listeners.clear();
1008
+ clear();
1009
+ }
1010
+ function get(id) {
1011
+ return collection.get(id);
1012
+ }
1013
+ function upsert(id, patch = {}) {
1014
+ const existing = get(id);
1015
+ if (!existing) return register({
1016
+ ...patch,
1017
+ id
1018
+ });
1019
+ const hasValue = Object.prototype.hasOwnProperty.call(patch, "value");
1020
+ let value = existing.value;
1021
+ let valueIsIndex = existing.valueIsIndex;
1022
+ if (hasValue) {
1023
+ if (patch.value === void 0) {
1024
+ value = existing.index;
1025
+ valueIsIndex = true;
1026
+ } else {
1027
+ value = patch.value;
1028
+ valueIsIndex = false;
1029
+ }
1030
+ if (!Object.is(value, existing.value)) {
1031
+ unassign(existing.value, id);
1032
+ assign(value, id);
1033
+ }
1034
+ }
1035
+ const updated = {
1036
+ ...existing,
1037
+ ...patch,
1038
+ id,
1039
+ index: existing.index,
1040
+ value,
1041
+ valueIsIndex
1042
+ };
1043
+ collection.set(id, updated);
1044
+ invalidate();
1045
+ emit("update:ticket", updated);
1046
+ return updated;
1047
+ }
1048
+ function browse(value) {
1049
+ return catalog.get(value);
1050
+ }
1051
+ function lookup(index) {
1052
+ return directory.get(index);
1053
+ }
1054
+ function has(id) {
1055
+ return collection.has(id);
1056
+ }
1057
+ function assign(value, id) {
1058
+ const bucket = catalog.get(value);
1059
+ if (bucket) {
1060
+ if (/* @__PURE__ */ isArray(bucket)) {
1061
+ if (!bucket.includes(id)) bucket.push(id);
1062
+ } else if (bucket !== id) catalog.set(value, [bucket, id]);
1063
+ } else catalog.set(value, id);
1064
+ }
1065
+ function unassign(value, id) {
1066
+ const bucket = catalog.get(value);
1067
+ if (!bucket) return;
1068
+ if (/* @__PURE__ */ isArray(bucket)) {
1069
+ const next = bucket.filter((v) => v !== id);
1070
+ if (next.length === 0) catalog.delete(value);
1071
+ else if (next.length === 1) catalog.set(value, next[0]);
1072
+ else catalog.set(value, next);
1073
+ } else if (bucket === id) catalog.delete(value);
1074
+ }
1075
+ function keys() {
1076
+ const cached = cache.get("keys");
1077
+ if (cached != void 0) return cached;
1078
+ const keys$1 = Array.from(collection.keys());
1079
+ cache.set("keys", keys$1);
1080
+ return keys$1;
1081
+ }
1082
+ function values() {
1083
+ const cached = cache.get("values");
1084
+ if (cached != void 0) return cached;
1085
+ const values$1 = Array.from(collection.values());
1086
+ cache.set("values", values$1);
1087
+ return values$1;
1088
+ }
1089
+ function entries() {
1090
+ const cached = cache.get("entries");
1091
+ if (cached != void 0) return cached;
1092
+ const entries$1 = Array.from(collection.entries());
1093
+ cache.set("entries", entries$1);
1094
+ return entries$1;
1095
+ }
1096
+ function clear() {
1097
+ if (collection.size > 0) collection.clear();
1098
+ if (catalog.size > 0) catalog.clear();
1099
+ if (directory.size > 0) directory.clear();
1100
+ invalidate();
1101
+ emit("clear:registry");
1102
+ }
1103
+ function invalidate() {
1104
+ if (cache.size > 0) cache.clear();
1105
+ }
1106
+ function reindex() {
1107
+ if (catalog.size > 0) catalog.clear();
1108
+ if (directory.size > 0) directory.clear();
1109
+ let index = 0;
1110
+ for (const ticket of values()) {
1111
+ if (ticket.index !== index) {
1112
+ ticket.index = index;
1113
+ if (ticket.valueIsIndex) ticket.value = index;
1114
+ }
1115
+ directory.set(index, ticket.id);
1116
+ assign(ticket.value, ticket.id);
1117
+ index++;
1118
+ }
1119
+ invalidate();
1120
+ }
1121
+ function register(registration = {}) {
1122
+ const size = collection.size;
1123
+ const id = registration.id ?? /* @__PURE__ */ genId();
1124
+ if (has(id)) {
1125
+ logger.warn(`Ticket with id "${id}" already exists in the registry. Skipping registration.`);
1126
+ return get(id);
1127
+ }
1128
+ const index = registration.index ?? size;
1129
+ const value = registration.value === void 0 ? index : registration.value;
1130
+ const valueIsIndex = registration.value === void 0;
1131
+ const ticket = {
1132
+ ...registration,
1133
+ id,
1134
+ index,
1135
+ value,
1136
+ valueIsIndex
1137
+ };
1138
+ collection.set(ticket.id, ticket);
1139
+ directory.set(ticket.index, ticket.id);
1140
+ assign(ticket.value, ticket.id);
1141
+ invalidate();
1142
+ emit("register:ticket", ticket);
1143
+ return ticket;
1144
+ }
1145
+ function unregister(id) {
1146
+ const ticket = collection.get(id);
1147
+ if (!ticket) return;
1148
+ collection.delete(ticket.id);
1149
+ directory.delete(ticket.index);
1150
+ unassign(ticket.value, ticket.id);
1151
+ invalidate();
1152
+ emit("unregister:ticket", ticket);
1153
+ reindex();
1154
+ }
1155
+ function seek(direction = "first", from, predicate) {
1156
+ if (collection.size === 0) return void 0;
1157
+ const tickets = values();
1158
+ const index = /* @__PURE__ */ isUndefined(from) ? void 0 : Math.max(0, Math.min(from, tickets.length - 1));
1159
+ if (direction === "last") {
1160
+ const start = /* @__PURE__ */ isUndefined(index) ? tickets.length - 1 : index;
1161
+ for (let i = start; i >= 0; i--) {
1162
+ const ticket = tickets[i];
1163
+ if (!predicate || predicate(ticket)) return ticket;
1164
+ }
1165
+ } else {
1166
+ const start = /* @__PURE__ */ isUndefined(index) ? 0 : index;
1167
+ for (let i = start; i < tickets.length; i++) {
1168
+ const ticket = tickets[i];
1169
+ if (!predicate || predicate(ticket)) return ticket;
1170
+ }
1171
+ }
1172
+ }
1173
+ return {
1174
+ collection,
1175
+ emit,
1176
+ on,
1177
+ off,
1178
+ dispose,
1179
+ has,
1180
+ keys,
1181
+ clear,
1182
+ browse,
1183
+ entries,
1184
+ values,
1185
+ lookup,
1186
+ get,
1187
+ upsert,
1188
+ register,
1189
+ unregister,
1190
+ reindex,
1191
+ seek,
1192
+ onboard(registrations) {
1193
+ return registrations.map((registration) => this.register(registration));
1194
+ },
1195
+ get size() {
1196
+ return collection.size;
1197
+ }
1198
+ };
1199
+ }
1200
+ /**
1201
+ * Creates a new registry context.
1202
+ *
1203
+ * @param namespace The namespace for the registry context.
1204
+ * @param options The options for the registry context.
1205
+ *
1206
+ * @template Z The type of registry ticket that extends RegistryTicket. Use this to add custom properties to tickets.
1207
+ * @template E The type of registry context that extends RegistryContext<Z>. Use this when extending the registry with additional methods.
1208
+ *
1209
+ * @see https://0.vuetifyjs.com/composables/registration/use-registry
1210
+ *
1211
+ * @example
1212
+ * ```ts
1213
+ * import { createRegistryContext } from '@vuetify/v0'
1214
+ *
1215
+ * export const [useItems, provideItems, items] = createRegistryContext('items')
1216
+ *
1217
+ * // In a parent component:
1218
+ * provideItems()
1219
+ *
1220
+ * // In a child component:
1221
+ * const items = useItems()
1222
+ * items.register({ id: 'item-1', value: 'Value 1' })
1223
+ * ```
1224
+ */
1225
+ function createRegistryContext(namespace, options) {
1226
+ const [useRegistryContext, _provideRegistryContext] = createContext(namespace);
1227
+ const context = useRegistry(options);
1228
+ function provideRegistryContext(_context = context, app) {
1229
+ return _provideRegistryContext(_context, app);
1230
+ }
1231
+ return createTrinity(useRegistryContext, provideRegistryContext, context);
1232
+ }
1233
+
1234
+ //#endregion
1235
+ //#region src/composables/useSelection/index.ts
1236
+ /**
1237
+ * Creates a new selection instance.
1238
+ *
1239
+ * @param options The options for the selection instance.
1240
+ * @template Z The type of the selection ticket.
1241
+ * @template E The type of the selection context.
1242
+ * @returns A new selection instance.
1243
+ *
1244
+ * @see https://0.vuetifyjs.com/composables/selection/use-selection
1245
+ *
1246
+ * @example
1247
+ * ```ts
1248
+ * import { useSelection } from '@vuetify/v0'
1249
+ *
1250
+ * const selection = useSelection({ mandatory: true })
1251
+ *
1252
+ * selection.onboard([
1253
+ * { id: 'item-1', value: 'Item 1' },
1254
+ * { id: 'item-2', value: 'Item 2', disabled: true },
1255
+ * { id: 'item-3', value: 'Item 3' },
1256
+ * ])
1257
+ *
1258
+ * selection.select('item-1')
1259
+ * selection.select('item-3')
1260
+ *
1261
+ * console.log(selection.selectedIds) // Set { 'item-1', 'item-3' }
1262
+ * ```
1263
+ */
1264
+ function useSelection(options) {
1265
+ const registry = useRegistry(options);
1266
+ const selectedIds = shallowReactive(/* @__PURE__ */ new Set());
1267
+ const enroll = options?.enroll ?? false;
1268
+ const mandatory = options?.mandatory ?? false;
1269
+ const selectedItems = computed(() => {
1270
+ return new Set(Array.from(selectedIds).map((id) => registry.get(id)));
1271
+ });
1272
+ const selectedValues = computed(() => {
1273
+ return new Set(Array.from(selectedItems.value).map((item) => item?.value));
1274
+ });
1275
+ function seek(direction = "first", from) {
1276
+ return registry.seek(direction, from, (ticket) => !ticket.disabled);
1277
+ }
1278
+ function mandate() {
1279
+ if (!mandatory || registry.size === 0 || selectedIds.size > 0) return;
1280
+ const ticket = seek("first");
1281
+ if (ticket) select(ticket.id);
1282
+ }
1283
+ function select(id) {
1284
+ const item = registry.get(id);
1285
+ if (!item || item.disabled) return;
1286
+ selectedIds.add(id);
1287
+ }
1288
+ function unselect(id) {
1289
+ if (mandatory && selectedIds.size === 1) return;
1290
+ selectedIds.delete(id);
1291
+ }
1292
+ function toggle(id) {
1293
+ if (selectedIds.has(id)) unselect(id);
1294
+ else select(id);
1295
+ }
1296
+ function selected(id) {
1297
+ return selectedIds.has(id);
1298
+ }
1299
+ function register(registration = {}) {
1300
+ const id = registration.id ?? /* @__PURE__ */ genId();
1301
+ const item = {
1302
+ disabled: false,
1303
+ ...registration,
1304
+ id,
1305
+ isSelected: toRef(() => selectedIds.has(id)),
1306
+ select: () => select(id),
1307
+ unselect: () => unselect(id),
1308
+ toggle: () => toggle(id)
1309
+ };
1310
+ const ticket = registry.register(item);
1311
+ if (enroll && !item.disabled) selectedIds.add(ticket.id);
1312
+ if (mandatory === "force") mandate();
1313
+ return ticket;
1314
+ }
1315
+ function unregister(id) {
1316
+ selectedIds.delete(id);
1317
+ registry.unregister(id);
1318
+ }
1319
+ function reset() {
1320
+ registry.clear();
1321
+ selectedIds.clear();
1322
+ mandate();
1323
+ }
1324
+ return {
1325
+ ...registry,
1326
+ selectedIds,
1327
+ selectedItems,
1328
+ selectedValues,
1329
+ register,
1330
+ unregister,
1331
+ reset,
1332
+ mandate,
1333
+ seek,
1334
+ select,
1335
+ unselect,
1336
+ toggle,
1337
+ selected,
1338
+ get size() {
1339
+ return registry.size;
1340
+ }
1341
+ };
1342
+ }
1343
+ /**
1344
+ * Creates a new selection context.
1345
+ *
1346
+ * @param namespace The namespace for the selection context.
1347
+ * @param options The options for the selection context.
1348
+ * @template Z The type of the selection ticket.
1349
+ * @template E The type of the selection context.
1350
+ * @returns A new selection context.
1351
+ *
1352
+ * @see https://0.vuetifyjs.com/composables/selection/use-selection
1353
+ *
1354
+ * @example
1355
+ * ```ts
1356
+ * import { createSelectionContext } from '@vuetify/v0'
1357
+ *
1358
+ * export const [useCheckboxes, provideCheckboxes, checkboxes] = createSelectionContext('checkboxes')
1359
+ *
1360
+ * // In a parent component:
1361
+ * provideCheckboxes()
1362
+ *
1363
+ * // In a child component:
1364
+ * const checkboxes = useCheckboxes()
1365
+ * checkboxes.select('checkbox-1')
1366
+ * ```
1367
+ */
1368
+ function createSelectionContext(namespace, options) {
1369
+ const [useSelectionContext, _provideSelectionContext] = createContext(namespace);
1370
+ const context = useSelection(options);
1371
+ function provideSelectionContext(_context = context, app) {
1372
+ return _provideSelectionContext(_context, app);
1373
+ }
1374
+ return createTrinity(useSelectionContext, provideSelectionContext, context);
1375
+ }
1376
+
1377
+ //#endregion
1378
+ //#region src/composables/useGroup/index.ts
1379
+ /**
1380
+ * Creates a new group instance.
1381
+ *
1382
+ * @param options The options for the group instance.
1383
+ * @template Z The type of the group ticket.
1384
+ * @template E The type of the group context.
1385
+ * @returns A new group instance.
1386
+ *
1387
+ * @see https://0.vuetifyjs.com/composables/selection/use-group
1388
+ *
1389
+ * @example
1390
+ * ```ts
1391
+ * import { useGroup } from '@vuetify/v0'
1392
+ *
1393
+ * const group = useGroup()
1394
+ *
1395
+ * group.onboard([
1396
+ * { id: 'item-1', value: 'Item 1' },
1397
+ * { id: 'item-2', value: 'Item 2' },
1398
+ * { id: 'item-3', value: 'Item 3' },
1399
+ * ])
1400
+ *
1401
+ * group.select(['item-1', 'item-2'])
1402
+ *
1403
+ * console.log(group.selectedIds) // Set { 'item-1', 'item-2' }
1404
+ * ```
1405
+ */
1406
+ function useGroup(options) {
1407
+ const registry = useSelection(options);
1408
+ const selectedIndexes = computed(() => {
1409
+ return new Set(Array.from(registry.selectedItems.value).map((item) => item?.index));
1410
+ });
1411
+ function select(ids) {
1412
+ for (const id of toArray(ids)) registry.select(id);
1413
+ }
1414
+ function unselect(ids) {
1415
+ for (const id of toArray(ids)) registry.unselect(id);
1416
+ }
1417
+ function toggle(ids) {
1418
+ for (const id of toArray(ids)) registry.toggle(id);
1419
+ }
1420
+ return {
1421
+ ...registry,
1422
+ select,
1423
+ unselect,
1424
+ toggle,
1425
+ selectedIndexes,
1426
+ get size() {
1427
+ return registry.size;
1428
+ }
1429
+ };
1430
+ }
1431
+ /**
1432
+ * Creates a new group context.
1433
+ *
1434
+ * @param namespace The namespace for the group context.
1435
+ * @param options The options for the group context.
1436
+ * @template Z The type of the group ticket.
1437
+ * @template E The type of the group context.
1438
+ * @returns A new group context.
1439
+ *
1440
+ * @see https://0.vuetifyjs.com/composables/selection/use-group
1441
+ *
1442
+ * @example
1443
+ * ```ts
1444
+ * import { createGroupContext } from '@vuetify/v0'
1445
+ *
1446
+ * export const [useMyGroup, provideMyGroup, myGroup] = createGroupContext('my-group')
1447
+ *
1448
+ * // In a parent component:
1449
+ * provideMyGroup()
1450
+ *
1451
+ * // In a child component:
1452
+ * const group = useMyGroup()
1453
+ * ```
1454
+ */
1455
+ function createGroupContext(namespace, options) {
1456
+ const [useGroupContext, _provideGroupContext] = createContext(namespace);
1457
+ const context = useGroup(options);
1458
+ function provideGroupContext(_context = context, app) {
1459
+ return _provideGroupContext(_context, app);
1460
+ }
1461
+ return createTrinity(useGroupContext, provideGroupContext, context);
1462
+ }
1463
+
1464
+ //#endregion
1465
+ //#region src/composables/useTokens/index.ts
1466
+ /**
1467
+ * Creates a new token instance.
1468
+ *
1469
+ * @param tokens The tokens to use.
1470
+ * @param options The options for the token instance.
1471
+ * @template Z The type of the token ticket.
1472
+ * @template E The type of the token context.
1473
+ * @returns A new token instance.
1474
+ *
1475
+ * @see https://www.designtokens.org/tr/drafts/format/
1476
+ * @see https://0.vuetifyjs.com/composables/registration/use-tokens
1477
+ *
1478
+ * @example
1479
+ * ```ts
1480
+ * import { useTokens } from '@vuetify/v0'
1481
+ *
1482
+ * const tokens = useTokens({
1483
+ * colors: {
1484
+ * primary: '#3b82f6',
1485
+ * secondary: '{colors.primary}', // Alias reference
1486
+ * },
1487
+ * })
1488
+ *
1489
+ * console.log(tokens.resolve('{colors.primary}')) // '#3b82f6'
1490
+ * console.log(tokens.resolve('{colors.secondary}')) // '#3b82f6'
1491
+ * ```
1492
+ */
1493
+ function useTokens(tokens = {}, options = {}) {
1494
+ const logger = useLogger();
1495
+ const registry = useRegistry();
1496
+ const cache = /* @__PURE__ */ new Map();
1497
+ registry.onboard(flatten(tokens, options.prefix, !!options.flat));
1498
+ function isAlias(token) {
1499
+ return /* @__PURE__ */ isString(token) && token.length > 2 && token[0] === "{" && token.at(-1) === "}";
1500
+ }
1501
+ function isTokenAlias(value) {
1502
+ return /* @__PURE__ */ isObject(value) && "$value" in value;
1503
+ }
1504
+ function resolve(token) {
1505
+ const cacheKey = /* @__PURE__ */ isString(token) ? token : JSON.stringify(token);
1506
+ const cached = cache.get(cacheKey);
1507
+ if (cached !== void 0) return cached;
1508
+ const reference = isTokenAlias(token) ? token.$value : token;
1509
+ const clean = /* @__PURE__ */ isString(reference) && isAlias(reference) ? reference.slice(1, -1) : String(reference);
1510
+ let found = registry.get(clean);
1511
+ let segments = [];
1512
+ if (!found && clean.includes(".")) {
1513
+ const parts = clean.split(".");
1514
+ for (let i = parts.length - 1; i > 0; i--) {
1515
+ const prefix = parts.slice(0, i).join(".");
1516
+ const suffix = parts.slice(i);
1517
+ const candidate = registry.get(prefix);
1518
+ if (candidate?.value !== void 0) {
1519
+ found = candidate;
1520
+ segments = suffix;
1521
+ break;
1522
+ }
1523
+ }
1524
+ }
1525
+ if (found?.value === void 0) {
1526
+ logger.warn(`Alias not found for "${String(reference)}"`);
1527
+ cache.set(cacheKey, void 0);
1528
+ return;
1529
+ }
1530
+ let result;
1531
+ let current = found.value;
1532
+ if (segments.length > 0) {
1533
+ if (isTokenAlias(current)) current = current.$value;
1534
+ for (const segment of segments) {
1535
+ if (!/* @__PURE__ */ isObject(current) || !(segment in current)) {
1536
+ current = void 0;
1537
+ break;
1538
+ }
1539
+ current = current[segment];
1540
+ if (isTokenAlias(current)) current = current.$value;
1541
+ }
1542
+ if (current === void 0) {
1543
+ logger.warn(`Path not found inside "${clean}": ${segments.join(".")}`);
1544
+ cache.set(cacheKey, void 0);
1545
+ return;
1546
+ }
1547
+ result = current;
1548
+ } else if (isTokenAlias(current)) {
1549
+ const inner = current.$value;
1550
+ if (/* @__PURE__ */ isString(inner) && isAlias(inner)) return resolve(inner);
1551
+ result = inner;
1552
+ } else if (/* @__PURE__ */ isString(current) && isAlias(current)) return resolve(current);
1553
+ else result = current;
1554
+ cache.set(cacheKey, result);
1555
+ return result;
1556
+ }
1557
+ return {
1558
+ ...registry,
1559
+ resolve,
1560
+ isAlias,
1561
+ get size() {
1562
+ return registry.size;
1563
+ }
1564
+ };
1565
+ }
1566
+ /**
1567
+ * Creates a new token context.
1568
+ *
1569
+ * @param namespace The namespace for the token context.
1570
+ * @param tokens The tokens to use.
1571
+ * @template Z The type of the token ticket.
1572
+ * @template E The type of the token context.
1573
+ * @returns A new token context.
1574
+ *
1575
+ * @see https://0.vuetifyjs.com/composables/registration/use-tokens
1576
+ *
1577
+ * @example
1578
+ * ```ts
1579
+ * import { createTokensContext } from '@vuetify/v0'
1580
+ *
1581
+ * const myTokens = {
1582
+ * spacing: {
1583
+ * sm: '8px',
1584
+ * md: '16px',
1585
+ * lg: '24px',
1586
+ * },
1587
+ * }
1588
+ *
1589
+ * export const [useDesignTokens, provideDesignTokens, designTokens] = createTokensContext('design-tokens', myTokens)
1590
+ *
1591
+ * // In a parent component:
1592
+ * provideDesignTokens()
1593
+ *
1594
+ * // In a child component:
1595
+ * const tokens = useDesignTokens()
1596
+ *
1597
+ * console.log(tokens.resolve('{spacing.md}')) // '16px'
1598
+ * ```
1599
+ */
1600
+ function createTokensContext(namespace, tokens = {}) {
1601
+ const [useTokensContext, _provideTokensContext] = createContext(namespace);
1602
+ const context = useTokens(tokens);
1603
+ function provideTokensContext(_context = context, app) {
1604
+ return _provideTokensContext(_context, app);
1605
+ }
1606
+ return createTrinity(useTokensContext, provideTokensContext, context);
1607
+ }
1608
+ /**
1609
+ * Flattens a nested collection of tokens into a flat array of tokens.
1610
+ * Each token is represented by an object containing its ID & value.
1611
+ * @param tokens The collection of tokens to flatten.
1612
+ * @param prefix An optional prefix to prepend to each token ID.
1613
+ * @returns An array of flattened tokens, each with an ID and value.
1614
+ */
1615
+ function flatten(tokens, prefix = "", flat = false) {
1616
+ const flattened = [];
1617
+ const stack = [{
1618
+ tokens,
1619
+ prefix,
1620
+ flat
1621
+ }];
1622
+ while (stack.length > 0) {
1623
+ const { tokens: currentTokens, prefix: currentPrefix, flat: flat$1 } = stack.pop();
1624
+ const meta = {};
1625
+ for (const k in currentTokens) if (k.startsWith("$")) meta[k] = currentTokens[k];
1626
+ if (Object.keys(meta).length > 0 && currentPrefix) flattened.push({
1627
+ id: currentPrefix,
1628
+ value: meta
1629
+ });
1630
+ for (const key in currentTokens) {
1631
+ if (key.startsWith("$")) continue;
1632
+ const value = currentTokens[key];
1633
+ const id = currentPrefix ? `${currentPrefix}.${key}` : key;
1634
+ if (!/* @__PURE__ */ isObject(value)) {
1635
+ flattened.push({
1636
+ id,
1637
+ value
1638
+ });
1639
+ continue;
1640
+ }
1641
+ if ("$value" in value) {
1642
+ flattened.push({
1643
+ id,
1644
+ value
1645
+ });
1646
+ const inner = value.$value;
1647
+ if (/* @__PURE__ */ isObject(inner) && !flat$1) for (const innerKey in inner) {
1648
+ if (innerKey.startsWith("$")) continue;
1649
+ const child = inner[innerKey];
1650
+ const childId = `${id}.${innerKey}`;
1651
+ if (!/* @__PURE__ */ isObject(child)) flattened.push({
1652
+ id: childId,
1653
+ value: child
1654
+ });
1655
+ else if ("$value" in child) flattened.push({
1656
+ id: childId,
1657
+ value: child
1658
+ });
1659
+ else stack.push({
1660
+ tokens: child,
1661
+ prefix: childId,
1662
+ flat: flat$1
1663
+ });
1664
+ }
1665
+ continue;
1666
+ }
1667
+ if (flat$1) {
1668
+ flattened.push({
1669
+ id,
1670
+ value
1671
+ });
1672
+ continue;
1673
+ }
1674
+ stack.push({
1675
+ tokens: value,
1676
+ prefix: id,
1677
+ flat: flat$1
1678
+ });
1679
+ }
1680
+ }
1681
+ return flattened;
1682
+ }
1683
+
1684
+ //#endregion
1685
+ //#region src/composables/useFeatures/index.ts
1686
+ /**
1687
+ * Creates a new features instance.
1688
+ *
1689
+ * @param namespace The namespace to use for the features instance.
1690
+ * @param options The options for the features instance.
1691
+ * @template Z The type of the feature ticket.
1692
+ * @template E The type of the feature context.
1693
+ * @returns A new features instance.
1694
+ *
1695
+ * @see https://0.vuetifyjs.com/composables/plugins/create-features
1696
+ *
1697
+ * @example
1698
+ * ```ts
1699
+ * import { createFeatures } from '@vuetify/v0'
1700
+ *
1701
+ * const [useFeatures, provideFeaturesContext] = createFeatures('v0:features', {
1702
+ * features: {
1703
+ * 'dark-mode': true,
1704
+ * 'theme-color': { $variation: 'blue' },
1705
+ * },
1706
+ * })
1707
+ * ```
1708
+ */
1709
+ function createFeatures(namespace = "v0:features", options = {}) {
1710
+ const [useFeaturesContext, _provideFeaturesContext] = createContext(namespace);
1711
+ const tokens = useTokens(options.features, { flat: true });
1712
+ const registry = useGroup();
1713
+ for (const [id, { value }] of tokens.entries()) register({
1714
+ id,
1715
+ value
1716
+ });
1717
+ function variation(id, fallback = null) {
1718
+ const ticket = registry.get(id);
1719
+ if (!ticket) return fallback;
1720
+ return /* @__PURE__ */ isObject(ticket.value) ? ticket.value.$variation ?? fallback : ticket.value ?? fallback;
1721
+ }
1722
+ function register(registration = {}) {
1723
+ const item = {
1724
+ value: false,
1725
+ ...registration
1726
+ };
1727
+ const ticket = registry.register(item);
1728
+ if (/* @__PURE__ */ isBoolean(ticket.value) && ticket.value === true || /* @__PURE__ */ isObject(ticket.value) && /* @__PURE__ */ isBoolean(ticket.value.$value) && ticket.value.$value === true) registry.select(ticket.id);
1729
+ return ticket;
1730
+ }
1731
+ const context = {
1732
+ ...registry,
1733
+ variation,
1734
+ register,
1735
+ get size() {
1736
+ return registry.size;
1737
+ }
1738
+ };
1739
+ function provideFeaturesContext(_context = context, app) {
1740
+ return _provideFeaturesContext(_context, app);
1741
+ }
1742
+ return createTrinity(useFeaturesContext, provideFeaturesContext, context);
1743
+ }
1744
+ /**
1745
+ * Returns the current features instance.
1746
+ *
1747
+ * @template Z The type of the feature ticket.
1748
+ * @returns The current features instance.
1749
+ *
1750
+ * @see https://0.vuetifyjs.com/composables/plugins/create-features
1751
+ *
1752
+ * @example
1753
+ * ```vue
1754
+ * <script setup lang="ts">
1755
+ * import { useFeatures } from '@vuetify/v0'
1756
+ *
1757
+ * const features = useFeatures()
1758
+ * <\/script>
1759
+ *
1760
+ * <template>
1761
+ * <div>
1762
+ * <p>Features: {{ features.get('dark-mode') }}</p>
1763
+ * <p>Theme Color: {{ features.variation('theme-color') }}</p>
1764
+ * </div>
1765
+ * </template>
1766
+ * ```
1767
+ */
1768
+ function useFeatures() {
1769
+ return useContext("v0:features");
1770
+ }
1771
+ /**
1772
+ * Creates a new features plugin.
1773
+ *
1774
+ * @param options The options for the features plugin.
1775
+ * @template Z The type of the feature ticket.
1776
+ * @template E The type of the feature context.
1777
+ * @returns A new features plugin.
1778
+ *
1779
+ * @see https://0.vuetifyjs.com/composables/plugins/create-features
1780
+ *
1781
+ * @example
1782
+ * ```ts
1783
+ * import { createApp } from 'vue'
1784
+ * import { createFeaturesPlugin } from '@vuetify/v0'
1785
+ * import App from './App.vue'
1786
+ *
1787
+ * const app = createApp(App)
1788
+ *
1789
+ * app.use(
1790
+ * createFeaturesPlugin({
1791
+ * features: {
1792
+ * 'dark-mode': true,
1793
+ * 'theme-color': { $variation: 'blue' },
1794
+ * },
1795
+ * })
1796
+ * )
1797
+ *
1798
+ * app.mount('#app')
1799
+ * ```
1800
+ */
1801
+ function createFeaturesPlugin(options = {}) {
1802
+ const [, provideFeaturesContext, context] = createFeatures("v0:features", options);
1803
+ return createPlugin({
1804
+ namespace: "v0:features",
1805
+ provide: (app) => {
1806
+ provideFeaturesContext(context, app);
1807
+ }
1808
+ });
1809
+ }
1810
+
1811
+ //#endregion
1812
+ //#region src/composables/useFilter/index.ts
1813
+ function defaultFilter(query, item, keys, mode = "some") {
1814
+ const queries = Array.isArray(query) ? query.map((q) => String(q).toLowerCase()) : [String(query).toLowerCase()];
1815
+ function match(value, q) {
1816
+ return String(value).toLowerCase().includes(q);
1817
+ }
1818
+ const stringValues = (typeof item === "object" && item !== null ? keys?.length ? keys.map((k) => item[k]) : Object.values(item) : [item]).map((v) => String(v).toLowerCase());
1819
+ if (mode === "some") return stringValues.some((val) => match(val, queries[0]));
1820
+ if (mode === "every") return stringValues.every((val) => match(val, queries[0]));
1821
+ if (mode === "union") return queries.some((q) => stringValues.some((val) => match(val, q)));
1822
+ if (mode === "intersection") return queries.every((q) => stringValues.some((val) => match(val, q)));
1823
+ return false;
1824
+ }
1825
+ /**
1826
+ * A reusable function for filtering an array of items.
1827
+ *
1828
+ * @param query The query to filter by.
1829
+ * @param items The items to filter.
1830
+ * @param options The filter options.
1831
+ * @template Z The type of the items.
1832
+ * @returns The filtered items.
1833
+ *
1834
+ * @see https://0.vuetifyjs.com/composables/selection/use-filter
1835
+ *
1836
+ * @example
1837
+ * ```ts
1838
+ * import { ref } from 'vue'
1839
+ * import { useFilter } from '@vuetify/v0'
1840
+ *
1841
+ * const items = ref([
1842
+ * { name: 'John Doe', age: 30 },
1843
+ * { name: 'Jane Doe', age: 25 },
1844
+ * { name: 'Peter Jones', age: 40 },
1845
+ * ])
1846
+ *
1847
+ * const query = ref('doe')
1848
+ * const { items: filtered } = useFilter(query, items, { keys: ['name'] })
1849
+ *
1850
+ * console.log(filtered.value) // [ { name: 'John Doe', age: 30 }, { name: 'Jane Doe', age: 25 } ]
1851
+ * ```
1852
+ */
1853
+ function useFilter(query, items, options = {}) {
1854
+ const { customFilter, keys, mode = "some" } = options;
1855
+ const filterFunction = customFilter ?? ((q, i) => defaultFilter(q, i, keys, mode));
1856
+ const itemsRef = isRef(items) ? items : toRef(() => items);
1857
+ const queryRef = toRef(query);
1858
+ return { items: computed(() => {
1859
+ const q = toValue(queryRef);
1860
+ const queries = (Array.isArray(q) ? q : [q]).filter((q$1) => String(q$1).trim());
1861
+ if (queries.length === 0) return itemsRef.value;
1862
+ const queryParam = queries.length === 1 ? queries[0] : queries;
1863
+ return itemsRef.value.filter((item) => filterFunction(queryParam, item));
1864
+ }) };
1865
+ }
1866
+
1867
+ //#endregion
1868
+ //#region src/composables/useForm/index.ts
1869
+ /**
1870
+ * Creates a new form instance.
1871
+ *
1872
+ * @param options The options for the form instance.
1873
+ * @template Z The type of the form ticket.
1874
+ * @template E The type of the form context.
1875
+ * @returns A new form instance.
1876
+ *
1877
+ * @see https://0.vuetifyjs.com/composables/forms/use-form
1878
+ *
1879
+ * @example
1880
+ * ```ts
1881
+ * import { useForm } from '@vuetify/v0'
1882
+ *
1883
+ * const form = useForm()
1884
+ *
1885
+ * const username = form.register({
1886
+ * id: 'username',
1887
+ * value: '',
1888
+ * rules: [(v) => v.length > 0 || 'Username is required'],
1889
+ * })
1890
+ *
1891
+ * await form.submit()
1892
+ *
1893
+ * console.log(username.errors.value) // ['Username is required']
1894
+ *
1895
+ * form.reset()
1896
+ * ```
1897
+ */
1898
+ function useForm(options) {
1899
+ const registry = useRegistry(options);
1900
+ const validateOn = options?.validateOn || "submit";
1901
+ function parse(value) {
1902
+ return value.toLowerCase().split(/\s+/);
1903
+ }
1904
+ function validatesOn(event) {
1905
+ return parse(validateOn).includes(event);
1906
+ }
1907
+ const isValidating = computed(() => {
1908
+ for (const ticket of registry.collection.values()) if (ticket.isValidating.value) return true;
1909
+ return false;
1910
+ });
1911
+ const isValid = computed(() => {
1912
+ let hasFields = false;
1913
+ for (const ticket of registry.values()) {
1914
+ hasFields = true;
1915
+ if (ticket.isValid.value === false) return false;
1916
+ if (ticket.isValid.value === null) return null;
1917
+ }
1918
+ return hasFields ? true : null;
1919
+ });
1920
+ function reset() {
1921
+ for (const ticket of registry.values()) ticket.reset();
1922
+ }
1923
+ async function submit() {
1924
+ return validate(registry.keys());
1925
+ }
1926
+ async function validate(id) {
1927
+ const validating = toArray(id);
1928
+ if (validatesOn("submit")) return (await Promise.all(validating.map(async (id$1) => await registry.get(id$1)?.validate() ?? true))).every(Boolean);
1929
+ return validating.map((id$1) => registry.get(id$1)).filter(Boolean).every((ticket) => ticket.isValid.value === true);
1930
+ }
1931
+ function register(registration) {
1932
+ const model = shallowRef(registration.value == null ? "" : toValue(registration.value));
1933
+ const rules = registration.rules || [];
1934
+ const errors = shallowRef([]);
1935
+ const isValidating$1 = shallowRef(false);
1936
+ const initialValue = model.value;
1937
+ const triggers = registration.validateOn || validateOn;
1938
+ const isPristine = shallowRef(true);
1939
+ const isValid$1 = shallowRef(null);
1940
+ function _validatesOn(event) {
1941
+ return parse(triggers).includes(event);
1942
+ }
1943
+ function _reset() {
1944
+ model.value = initialValue;
1945
+ errors.value = [];
1946
+ isPristine.value = true;
1947
+ isValid$1.value = null;
1948
+ }
1949
+ async function validate$1(silent = false) {
1950
+ if (rules.length === 0) return true;
1951
+ isValidating$1.value = true;
1952
+ try {
1953
+ const errorMessages = (await Promise.all(rules.map((rule) => rule(model.value)))).filter((result) => typeof result === "string");
1954
+ if (!silent) {
1955
+ errors.value = errorMessages;
1956
+ isValid$1.value = errorMessages.length === 0;
1957
+ isPristine.value = toValue(model) === initialValue;
1958
+ }
1959
+ return errorMessages.length === 0;
1960
+ } finally {
1961
+ isValidating$1.value = false;
1962
+ }
1963
+ }
1964
+ const item = {
1965
+ ...registration,
1966
+ rules,
1967
+ errors,
1968
+ disabled: registration.disabled || false,
1969
+ validateOn: triggers,
1970
+ isValidating: isValidating$1,
1971
+ isPristine,
1972
+ isValid: isValid$1,
1973
+ reset: _reset,
1974
+ validate: validate$1
1975
+ };
1976
+ const ticket = registry.register(item);
1977
+ Object.defineProperty(ticket, "value", {
1978
+ get() {
1979
+ return model.value;
1980
+ },
1981
+ set(val) {
1982
+ model.value = val;
1983
+ isPristine.value = val === initialValue;
1984
+ isValid$1.value = null;
1985
+ if (_validatesOn("change")) validate$1();
1986
+ },
1987
+ enumerable: true,
1988
+ configurable: true
1989
+ });
1990
+ return ticket;
1991
+ }
1992
+ return {
1993
+ ...registry,
1994
+ register,
1995
+ reset,
1996
+ submit,
1997
+ validateOn,
1998
+ isValid,
1999
+ isValidating,
2000
+ get size() {
2001
+ return registry.size;
2002
+ }
2003
+ };
2004
+ }
2005
+
2006
+ //#endregion
2007
+ //#region src/composables/useIntersectionObserver/index.ts
2008
+ /**
2009
+ * A composable that uses the Intersection Observer API to detect when an element
2010
+ * is visible in the viewport.
2011
+ *
2012
+ * @param target The element to observe.
2013
+ * @param callback The callback to execute when the element's intersection changes.
2014
+ * @param options The options for the Intersection Observer.
2015
+ * @returns An object with methods to control the observer.
2016
+ *
2017
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver
2018
+ * @see https://0.vuetifyjs.com/composables/system/use-intersection-observer
2019
+ *
2020
+ * @example
2021
+ * ```ts
2022
+ * import { ref } from 'vue'
2023
+ * import { useIntersectionObserver } from '@vuetify/v0'
2024
+ *
2025
+ * const target = ref<HTMLElement>()
2026
+ * const isVisible = ref(false)
2027
+ *
2028
+ * const { isIntersecting, pause, resume } = useIntersectionObserver(
2029
+ * target,
2030
+ * (entries) => {
2031
+ * const entry = entries[0]
2032
+ * if (entry) {
2033
+ * isVisible.value = entry.isIntersecting
2034
+ * console.log('Element is visible:', entry.isIntersecting)
2035
+ * }
2036
+ * },
2037
+ * { threshold: 0.5 }
2038
+ * )
2039
+ *
2040
+ * // Pause observation
2041
+ * pause()
2042
+ *
2043
+ * // Resume observation
2044
+ * resume()
2045
+ * ```
2046
+ */
2047
+ function useIntersectionObserver(target, callback, options = {}) {
2048
+ const { isHydrated } = useHydration();
2049
+ const observer = shallowRef();
2050
+ const isPaused = shallowRef(false);
2051
+ const isIntersecting = shallowRef(false);
2052
+ function setup() {
2053
+ if (!isHydrated.value || !SUPPORTS_INTERSECTION_OBSERVER || !target.value || isPaused.value) return;
2054
+ observer.value = new IntersectionObserver((entries) => {
2055
+ const transformedEntries = entries.map((entry) => ({
2056
+ boundingClientRect: entry.boundingClientRect,
2057
+ intersectionRatio: entry.intersectionRatio,
2058
+ intersectionRect: entry.intersectionRect,
2059
+ isIntersecting: entry.isIntersecting,
2060
+ rootBounds: entry.rootBounds,
2061
+ target: entry.target,
2062
+ time: entry.time
2063
+ }));
2064
+ const latestEntry = transformedEntries.at(-1);
2065
+ if (latestEntry) isIntersecting.value = latestEntry.isIntersecting;
2066
+ callback(transformedEntries);
2067
+ }, {
2068
+ root: options.root || null,
2069
+ rootMargin: options.rootMargin || "0px",
2070
+ threshold: options.threshold || 0
2071
+ });
2072
+ observer.value.observe(target.value);
2073
+ if (options.immediate) callback([{
2074
+ boundingClientRect: target.value.getBoundingClientRect(),
2075
+ intersectionRatio: 0,
2076
+ intersectionRect: new DOMRect(0, 0, 0, 0),
2077
+ isIntersecting: false,
2078
+ rootBounds: null,
2079
+ target: target.value,
2080
+ time: performance.now()
2081
+ }]);
2082
+ }
2083
+ watch([isHydrated, target], () => {
2084
+ cleanup();
2085
+ setup();
2086
+ }, { immediate: true });
2087
+ function cleanup() {
2088
+ if (observer.value) {
2089
+ observer.value.disconnect();
2090
+ observer.value = void 0;
2091
+ }
2092
+ }
2093
+ function pause() {
2094
+ isPaused.value = true;
2095
+ isIntersecting.value = false;
2096
+ observer.value?.disconnect();
2097
+ }
2098
+ function resume() {
2099
+ isPaused.value = false;
2100
+ setup();
2101
+ }
2102
+ function stop() {
2103
+ cleanup();
2104
+ }
2105
+ onUnmounted(stop);
2106
+ return {
2107
+ isIntersecting: readonly(isIntersecting),
2108
+ isPaused: readonly(isPaused),
2109
+ pause,
2110
+ resume,
2111
+ stop
2112
+ };
2113
+ }
2114
+ /**
2115
+ * A convenience composable that uses the Intersection Observer API to detect
2116
+ * when an element is visible in the viewport.
2117
+ *
2118
+ * @param target The element to observe.
2119
+ * @param options The options for the Intersection Observer.
2120
+ * @returns An object with the intersection state.
2121
+ *
2122
+ * @see https://0.vuetifyjs.com/composables/system/use-intersection-observer
2123
+ *
2124
+ * @example
2125
+ * ```ts
2126
+ * import { ref } from 'vue'
2127
+ * import { useElementIntersection } from '@vuetify/v0'
2128
+ *
2129
+ * const myElement = ref<HTMLElement>()
2130
+ * const { isIntersecting, intersectionRatio } = useElementIntersection(myElement, {
2131
+ * threshold: 0.5
2132
+ * })
2133
+ *
2134
+ * // Use in template to conditionally render or animate
2135
+ * watchEffect(() => {
2136
+ * if (isIntersecting.value) {
2137
+ * console.log('Element is visible!', intersectionRatio.value)
2138
+ * }
2139
+ * })
2140
+ * ```
2141
+ */
2142
+ function useElementIntersection(target, options = {}) {
2143
+ const isIntersecting = shallowRef(false);
2144
+ const intersectionRatio = shallowRef(0);
2145
+ const { pause: _pause, resume, stop, isPaused } = useIntersectionObserver(target, (entries) => {
2146
+ const entry = entries.at(-1);
2147
+ if (entry) {
2148
+ isIntersecting.value = entry.isIntersecting;
2149
+ intersectionRatio.value = entry.intersectionRatio;
2150
+ }
2151
+ }, {
2152
+ immediate: true,
2153
+ ...options
2154
+ });
2155
+ function pause() {
2156
+ isIntersecting.value = false;
2157
+ intersectionRatio.value = 0;
2158
+ _pause();
2159
+ }
2160
+ return {
2161
+ isIntersecting: readonly(isIntersecting),
2162
+ intersectionRatio: readonly(intersectionRatio),
2163
+ isPaused,
2164
+ pause,
2165
+ resume,
2166
+ stop
2167
+ };
2168
+ }
2169
+
2170
+ //#endregion
2171
+ //#region src/composables/useKeydown/index.ts
2172
+ /**
2173
+ * A composable that adds a keydown event listener to the document.
2174
+ *
2175
+ * @param handlers The key handlers to add.
2176
+ * @returns An object with methods to start and stop listening.
2177
+ *
2178
+ * @see https://0.vuetifyjs.com/composables/system/use-keydown
2179
+ *
2180
+ * @example
2181
+ * ```ts
2182
+ * import { useKeydown } from '@vuetify/v0'
2183
+ *
2184
+ * const { startListening, stopListening } = useKeydown([
2185
+ * { key: 'Enter', handler: () => console.log('Enter pressed') },
2186
+ * { key: 'Escape', handler: () => console.log('Escape pressed'), preventDefault: true },
2187
+ * ])
2188
+ *
2189
+ * startListening()
2190
+ * stopListening()
2191
+ * ```
2192
+ */
2193
+ function useKeydown(handlers) {
2194
+ const keyHandlers = Array.isArray(handlers) ? handlers : [handlers];
2195
+ function onKeydown(event) {
2196
+ const handler = keyHandlers.find((h$1) => h$1.key === event.key);
2197
+ if (handler) {
2198
+ if (handler.preventDefault) event.preventDefault();
2199
+ if (handler.stopPropagation) event.stopPropagation();
2200
+ handler.handler(event);
2201
+ }
2202
+ }
2203
+ function startListening() {
2204
+ document.addEventListener("keydown", onKeydown);
2205
+ }
2206
+ function stopListening() {
2207
+ document.removeEventListener("keydown", onKeydown);
2208
+ }
2209
+ if (getCurrentScope()) onMounted(startListening);
2210
+ onScopeDispose(stopListening, true);
2211
+ return {
2212
+ startListening,
2213
+ stopListening
2214
+ };
2215
+ }
2216
+
2217
+ //#endregion
2218
+ //#region src/composables/useSingle/index.ts
2219
+ /**
2220
+ * Creates a new single selection instance.
2221
+ *
2222
+ * @param options The options for the single selection instance.
2223
+ * @template Z The type of the single selection ticket.
2224
+ * @template E The type of the single selection context.
2225
+ * @returns A new single selection instance.
2226
+ *
2227
+ * @see https://0.vuetifyjs.com/composables/selection/use-single
2228
+ *
2229
+ * @example
2230
+ * ```ts
2231
+ * import { useSingle } from '@vuetify/v0'
2232
+ *
2233
+ * const single = useSingle()
2234
+ *
2235
+ * single.onboard([
2236
+ * { id: 'option-1', value: 'Option 1' },
2237
+ * { id: 'option-2', value: 'Option 2' },
2238
+ * ])
2239
+ *
2240
+ * single.select('option-1')
2241
+ *
2242
+ * console.log(single.selectedId.value) // 'option-1'
2243
+ * ```
2244
+ */
2245
+ function useSingle(options) {
2246
+ const registry = useSelection(options);
2247
+ const mandatory = options?.mandatory ?? false;
2248
+ const selectedId = computed(() => registry.selectedIds.values().next().value);
2249
+ const selectedItem = computed(() => registry.selectedItems.value.values().next().value);
2250
+ const selectedIndex = computed(() => selectedItem.value?.index ?? -1);
2251
+ const selectedValue = computed(() => selectedItem.value?.value);
2252
+ function select(id) {
2253
+ const item = registry.get(id);
2254
+ if (!item || item.disabled) return;
2255
+ registry.selectedIds.clear();
2256
+ registry.select(id);
2257
+ }
2258
+ function unselect(id) {
2259
+ if (mandatory && registry.selectedIds.size === 1) return;
2260
+ registry.selectedIds.delete(id);
2261
+ }
2262
+ function toggle(id) {
2263
+ if (registry.selectedIds.has(id)) unselect(id);
2264
+ else select(id);
2265
+ }
2266
+ return {
2267
+ ...registry,
2268
+ selectedId,
2269
+ selectedItem,
2270
+ selectedIndex,
2271
+ selectedValue,
2272
+ select,
2273
+ unselect,
2274
+ toggle,
2275
+ get size() {
2276
+ return registry.size;
2277
+ }
2278
+ };
2279
+ }
2280
+ /**
2281
+ * Creates a new single selection context.
2282
+ *
2283
+ * @param namespace The namespace for the single selection context.
2284
+ * @param options The options for the single selection context.
2285
+ * @template Z The type of the single selection ticket.
2286
+ * @template E The type of the single selection context.
2287
+ * @returns A new single selection context.
2288
+ *
2289
+ * @see https://0.vuetifyjs.com/composables/selection/use-single
2290
+ *
2291
+ * @example
2292
+ * ```ts
2293
+ * import { createSingleContext } from '@vuetify/v0'
2294
+ *
2295
+ * export const [useTabs, provideTabs, tabs] = createSingleContext('tabs', { mandatory: true })
2296
+ *
2297
+ * // In a parent component:
2298
+ * provideTabs()
2299
+ *
2300
+ * // In a child component:
2301
+ * const tabs = useTabs()
2302
+ * tabs.select('tab-1')
2303
+ * ```
2304
+ */
2305
+ function createSingleContext(namespace, options) {
2306
+ const [useSingleContext, _provideSingleContext] = createContext(namespace);
2307
+ const context = useSingle(options);
2308
+ function provideSingleContext(_context = context, app) {
2309
+ return _provideSingleContext(_context, app);
2310
+ }
2311
+ return createTrinity(useSingleContext, provideSingleContext, context);
2312
+ }
2313
+
2314
+ //#endregion
2315
+ //#region src/composables/useLocale/adapters/v0.ts
2316
+ /**
2317
+ * Vuetify0.x locale adapter implementation
2318
+ *
2319
+ * This adapter provides translation and number formatting
2320
+ * capabilities using the Intl API and supports both
2321
+ * numbered and named variables in translation strings.
2322
+ */
2323
+ var Vuetify0LocaleAdapter = class {
2324
+ t(message, ...params) {
2325
+ let resolvedMessage = message;
2326
+ if (params.length > 0 && typeof params[0] === "object" && params[0] !== null && !Array.isArray(params[0])) {
2327
+ const variables = params[0];
2328
+ resolvedMessage = resolvedMessage.replace(/{([a-zA-Z][a-zA-Z0-9_]*)}/g, (match, name) => {
2329
+ return variables[name] === void 0 ? match : String(variables[name]);
2330
+ });
2331
+ params = params.slice(1);
2332
+ }
2333
+ resolvedMessage = resolvedMessage.replace(/\{(\d+)\}/g, (match, index) => {
2334
+ const idx = Number.parseInt(index, 10);
2335
+ if (params[idx] !== void 0) return String(params[idx]);
2336
+ return match;
2337
+ });
2338
+ return resolvedMessage;
2339
+ }
2340
+ n(value, locale, ...params) {
2341
+ if (!IN_BROWSER || !locale) return value.toString();
2342
+ const options = params[0];
2343
+ return new Intl.NumberFormat(String(locale), options).format(value);
2344
+ }
2345
+ };
2346
+
2347
+ //#endregion
2348
+ //#region src/composables/useLocale/index.ts
2349
+ /**
2350
+ * Creates a new locale instance.
2351
+ *
2352
+ * @param namespace The namespace for the locale instance.
2353
+ * @param options The options for the locale instance.
2354
+ * @template Z The type of the locale ticket.
2355
+ * @template E The type of the locale context.
2356
+ * @returns A new locale instance.
2357
+ *
2358
+ * @see https://0.vuetifyjs.com/composables/plugins/use-locale
2359
+ */
2360
+ function createLocale(namespace = "v0:locale", options = {}) {
2361
+ const { adapter = new Vuetify0LocaleAdapter(), messages = {} } = options;
2362
+ const [useLocaleContext, _provideLocaleContext] = createContext(namespace);
2363
+ const registry = useSingle();
2364
+ for (const id in messages) {
2365
+ registry.register({
2366
+ value: messages[id],
2367
+ id
2368
+ });
2369
+ if (id === options.default && !registry.selectedId.value) registry.select(id);
2370
+ }
2371
+ function t(key, ...params) {
2372
+ const locale = registry.selectedId.value;
2373
+ if (!locale) return key;
2374
+ const message = messages[locale]?.[key];
2375
+ const template = typeof message === "string" ? resolve(locale, message) : key;
2376
+ return adapter.t(template, ...params);
2377
+ }
2378
+ function n(value, ...params) {
2379
+ return adapter.n(value, registry.selectedId.value, ...params);
2380
+ }
2381
+ function resolve(locale, str) {
2382
+ return str.replace(/{([a-zA-Z0-9.-_]+)}/g, (match, linkedKey) => {
2383
+ const [linkedLocale, ...rest] = linkedKey.split(".");
2384
+ const keyPath = rest.join(".");
2385
+ const targetLocale = messages[linkedLocale] ? linkedLocale : locale;
2386
+ const targetKey = messages[linkedLocale] ? keyPath : linkedKey;
2387
+ const resolved = messages[targetLocale]?.[targetKey];
2388
+ return typeof resolved === "string" ? resolve(targetLocale, resolved) : match;
2389
+ });
2390
+ }
2391
+ const context = {
2392
+ ...registry,
2393
+ t,
2394
+ n,
2395
+ get size() {
2396
+ return registry.size;
2397
+ }
2398
+ };
2399
+ function provideLocaleContext(_context = context, app) {
2400
+ return _provideLocaleContext(_context, app);
2401
+ }
2402
+ return createTrinity(useLocaleContext, provideLocaleContext, context);
2403
+ }
2404
+ /**
2405
+ * Returns the current locale instance.
2406
+ *
2407
+ * @returns The current locale instance.
2408
+ *
2409
+ * @see https://0.vuetifyjs.com/composables/plugins/use-locale
2410
+ */
2411
+ function useLocale() {
2412
+ return useContext("v0:locale");
2413
+ }
2414
+ /**
2415
+ * Creates a new locale plugin.
2416
+ *
2417
+ * @param options The options for the locale plugin.
2418
+ * @template Z The type of the locale ticket.
2419
+ * @template E The type of the locale context.
2420
+ * @template R The type of the token ticket.
2421
+ * @template O The type of the token context.
2422
+ * @returns A new locale plugin.
2423
+ *
2424
+ * @see https://0.vuetifyjs.com/composables/plugins/use-locale
2425
+ */
2426
+ function createLocalePlugin(options = {}) {
2427
+ const { adapter = new Vuetify0LocaleAdapter(), messages = {} } = options;
2428
+ const [, provideLocaleTokenContext, tokensContext] = createTokensContext("v0:locale:tokens", messages);
2429
+ const [, provideLocaleContext, localeContext] = createLocale("v0:locale", {
2430
+ adapter,
2431
+ messages
2432
+ });
2433
+ return createPlugin({
2434
+ namespace: "v0:locale",
2435
+ provide: (app) => {
2436
+ provideLocaleContext(localeContext, app);
2437
+ provideLocaleTokenContext(tokensContext, app);
2438
+ }
2439
+ });
2440
+ }
2441
+
2442
+ //#endregion
2443
+ //#region src/composables/useMutationObserver/index.ts
2444
+ /**
2445
+ * A composable that uses the Mutation Observer API to detect changes in the DOM.
2446
+ *
2447
+ * @param target The element to observe.
2448
+ * @param callback The callback to execute when a mutation is observed.
2449
+ * @param options The options for the Mutation Observer.
2450
+ * @returns An object with methods to control the observer.
2451
+ *
2452
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver
2453
+ * @see https://0.vuetifyjs.com/composables/system/use-mutation-observer
2454
+ *
2455
+ * @example
2456
+ * ```ts
2457
+ * import { ref } from 'vue'
2458
+ * import { useMutationObserver } from '@vuetify/v0'
2459
+ *
2460
+ * const container = ref<HTMLElement>()
2461
+ *
2462
+ * const { pause, resume, isPaused } = useMutationObserver(
2463
+ * container,
2464
+ * (mutations) => {
2465
+ * mutations.forEach((mutation) => {
2466
+ * if (mutation.type === 'childList') {
2467
+ * console.log('Children changed:', mutation.addedNodes, mutation.removedNodes)
2468
+ * } else if (mutation.type === 'attributes') {
2469
+ * console.log('Attribute changed:', mutation.attributeName)
2470
+ * }
2471
+ * })
2472
+ * },
2473
+ * {
2474
+ * childList: true,
2475
+ * attributes: true,
2476
+ * subtree: true
2477
+ * }
2478
+ * )
2479
+ *
2480
+ * // Pause observation
2481
+ * pause()
2482
+ *
2483
+ * // Resume observation
2484
+ * resume()
2485
+ * ```
2486
+ */
2487
+ function useMutationObserver(target, callback, options = {}) {
2488
+ const { isHydrated } = useHydration();
2489
+ const observer = shallowRef();
2490
+ const isPaused = shallowRef(false);
2491
+ const observerOptions = {
2492
+ childList: options.childList ?? true,
2493
+ attributes: options.attributes ?? false,
2494
+ characterData: options.characterData ?? false,
2495
+ subtree: options.subtree ?? false,
2496
+ attributeOldValue: options.attributeOldValue ?? false,
2497
+ characterDataOldValue: options.characterDataOldValue ?? false,
2498
+ attributeFilter: options.attributeFilter
2499
+ };
2500
+ function setup() {
2501
+ if (!isHydrated.value || !SUPPORTS_MUTATION_OBSERVER || !target.value || isPaused.value) return;
2502
+ observer.value = new MutationObserver((mutations) => {
2503
+ callback(mutations.map((mutation) => ({
2504
+ type: mutation.type,
2505
+ target: mutation.target,
2506
+ addedNodes: mutation.addedNodes,
2507
+ removedNodes: mutation.removedNodes,
2508
+ previousSibling: mutation.previousSibling,
2509
+ nextSibling: mutation.nextSibling,
2510
+ attributeName: mutation.attributeName,
2511
+ attributeNamespace: mutation.attributeNamespace,
2512
+ oldValue: mutation.oldValue
2513
+ })));
2514
+ });
2515
+ observer.value.observe(target.value, observerOptions);
2516
+ if (options.immediate) {
2517
+ const emptyNodeList = {
2518
+ length: 0,
2519
+ item: () => null,
2520
+ forEach: () => {},
2521
+ *[Symbol.iterator]() {}
2522
+ };
2523
+ callback([{
2524
+ type: "childList",
2525
+ target: target.value,
2526
+ addedNodes: emptyNodeList,
2527
+ removedNodes: emptyNodeList,
2528
+ previousSibling: null,
2529
+ nextSibling: null,
2530
+ attributeName: null,
2531
+ attributeNamespace: null,
2532
+ oldValue: null
2533
+ }]);
2534
+ }
2535
+ }
2536
+ watch([isHydrated, target], () => {
2537
+ cleanup();
2538
+ setup();
2539
+ }, { immediate: true });
2540
+ function cleanup() {
2541
+ if (observer.value) {
2542
+ observer.value.disconnect();
2543
+ observer.value = void 0;
2544
+ }
2545
+ }
2546
+ function pause() {
2547
+ isPaused.value = true;
2548
+ observer.value?.disconnect();
2549
+ }
2550
+ function resume() {
2551
+ isPaused.value = false;
2552
+ setup();
2553
+ }
2554
+ function stop() {
2555
+ cleanup();
2556
+ }
2557
+ onUnmounted(stop);
2558
+ return {
2559
+ isPaused: readonly(isPaused),
2560
+ pause,
2561
+ resume,
2562
+ stop
2563
+ };
2564
+ }
2565
+
2566
+ //#endregion
2567
+ //#region src/composables/usePermissions/adapters/adapter.ts
2568
+ var PermissionAdapter = class {};
2569
+
2570
+ //#endregion
2571
+ //#region src/composables/usePermissions/adapters/v0.ts
2572
+ var Vuetify0PermissionAdapter = class extends PermissionAdapter {
2573
+ constructor() {
2574
+ super();
2575
+ }
2576
+ can(role, action, subject, context, permissions) {
2577
+ const access = `${role}.${action}.${subject}`;
2578
+ const ticket = permissions.get(access);
2579
+ if (!ticket || !ticket.value) return false;
2580
+ return /* @__PURE__ */ isFunction(ticket.value) ? ticket.value(context) : ticket.value;
2581
+ }
2582
+ };
2583
+
2584
+ //#endregion
2585
+ //#region src/composables/usePermissions/index.ts
2586
+ /**
2587
+ * Creates a new permissions instance.
2588
+ *
2589
+ * @param namespace The namespace for the permissions instance.
2590
+ * @param options The options for the permissions instance.
2591
+ * @template Z The type of the permission ticket.
2592
+ * @template E The type of the permission context.
2593
+ * @returns A new permissions instance.
2594
+ *
2595
+ * @see https://0.vuetifyjs.com/composables/plugins/create-permissions
2596
+ *
2597
+ * @example
2598
+ * ```ts
2599
+ * import { createPermissions } from '@vuetify/v0'
2600
+ *
2601
+ * const [usePermissions, providePermissions] = createPermissions('v0:permissions', {
2602
+ * permissions: {
2603
+ * admin: [['read', 'users']],
2604
+ * editor: [['edit', 'posts']],
2605
+ * },
2606
+ * })
2607
+ * ```
2608
+ */
2609
+ function createPermissions(namespace = "v0:permissions", options = {}) {
2610
+ const { adapter = new Vuetify0PermissionAdapter(), permissions = {} } = options;
2611
+ const [usePermissionsContext, _providePermissionsContext] = createContext(namespace);
2612
+ const record = {};
2613
+ for (const role in permissions) {
2614
+ if (!record[role]) record[role] = {};
2615
+ for (const [actions, subjects, condition = true] of permissions[role]) for (const action of toArray(actions)) for (const subject of toArray(subjects)) {
2616
+ if (!record[role][action]) record[role][action] = {};
2617
+ record[role][action][subject] = condition;
2618
+ }
2619
+ }
2620
+ const tokens = useTokens(record);
2621
+ function can(id, action, subject, context$1 = {}) {
2622
+ return adapter.can(id, action, subject, context$1, tokens);
2623
+ }
2624
+ const context = {
2625
+ ...tokens,
2626
+ can
2627
+ };
2628
+ function providePermissionsContext(_context = context, app) {
2629
+ return _providePermissionsContext(_context, app);
2630
+ }
2631
+ return createTrinity(usePermissionsContext, providePermissionsContext, context);
2632
+ }
2633
+ /**
2634
+ * Returns the current permissions instance.
2635
+ *
2636
+ * @template Z The type of the permission ticket.
2637
+ * @returns The current permissions instance.
2638
+ *
2639
+ * @see https://0.vuetifyjs.com/composables/plugins/use-permissions
2640
+ *
2641
+ * @example
2642
+ * ```vue
2643
+ * <script setup lang="ts">
2644
+ * import { usePermissions } from '@vuetify/v0'
2645
+ *
2646
+ * const { can } = usePermissions()
2647
+ * <\/script>
2648
+ *
2649
+ * <template>
2650
+ * <div>
2651
+ * <p v-if="can('admin', 'read', 'users')">Admin access</p>
2652
+ * </div>
2653
+ * </template>
2654
+ * ```
2655
+ */
2656
+ function usePermissions() {
2657
+ return useContext("v0:permissions");
2658
+ }
2659
+ /**
2660
+ * Creates a new permissions plugin.
2661
+ *
2662
+ * @param options The options for the permissions plugin.
2663
+ * @template Z The type of the permission ticket.
2664
+ * @template E The type of the permission context.
2665
+ * @returns A new permissions plugin.
2666
+ *
2667
+ * @see https://0.vuetifyjs.com/composables/plugins/use-permissions
2668
+ *
2669
+ * @example
2670
+ * ```ts
2671
+ * import { createApp } from 'vue'
2672
+ * import { createPermissionsPlugin } from '@vuetify/v0'
2673
+ * import App from './App.vue'
2674
+ *
2675
+ * const app = createApp(App)
2676
+ *
2677
+ * app.use(
2678
+ * createPermissionsPlugin({
2679
+ * permissions: {
2680
+ * admin: [['read', 'users']],
2681
+ * editor: [['edit', 'posts']],
2682
+ * },
2683
+ * })
2684
+ * )
2685
+ *
2686
+ * app.mount('#app')
2687
+ * ```
2688
+ */
2689
+ function createPermissionsPlugin(options = {}) {
2690
+ const [, providePermissionContext, context] = createPermissions("v0:permissions", options);
2691
+ return createPlugin({
2692
+ namespace: "v0:permissions",
2693
+ provide: (app) => {
2694
+ providePermissionContext(context, app);
2695
+ }
2696
+ });
2697
+ }
2698
+
2699
+ //#endregion
2700
+ //#region src/composables/useProxyModel/index.ts
2701
+ /**
2702
+ * Creates a proxy model that can be used to bind to a selection.
2703
+ *
2704
+ * @param registry The selection registry to bind to.
2705
+ * @param initial The initial value of the model.
2706
+ * @param options The options for the proxy model.
2707
+ * @param transformIn A function to transform the value before setting it.
2708
+ * @param transformOut A function to transform the value before getting it.
2709
+ * @template Z The type of the selection ticket.
2710
+ * @returns A proxy model that can be used to bind to a selection.
2711
+ *
2712
+ * @see https://0.vuetifyjs.com/composables/forms/use-proxy-model
2713
+ *
2714
+ * @example
2715
+ * ```ts
2716
+ * import { useSelection, useProxyModel } from '@vuetify/v0'
2717
+ *
2718
+ * const registry = useSelection({ events: true })
2719
+ * registry.onboard([
2720
+ * { id: 'item-1', value: 'Item 1' },
2721
+ * { id: 'item-2', value: 'Item 2' },
2722
+ * ])
2723
+ *
2724
+ * const model = useProxyModel(registry, 'Item 1')
2725
+ * ```
2726
+ */
2727
+ function useProxyModel(registry, initial, options, _transformIn, _transformOut) {
2728
+ const internal = (options?.deep ? ref : shallowRef)(initial ? toArray(initial) : []);
2729
+ const isModelArray = /* @__PURE__ */ isArray(initial);
2730
+ function transformIn(val) {
2731
+ return /* @__PURE__ */ isFunction(_transformIn) ? _transformIn(val) : toArray(val);
2732
+ }
2733
+ function transformOut(val) {
2734
+ if (/* @__PURE__ */ isFunction(_transformOut)) return _transformOut(val);
2735
+ return isModelArray ? val : val[0];
2736
+ }
2737
+ const model = computed({
2738
+ get() {
2739
+ return transformOut(internal.value);
2740
+ },
2741
+ set(val) {
2742
+ internal.value = transformIn(val);
2743
+ }
2744
+ });
2745
+ const registryWatcher = watch(registry.selectedValues, (val) => {
2746
+ modelWatcher.pause();
2747
+ model.value = Array.from(toValue(val));
2748
+ modelWatcher.resume();
2749
+ });
2750
+ const modelWatcher = watch(model, (val) => {
2751
+ const currentIds = new Set(toValue(registry.selectedIds));
2752
+ const targetIds = /* @__PURE__ */ new Set();
2753
+ for (const value of toArray(val)) {
2754
+ const ids = registry.browse(value);
2755
+ if (/* @__PURE__ */ isArray(ids)) for (const single of ids) targetIds.add(single);
2756
+ else if (ids) targetIds.add(ids);
2757
+ }
2758
+ registryWatcher.pause();
2759
+ if (isModelArray) {
2760
+ for (const id of currentIds.difference(targetIds)) registry.selectedIds.delete(id);
2761
+ for (const id of targetIds.difference(currentIds)) registry.selectedIds.add(id);
2762
+ } else {
2763
+ const next = targetIds.values().next().value;
2764
+ const last = currentIds.values().next().value;
2765
+ if (last !== void 0) registry.unselect(last);
2766
+ if (next !== void 0) registry.select(next);
2767
+ }
2768
+ registryWatcher.resume();
2769
+ });
2770
+ function onRegister(ticket) {
2771
+ if (!internal.value.includes(ticket.value)) return;
2772
+ registryWatcher.pause();
2773
+ modelWatcher.pause();
2774
+ registry.select(ticket.id);
2775
+ registryWatcher.resume();
2776
+ modelWatcher.resume();
2777
+ }
2778
+ function onUnregister(ticket) {
2779
+ if (!internal.value.includes(ticket.value)) return;
2780
+ registryWatcher.pause();
2781
+ modelWatcher.pause();
2782
+ registry.unselect(ticket.id);
2783
+ registryWatcher.resume();
2784
+ modelWatcher.resume();
2785
+ }
2786
+ function onUpdate(ticket) {
2787
+ const hasValue = internal.value.includes(ticket.value);
2788
+ const isSelected = toValue(registry.selectedIds).has(ticket.id);
2789
+ if (!hasValue && isSelected) onUnregister(ticket);
2790
+ else if (hasValue && !isSelected) onRegister(ticket);
2791
+ }
2792
+ function onClear() {
2793
+ registryWatcher.pause();
2794
+ modelWatcher.pause();
2795
+ registry.selectedIds.clear();
2796
+ registryWatcher.resume();
2797
+ modelWatcher.resume();
2798
+ }
2799
+ registry.on("register:ticket", onRegister);
2800
+ registry.on("unregister:ticket", onUnregister);
2801
+ registry.on("update:ticket", onUpdate);
2802
+ registry.on("clear:registry", onClear);
2803
+ onScopeDispose(() => {
2804
+ registryWatcher();
2805
+ modelWatcher();
2806
+ registry.off("register:item", onRegister);
2807
+ registry.off("unregister:ticket", onUnregister);
2808
+ registry.off("update:ticket", onUpdate);
2809
+ registry.off("clear:registry", onClear);
2810
+ }, true);
2811
+ return model;
2812
+ }
2813
+
2814
+ //#endregion
2815
+ //#region src/composables/useProxyRegistry/index.ts
2816
+ /**
2817
+ * Creates a proxy registry that provides reactive objects for registry data.
2818
+ *
2819
+ * @param registry The registry instance to proxy.
2820
+ * @param options The options for the proxy registry.
2821
+ * @template Z The type of the registry ticket.
2822
+ * @returns A proxy registry with reactive objects.
2823
+ *
2824
+ * @see https://0.vuetifyjs.com/composables/registration/use-proxy-registry
2825
+ *
2826
+ * @example
2827
+ * ```ts
2828
+ * import { useRegistry, useProxyRegistry } from '@vuetify/v0'
2829
+ *
2830
+ * const registry = useRegistry({ events: true })
2831
+ * const proxy = useProxyRegistry(registry)
2832
+ *
2833
+ * registry.register({ value: 'Item 1' })
2834
+ * console.log(proxy.size) // 1
2835
+ * ```
2836
+ */
2837
+ function useProxyRegistry(registry, options) {
2838
+ const state = (options?.deep ? reactive : shallowReactive)({
2839
+ keys: registry.keys(),
2840
+ values: registry.values(),
2841
+ entries: registry.entries(),
2842
+ size: registry.size
2843
+ });
2844
+ function update() {
2845
+ state.keys = registry.keys();
2846
+ state.values = registry.values();
2847
+ state.entries = registry.entries();
2848
+ state.size = registry.size;
2849
+ }
2850
+ registry.on("register:ticket", update);
2851
+ registry.on("unregister:ticket", update);
2852
+ registry.on("update:ticket", update);
2853
+ registry.on("clear:registry", update);
2854
+ onScopeDispose(() => {
2855
+ registry.off("register:item", update);
2856
+ registry.off("unregister:ticket", update);
2857
+ registry.off("update:ticket", update);
2858
+ registry.off("clear:registry", update);
2859
+ }, true);
2860
+ return state;
2861
+ }
2862
+
2863
+ //#endregion
2864
+ //#region src/composables/useQueue/index.ts
2865
+ /**
2866
+ * Creates a new queue instance
2867
+ *
2868
+ * @param options The options for the queue instance
2869
+ * @template Z The type of queue ticket that extends QueueTicket. Use this to add custom properties to tickets.
2870
+ * @template E The type of queue context that extends QueueContext<Z>. Use this when extending the queue with additional methods.
2871
+ * @returns A new queue instance
2872
+ *
2873
+ * @see https://0.vuetifyjs.com/composables/registration/use-queue
2874
+ *
2875
+ * @example
2876
+ * ```ts
2877
+ * import { useQueue } from '@vuetify/v0'
2878
+ *
2879
+ * const queue = useQueue()
2880
+ *
2881
+ * // Register an ticket with default timeout (3000ms)
2882
+ * const ticket1 = queue.register({ value: 'Ticket 1' })
2883
+ *
2884
+ * // Register an ticket with custom timeout
2885
+ * const ticket2 = queue.register({ value: 'Ticket 2', timeout: 5000 })
2886
+ *
2887
+ * // Register a persistent ticket that must be manually dismissed
2888
+ * const ticket3 = queue.register({ value: 'Ticket 3', timeout: -1 })
2889
+ *
2890
+ * // Dismiss an ticket using the convenience method
2891
+ * ticket3.dismiss()
2892
+ *
2893
+ * console.log(queue.size) // 2
2894
+ * ```
2895
+ */
2896
+ function useQueue(_options) {
2897
+ const { timeout: _timeout = 3e3,...options } = _options ?? {};
2898
+ const registry = useRegistry({
2899
+ ...options,
2900
+ events: true
2901
+ });
2902
+ const timeouts = /* @__PURE__ */ new Map();
2903
+ function startTimeout(ticket) {
2904
+ if (ticket.timeout === void 0 || ticket.timeout === -1 || ticket.isPaused) return;
2905
+ const timeout = setTimeout(() => {
2906
+ timeouts.delete(ticket.id);
2907
+ registry.unregister(ticket.id);
2908
+ resume();
2909
+ }, ticket.timeout);
2910
+ timeouts.set(ticket.id, timeout);
2911
+ }
2912
+ function clearTimeout(id) {
2913
+ const timeout = timeouts.get(id);
2914
+ if (timeout) {
2915
+ globalThis.clearTimeout(timeout);
2916
+ timeouts.delete(id);
2917
+ }
2918
+ }
2919
+ function register(registration = {}) {
2920
+ const id = registration.id ?? /* @__PURE__ */ genId();
2921
+ const timeout = Object.prototype.hasOwnProperty.call(registration, "timeout") ? registration.timeout : _timeout;
2922
+ const ticket = {
2923
+ ...registration,
2924
+ id,
2925
+ timeout,
2926
+ isPaused: registry.size > 0,
2927
+ dismiss: () => unregister(id)
2928
+ };
2929
+ const registered = registry.register(ticket);
2930
+ startTimeout(registered);
2931
+ return registered;
2932
+ }
2933
+ function unregister(id) {
2934
+ const ticket = id === void 0 ? registry.seek("first") : registry.get(id);
2935
+ if (!ticket) return void 0;
2936
+ const wasFirst = ticket.index === 0;
2937
+ clearTimeout(ticket.id);
2938
+ registry.unregister(ticket.id);
2939
+ if (wasFirst) resume();
2940
+ return ticket;
2941
+ }
2942
+ function pause() {
2943
+ const ticket = registry.seek("first");
2944
+ if (!ticket || ticket.isPaused) return void 0;
2945
+ clearTimeout(ticket.id);
2946
+ registry.upsert(ticket.id, { isPaused: true });
2947
+ return ticket;
2948
+ }
2949
+ function resume() {
2950
+ const ticket = registry.seek("first");
2951
+ if (!ticket || ticket.index !== 0 || !ticket.isPaused) return void 0;
2952
+ registry.upsert(ticket.id, { isPaused: false });
2953
+ startTimeout(ticket);
2954
+ return ticket;
2955
+ }
2956
+ function clear() {
2957
+ for (const id of timeouts.keys()) clearTimeout(id);
2958
+ registry.clear();
2959
+ }
2960
+ function dispose() {
2961
+ clear();
2962
+ registry.dispose();
2963
+ }
2964
+ onScopeDispose(dispose, true);
2965
+ return {
2966
+ ...registry,
2967
+ register,
2968
+ unregister,
2969
+ pause,
2970
+ resume,
2971
+ clear,
2972
+ dispose,
2973
+ get size() {
2974
+ return registry.size;
2975
+ }
2976
+ };
2977
+ }
2978
+
2979
+ //#endregion
2980
+ //#region src/composables/useResizeObserver/index.ts
2981
+ /**
2982
+ * A composable that uses the Resize Observer API to detect when an element's
2983
+ * size changes.
2984
+ *
2985
+ * @param target The element to observe.
2986
+ * @param callback The callback to execute when the element's size changes.
2987
+ * @param options The options for the Resize Observer.
2988
+ * @returns An object with methods to control the observer.
2989
+ *
2990
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver
2991
+ * @see https://0.vuetifyjs.com/composables/system/use-resize-observer
2992
+ *
2993
+ * @example
2994
+ * ```ts
2995
+ * import { ref } from 'vue'
2996
+ * import { useResizeObserver } from '@vuetify/v0'
2997
+ *
2998
+ * const el = ref<HTMLElement>()
2999
+ * const width = ref(0)
3000
+ * const height = ref(0)
3001
+ *
3002
+ * const { pause, resume, isPaused } = useResizeObserver(
3003
+ * el,
3004
+ * (entries) => {
3005
+ * const entry = entries[0]
3006
+ * if (entry) {
3007
+ * width.value = entry.contentRect.width
3008
+ * height.value = entry.contentRect.height
3009
+ * console.log('Size changed:', width.value, 'x', height.value)
3010
+ * }
3011
+ * },
3012
+ * { immediate: true }
3013
+ * )
3014
+ *
3015
+ * // Pause observation
3016
+ * pause()
3017
+ *
3018
+ * // Resume observation
3019
+ * resume()
3020
+ * ```
3021
+ */
3022
+ function useResizeObserver(target, callback, options = {}) {
3023
+ const { isHydrated } = useHydration();
3024
+ const observer = shallowRef();
3025
+ const isPaused = shallowRef(false);
3026
+ function setup() {
3027
+ if (!isHydrated.value || !SUPPORTS_OBSERVER || !target.value || isPaused.value) return;
3028
+ observer.value = new ResizeObserver((entries) => {
3029
+ callback(entries.map((entry) => ({
3030
+ contentRect: {
3031
+ width: entry.contentRect.width,
3032
+ height: entry.contentRect.height,
3033
+ top: entry.contentRect.top,
3034
+ left: entry.contentRect.left
3035
+ },
3036
+ target: entry.target
3037
+ })));
3038
+ });
3039
+ observer.value.observe(target.value, { box: options.box || "content-box" });
3040
+ if (options.immediate) {
3041
+ const rect = target.value.getBoundingClientRect();
3042
+ callback([{
3043
+ contentRect: {
3044
+ width: rect.width,
3045
+ height: rect.height,
3046
+ top: rect.top,
3047
+ left: rect.left
3048
+ },
3049
+ target: target.value
3050
+ }]);
3051
+ }
3052
+ }
3053
+ watch([isHydrated, target], () => {
3054
+ cleanup();
3055
+ setup();
3056
+ }, { immediate: true });
3057
+ function cleanup() {
3058
+ if (observer.value) {
3059
+ observer.value.disconnect();
3060
+ observer.value = void 0;
3061
+ }
3062
+ }
3063
+ function pause() {
3064
+ isPaused.value = true;
3065
+ observer.value?.disconnect();
3066
+ }
3067
+ function resume() {
3068
+ isPaused.value = false;
3069
+ setup();
3070
+ }
3071
+ function stop() {
3072
+ cleanup();
3073
+ }
3074
+ onUnmounted(stop);
3075
+ return {
3076
+ isPaused: readonly(isPaused),
3077
+ pause,
3078
+ resume,
3079
+ stop
3080
+ };
3081
+ }
3082
+ /**
3083
+ * A convenience composable that uses the Resize Observer API to track an
3084
+ * element's size.
3085
+ *
3086
+ * @param target The element to observe.
3087
+ * @returns An object with the element's width and height.
3088
+ *
3089
+ * @see https://0.vuetifyjs.com/composables/system/use-resize-observer#use-element-size
3090
+ *
3091
+ * @example
3092
+ * ```ts
3093
+ * import { ref, watchEffect } from 'vue'
3094
+ * import { useElementSize } from '@vuetify/v0'
3095
+ *
3096
+ * const box = ref<HTMLElement>()
3097
+ * const { width, height } = useElementSize(box)
3098
+ *
3099
+ * // Width and height are reactive refs
3100
+ * watchEffect(() => {
3101
+ * console.log('Box size:', width.value, 'x', height.value)
3102
+ * })
3103
+ * ```
3104
+ */
3105
+ function useElementSize(target) {
3106
+ const width = shallowRef(0);
3107
+ const height = shallowRef(0);
3108
+ const { pause: _pause, resume, stop, isPaused } = useResizeObserver(target, (entries) => {
3109
+ const entry = entries[0];
3110
+ if (entry) {
3111
+ width.value = entry.contentRect.width;
3112
+ height.value = entry.contentRect.height;
3113
+ }
3114
+ }, { immediate: true });
3115
+ function pause() {
3116
+ width.value = 0;
3117
+ height.value = 0;
3118
+ _pause();
3119
+ }
3120
+ return {
3121
+ width,
3122
+ height,
3123
+ isPaused,
3124
+ pause,
3125
+ resume,
3126
+ stop
3127
+ };
3128
+ }
3129
+
3130
+ //#endregion
3131
+ //#region src/composables/useStep/index.ts
3132
+ /**
3133
+ * Creates a new step instance.
3134
+ *
3135
+ * @param options The options for the step instance.
3136
+ * @template Z The type of the step ticket.
3137
+ * @template E The type of the step context.
3138
+ * @returns A new step instance.
3139
+ *
3140
+ * @see https://0.vuetifyjs.com/composables/selection/use-step
3141
+ *
3142
+ * @example
3143
+ * ```ts
3144
+ * import { useStep } from '@vuetify/v0'
3145
+ *
3146
+ * const stepper = useStep()
3147
+ *
3148
+ * stepper.onboard([
3149
+ * { id: 'step-1', value: 'Account Info' },
3150
+ * { id: 'step-2', value: 'Payment' },
3151
+ * { id: 'step-3', value: 'Confirmation' },
3152
+ * ])
3153
+ *
3154
+ * stepper.first()
3155
+ * stepper.next() // Move to step-2
3156
+ *
3157
+ * console.log(stepper.selectedIndex.value) // 1
3158
+ * ```
3159
+ */
3160
+ function useStep(options) {
3161
+ const registry = useSingle(options);
3162
+ function first() {
3163
+ const ticket = registry.seek("first");
3164
+ if (ticket) registry.select(ticket.id);
3165
+ }
3166
+ function last() {
3167
+ const ticket = registry.seek("last");
3168
+ if (ticket) registry.select(ticket.id);
3169
+ }
3170
+ function next() {
3171
+ step(1);
3172
+ }
3173
+ function prev() {
3174
+ step(-1);
3175
+ }
3176
+ function wrapped(length, index) {
3177
+ return (index % length + length) % length;
3178
+ }
3179
+ function step(count = 1) {
3180
+ const length = registry.size;
3181
+ if (!length) return;
3182
+ const direction = Math.sign(count || 1);
3183
+ let hops = 0;
3184
+ let index = wrapped(length, registry.selectedIndex.value + count);
3185
+ let id = registry.lookup(index);
3186
+ while (id !== void 0 && registry.get(id)?.disabled && hops < length) {
3187
+ index = wrapped(length, index + direction);
3188
+ id = registry.lookup(index);
3189
+ hops++;
3190
+ }
3191
+ if (id === void 0 || hops === length) return;
3192
+ registry.selectedIds.clear();
3193
+ registry.select(id);
3194
+ }
3195
+ return {
3196
+ ...registry,
3197
+ first,
3198
+ last,
3199
+ next,
3200
+ prev,
3201
+ step,
3202
+ get size() {
3203
+ return registry.size;
3204
+ }
3205
+ };
3206
+ }
3207
+ /**
3208
+ * Creates a new step context.
3209
+ *
3210
+ * @param namespace The namespace for the step context.
3211
+ * @param options The options for the step context.
3212
+ * @template Z The type of the step ticket.
3213
+ * @template E The type of the step context.
3214
+ * @returns A new step context.
3215
+ *
3216
+ * @see https://0.vuetifyjs.com/composables/selection/use-step
3217
+ *
3218
+ * @example
3219
+ * ```ts
3220
+ * import { createStepContext } from '@vuetify/v0'
3221
+ *
3222
+ * export const [useWizard, provideWizard, wizard] = createStepContext('wizard')
3223
+ *
3224
+ * // In a parent component:
3225
+ * provideWizard()
3226
+ *
3227
+ * // In a child component:
3228
+ * const wizard = useWizard()
3229
+ * wizard.next() // Progress to next step
3230
+ * ```
3231
+ */
3232
+ function createStepContext(namespace, options) {
3233
+ const [useStepContext, _provideStepContext] = createContext(namespace);
3234
+ const context = useStep(options);
3235
+ function provideStepContext(_context = context, app) {
3236
+ return _provideStepContext(_context, app);
3237
+ }
3238
+ return createTrinity(useStepContext, provideStepContext, context);
3239
+ }
3240
+
3241
+ //#endregion
3242
+ //#region src/composables/useStorage/adapters/memory.ts
3243
+ /**
3244
+ * In-memory storage adapter that implements the StorageAdapter interface.
3245
+ * This adapter provides temporary storage that persists only for the current
3246
+ * session and is useful for testing or when persistent storage is not available.
3247
+ */
3248
+ var MemoryAdapter = class {
3249
+ store = /* @__PURE__ */ new Map();
3250
+ get length() {
3251
+ return this.store.size;
3252
+ }
3253
+ getItem(key) {
3254
+ return this.store.get(key) ?? null;
3255
+ }
3256
+ setItem(key, value) {
3257
+ this.store.set(key, value);
3258
+ }
3259
+ removeItem(key) {
3260
+ this.store.delete(key);
3261
+ }
3262
+ key(index) {
3263
+ return String(Array.from(this.store.keys())[index] ?? "");
3264
+ }
3265
+ };
3266
+
3267
+ //#endregion
3268
+ //#region src/composables/useStorage/index.ts
3269
+ const [useStorageContext, provideStorageContext] = createContext("v0:storage");
3270
+ /**
3271
+ * Creates a new storage instance.
3272
+ *
3273
+ * @param options The options for the storage instance.
3274
+ * @template E The type of the storage context.
3275
+ * @returns A new storage instance.
3276
+ *
3277
+ * @see https://0.vuetifyjs.com/composables/plugins/use-storage
3278
+ *
3279
+ * @example
3280
+ * ```ts
3281
+ * import { createStorage } from '@vuetify/v0'
3282
+ *
3283
+ * const storage = createStorage()
3284
+ *
3285
+ * storage.set('username', 'MyUsername')
3286
+ *
3287
+ * const username = storage.get('username')
3288
+ *
3289
+ * console.log(username.value) // MyUsername
3290
+ *
3291
+ * storage.clear()
3292
+ * ```
3293
+ */
3294
+ function createStorage(options = {}) {
3295
+ const { adapter = IN_BROWSER ? window.localStorage : new MemoryAdapter(), prefix = "v0:", serializer = {
3296
+ read: JSON.parse,
3297
+ write: JSON.stringify
3298
+ } } = options;
3299
+ const cache = /* @__PURE__ */ new Map();
3300
+ const watchers = /* @__PURE__ */ new Map();
3301
+ function has(key) {
3302
+ const prefixedKey = `${prefix}${key}`;
3303
+ return cache.has(prefixedKey);
3304
+ }
3305
+ function get(key, defaultValue) {
3306
+ const prefixedKey = `${prefix}${key}`;
3307
+ if (cache.has(prefixedKey)) return cache.get(prefixedKey);
3308
+ const storedValue = adapter?.getItem(prefixedKey);
3309
+ let initialValue = defaultValue;
3310
+ if (storedValue) try {
3311
+ initialValue = serializer.read(storedValue);
3312
+ } catch (error) {
3313
+ console.error(`[v0:storage] Failed to parse stored value for key "${prefixedKey}":`, error);
3314
+ }
3315
+ const valueRef = ref(initialValue);
3316
+ const stop = watch(valueRef, (newValue) => {
3317
+ if (newValue === void 0 || newValue === null) adapter?.removeItem(prefixedKey);
3318
+ else adapter?.setItem(prefixedKey, serializer.write(newValue));
3319
+ }, { deep: true });
3320
+ watchers.set(prefixedKey, stop);
3321
+ cache.set(prefixedKey, valueRef);
3322
+ return valueRef;
3323
+ }
3324
+ function set(key, value) {
3325
+ const valueRef = get(key);
3326
+ valueRef.value = value;
3327
+ }
3328
+ function remove(key) {
3329
+ const prefixedKey = `${prefix}${key}`;
3330
+ const stop = watchers.get(prefixedKey);
3331
+ if (!stop) return;
3332
+ stop();
3333
+ watchers.delete(prefixedKey);
3334
+ adapter?.removeItem(prefixedKey);
3335
+ cache.delete(prefixedKey);
3336
+ }
3337
+ function clear() {
3338
+ if (watchers.size > 0) {
3339
+ for (const stop of watchers.values()) stop();
3340
+ watchers.clear();
3341
+ }
3342
+ if (cache.size > 0) {
3343
+ for (const key of cache.keys()) adapter?.removeItem(key);
3344
+ cache.clear();
3345
+ }
3346
+ }
3347
+ return {
3348
+ has,
3349
+ get,
3350
+ set,
3351
+ remove,
3352
+ clear
3353
+ };
3354
+ }
3355
+ /**
3356
+ * Returns the current storage instance.
3357
+ *
3358
+ * @returns The current storage instance.
3359
+ *
3360
+ * @see https://0.vuetifyjs.com/composables/plugins/use-storage
3361
+ *
3362
+ * @example
3363
+ * ```vue
3364
+ * <script setup lang="ts">
3365
+ * import { useStorage } from '@vuetify/v0'
3366
+ *
3367
+ * const storage = useStorage()
3368
+ * const username = storage.get('username', 'Guest')
3369
+ * <\/script>
3370
+ *
3371
+ * <template>
3372
+ * <div>
3373
+ * <p>Username: {{ username }}</p>
3374
+ * </div>
3375
+ * </template>
3376
+ * ```
3377
+ */
3378
+ function useStorage() {
3379
+ return useStorageContext();
3380
+ }
3381
+ /**
3382
+ * Creates a new storage plugin.
3383
+ *
3384
+ * @param options The options for the storage plugin.
3385
+ * @returns A new storage plugin.
3386
+ *
3387
+ * @see https://0.vuetifyjs.com/composables/plugins/use-storage
3388
+ *
3389
+ * @example
3390
+ * ```ts
3391
+ * import { createApp } from 'vue'
3392
+ * import { createStoragePlugin } from '@vuetify/v0'
3393
+ * import App from './App.vue'
3394
+ *
3395
+ * const app = createApp(App)
3396
+ *
3397
+ * app.use(createStoragePlugin())
3398
+ *
3399
+ * app.mount('#app')
3400
+ * ```
3401
+ */
3402
+ function createStoragePlugin(options = {}) {
3403
+ const context = createStorage(options);
3404
+ return createPlugin({
3405
+ namespace: "v0:storage",
3406
+ provide: (app) => {
3407
+ provideStorageContext(context, app);
3408
+ }
3409
+ });
3410
+ }
3411
+
3412
+ //#endregion
3413
+ //#region src/composables/useTheme/adapters/adapter.ts
3414
+ var ThemeAdapter = class {
3415
+ stylesheetId = "v0-theme-stylesheet";
3416
+ prefix;
3417
+ constructor(prefix) {
3418
+ this.prefix = prefix;
3419
+ }
3420
+ generate(colors) {
3421
+ let css = "";
3422
+ for (const theme in colors) {
3423
+ const themeColors = colors[theme];
3424
+ if (!themeColors) continue;
3425
+ const vars = Object.entries(themeColors).map(([key, val]) => ` --${this.prefix}-${key}: ${val};`).join("\n");
3426
+ css += `.${this.prefix}-theme--${theme} {\n${vars}\n}\n`;
3427
+ }
3428
+ return css;
3429
+ }
3430
+ };
3431
+
3432
+ //#endregion
3433
+ //#region src/composables/useTheme/adapters/v0.ts
3434
+ /**
3435
+ * Theme adapter implementation for Vuetify v0 design system.
3436
+ * This adapter generates CSS custom properties and injects them into the DOM
3437
+ * as a stylesheet, allowing themes to be applied globally.
3438
+ */
3439
+ var Vuetify0ThemeAdapter = class extends ThemeAdapter {
3440
+ cspNonce;
3441
+ constructor(options = {}) {
3442
+ super(options.prefix ?? "v0");
3443
+ this.cspNonce = options.cspNonce;
3444
+ this.stylesheetId = options.stylesheetId ?? this.stylesheetId;
3445
+ }
3446
+ update(colors) {
3447
+ if (!IN_BROWSER) return;
3448
+ this.upsert(this.generate(colors));
3449
+ }
3450
+ upsert(styles) {
3451
+ if (!IN_BROWSER) return;
3452
+ let styleEl = document.querySelector(`#${this.stylesheetId}`);
3453
+ if (!styleEl) {
3454
+ styleEl = document.createElement("style");
3455
+ styleEl.id = this.stylesheetId.startsWith("#") ? this.stylesheetId.slice(1) : this.stylesheetId;
3456
+ if (this.cspNonce) styleEl.setAttribute("nonce", this.cspNonce);
3457
+ document.head.append(styleEl);
3458
+ }
3459
+ styleEl.textContent = styles;
3460
+ }
3461
+ };
3462
+
3463
+ //#endregion
3464
+ //#region src/composables/useTheme/index.ts
3465
+ /**
3466
+ * Creates a new theme instance.
3467
+ *
3468
+ * @param namespace The namespace for the theme instance.
3469
+ * @param options The options for the theme instance.
3470
+ * @template Z The type of the theme ticket.
3471
+ * @template E The type of the theme context.
3472
+ * @returns A new theme instance.
3473
+ *
3474
+ * @see https://0.vuetifyjs.com/composables/plugins/use-theme
3475
+ *
3476
+ * @example
3477
+ * ```ts
3478
+ * import { createTheme } from '@vuetify/v0'
3479
+ *
3480
+ * export const [useTheme, provideTheme] = createTheme('v0:theme', {
3481
+ * default: 'light',
3482
+ * themes: {
3483
+ * light: {
3484
+ * dark: false,
3485
+ * colors: {
3486
+ * primary: '#3b82f6',
3487
+ * },
3488
+ * },
3489
+ * dark: {
3490
+ * dark: true,
3491
+ * colors: {
3492
+ * primary: '#675496',
3493
+ * },
3494
+ * },
3495
+ * },
3496
+ * })
3497
+ * ```
3498
+ */
3499
+ function createTheme(namespace = "v0:theme", options = {}) {
3500
+ const { themes = {}, palette = {} } = options;
3501
+ const [useThemeContext, _provideThemeContext] = createContext(namespace);
3502
+ const tokens = useTokens({
3503
+ palette,
3504
+ ...themes
3505
+ }, { flat: true });
3506
+ const registry = useSingle();
3507
+ for (const id in themes) {
3508
+ const { colors: value,...theme } = themes[id];
3509
+ register({
3510
+ id,
3511
+ value,
3512
+ ...theme
3513
+ });
3514
+ if (id === options.default && !registry.selectedId.value) registry.select(id);
3515
+ }
3516
+ const names = computed(() => registry.keys());
3517
+ const colors = computed(() => {
3518
+ const resolved = {};
3519
+ for (const theme of registry.values()) {
3520
+ if (theme.lazy && theme.id !== registry.selectedId.value) continue;
3521
+ resolved[theme.id] = resolve(theme.value);
3522
+ }
3523
+ return resolved;
3524
+ });
3525
+ function cycle(themes$1 = names.value) {
3526
+ const current = themes$1.indexOf(registry.selectedId.value ?? "");
3527
+ const next = current === -1 ? 0 : (current + 1) % themes$1.length;
3528
+ registry.select(themes$1[next]);
3529
+ }
3530
+ function resolve(colors$1) {
3531
+ const resolved = {};
3532
+ for (const [key, value] of Object.entries(colors$1)) resolved[key] = tokens.isAlias(value) ? tokens.resolve(value) : value;
3533
+ return resolved;
3534
+ }
3535
+ function register(registration = {}) {
3536
+ const item = {
3537
+ lazy: false,
3538
+ dark: false,
3539
+ ...registration
3540
+ };
3541
+ return registry.register(item);
3542
+ }
3543
+ const context = {
3544
+ ...registry,
3545
+ colors,
3546
+ register,
3547
+ cycle,
3548
+ get size() {
3549
+ return registry.size;
3550
+ }
3551
+ };
3552
+ function provideThemeContext(_context = context, app) {
3553
+ return _provideThemeContext(_context, app);
3554
+ }
3555
+ return createTrinity(useThemeContext, provideThemeContext, context);
3556
+ }
3557
+ /**
3558
+ * Returns the current theme instance.
3559
+ *
3560
+ * @returns The current theme instance.
3561
+ *
3562
+ * @see https://0.vuetifyjs.com/composables/plugins/use-theme
3563
+ *
3564
+ * @example
3565
+ * ```vue
3566
+ * <script setup lang="ts">
3567
+ * import { useTheme } from '@vuetify/v0'
3568
+ *
3569
+ * const theme = useTheme()
3570
+ * <\/script>
3571
+ *
3572
+ * <template>
3573
+ * <div>
3574
+ * <p>Current theme: {{ theme.selected.value }}</p>
3575
+ * </div>
3576
+ * </template>
3577
+ * ```
3578
+ */
3579
+ function useTheme() {
3580
+ return useContext("v0:theme");
3581
+ }
3582
+ /**
3583
+ * Creates a new theme plugin.
3584
+ *
3585
+ * @param _options The options for the theme plugin.
3586
+ * @template Z The type of the theme ticket.
3587
+ * @template E The type of the theme context.
3588
+ * @returns A new theme plugin.
3589
+ *
3590
+ * @see https://0.vuetifyjs.com/composables/plugins/use-theme
3591
+ *
3592
+ * @example
3593
+ * ```ts
3594
+ * import { createApp } from 'vue'
3595
+ * import { createThemePlugin } from '@vuetify/v0'
3596
+ * import App from './App.vue'
3597
+ *
3598
+ * const app = createApp(App)
3599
+ *
3600
+ * app.use(
3601
+ * createThemePlugin({
3602
+ * default: 'light',
3603
+ * themes: {
3604
+ * light: {
3605
+ * dark: false,
3606
+ * colors: {
3607
+ * primary: '#3b82f6',
3608
+ * },
3609
+ * },
3610
+ * dark: {
3611
+ * dark: true,
3612
+ * colors: {
3613
+ * primary: '#675496',
3614
+ * },
3615
+ * },
3616
+ * },
3617
+ * })
3618
+ * )
3619
+ *
3620
+ * app.mount('#app')
3621
+ * ```
3622
+ */
3623
+ function createThemePlugin(_options = {}) {
3624
+ const { adapter = new Vuetify0ThemeAdapter(), palette = {}, themes = {}, target,...options } = _options;
3625
+ const [, provideThemeContext, themeContext] = createTheme("v0:theme", {
3626
+ ...options,
3627
+ themes,
3628
+ palette
3629
+ });
3630
+ return createPlugin({
3631
+ namespace: "v0:theme",
3632
+ provide: (app) => {
3633
+ provideThemeContext(themeContext, app);
3634
+ },
3635
+ setup: (app) => {
3636
+ if (IN_BROWSER) {
3637
+ onScopeDispose(watch(themeContext.colors, (colors) => {
3638
+ adapter.update(colors);
3639
+ }, { immediate: true }), true);
3640
+ if (target === null) return;
3641
+ const targetEl = target instanceof HTMLElement ? target : typeof target === "string" ? document.querySelector(target) : app._container || document.querySelector("#app") || document.body;
3642
+ if (!targetEl) return;
3643
+ let prevClass = "";
3644
+ onScopeDispose(watch(themeContext.selectedId, (id) => {
3645
+ if (!id) return;
3646
+ const themeClass = `${adapter.prefix}-theme--${id}`;
3647
+ if (prevClass) targetEl.classList.remove(prevClass);
3648
+ targetEl.classList.add(themeClass);
3649
+ prevClass = themeClass;
3650
+ }, { immediate: true }), true);
3651
+ } else {
3652
+ const head = app._context?.provides?.usehead ?? app._context?.provides?.head;
3653
+ if (head?.push) {
3654
+ const id = themeContext.selectedId.value;
3655
+ head.push({
3656
+ htmlAttrs: { class: id ? `${adapter.prefix}-theme--${id}` : "" },
3657
+ style: [{
3658
+ innerHTML: adapter.generate(themeContext.colors.value),
3659
+ id: adapter.stylesheetId
3660
+ }]
3661
+ });
3662
+ }
3663
+ }
3664
+ }
3665
+ });
3666
+ }
3667
+
3668
+ //#endregion
3669
+ //#region src/composables/useTimeline/index.ts
3670
+ /**
3671
+ * Creates a new timeline instance.
3672
+ *
3673
+ * @param _options The options for the timeline instance.
3674
+ * @template Z The type of the timeline ticket.
3675
+ * @template E The type of the timeline context.
3676
+ * @returns A new timeline instance.
3677
+ *
3678
+ * @see https://0.vuetifyjs.com/composables/registration/use-timeline
3679
+ *
3680
+ * @example
3681
+ * ```ts
3682
+ * import { useTimeline } from '@vuetify/v0'
3683
+ *
3684
+ * const timeline = useTimeline({ size: 3 })
3685
+ *
3686
+ * timeline.onboard([{ id: 'one' }, { id: 'two' }, { id: 'three' }])
3687
+ *
3688
+ * console.log(timeline.values()) // [{ id: 'one' }, { id: 'two' }, { id: 'three' }]
3689
+ *
3690
+ * timeline.undo()
3691
+ * console.log(timeline.values()) // [{ id: 'one' }, { id: 'two' }]
3692
+ *
3693
+ * timeline.redo()
3694
+ * console.log(timeline.values()) // [{ id: 'one' }, { id: 'two' }, { id: 'three' }]
3695
+ * ```
3696
+ */
3697
+ function useTimeline(_options = {}) {
3698
+ const { size = 10,...options } = _options;
3699
+ const registry = useRegistry(options);
3700
+ const stack = [];
3701
+ const overflow = [];
3702
+ function register(item) {
3703
+ stack.length = 0;
3704
+ if (registry.size < size) return registry.register({ ...item });
3705
+ const removing = registry.seek("first");
3706
+ if (overflow.length === size) overflow.shift();
3707
+ overflow.push(removing);
3708
+ registry.unregister(removing.id);
3709
+ const ticket = registry.register({ ...item });
3710
+ registry.reindex();
3711
+ return ticket;
3712
+ }
3713
+ function undo() {
3714
+ const item = registry.seek("last");
3715
+ if (!item) return void 0;
3716
+ stack.push(item);
3717
+ registry.unregister(item.id);
3718
+ const restored = overflow.pop();
3719
+ if (restored) {
3720
+ const remaining = registry.values();
3721
+ registry.clear();
3722
+ registry.onboard([restored, ...remaining]);
3723
+ registry.reindex();
3724
+ }
3725
+ return item;
3726
+ }
3727
+ function redo() {
3728
+ if (stack.length === 0) return void 0;
3729
+ const item = stack.pop();
3730
+ const ticket = registry.register(item);
3731
+ registry.reindex();
3732
+ return ticket;
3733
+ }
3734
+ return {
3735
+ ...registry,
3736
+ register,
3737
+ undo,
3738
+ redo,
3739
+ get size() {
3740
+ return registry.size;
3741
+ }
3742
+ };
3743
+ }
3744
+
3745
+ //#endregion
3746
+ export { useEventListener as $, useKeydown as A, createGroupContext as B, useMutationObserver as C, Vuetify0LocaleAdapter as D, useLocale as E, createFeatures as F, useRegistry as G, createSelectionContext as H, createFeaturesPlugin as I, useLogger as J, createLogger as K, useFeatures as L, useIntersectionObserver as M, useForm as N, createSingleContext as O, useFilter as P, useDocumentEventListener as Q, createTokensContext as R, PermissionAdapter as S, createLocalePlugin as T, useSelection as U, useGroup as V, createRegistryContext as W, PinoLoggerAdapter as X, Vuetify0LoggerAdapter as Y, ConsolaLoggerAdapter as Z, useProxyRegistry as _, Vuetify0ThemeAdapter as a, createHydrationPlugin as at, createPermissionsPlugin as b, provideStorageContext as c, useHydrationContext as ct, MemoryAdapter as d, createTrinity as dt, useWindowEventListener as et, createStepContext as f, createPlugin as ft, useQueue as g, useResizeObserver as h, useContext as ht, useTheme as i, createHydration as it, useElementIntersection as j, useSingle as k, useStorage as l, toReactive as lt, useElementSize as m, provideContext as mt, createTheme as n, createBreakpointsPlugin as nt, createStorage as o, provideHydrationContext as ot, useStep as p, createContext as pt, createLoggerPlugin as q, createThemePlugin as r, useBreakpoints as rt, createStoragePlugin as s, useHydration as st, useTimeline as t, createBreakpoints as tt, useStorageContext as u, toArray as ut, useProxyModel as v, createLocale as w, usePermissions as x, createPermissions as y, useTokens as z };