@vuetify/v0 0.0.16 → 0.0.20

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 (30) hide show
  1. package/README.md +125 -47
  2. package/dist/browser/index.js +1801 -1604
  3. package/dist/components/index.d.mts +4 -4
  4. package/dist/components/index.mjs +6 -6
  5. package/dist/{components-Dk00OFL2.mjs → components-D590hSY0.mjs} +151 -54
  6. package/dist/composables/index.d.mts +4 -4
  7. package/dist/composables/index.mjs +5 -5
  8. package/dist/{composables-YOUVfUsn.mjs → composables-FE6B8JUW.mjs} +370 -303
  9. package/dist/constants/index.d.mts +1 -1
  10. package/dist/constants/index.mjs +3 -3
  11. package/dist/{globals-Rnihe4SF.mjs → globals-exvZ8fiO.mjs} +1 -1
  12. package/dist/index-4jSy8KIt.d.mts +73 -0
  13. package/dist/{index-BzW68rBC.d.mts → index-BYyEPh1S.d.mts} +227 -17
  14. package/dist/index-CjzlIAtF.d.mts +296 -0
  15. package/dist/{index-BeJMYhId.d.mts → index-DahjxaTj.d.mts} +899 -136
  16. package/dist/{index-BulceeMA.d.mts → index-Gr6XPRWt.d.mts} +50 -18
  17. package/dist/index.d.mts +7 -7
  18. package/dist/index.mjs +8 -8
  19. package/dist/types/index.d.mts +1 -1
  20. package/dist/{useStep-Bqhi_DDs.mjs → useStep-Dw7XloDM.mjs} +1067 -1258
  21. package/dist/utilities/index.d.mts +2 -2
  22. package/dist/utilities/index.mjs +1 -1
  23. package/dist/utilities-BrFKLHFS.mjs +363 -0
  24. package/package.json +3 -3
  25. package/dist/index-BXN7M6o_.d.mts +0 -71
  26. package/dist/index-Bd3J4RNS.d.mts +0 -11
  27. package/dist/utilities-DQWf_4V_.mjs +0 -139
  28. /package/dist/{constants-BWV0uYsM.mjs → constants-DypzAkYp.mjs} +0 -0
  29. /package/dist/{htmlElements-BYo-fMlZ.mjs → htmlElements-CXObxj0V.mjs} +0 -0
  30. /package/dist/{index-B6lIRI3i.d.mts → index-B9mKi4pr.d.mts} +0 -0
@@ -1,4 +1,4 @@
1
- import { computed, createBlock, createCommentVNode, createPropsRestProxy, createTextVNode, defineComponent, effectScope, getCurrentInstance, guardReactiveProps, inject, isRef, mergeModels, mergeProps, normalizeProps, onBeforeUnmount, onMounted, onScopeDispose, onUnmounted, openBlock, provide, reactive, readonly, ref, renderSlot, resolveDynamicComponent, shallowReactive, shallowReadonly, shallowRef, toDisplayString, toRef, toValue, unref, useAttrs, useId, useModel, useTemplateRef, vShow, watch, withCtx, withDirectives } from "vue";
1
+ import { computed, createBlock, createCommentVNode, createPropsRestProxy, createTextVNode, defineComponent, effectScope, getCurrentInstance, guardReactiveProps, inject, isRef, mergeModels, mergeProps, normalizeProps, onBeforeUnmount, onMounted, onScopeDispose, onUnmounted, openBlock, provide, reactive, readonly, ref, renderSlot, resolveDynamicComponent, shallowReactive, shallowReadonly, shallowRef, toDisplayString, toRef, toValue, unref, useAttrs, useId, useModel, useTemplateRef, vShow, watch, watchEffect, withCtx, withDirectives } from "vue";
2
2
 
3
3
  //#region src/constants/htmlElements.ts
4
4
  const selfClosingTags = [
@@ -78,54 +78,263 @@ function isSelfClosingTag(tag) {
78
78
 
79
79
  //#endregion
80
80
  //#region src/utilities/helpers.ts
81
+ /**
82
+ * Checks if a value is a function
83
+ *
84
+ * @param item The value to check
85
+ * @returns True if the value is a function
86
+ *
87
+ * @example
88
+ * ```ts
89
+ * isFunction(() => {}) // true
90
+ * isFunction('string') // false
91
+ * ```
92
+ */
81
93
  /* @__NO_SIDE_EFFECTS__ */
82
94
  function isFunction(item) {
83
95
  return typeof item === "function";
84
96
  }
97
+ /**
98
+ * Checks if a value is a string
99
+ *
100
+ * @param item The value to check
101
+ * @returns True if the value is a string
102
+ *
103
+ * @example
104
+ * ```ts
105
+ * isString('hello') // true
106
+ * isString(123) // false
107
+ * ```
108
+ */
85
109
  /* @__NO_SIDE_EFFECTS__ */
86
110
  function isString(item) {
87
111
  return typeof item === "string";
88
112
  }
113
+ /**
114
+ * Checks if a value is a number
115
+ *
116
+ * @param item The value to check
117
+ * @returns True if the value is a number (including NaN)
118
+ *
119
+ * @example
120
+ * ```ts
121
+ * isNumber(123) // true
122
+ * isNumber(NaN) // true
123
+ * isNumber('123') // false
124
+ * ```
125
+ *
126
+ * @see {@link isNaN} to check for NaN specifically
127
+ */
89
128
  /* @__NO_SIDE_EFFECTS__ */
90
129
  function isNumber(item) {
91
130
  return typeof item === "number";
92
131
  }
132
+ /**
133
+ * Checks if a value is a boolean
134
+ *
135
+ * @param item The value to check
136
+ * @returns True if the value is a boolean
137
+ *
138
+ * @example
139
+ * ```ts
140
+ * isBoolean(true) // true
141
+ * isBoolean(false) // true
142
+ * isBoolean(0) // false
143
+ * ```
144
+ */
93
145
  /* @__NO_SIDE_EFFECTS__ */
94
146
  function isBoolean(item) {
95
147
  return typeof item === "boolean";
96
148
  }
149
+ /**
150
+ * Checks if a value is a plain object (excludes null and arrays)
151
+ *
152
+ * @param item The value to check
153
+ * @returns True if the value is a plain object
154
+ *
155
+ * @remarks
156
+ * Returns false for null and arrays, even though `typeof null === 'object'`
157
+ * and `typeof [] === 'object'` in JavaScript.
158
+ *
159
+ * @example
160
+ * ```ts
161
+ * isObject({}) // true
162
+ * isObject({ a: 1 }) // true
163
+ * isObject(null) // false
164
+ * isObject([]) // false
165
+ * ```
166
+ *
167
+ * @see {@link isArray} to check for arrays
168
+ * @see {@link isNull} to check for null
169
+ */
97
170
  /* @__NO_SIDE_EFFECTS__ */
98
171
  function isObject(item) {
99
172
  return typeof item === "object" && item !== null && !Array.isArray(item);
100
173
  }
174
+ /**
175
+ * Checks if a value is an array
176
+ *
177
+ * @param item The value to check
178
+ * @returns True if the value is an array
179
+ *
180
+ * @example
181
+ * ```ts
182
+ * isArray([]) // true
183
+ * isArray([1, 2, 3]) // true
184
+ * isArray('string') // false
185
+ * ```
186
+ */
101
187
  /* @__NO_SIDE_EFFECTS__ */
102
188
  function isArray(item) {
103
189
  return Array.isArray(item);
104
190
  }
191
+ /**
192
+ * Checks if a value is null
193
+ *
194
+ * @param item The value to check
195
+ * @returns True if the value is null
196
+ *
197
+ * @example
198
+ * ```ts
199
+ * isNull(null) // true
200
+ * isNull(undefined) // false
201
+ * ```
202
+ *
203
+ * @see {@link isUndefined} to check for undefined
204
+ * @see {@link isNullOrUndefined} to check for either
205
+ */
105
206
  /* @__NO_SIDE_EFFECTS__ */
106
207
  function isNull(item) {
107
208
  return item === null;
108
209
  }
210
+ /**
211
+ * Checks if a value is null or undefined
212
+ *
213
+ * @param item The value to check
214
+ * @returns True if the value is null or undefined
215
+ *
216
+ * @remarks
217
+ * Uses loose equality (`== null`) which matches both null and undefined.
218
+ *
219
+ * @example
220
+ * ```ts
221
+ * isNullOrUndefined(null) // true
222
+ * isNullOrUndefined(undefined) // true
223
+ * isNullOrUndefined(0) // false
224
+ * isNullOrUndefined('') // false
225
+ * ```
226
+ *
227
+ * @see {@link isNull} to check for null only
228
+ * @see {@link isUndefined} to check for undefined only
229
+ */
109
230
  /* @__NO_SIDE_EFFECTS__ */
110
231
  function isNullOrUndefined(item) {
111
232
  return item == null;
112
233
  }
234
+ /**
235
+ * Checks if a value is undefined
236
+ *
237
+ * @param item The value to check
238
+ * @returns True if the value is undefined
239
+ *
240
+ * @example
241
+ * ```ts
242
+ * isUndefined(undefined) // true
243
+ * isUndefined(null) // false
244
+ * ```
245
+ *
246
+ * @see {@link isNull} to check for null
247
+ * @see {@link isNullOrUndefined} to check for either
248
+ */
113
249
  /* @__NO_SIDE_EFFECTS__ */
114
250
  function isUndefined(item) {
115
251
  return item === void 0;
116
252
  }
253
+ /**
254
+ * Checks if a value is a primitive (string, number, or boolean)
255
+ *
256
+ * @param item The value to check
257
+ * @returns True if the value is a string, number, or boolean
258
+ *
259
+ * @example
260
+ * ```ts
261
+ * isPrimitive('hello') // true
262
+ * isPrimitive(123) // true
263
+ * isPrimitive(true) // true
264
+ * isPrimitive({}) // false
265
+ * isPrimitive(null) // false
266
+ * ```
267
+ */
117
268
  /* @__NO_SIDE_EFFECTS__ */
118
269
  function isPrimitive(item) {
119
270
  return typeof item === "string" || typeof item === "number" || typeof item === "boolean";
120
271
  }
272
+ /**
273
+ * Checks if a value is a symbol
274
+ *
275
+ * @param item The value to check
276
+ * @returns True if the value is a symbol
277
+ *
278
+ * @example
279
+ * ```ts
280
+ * isSymbol(Symbol('test')) // true
281
+ * isSymbol('symbol') // false
282
+ * ```
283
+ */
121
284
  /* @__NO_SIDE_EFFECTS__ */
122
285
  function isSymbol(item) {
123
286
  return typeof item === "symbol";
124
287
  }
288
+ /**
289
+ * Checks if a value is NaN (Not a Number)
290
+ *
291
+ * @param item The value to check
292
+ * @returns True if the value is NaN
293
+ *
294
+ * @remarks
295
+ * Uses `Number.isNaN()` which only returns true for the actual NaN value,
296
+ * unlike the global `isNaN()` which coerces the argument to a number first.
297
+ *
298
+ * @example
299
+ * ```ts
300
+ * isNaN(NaN) // true
301
+ * isNaN(123) // false
302
+ * isNaN('hello') // false (unlike global isNaN)
303
+ * isNaN(undefined) // false (unlike global isNaN)
304
+ * ```
305
+ *
306
+ * @see {@link isNumber} to check if a value is a number type
307
+ */
125
308
  /* @__NO_SIDE_EFFECTS__ */
126
309
  function isNaN(item) {
127
310
  return /* @__PURE__ */ isNumber(item) && Number.isNaN(item);
128
311
  }
312
+ /**
313
+ * Deeply merges source objects into a target object
314
+ *
315
+ * @param target The target object to merge into (will be mutated)
316
+ * @param sources One or more source objects to merge from
317
+ * @returns The mutated target object
318
+ *
319
+ * @remarks
320
+ * - Mutates the target object in place
321
+ * - Nested objects are recursively merged
322
+ * - Arrays are replaced, not merged
323
+ * - Primitives from sources overwrite target values
324
+ *
325
+ * @example
326
+ * ```ts
327
+ * const target = { a: 1, b: { c: 2 } }
328
+ * mergeDeep(target, { b: { d: 3 } })
329
+ * // target is now { a: 1, b: { c: 2, d: 3 } }
330
+ *
331
+ * // Multiple sources
332
+ * mergeDeep({}, { a: 1 }, { b: 2 }) // { a: 1, b: 2 }
333
+ *
334
+ * // Arrays are replaced
335
+ * mergeDeep({ arr: [1, 2] }, { arr: [3] }) // { arr: [3] }
336
+ * ```
337
+ */
129
338
  /* @__NO_SIDE_EFFECTS__ */
130
339
  function mergeDeep(target, ...sources) {
131
340
  if (sources.length === 0) return target;
@@ -141,6 +350,21 @@ function mergeDeep(target, ...sources) {
141
350
  }
142
351
  return /* @__PURE__ */ mergeDeep(target, ...sources);
143
352
  }
353
+ /**
354
+ * Generates a random 7-character alphanumeric ID
355
+ *
356
+ * @returns A random string of 7 characters (a-z, 0-9)
357
+ *
358
+ * @remarks
359
+ * Uses `Math.random()` converted to base-36. Not cryptographically secure.
360
+ * Suitable for unique keys in UI components, not for security purposes.
361
+ *
362
+ * @example
363
+ * ```ts
364
+ * genId() // 'k7x9m2p'
365
+ * genId() // 'a3b8c1d'
366
+ * ```
367
+ */
144
368
  /* @__NO_SIDE_EFFECTS__ */
145
369
  function genId() {
146
370
  return Math.random().toString(36).slice(2, 9);
@@ -216,7 +440,7 @@ function debounce(fn, delay) {
216
440
 
217
441
  //#endregion
218
442
  //#region src/components/Atom/Atom.vue
219
- const _sfc_main$26 = /* @__PURE__ */ defineComponent({
443
+ const _sfc_main$27 = /* @__PURE__ */ defineComponent({
220
444
  name: "Atom",
221
445
  __name: "Atom",
222
446
  props: {
@@ -247,27 +471,11 @@ const _sfc_main$26 = /* @__PURE__ */ defineComponent({
247
471
  };
248
472
  }
249
473
  });
250
- var Atom_default = _sfc_main$26;
474
+ var Atom_default = _sfc_main$27;
251
475
 
252
476
  //#endregion
253
477
  //#region src/composables/createContext/index.ts
254
478
  /**
255
- * @module createContext
256
- *
257
- * @see https://0.vuetifyjs.com/composables/foundation/create-context
258
- *
259
- * @remarks
260
- * Factory for creating type-safe Vue dependency injection contexts.
261
- *
262
- * Provides a wrapper around Vue's provide/inject that throws errors when context is not found,
263
- * eliminating silent failures and improving developer experience. Supports both app-level and
264
- * component-level provision.
265
- *
266
- * Supports two modes:
267
- * - **Static key**: `createContext('my-key')` - key is fixed at creation time
268
- * - **Dynamic key**: `createContext()` or `createContext({ suffix: 'item' })` - key provided at runtime
269
- */
270
- /**
271
479
  * Injects a context provided by an ancestor component.
272
480
  *
273
481
  * @param key The key of the context to inject.
@@ -513,7 +721,7 @@ const SUPPORTS_MATCH_MEDIA = IN_BROWSER && "matchMedia" in window && typeof wind
513
721
  const SUPPORTS_OBSERVER = IN_BROWSER && "ResizeObserver" in window;
514
722
  const SUPPORTS_INTERSECTION_OBSERVER = IN_BROWSER && "IntersectionObserver" in window;
515
723
  const SUPPORTS_MUTATION_OBSERVER = IN_BROWSER && "MutationObserver" in window;
516
- const version = "0.0.16";
724
+ const version = "0.0.20";
517
725
  const __LOGGER_ENABLED__ = false;
518
726
 
519
727
  //#endregion
@@ -700,12 +908,12 @@ function createFallbackLogger(namespace = "v0:logger") {
700
908
  return `[${namespace} ${type}] ${message}`;
701
909
  }
702
910
  return {
703
- debug: (message, ...args) => console.log(format(message, "debug"), ...args),
704
- info: (message, ...args) => console.log(format(message, "info"), ...args),
705
- warn: (message, ...args) => console.log(format(message, "warn"), ...args),
706
- error: (message, ...args) => console.log(format(message, "error"), ...args),
707
- trace: (message, ...args) => console.log(format(message, "trace"), ...args),
708
- fatal: (message, ...args) => console.log(format(message, "fatal"), ...args),
911
+ debug: (message, ...args) => console.debug(format(message, "debug"), ...args),
912
+ info: (message, ...args) => console.info(format(message, "info"), ...args),
913
+ warn: (message, ...args) => console.warn(format(message, "warn"), ...args),
914
+ error: (message, ...args) => console.error(format(message, "error"), ...args),
915
+ trace: (message, ...args) => console.trace(format(message, "trace"), ...args),
916
+ fatal: (message, ...args) => console.error(format(message, "fatal"), ...args),
709
917
  level: () => {},
710
918
  current: () => "info",
711
919
  enabled: () => true,
@@ -733,7 +941,7 @@ function createFallbackLogger(namespace = "v0:logger") {
733
941
  * ```
734
942
  */
735
943
  function createLoggerContext(_options = {}) {
736
- const { namespace = "v0:logger",...options } = _options;
944
+ const { namespace = "v0:logger", ...options } = _options;
737
945
  const [useLoggerContext, _provideLoggerContext] = createContext(namespace);
738
946
  const context = createLogger(options);
739
947
  function provideLoggerContext(_context = context, app) {
@@ -768,7 +976,7 @@ function createLoggerContext(_options = {}) {
768
976
  * ```
769
977
  */
770
978
  function createLoggerPlugin(_options = {}) {
771
- const { namespace = "v0:logger",...options } = _options;
979
+ const { namespace = "v0:logger", ...options } = _options;
772
980
  const [, provideLoggerContext, context] = createLoggerContext({
773
981
  ...options,
774
982
  namespace
@@ -815,21 +1023,6 @@ function useLogger(namespace = "v0:logger") {
815
1023
  //#endregion
816
1024
  //#region src/composables/useRegistry/index.ts
817
1025
  /**
818
- * @module useRegistry
819
- *
820
- * @remarks
821
- * A foundational composable for managing collections of items (tickets) with:
822
- * - Unique ID-based access
823
- * - Index-based ordering
824
- * - Value-based reverse lookup
825
- * - Automatic reindexing
826
- * - Optional event emission
827
- * - Performance-optimized caching
828
- *
829
- * The registry serves as the base for many other composables in the system,
830
- * including useSelection, useForm, useTimeline, and more.
831
- */
832
- /**
833
1026
  * Creates a new registry instance.
834
1027
  *
835
1028
  * @param options The options for the registry instance.
@@ -863,6 +1056,8 @@ function useRegistry(options) {
863
1056
  let indexDependentCount = 0;
864
1057
  let needsReindex = false;
865
1058
  let minDirtyIndex = Infinity;
1059
+ let batching = false;
1060
+ let pendingEmits = [];
866
1061
  function emit(event, data = void 0) {
867
1062
  if (!events) return;
868
1063
  const cbs = listeners.get(event);
@@ -871,17 +1066,21 @@ function useRegistry(options) {
871
1066
  }
872
1067
  function on(event, cb) {
873
1068
  if (!events) {
874
- logger.warn(`Attempted to register event listener for "${event}" but events are disabled.`);
1069
+ logger.warn(`Events are disabled. Initialize with \`useRegistry({ events: true })\` to enable.`);
875
1070
  return;
876
1071
  }
877
1072
  if (!listeners.has(event)) listeners.set(event, /* @__PURE__ */ new Set());
878
1073
  listeners.get(event).add(cb);
879
1074
  }
880
1075
  function off(event, cb) {
1076
+ if (!events) {
1077
+ logger.warn(`Events are disabled. Initialize with \`useRegistry({ events: true })\` to enable.`);
1078
+ return;
1079
+ }
881
1080
  listeners.get(event)?.delete(cb);
882
1081
  }
883
1082
  function dispose() {
884
- if (listeners.size > 0) listeners.clear();
1083
+ listeners.clear();
885
1084
  clear();
886
1085
  }
887
1086
  function get(id) {
@@ -938,24 +1137,19 @@ function useRegistry(options) {
938
1137
  function assign(value, id) {
939
1138
  const bucket = catalog.get(value);
940
1139
  if (bucket) {
941
- if (/* @__PURE__ */ isArray(bucket)) {
942
- if (!bucket.includes(id)) bucket.push(id);
943
- } else if (bucket !== id) catalog.set(value, [bucket, id]);
944
- } else catalog.set(value, id);
1140
+ if (!bucket.includes(id)) bucket.push(id);
1141
+ } else catalog.set(value, [id]);
945
1142
  }
946
1143
  function unassign(value, id) {
947
1144
  const bucket = catalog.get(value);
948
1145
  if (!bucket) return;
949
- if (/* @__PURE__ */ isArray(bucket)) {
950
- const next = bucket.filter((v) => v !== id);
951
- if (next.length === 0) catalog.delete(value);
952
- else if (next.length === 1) catalog.set(value, next[0]);
953
- else catalog.set(value, next);
954
- } else if (bucket === id) catalog.delete(value);
1146
+ const next = bucket.filter((v) => v !== id);
1147
+ if (next.length === 0) catalog.delete(value);
1148
+ else catalog.set(value, next);
955
1149
  }
956
1150
  function keys() {
957
1151
  const cached = cache.get("keys");
958
- if (cached != void 0) return cached;
1152
+ if (!/* @__PURE__ */ isUndefined(cached)) return cached;
959
1153
  const keys$1 = Array.from(collection.keys());
960
1154
  cache.set("keys", keys$1);
961
1155
  return keys$1;
@@ -975,9 +1169,9 @@ function useRegistry(options) {
975
1169
  return entries$1;
976
1170
  }
977
1171
  function clear() {
978
- if (collection.size > 0) collection.clear();
979
- if (catalog.size > 0) catalog.clear();
980
- if (directory.size > 0) directory.clear();
1172
+ collection.clear();
1173
+ catalog.clear();
1174
+ directory.clear();
981
1175
  invalidate();
982
1176
  indexDependentCount = 0;
983
1177
  needsReindex = false;
@@ -985,13 +1179,35 @@ function useRegistry(options) {
985
1179
  emit("clear:registry");
986
1180
  }
987
1181
  function invalidate() {
988
- if (cache.size > 0) cache.clear();
1182
+ if (batching) return;
1183
+ cache.clear();
1184
+ }
1185
+ function queueEmit(event, data) {
1186
+ if (batching) pendingEmits.push({
1187
+ event,
1188
+ data
1189
+ });
1190
+ else emit(event, data);
1191
+ }
1192
+ function batch(fn) {
1193
+ if (batching) return fn();
1194
+ batching = true;
1195
+ pendingEmits = [];
1196
+ try {
1197
+ const result = fn();
1198
+ cache.clear();
1199
+ for (const { event, data } of pendingEmits) emit(event, data);
1200
+ return result;
1201
+ } finally {
1202
+ batching = false;
1203
+ pendingEmits = [];
1204
+ }
989
1205
  }
990
1206
  function reindex() {
991
1207
  const startIndex = minDirtyIndex === Infinity ? 0 : minDirtyIndex;
992
1208
  if (startIndex === 0) {
993
- if (catalog.size > 0) catalog.clear();
994
- if (directory.size > 0) directory.clear();
1209
+ catalog.clear();
1210
+ directory.clear();
995
1211
  }
996
1212
  invalidate();
997
1213
  let index = 0;
@@ -1018,7 +1234,7 @@ function useRegistry(options) {
1018
1234
  const size = collection.size;
1019
1235
  const id = registration.id ?? /* @__PURE__ */ genId();
1020
1236
  if (has(id)) {
1021
- logger.warn(`Ticket with id "${id}" already exists in the registry. Skipping registration.`);
1237
+ logger.warn(`Ticket "${id}" already exists. Use \`upsert()\` to update or check \`has()\` before registering.`);
1022
1238
  return get(id);
1023
1239
  }
1024
1240
  const valueIsUndefined = /* @__PURE__ */ isUndefined(registration.value);
@@ -1037,7 +1253,7 @@ function useRegistry(options) {
1037
1253
  directory.set(ticket.index, ticket.id);
1038
1254
  assign(ticket.value, ticket.id);
1039
1255
  invalidate();
1040
- emit("register:ticket", ticket);
1256
+ queueEmit("register:ticket", ticket);
1041
1257
  return ticket;
1042
1258
  }
1043
1259
  function unregister(id) {
@@ -1047,15 +1263,12 @@ function useRegistry(options) {
1047
1263
  collection.delete(ticket.id);
1048
1264
  directory.delete(ticket.index);
1049
1265
  unassign(ticket.value, ticket.id);
1050
- invalidate();
1266
+ const willReindex = indexDependentCount > 0 && ticket.index < collection.size;
1267
+ if (!willReindex) invalidate();
1051
1268
  emit("unregister:ticket", ticket);
1052
- if (indexDependentCount > 0 && ticket.index < collection.size) {
1053
- minDirtyIndex = Math.min(minDirtyIndex, ticket.index);
1054
- reindex();
1055
- } else {
1056
- minDirtyIndex = Math.min(minDirtyIndex, ticket.index);
1057
- needsReindex = true;
1058
- }
1269
+ minDirtyIndex = Math.min(minDirtyIndex, ticket.index);
1270
+ if (willReindex) reindex();
1271
+ else needsReindex = true;
1059
1272
  }
1060
1273
  function offboard(ids) {
1061
1274
  const removed = [];
@@ -1071,12 +1284,16 @@ function useRegistry(options) {
1071
1284
  }
1072
1285
  if (removed.length === 0) return;
1073
1286
  invalidate();
1074
- if (events) for (const ticket of removed) emit("unregister:ticket", ticket);
1287
+ for (const ticket of removed) queueEmit("unregister:ticket", ticket);
1075
1288
  needsReindex = true;
1076
1289
  }
1077
1290
  function seek(direction = "first", from, predicate) {
1078
1291
  if (collection.size === 0) return void 0;
1079
1292
  if (needsReindex) reindex();
1293
+ if (!predicate && /* @__PURE__ */ isUndefined(from)) {
1294
+ const tickets$1 = values();
1295
+ return direction === "first" ? tickets$1[0] : tickets$1.at(-1);
1296
+ }
1080
1297
  const tickets = values();
1081
1298
  const index = /* @__PURE__ */ isUndefined(from) ? void 0 : Math.max(0, Math.min(from, tickets.length - 1));
1082
1299
  if (direction === "last") {
@@ -1112,8 +1329,9 @@ function useRegistry(options) {
1112
1329
  unregister,
1113
1330
  reindex,
1114
1331
  seek,
1332
+ batch,
1115
1333
  onboard(registrations) {
1116
- return registrations.map((registration) => register(registration));
1334
+ return batch(() => registrations.map((registration) => register(registration)));
1117
1335
  },
1118
1336
  offboard,
1119
1337
  get size() {
@@ -1124,8 +1342,7 @@ function useRegistry(options) {
1124
1342
  /**
1125
1343
  * Creates a new registry context.
1126
1344
  *
1127
- * @param namespace The namespace for the registry context.
1128
- * @param options The options for the registry context.
1345
+ * @param options The options for the registry context, including `namespace` (defaults to `'v0:registry'`) and `events`.
1129
1346
  * @template Z The type of registry ticket that extends RegistryTicket. Use this to add custom properties to tickets.
1130
1347
  * @template E The type of registry context that extends RegistryContext<Z>. Use this when extending the registry with additional methods.
1131
1348
  * @returns A new registry context.
@@ -1151,7 +1368,7 @@ function useRegistry(options) {
1151
1368
  * ```
1152
1369
  */
1153
1370
  function createRegistryContext(_options = {}) {
1154
- const { namespace = "v0:registry",...options } = _options;
1371
+ const { namespace = "v0:registry", ...options } = _options;
1155
1372
  const [useRegistryContext, _provideRegistryContext] = createContext(namespace);
1156
1373
  const context = useRegistry(options);
1157
1374
  function provideRegistryContext(_context = context, app) {
@@ -1163,21 +1380,6 @@ function createRegistryContext(_options = {}) {
1163
1380
  //#endregion
1164
1381
  //#region src/composables/useSelection/index.ts
1165
1382
  /**
1166
- * @module useSelection
1167
- *
1168
- * @remarks
1169
- * Base composable for managing selected items in a collection with Set-based tracking.
1170
- *
1171
- * Key features:
1172
- * - Set-based selectedIds for O(1) selection checks
1173
- * - Mandatory selection mode (prevents deselecting last item)
1174
- * - Auto-enrollment option (selects non-disabled items on register)
1175
- * - Disabled item filtering
1176
- * - Computed selectedItems and selectedValues Sets
1177
- *
1178
- * Extends useRegistry and serves as the base for useSingle, useGroup, useStep, and useFeatures.
1179
- */
1180
- /**
1181
1383
  * Creates a new selection instance for managing multiple selected items.
1182
1384
  *
1183
1385
  * Extends `useRegistry` with selection tracking via a reactive `Set` of selected IDs.
@@ -1224,14 +1426,14 @@ function createRegistryContext(_options = {}) {
1224
1426
  * ```
1225
1427
  */
1226
1428
  function createSelection(_options = {}) {
1227
- const { disabled = false, enroll = false, mandatory = false, multiple = false,...options } = _options;
1429
+ const { disabled = false, enroll = false, mandatory = false, multiple = false, ...options } = _options;
1228
1430
  const registry = useRegistry(options);
1229
1431
  const selectedIds = shallowReactive(/* @__PURE__ */ new Set());
1230
1432
  const selectedItems = computed(() => {
1231
- return new Set(Array.from(selectedIds).map((id) => registry.get(id)));
1433
+ return new Set(Array.from(selectedIds).map((id) => registry.get(id)).filter((item) => !/* @__PURE__ */ isUndefined(item)));
1232
1434
  });
1233
1435
  const selectedValues = computed(() => {
1234
- return new Set(Array.from(selectedItems.value).map((item) => item?.value));
1436
+ return new Set(Array.from(selectedItems.value).map((item) => item.value));
1235
1437
  });
1236
1438
  function seek(direction = "first", from) {
1237
1439
  return registry.seek(direction, from, (ticket) => !toValue(ticket.disabled));
@@ -1242,16 +1444,19 @@ function createSelection(_options = {}) {
1242
1444
  if (ticket) select(ticket.id);
1243
1445
  }
1244
1446
  function select(id) {
1447
+ if (toValue(disabled)) return;
1245
1448
  const item = registry.get(id);
1246
1449
  if (!item || toValue(item.disabled)) return;
1247
1450
  if (!multiple) selectedIds.clear();
1248
1451
  selectedIds.add(id);
1249
1452
  }
1250
1453
  function unselect(id) {
1454
+ if (toValue(disabled)) return;
1251
1455
  if (mandatory && selectedIds.size === 1) return;
1252
1456
  selectedIds.delete(id);
1253
1457
  }
1254
1458
  function toggle(id) {
1459
+ if (toValue(disabled)) return;
1255
1460
  if (selected(id)) unselect(id);
1256
1461
  else select(id);
1257
1462
  }
@@ -1270,7 +1475,7 @@ function createSelection(_options = {}) {
1270
1475
  id
1271
1476
  };
1272
1477
  const ticket = registry.register(item);
1273
- if (enroll && !toValue(item.disabled)) selectedIds.add(ticket.id);
1478
+ if (enroll && !toValue(disabled) && !toValue(item.disabled)) selectedIds.add(ticket.id);
1274
1479
  if (mandatory === "force") mandate();
1275
1480
  return ticket;
1276
1481
  }
@@ -1341,7 +1546,7 @@ function createSelection(_options = {}) {
1341
1546
  * ```
1342
1547
  */
1343
1548
  function createSelectionContext(_options = {}) {
1344
- const { namespace = "v0:selection",...options } = _options;
1549
+ const { namespace = "v0:selection", ...options } = _options;
1345
1550
  const [useSelectionContext, _provideSelectionContext] = createContext(namespace);
1346
1551
  const context = createSelection(options);
1347
1552
  function provideSelectionContext(_context = context, app) {
@@ -1379,7 +1584,7 @@ function useSelection(namespace = "v0:selection") {
1379
1584
  //#endregion
1380
1585
  //#region src/components/Avatar/AvatarRoot.vue
1381
1586
  const [useAvatarRoot, provideAvatarContext] = createContext();
1382
- const _sfc_main$25 = /* @__PURE__ */ defineComponent({
1587
+ const _sfc_main$26 = /* @__PURE__ */ defineComponent({
1383
1588
  name: "AvatarRoot",
1384
1589
  __name: "AvatarRoot",
1385
1590
  props: {
@@ -1404,11 +1609,11 @@ const _sfc_main$25 = /* @__PURE__ */ defineComponent({
1404
1609
  };
1405
1610
  }
1406
1611
  });
1407
- var AvatarRoot_default = _sfc_main$25;
1612
+ var AvatarRoot_default = _sfc_main$26;
1408
1613
 
1409
1614
  //#endregion
1410
1615
  //#region src/components/Avatar/AvatarFallback.vue
1411
- const _sfc_main$24 = /* @__PURE__ */ defineComponent({
1616
+ const _sfc_main$25 = /* @__PURE__ */ defineComponent({
1412
1617
  name: "AvatarFallback",
1413
1618
  __name: "AvatarFallback",
1414
1619
  props: {
@@ -1433,11 +1638,11 @@ const _sfc_main$24 = /* @__PURE__ */ defineComponent({
1433
1638
  };
1434
1639
  }
1435
1640
  });
1436
- var AvatarFallback_default = _sfc_main$24;
1641
+ var AvatarFallback_default = _sfc_main$25;
1437
1642
 
1438
1643
  //#endregion
1439
1644
  //#region src/components/Avatar/AvatarImage.vue
1440
- const _sfc_main$23 = /* @__PURE__ */ defineComponent({
1645
+ const _sfc_main$24 = /* @__PURE__ */ defineComponent({
1441
1646
  name: "AvatarImage",
1442
1647
  inheritAttrs: false,
1443
1648
  __name: "AvatarImage",
@@ -1497,14 +1702,19 @@ const _sfc_main$23 = /* @__PURE__ */ defineComponent({
1497
1702
  };
1498
1703
  }
1499
1704
  });
1500
- var AvatarImage_default = _sfc_main$23;
1705
+ var AvatarImage_default = _sfc_main$24;
1501
1706
 
1502
1707
  //#endregion
1503
1708
  //#region src/components/Avatar/index.ts
1709
+ /**
1710
+ * Avatar component with sub-components for building avatars.
1711
+ *
1712
+ * @see https://0.vuetifyjs.com/components/avatar
1713
+ */
1504
1714
  const Avatar = {
1505
- Fallback: AvatarFallback_default,
1715
+ Root: AvatarRoot_default,
1506
1716
  Image: AvatarImage_default,
1507
- Root: AvatarRoot_default
1717
+ Fallback: AvatarFallback_default
1508
1718
  };
1509
1719
 
1510
1720
  //#endregion
@@ -1545,20 +1755,6 @@ function toArray(value) {
1545
1755
  //#endregion
1546
1756
  //#region src/composables/useProxyModel/index.ts
1547
1757
  /**
1548
- * @module useProxyModel
1549
- *
1550
- * @remarks
1551
- * Proxy composable for bidirectional sync between selection registry and v-model.
1552
- *
1553
- * Key features:
1554
- * - Bidirectional synchronization
1555
- * - Array and single-value modes
1556
- * - Automatic cleanup on scope disposal
1557
- * - Perfect for form controls with selection backing
1558
- *
1559
- * Bridges the gap between selection composables and Vue's v-model.
1560
- */
1561
- /**
1562
1758
  * Syncs a ref with a selection registry bidirectionally.
1563
1759
  *
1564
1760
  * @param registry The selection registry to bind to.
@@ -1599,12 +1795,9 @@ function useProxyModel(registry, model, options) {
1599
1795
  const pending = new Set(modelAsArray);
1600
1796
  for (const value of modelAsArray) {
1601
1797
  const ids = registry.browse(value);
1602
- if (/* @__PURE__ */ isArray(ids)) {
1798
+ if (ids) {
1603
1799
  for (const id of ids) registry.select(id);
1604
1800
  pending.delete(value);
1605
- } else if (ids) {
1606
- registry.select(ids);
1607
- pending.delete(value);
1608
1801
  }
1609
1802
  }
1610
1803
  const registryWatch = watch(registry.selectedValues, (val) => {
@@ -1618,8 +1811,7 @@ function useProxyModel(registry, model, options) {
1618
1811
  const targetIds = /* @__PURE__ */ new Set();
1619
1812
  for (const value of transformIn(val)) {
1620
1813
  const ids = registry.browse(value);
1621
- if (/* @__PURE__ */ isArray(ids)) for (const single of ids) targetIds.add(single);
1622
- else if (ids) targetIds.add(ids);
1814
+ if (ids) for (const id of ids) targetIds.add(id);
1623
1815
  }
1624
1816
  if (multiple) {
1625
1817
  for (const id of currentIds.difference(targetIds)) registry.selectedIds.delete(id);
@@ -1635,7 +1827,8 @@ function useProxyModel(registry, model, options) {
1635
1827
  flush: "sync",
1636
1828
  deep: multiple
1637
1829
  });
1638
- function onRegister(ticket) {
1830
+ function onRegister(data) {
1831
+ const ticket = data;
1639
1832
  if (!pending.has(ticket.value) || ticket.disabled) return;
1640
1833
  registryWatch.pause();
1641
1834
  modelWatch.pause();
@@ -1657,7 +1850,7 @@ function useProxyModel(registry, model, options) {
1657
1850
  //#endregion
1658
1851
  //#region src/components/ExpansionPanel/ExpansionPanelRoot.vue
1659
1852
  const [useExpansionPanelRoot, provideExpansionPanelSelection] = createContext();
1660
- const _sfc_main$22 = /* @__PURE__ */ defineComponent({
1853
+ const _sfc_main$23 = /* @__PURE__ */ defineComponent({
1661
1854
  name: "ExpansionPanelRoot",
1662
1855
  __name: "ExpansionPanelRoot",
1663
1856
  props: /* @__PURE__ */ mergeModels({
@@ -1714,12 +1907,12 @@ const _sfc_main$22 = /* @__PURE__ */ defineComponent({
1714
1907
  };
1715
1908
  }
1716
1909
  });
1717
- var ExpansionPanelRoot_default = _sfc_main$22;
1910
+ var ExpansionPanelRoot_default = _sfc_main$23;
1718
1911
 
1719
1912
  //#endregion
1720
1913
  //#region src/components/ExpansionPanel/ExpansionPanelItem.vue
1721
1914
  const [useExpansionPanelItem, provideExpansionPanelItem] = createContext({ suffix: "item" });
1722
- const _sfc_main$21 = /* @__PURE__ */ defineComponent({
1915
+ const _sfc_main$22 = /* @__PURE__ */ defineComponent({
1723
1916
  name: "ExpansionPanelItem",
1724
1917
  __name: "ExpansionPanelItem",
1725
1918
  props: {
@@ -1763,11 +1956,11 @@ const _sfc_main$21 = /* @__PURE__ */ defineComponent({
1763
1956
  };
1764
1957
  }
1765
1958
  });
1766
- var ExpansionPanelItem_default = _sfc_main$21;
1959
+ var ExpansionPanelItem_default = _sfc_main$22;
1767
1960
 
1768
1961
  //#endregion
1769
1962
  //#region src/components/ExpansionPanel/ExpansionPanelActivator.vue
1770
- const _sfc_main$20 = /* @__PURE__ */ defineComponent({
1963
+ const _sfc_main$21 = /* @__PURE__ */ defineComponent({
1771
1964
  name: "ExpansionPanelActivator",
1772
1965
  __name: "ExpansionPanelActivator",
1773
1966
  props: {
@@ -1813,11 +2006,11 @@ const _sfc_main$20 = /* @__PURE__ */ defineComponent({
1813
2006
  };
1814
2007
  }
1815
2008
  });
1816
- var ExpansionPanelActivator_default = _sfc_main$20;
2009
+ var ExpansionPanelActivator_default = _sfc_main$21;
1817
2010
 
1818
2011
  //#endregion
1819
2012
  //#region src/components/ExpansionPanel/ExpansionPanelContent.vue
1820
- const _sfc_main$19 = /* @__PURE__ */ defineComponent({
2013
+ const _sfc_main$20 = /* @__PURE__ */ defineComponent({
1821
2014
  name: "ExpansionPanelContent",
1822
2015
  __name: "ExpansionPanelContent",
1823
2016
  props: {
@@ -1848,11 +2041,11 @@ const _sfc_main$19 = /* @__PURE__ */ defineComponent({
1848
2041
  };
1849
2042
  }
1850
2043
  });
1851
- var ExpansionPanelContent_default = _sfc_main$19;
2044
+ var ExpansionPanelContent_default = _sfc_main$20;
1852
2045
 
1853
2046
  //#endregion
1854
2047
  //#region src/components/ExpansionPanel/ExpansionPanelHeader.vue
1855
- const _sfc_main$18 = /* @__PURE__ */ defineComponent({
2048
+ const _sfc_main$19 = /* @__PURE__ */ defineComponent({
1856
2049
  name: "ExpansionPanelHeader",
1857
2050
  __name: "ExpansionPanelHeader",
1858
2051
  props: {
@@ -1877,10 +2070,15 @@ const _sfc_main$18 = /* @__PURE__ */ defineComponent({
1877
2070
  };
1878
2071
  }
1879
2072
  });
1880
- var ExpansionPanelHeader_default = _sfc_main$18;
2073
+ var ExpansionPanelHeader_default = _sfc_main$19;
1881
2074
 
1882
2075
  //#endregion
1883
2076
  //#region src/components/ExpansionPanel/index.ts
2077
+ /**
2078
+ * ExpansionPanel component with sub-components for building expansion panels.
2079
+ *
2080
+ * @see https://0.vuetifyjs.com/components/expansion-panels
2081
+ */
1884
2082
  const ExpansionPanel = {
1885
2083
  Root: ExpansionPanelRoot_default,
1886
2084
  Item: ExpansionPanelItem_default,
@@ -1892,21 +2090,6 @@ const ExpansionPanel = {
1892
2090
  //#endregion
1893
2091
  //#region src/composables/useProxyRegistry/index.ts
1894
2092
  /**
1895
- * @module useProxyRegistry
1896
- *
1897
- * @remarks
1898
- * Proxy composable for reactive registry keys, values, entries, and size.
1899
- *
1900
- * Key features:
1901
- * - Reactive proxy for registry data
1902
- * - Deep or shallow reactivity options
1903
- * - Event-based updates
1904
- * - Automatic cleanup on scope disposal
1905
- * - Transforms Map-based registry into reactive refs
1906
- *
1907
- * Perfect for exposing registry data as reactive computed properties.
1908
- */
1909
- /**
1910
2093
  * Creates a proxy registry that provides reactive objects for registry data.
1911
2094
  *
1912
2095
  * @param registry The registry instance to proxy.
@@ -1956,26 +2139,6 @@ function useProxyRegistry(registry, options) {
1956
2139
  //#endregion
1957
2140
  //#region src/composables/useGroup/index.ts
1958
2141
  /**
1959
- * @module useGroup
1960
- *
1961
- * @remarks
1962
- * Multi-selection composable that extends useSelection with batch operations and tri-state support.
1963
- *
1964
- * Key features:
1965
- * - Batch operations (select/unselect/toggle accept ID | ID[])
1966
- * - Tri-state support via mixed/indeterminate state (mix/unmix)
1967
- * - selectedIndexes computed Set for position-based tracking
1968
- * - Perfect for checkbox trees, multi-select dropdowns, filter panels
1969
- *
1970
- * Tri-state behavior:
1971
- * - Items can be selected, mixed (indeterminate), or unselected
1972
- * - select() clears mixed state, mix() clears selected state (mutually exclusive)
1973
- * - toggle() on a mixed item selects it (resolves positively)
1974
- *
1975
- * Inheritance chain: useRegistry → useSelection → useGroup
1976
- * Extended by: useFeatures
1977
- */
1978
- /**
1979
2142
  * Creates a new group instance with batch selection and tri-state support.
1980
2143
  *
1981
2144
  * Extends `createSelection` to support selecting, unselecting, and toggling multiple items
@@ -2049,7 +2212,7 @@ function useProxyRegistry(registry, options) {
2049
2212
  * ```
2050
2213
  */
2051
2214
  function createGroup(_options = {}) {
2052
- const { mandatory = false, multiple = true,...options } = _options;
2215
+ const { mandatory = false, multiple = true, ...options } = _options;
2053
2216
  const selection = createSelection({
2054
2217
  ...options,
2055
2218
  mandatory,
@@ -2059,10 +2222,10 @@ function createGroup(_options = {}) {
2059
2222
  const proxy = useProxyRegistry(selection);
2060
2223
  const mixedIds = shallowReactive(/* @__PURE__ */ new Set());
2061
2224
  const selectedIndexes = computed(() => {
2062
- return new Set(Array.from(selection.selectedItems.value).map((item) => item?.index));
2225
+ return new Set(Array.from(selection.selectedItems.value).map((item) => item?.index).filter((index) => !/* @__PURE__ */ isUndefined(index)));
2063
2226
  });
2064
2227
  const mixedItems = computed(() => {
2065
- return new Set(Array.from(mixedIds).map((id) => selection.get(id)));
2228
+ return new Set(Array.from(mixedIds).map((id) => selection.get(id)).filter((item) => !/* @__PURE__ */ isUndefined(item)));
2066
2229
  });
2067
2230
  function mixed(id) {
2068
2231
  return mixedIds.has(id);
@@ -2129,10 +2292,10 @@ function createGroup(_options = {}) {
2129
2292
  if (items.length === 0) return false;
2130
2293
  return items.every((item) => selection.selectedIds.has(item.id));
2131
2294
  });
2132
- const isMixed = toRef(() => {
2295
+ const isNoneSelected = computed(() => selection.selectedIds.size === 0);
2296
+ const isMixed = computed(() => {
2133
2297
  return mixedIds.size > 0 || !isNoneSelected.value && !isAllSelected.value;
2134
2298
  });
2135
- const isNoneSelected = toRef(() => selection.selectedIds.size === 0);
2136
2299
  function selectAll() {
2137
2300
  for (const item of selectableItems.value) {
2138
2301
  mixedIds.delete(item.id);
@@ -2204,7 +2367,7 @@ function createGroup(_options = {}) {
2204
2367
  * ```
2205
2368
  */
2206
2369
  function createGroupContext(_options = {}) {
2207
- const { namespace = "v0:group",...options } = _options;
2370
+ const { namespace = "v0:group", ...options } = _options;
2208
2371
  const [useGroupContext, _provideGroupContext] = createContext(namespace);
2209
2372
  const context = createGroup(options);
2210
2373
  function provideGroupContext(_context = context, app) {
@@ -2242,7 +2405,7 @@ function useGroup(namespace = "v0:group") {
2242
2405
  //#endregion
2243
2406
  //#region src/components/Group/GroupRoot.vue
2244
2407
  const [useGroupRoot, provideGroupRoot] = createContext();
2245
- const _sfc_main$17 = /* @__PURE__ */ defineComponent({
2408
+ const _sfc_main$18 = /* @__PURE__ */ defineComponent({
2246
2409
  name: "GroupRoot",
2247
2410
  __name: "GroupRoot",
2248
2411
  props: /* @__PURE__ */ mergeModels({
@@ -2263,7 +2426,7 @@ const _sfc_main$17 = /* @__PURE__ */ defineComponent({
2263
2426
  "modelValue": {},
2264
2427
  "modelModifiers": {}
2265
2428
  }),
2266
- emits: ["update:modelValue"],
2429
+ emits: /* @__PURE__ */ mergeModels(["update:model-value"], ["update:modelValue"]),
2267
2430
  setup(__props) {
2268
2431
  const model = useModel(__props, "modelValue");
2269
2432
  const group = createGroup({
@@ -2292,11 +2455,11 @@ const _sfc_main$17 = /* @__PURE__ */ defineComponent({
2292
2455
  };
2293
2456
  }
2294
2457
  });
2295
- var GroupRoot_default = _sfc_main$17;
2458
+ var GroupRoot_default = _sfc_main$18;
2296
2459
 
2297
2460
  //#endregion
2298
2461
  //#region src/components/Group/GroupItem.vue
2299
- const _sfc_main$16 = /* @__PURE__ */ defineComponent({
2462
+ const _sfc_main$17 = /* @__PURE__ */ defineComponent({
2300
2463
  name: "GroupItem",
2301
2464
  __name: "GroupItem",
2302
2465
  props: {
@@ -2332,7 +2495,8 @@ const _sfc_main$16 = /* @__PURE__ */ defineComponent({
2332
2495
  mix: ticket.mix,
2333
2496
  unmix: ticket.unmix,
2334
2497
  attrs: {
2335
- "aria-selected": toValue(ticket.isSelected),
2498
+ "role": "checkbox",
2499
+ "aria-checked": toValue(ticket.isMixed) ? "mixed" : toValue(ticket.isSelected),
2336
2500
  "aria-disabled": toValue(isDisabled),
2337
2501
  "data-selected": toValue(ticket.isSelected) || void 0,
2338
2502
  "data-disabled": toValue(isDisabled) || void 0,
@@ -2344,1355 +2508,1254 @@ const _sfc_main$16 = /* @__PURE__ */ defineComponent({
2344
2508
  };
2345
2509
  }
2346
2510
  });
2347
- var GroupItem_default = _sfc_main$16;
2511
+ var GroupItem_default = _sfc_main$17;
2348
2512
 
2349
2513
  //#endregion
2350
2514
  //#region src/components/Group/index.ts
2515
+ /**
2516
+ * Group component with sub-components for multi-selection.
2517
+ *
2518
+ * @see https://0.vuetifyjs.com/components/group
2519
+ */
2351
2520
  const Group = {
2352
2521
  Root: GroupRoot_default,
2353
2522
  Item: GroupItem_default
2354
2523
  };
2355
2524
 
2356
2525
  //#endregion
2357
- //#region src/composables/useHydration/index.ts
2526
+ //#region src/composables/useLocale/adapters/v0.ts
2358
2527
  /**
2359
- * @module useHydration
2360
- *
2361
- * @see https://0.vuetifyjs.com/composables/plugins/use-hydration
2362
- *
2363
- * @remarks
2364
- * SSR hydration state management composable.
2365
- *
2366
- * Key features:
2367
- * - Hydration state detection (browser vs SSR)
2368
- * - Root component detection
2369
- * - Readonly hydration state refs
2370
- * - Plugin installation support
2371
- * - Perfect for hydration-safe rendering
2528
+ * Vuetify0.x locale adapter implementation
2372
2529
  *
2373
- * Essential for composables that need to behave differently during SSR vs client-side.
2530
+ * This adapter provides translation and number formatting
2531
+ * capabilities using the Intl API and supports both
2532
+ * numbered ({0}, {1}) and named ({name}) variables in translation strings.
2374
2533
  */
2534
+ var Vuetify0LocaleAdapter = class {
2535
+ t(message, ...params) {
2536
+ let resolvedMessage = message;
2537
+ if (params.length > 0 && /* @__PURE__ */ isObject(params[0])) {
2538
+ const variables = params[0];
2539
+ resolvedMessage = resolvedMessage.replace(/{([a-zA-Z][a-zA-Z0-9_]*)}/g, (match, name) => {
2540
+ return /* @__PURE__ */ isUndefined(variables[name]) ? match : String(variables[name]);
2541
+ });
2542
+ params = params.slice(1);
2543
+ }
2544
+ resolvedMessage = resolvedMessage.replace(/\{(\d+)\}/g, (match, index) => {
2545
+ const idx = Number.parseInt(index, 10);
2546
+ if (!/* @__PURE__ */ isUndefined(params[idx])) return String(params[idx]);
2547
+ return match;
2548
+ });
2549
+ return resolvedMessage;
2550
+ }
2551
+ n(value, locale, ...params) {
2552
+ if (!IN_BROWSER || !locale) return value.toString();
2553
+ const options = params[0];
2554
+ return new Intl.NumberFormat(String(locale), options).format(value);
2555
+ }
2556
+ };
2557
+
2558
+ //#endregion
2559
+ //#region src/composables/useSingle/index.ts
2375
2560
  /**
2376
- * Creates a new hydration instance.
2377
- *
2378
- * @returns A new hydration instance.
2561
+ * Creates a new single selection instance that enforces only one selected item at a time.
2379
2562
  *
2380
- * @see https://0.vuetifyjs.com/composables/plugins/use-hydration
2563
+ * Extends `createSelection` by automatically clearing previous selections when a new item is selected.
2564
+ * Adds computed singular properties: `selectedId`, `selectedItem`, `selectedIndex`, `selectedValue`.
2381
2565
  *
2382
- * @example
2383
- * ```ts
2384
- * import { createHydration } from '@vuetify/v0'
2566
+ * @param options The options for the single selection instance.
2567
+ * @template Z The type of the single selection ticket.
2568
+ * @template E The type of the single selection context.
2569
+ * @returns A new single selection instance with single-selection enforcement.
2385
2570
  *
2386
- * const hydration = createHydration()
2387
- * console.log(hydration.isHydrated.value) // false
2388
- * hydration.hydrate()
2389
- * console.log(hydration.isHydrated.value) // true
2390
- * ```
2391
- */
2392
- function createHydration() {
2393
- const isHydrated = shallowRef(false);
2394
- function hydrate() {
2395
- isHydrated.value = true;
2396
- }
2397
- return {
2398
- isHydrated: shallowReadonly(isHydrated),
2399
- hydrate
2400
- };
2401
- }
2402
- function createFallbackHydration() {
2403
- return {
2404
- isHydrated: shallowReadonly(shallowRef(true)),
2405
- hydrate: () => {}
2406
- };
2407
- }
2408
- /**
2409
- * Creates a new hydration context trinity.
2571
+ * @remarks
2572
+ * **Key Differences from `createSelection`:**
2573
+ * - Automatically clears `selectedIds` before selecting a new item (enforces single selection)
2574
+ * - Provides singular computed properties instead of plural sets
2575
+ * - Perfect for tabs, radio buttons, theme selectors, and other single-choice UI components
2410
2576
  *
2411
- * @param options Options for creating the hydration context.
2412
- * @template E The type of the hydration context.
2413
- * @returns A new hydration context trinity.
2577
+ * **Computed Properties:**
2578
+ * - `selectedId`: The ID of the selected item (undefined if none selected)
2579
+ * - `selectedItem`: The selected ticket object (undefined if none selected)
2580
+ * - `selectedIndex`: The index of the selected item (-1 if none selected)
2581
+ * - `selectedValue`: The value of the selected item (undefined if none selected)
2414
2582
  *
2415
- * @see https://0.vuetifyjs.com/composables/plugins/use-hydration
2583
+ * **Inheritance Chain:**
2584
+ * `useRegistry` → `createSelection` → `createSingle` → `createStep`
2585
+ *
2586
+ * @see https://0.vuetifyjs.com/composables/selection/use-single
2416
2587
  *
2417
2588
  * @example
2418
2589
  * ```ts
2419
- * import { createHydrationContext } from '@vuetify/v0'
2590
+ * import { createSingle } from '@vuetify/v0'
2420
2591
  *
2421
- * export const [useHydrationContext, provideHydrationContext, context] = createHydrationContext({
2422
- * namespace: 'app:hydration',
2423
- * })
2592
+ * const tabs = createSingle({ mandatory: true })
2593
+ *
2594
+ * tabs.onboard([
2595
+ * { id: 'home', value: 'Home' },
2596
+ * { id: 'about', value: 'About' },
2597
+ * { id: 'contact', value: 'Contact' },
2598
+ * ])
2599
+ *
2600
+ * tabs.first() // Select first tab
2601
+ *
2602
+ * console.log(tabs.selectedId.value) // 'home'
2603
+ * console.log(tabs.selectedIndex.value) // 0
2604
+ *
2605
+ * tabs.select('about') // Switch to about tab
2606
+ * console.log(tabs.selectedId.value) // 'about'
2607
+ * console.log(tabs.selectedIds.size) // 1 (always enforces single selection)
2424
2608
  * ```
2425
2609
  */
2426
- function createHydrationContext(_options = {}) {
2427
- const { namespace = "v0:hydration" } = _options;
2428
- const [useHydrationContext, _provideHydrationContext] = createContext(namespace);
2429
- const context = createHydration();
2430
- function provideHydrationContext(_context = context, app) {
2431
- return _provideHydrationContext(_context, app);
2610
+ function createSingle(_options = {}) {
2611
+ const { mandatory = false, multiple = false, ...options } = _options;
2612
+ const registry = createSelection({
2613
+ ...options,
2614
+ mandatory,
2615
+ multiple
2616
+ });
2617
+ const selectedId = computed(() => registry.selectedIds.values().next().value);
2618
+ const selectedItem = computed(() => registry.selectedItems.value.values().next().value);
2619
+ const selectedIndex = computed(() => selectedItem.value?.index ?? -1);
2620
+ const selectedValue = computed(() => selectedItem.value?.value);
2621
+ function unselect(id) {
2622
+ if (mandatory && registry.selectedIds.size === 1) return;
2623
+ registry.selectedIds.delete(id);
2432
2624
  }
2433
- return createTrinity(useHydrationContext, provideHydrationContext, context);
2625
+ function toggle(id) {
2626
+ if (registry.selectedIds.has(id)) unselect(id);
2627
+ else registry.select(id);
2628
+ }
2629
+ return {
2630
+ ...registry,
2631
+ selectedId,
2632
+ selectedItem,
2633
+ selectedIndex,
2634
+ selectedValue,
2635
+ unselect,
2636
+ toggle,
2637
+ get size() {
2638
+ return registry.size;
2639
+ }
2640
+ };
2434
2641
  }
2435
2642
  /**
2436
- * Creates a new hydration plugin.
2643
+ * Creates a new single selection context.
2437
2644
  *
2438
- * @param options The options for the hydration plugin.
2439
- * @template E The type of the hydration context.
2440
- * @returns A new hydration plugin.
2645
+ * @param options The options for the single selection context.
2646
+ * @template Z The type of the single selection ticket.
2647
+ * @template E The type of the single selection context.
2648
+ * @returns A new single selection context.
2441
2649
  *
2442
- * @see https://0.vuetifyjs.com/composables/plugins/use-hydration
2650
+ * @see https://0.vuetifyjs.com/composables/selection/use-single
2443
2651
  *
2444
2652
  * @example
2445
2653
  * ```ts
2446
- * import { createApp } from 'vue'
2447
- * import { createHydrationPlugin } from '@vuetify/v0'
2448
- * import App from './App.vue'
2654
+ * import { createSingleContext } from '@vuetify/v0'
2449
2655
  *
2450
- * const app = createApp(App)
2656
+ * // With default namespace 'v0:single'
2657
+ * export const [useSingle, provideSingle, context] = createSingleContext()
2451
2658
  *
2452
- * app.use(createHydrationPlugin())
2659
+ * // In a parent component:
2660
+ * provideSingle()
2453
2661
  *
2454
- * app.mount('#app')
2662
+ * // In a child component:
2663
+ * const single = useSingle()
2664
+ * single.select('tab-1')
2455
2665
  * ```
2456
2666
  */
2457
- function createHydrationPlugin(_options = {}) {
2458
- const { namespace = "v0:hydration",...options } = _options;
2459
- const [, provideHydrationContext, context] = createHydrationContext({
2460
- ...options,
2461
- namespace
2462
- });
2463
- return createPlugin({
2464
- namespace,
2465
- provide: (app) => {
2466
- provideHydrationContext(context, app);
2467
- },
2468
- setup: (app) => {
2469
- app.mixin({ mounted() {
2470
- if (this.$parent !== null) return;
2471
- context.hydrate();
2472
- } });
2473
- }
2474
- });
2667
+ function createSingleContext(_options = {}) {
2668
+ const { namespace = "v0:single", ...options } = _options;
2669
+ const [useSingleContext, _provideSingleContext] = createContext(namespace);
2670
+ const context = createSingle(options);
2671
+ function provideSingleContext(_context = context, app) {
2672
+ return _provideSingleContext(_context, app);
2673
+ }
2674
+ return createTrinity(useSingleContext, provideSingleContext, context);
2475
2675
  }
2476
2676
  /**
2477
- * Returns the current hydration instance.
2677
+ * Returns the current single selection instance.
2478
2678
  *
2479
- * @param namespace The namespace for the hydration context. Defaults to `v0:hydration`.
2480
- * @returns The current hydration instance.
2679
+ * @param namespace The namespace for the single selection context. Defaults to `'v0:single'`.
2680
+ * @returns The current single selection instance.
2481
2681
  *
2482
- * @see https://0.vuetifyjs.com/composables/plugins/use-hydration
2682
+ * @see https://0.vuetifyjs.com/composables/selection/use-single
2483
2683
  *
2484
2684
  * @example
2485
2685
  * ```vue
2486
2686
  * <script setup lang="ts">
2487
- * import { useHydration } from '@vuetify/v0'
2687
+ * import { useSingle } from '@vuetify/v0'
2488
2688
  *
2489
- * const hydration = useHydration()
2689
+ * const tabs = useSingle()
2490
2690
  * <\/script>
2491
2691
  *
2492
2692
  * <template>
2493
2693
  * <div>
2494
- * <p>Is hydrated: {{ hydration.isHydrated.value }}</p>
2694
+ * <p>Selected: {{ tabs.selectedId }}</p>
2495
2695
  * </div>
2496
2696
  * </template>
2497
2697
  * ```
2498
2698
  */
2499
- function useHydration(namespace = "v0:hydration") {
2500
- const fallback = createFallbackHydration();
2501
- if (!getCurrentInstance()) return fallback;
2502
- try {
2503
- return useContext(namespace, fallback);
2504
- } catch {
2505
- return fallback;
2506
- }
2699
+ function useSingle(namespace = "v0:single") {
2700
+ return useContext(namespace);
2507
2701
  }
2508
2702
 
2509
2703
  //#endregion
2510
- //#region src/composables/useResizeObserver/index.ts
2511
- /**
2512
- * @module useResizeObserver
2513
- *
2514
- * @remarks
2515
- * ResizeObserver composable with lifecycle management.
2516
- *
2517
- * Key features:
2518
- * - ResizeObserver API wrapper
2519
- * - Pause/resume/stop functionality
2520
- * - Automatic cleanup on unmount
2521
- * - SSR-safe (checks SUPPORTS_OBSERVER)
2522
- * - Hydration-aware
2523
- * - Box model options (content-box/border-box)
2524
- *
2525
- * Perfect for responsive components and size-based rendering.
2526
- */
2704
+ //#region src/composables/useTokens/index.ts
2527
2705
  /**
2528
- * A composable that uses the Resize Observer API to detect when an element's
2529
- * size changes.
2706
+ * Creates a new token instance.
2530
2707
  *
2531
- * @param target The element to observe.
2532
- * @param callback The callback to execute when the element's size changes.
2533
- * @param options The options for the Resize Observer.
2534
- * @returns An object with methods to control the observer.
2708
+ * @param tokens The tokens to use.
2709
+ * @param options The options for the token instance.
2710
+ * @template Z The type of the token ticket.
2711
+ * @template E The type of the token context.
2712
+ * @returns A new token instance.
2535
2713
  *
2536
- * @see https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver
2537
- * @see https://0.vuetifyjs.com/composables/system/use-resize-observer
2714
+ * @see https://www.designtokens.org/tr/drafts/format/
2715
+ * @see https://0.vuetifyjs.com/composables/registration/use-tokens
2538
2716
  *
2539
2717
  * @example
2540
2718
  * ```ts
2541
- * import { ref } from 'vue'
2542
- * import { useResizeObserver } from '@vuetify/v0'
2543
- *
2544
- * const el = ref<HTMLElement>()
2545
- * const width = ref(0)
2546
- * const height = ref(0)
2719
+ * import { useTokens } from '@vuetify/v0'
2547
2720
  *
2548
- * const { pause, resume, isPaused } = useResizeObserver(
2549
- * el,
2550
- * (entries) => {
2551
- * const entry = entries[0]
2552
- * if (entry) {
2553
- * width.value = entry.contentRect.width
2554
- * height.value = entry.contentRect.height
2555
- * console.log('Size changed:', width.value, 'x', height.value)
2556
- * }
2721
+ * const tokens = useTokens({
2722
+ * colors: {
2723
+ * primary: '#3b82f6',
2724
+ * secondary: '{colors.primary}', // Alias reference
2557
2725
  * },
2558
- * { immediate: true }
2559
- * )
2560
- *
2561
- * // Pause observation
2562
- * pause()
2726
+ * })
2563
2727
  *
2564
- * // Resume observation
2565
- * resume()
2728
+ * console.log(tokens.resolve('{colors.primary}')) // '#3b82f6'
2729
+ * console.log(tokens.resolve('{colors.secondary}')) // '#3b82f6'
2566
2730
  * ```
2567
2731
  */
2568
- function useResizeObserver(target, callback, options = {}) {
2569
- const { isHydrated } = useHydration();
2570
- const observer = shallowRef();
2571
- const isPaused = shallowRef(false);
2572
- const isActive = toRef(() => !!observer.value);
2573
- function setup() {
2574
- if (!isHydrated.value || !SUPPORTS_OBSERVER || !target.value || isPaused.value) return;
2575
- observer.value = new ResizeObserver((entries) => {
2576
- callback(entries.map((entry) => ({
2577
- contentRect: {
2578
- width: entry.contentRect.width,
2579
- height: entry.contentRect.height,
2580
- top: entry.contentRect.top,
2581
- left: entry.contentRect.left
2582
- },
2583
- target: entry.target
2584
- })));
2585
- });
2586
- observer.value.observe(target.value, { box: options.box || "content-box" });
2587
- if (options.immediate) {
2588
- const rect = target.value.getBoundingClientRect();
2589
- callback([{
2590
- contentRect: {
2591
- width: rect.width,
2592
- height: rect.height,
2593
- top: rect.top,
2594
- left: rect.left
2595
- },
2596
- target: target.value
2597
- }]);
2598
- }
2599
- }
2600
- watch([isHydrated, target], () => {
2601
- cleanup();
2602
- setup();
2603
- }, { immediate: true });
2604
- function cleanup() {
2605
- if (observer.value) {
2606
- observer.value.disconnect();
2607
- observer.value = void 0;
2608
- }
2609
- }
2610
- function pause() {
2611
- isPaused.value = true;
2612
- observer.value?.disconnect();
2732
+ function createTokens(tokens = {}, options = {}) {
2733
+ const logger = useLogger();
2734
+ const registry = useRegistry(options);
2735
+ const cache = /* @__PURE__ */ new Map();
2736
+ registry.onboard(flatten(tokens, options.prefix, !!options.flat));
2737
+ function isAlias(token) {
2738
+ return /* @__PURE__ */ isString(token) && token.length > 2 && token[0] === "{" && token.at(-1) === "}";
2613
2739
  }
2614
- function resume() {
2615
- isPaused.value = false;
2616
- setup();
2740
+ function isTokenAlias(value) {
2741
+ return /* @__PURE__ */ isObject(value) && "$value" in value;
2617
2742
  }
2618
- function stop() {
2619
- cleanup();
2743
+ function resolve(token, visited = /* @__PURE__ */ new Set()) {
2744
+ const cacheKey = /* @__PURE__ */ isString(token) ? token : JSON.stringify(token);
2745
+ const cached = cache.get(cacheKey);
2746
+ if (!/* @__PURE__ */ isUndefined(cached)) return cached;
2747
+ const reference = isTokenAlias(token) ? token.$value : token;
2748
+ const isAliasReference = /* @__PURE__ */ isString(reference) && isAlias(reference);
2749
+ const clean = isAliasReference ? reference.slice(1, -1) : String(reference);
2750
+ if (visited.has(clean)) {
2751
+ logger.warn(`Circular alias detected for "${clean}"`);
2752
+ cache.set(cacheKey, void 0);
2753
+ return;
2754
+ }
2755
+ visited.add(clean);
2756
+ let found = registry.get(clean);
2757
+ let segments = [];
2758
+ if (!found && clean.includes(".")) {
2759
+ const parts = clean.split(".");
2760
+ for (let i = parts.length - 1; i > 0; i--) {
2761
+ const prefix = parts.slice(0, i).join(".");
2762
+ const suffix = parts.slice(i);
2763
+ const candidate = registry.get(prefix);
2764
+ if (!/* @__PURE__ */ isUndefined(candidate?.value)) {
2765
+ found = candidate;
2766
+ segments = suffix;
2767
+ break;
2768
+ }
2769
+ }
2770
+ }
2771
+ if (/* @__PURE__ */ isUndefined(found?.value)) {
2772
+ if (isAliasReference) logger.warn(`Alias not found for "${String(reference)}"`);
2773
+ cache.set(cacheKey, void 0);
2774
+ return;
2775
+ }
2776
+ let result;
2777
+ let current = found.value;
2778
+ if (segments.length > 0) {
2779
+ if (isTokenAlias(current)) current = current.$value;
2780
+ for (const segment of segments) {
2781
+ if (!/* @__PURE__ */ isObject(current) || !(segment in current)) {
2782
+ current = void 0;
2783
+ break;
2784
+ }
2785
+ current = current[segment];
2786
+ if (isTokenAlias(current)) current = current.$value;
2787
+ }
2788
+ if (/* @__PURE__ */ isUndefined(current)) {
2789
+ logger.warn(`Path not found inside "${clean}": ${segments.join(".")}`);
2790
+ cache.set(cacheKey, void 0);
2791
+ return;
2792
+ }
2793
+ result = current;
2794
+ } else if (isTokenAlias(current)) {
2795
+ const inner = current.$value;
2796
+ if (/* @__PURE__ */ isString(inner) && isAlias(inner)) return resolve(inner, visited);
2797
+ result = inner;
2798
+ } else if (/* @__PURE__ */ isString(current) && isAlias(current)) return resolve(current, visited);
2799
+ else result = current;
2800
+ cache.set(cacheKey, result);
2801
+ return result;
2620
2802
  }
2621
- onScopeDispose(stop, true);
2622
2803
  return {
2623
- isActive: shallowReadonly(isActive),
2624
- isPaused: shallowReadonly(isPaused),
2625
- pause,
2626
- resume,
2627
- stop
2804
+ ...registry,
2805
+ resolve,
2806
+ isAlias,
2807
+ get size() {
2808
+ return registry.size;
2809
+ }
2628
2810
  };
2629
2811
  }
2630
2812
  /**
2631
- * A convenience composable that uses the Resize Observer API to track an
2632
- * element's size.
2813
+ * Creates a new token context.
2633
2814
  *
2634
- * @param target The element to observe.
2635
- * @returns An object with the element's width and height.
2815
+ * @param namespace The namespace for the token context.
2816
+ * @param tokens The tokens to use.
2817
+ * @template Z The type of the token ticket.
2818
+ * @template E The type of the token context.
2819
+ * @returns A new token context.
2636
2820
  *
2637
- * @see https://0.vuetifyjs.com/composables/system/use-resize-observer#use-element-size
2821
+ * @see https://0.vuetifyjs.com/composables/registration/use-tokens
2638
2822
  *
2639
2823
  * @example
2640
2824
  * ```ts
2641
- * import { ref, watchEffect } from 'vue'
2642
- * import { useElementSize } from '@vuetify/v0'
2643
- *
2644
- * const box = ref<HTMLElement>()
2645
- * const { width, height } = useElementSize(box)
2825
+ * import { createTokensContext } from '@vuetify/v0'
2646
2826
  *
2647
- * // Width and height are reactive refs
2648
- * watchEffect(() => {
2649
- * console.log('Box size:', width.value, 'x', height.value)
2827
+ * export const [useTokens, provideTokens, context] = createTokensContext({
2828
+ * namespace: 'v0:tokens',
2829
+ * tokens: {
2830
+ * colors: {
2831
+ * primary: '#3b82f6',
2832
+ * secondary: '{colors.primary}', // Alias reference
2833
+ * },
2834
+ * },
2650
2835
  * })
2651
2836
  * ```
2652
2837
  */
2653
- function useElementSize(target) {
2654
- const width = shallowRef(0);
2655
- const height = shallowRef(0);
2656
- const { pause: _pause, resume, stop, isActive, isPaused } = useResizeObserver(target, (entries) => {
2657
- const entry = entries[0];
2658
- if (entry) {
2659
- width.value = entry.contentRect.width;
2660
- height.value = entry.contentRect.height;
2661
- }
2662
- }, { immediate: true });
2663
- function pause() {
2664
- width.value = 0;
2665
- height.value = 0;
2666
- _pause();
2838
+ function createTokensContext(_options) {
2839
+ const { namespace = "v0:tokens", tokens = {}, ...options } = _options;
2840
+ const [useTokensContext, _provideTokensContext] = createContext(namespace);
2841
+ const context = createTokens(tokens, options);
2842
+ function provideTokensContext(_context = context, app) {
2843
+ return _provideTokensContext(_context, app);
2667
2844
  }
2668
- return {
2669
- width,
2670
- height,
2671
- isActive,
2672
- isPaused,
2673
- pause,
2674
- resume,
2675
- stop
2676
- };
2845
+ return createTrinity(useTokensContext, provideTokensContext, context);
2677
2846
  }
2678
-
2679
- //#endregion
2680
- //#region src/composables/useOverflow/index.ts
2681
2847
  /**
2682
- * @module useOverflow
2683
- *
2684
- * @remarks
2685
- * Composable for computing how many items fit in a container based on available width.
2686
- * Enables responsive truncation logic for Pagination, Breadcrumbs, and similar components.
2848
+ * Returns the current tokens instance.
2687
2849
  *
2688
- * Key features:
2689
- * - Container width tracking via ResizeObserver
2690
- * - Two modes: variable-width (per-item) or uniform-width (sample-based)
2691
- * - Computes capacity (how many items fit)
2692
- * - SSR-safe with Infinity fallback
2693
- * - Supports reserved space for nav buttons, ellipsis, etc.
2694
- *
2695
- * Use variable mode (default) for items with different widths like Breadcrumbs.
2696
- * Use uniform mode (itemWidth option) for same-width items like Pagination buttons.
2697
- */
2698
- /**
2699
- * Creates a new overflow context for computing how many items fit in a container.
2850
+ * @param namespace The namespace for the tokens context. Defaults to `'v0:tokens'`.
2851
+ * @returns The current tokens instance.
2700
2852
  *
2701
- * @param options Configuration options
2702
- * @returns Overflow context with container ref, capacity, and measurement functions
2853
+ * @see https://0.vuetifyjs.com/composables/registration/use-tokens
2703
2854
  *
2704
- * @example Variable-width mode (Breadcrumbs)
2855
+ * @example
2705
2856
  * ```vue
2706
- * <script lang="ts" setup>
2707
- * import { useTemplateRef } from 'vue'
2708
- * import { createOverflow } from '@vuetify/v0'
2857
+ * <script setup lang="ts">
2858
+ * import { useTokens } from '@vuetify/v0'
2709
2859
  *
2710
- * const containerRef = useTemplateRef('container')
2711
- * const overflow = createOverflow({
2712
- * container: containerRef,
2713
- * gap: 8,
2714
- * reserved: 40,
2715
- * })
2860
+ * const tokens = useTokens()
2716
2861
  * <\/script>
2717
- *
2718
- * <template>
2719
- * <div ref="container">
2720
- * <span
2721
- * v-for="(item, i) in items.slice(0, overflow.capacity.value)"
2722
- * :key="i"
2723
- * :ref="el => overflow.measure(i, el)"
2724
- * >
2725
- * {{ item }}
2726
- * </span>
2727
- * <span v-if="overflow.isOverflowing.value">...</span>
2728
- * </div>
2729
- * </template>
2730
- * ```
2731
- *
2732
- * @example Uniform-width mode (Pagination)
2733
- * ```ts
2734
- * const overflow = createOverflow({
2735
- * container: () => atom.value?.element,
2736
- * itemWidth: buttonWidth,
2737
- * reserved: () => buttonWidth.value * 4,
2738
- * })
2739
2862
  * ```
2740
2863
  */
2741
- function createOverflow(options = {}) {
2742
- const { container: _container, gap = 0, reserved = 0, itemWidth, reverse } = options;
2743
- const container = /* @__PURE__ */ isUndefined(_container) ? shallowRef() : toRef(_container);
2744
- const widths = shallowRef(/* @__PURE__ */ new Map());
2745
- const { width } = useElementSize(container);
2746
- function measure(index, el) {
2747
- if (!el) {
2748
- if (widths.value.has(index)) {
2749
- const next = new Map(widths.value);
2750
- next.delete(index);
2751
- widths.value = next;
2864
+ function useTokens(namespace = "v0:tokens") {
2865
+ return useContext(namespace);
2866
+ }
2867
+ /**
2868
+ * Flattens a nested collection of tokens into a flat array of tokens.
2869
+ * Each token is represented by an object containing its ID & value.
2870
+ * @param tokens The collection of tokens to flatten.
2871
+ * @param prefix An optional prefix to prepend to each token ID.
2872
+ * @returns An array of flattened tokens, each with an ID and value.
2873
+ */
2874
+ function flatten(tokens, prefix = "", flat = false) {
2875
+ const flattened = [];
2876
+ const stack = [{
2877
+ tokens,
2878
+ prefix,
2879
+ flat
2880
+ }];
2881
+ while (stack.length > 0) {
2882
+ const { tokens: currentTokens, prefix: currentPrefix, flat: flat$1 } = stack.pop();
2883
+ const meta = {};
2884
+ for (const k in currentTokens) if (k.startsWith("$")) meta[k] = currentTokens[k];
2885
+ if (Object.keys(meta).length > 0 && currentPrefix) flattened.push({
2886
+ id: currentPrefix,
2887
+ value: meta
2888
+ });
2889
+ for (const key in currentTokens) {
2890
+ if (key.startsWith("$")) continue;
2891
+ const value = currentTokens[key];
2892
+ const id = currentPrefix ? `${currentPrefix}.${key}` : key;
2893
+ if (!/* @__PURE__ */ isObject(value)) {
2894
+ flattened.push({
2895
+ id,
2896
+ value
2897
+ });
2898
+ continue;
2752
2899
  }
2753
- return;
2900
+ if ("$value" in value) {
2901
+ flattened.push({
2902
+ id,
2903
+ value
2904
+ });
2905
+ const inner = value.$value;
2906
+ if (/* @__PURE__ */ isObject(inner) && !flat$1) for (const innerKey in inner) {
2907
+ if (innerKey.startsWith("$")) continue;
2908
+ const child = inner[innerKey];
2909
+ const childId = `${id}.${innerKey}`;
2910
+ if (!/* @__PURE__ */ isObject(child)) flattened.push({
2911
+ id: childId,
2912
+ value: child
2913
+ });
2914
+ else if ("$value" in child) flattened.push({
2915
+ id: childId,
2916
+ value: child
2917
+ });
2918
+ else stack.push({
2919
+ tokens: child,
2920
+ prefix: childId,
2921
+ flat: flat$1
2922
+ });
2923
+ }
2924
+ continue;
2925
+ }
2926
+ if (flat$1) {
2927
+ flattened.push({
2928
+ id,
2929
+ value
2930
+ });
2931
+ continue;
2932
+ }
2933
+ stack.push({
2934
+ tokens: value,
2935
+ prefix: id,
2936
+ flat: flat$1
2937
+ });
2754
2938
  }
2755
- const style = getComputedStyle(el);
2756
- const marginX = Number.parseFloat(style.marginLeft) + Number.parseFloat(style.marginRight);
2757
- const w = el.offsetWidth + marginX;
2758
- if (widths.value.get(index) !== w) widths.value = new Map(widths.value).set(index, w);
2759
2939
  }
2760
- function reset() {
2761
- widths.value = /* @__PURE__ */ new Map();
2940
+ return flattened;
2941
+ }
2942
+
2943
+ //#endregion
2944
+ //#region src/composables/useLocale/index.ts
2945
+ /**
2946
+ * Creates a new locale instance.
2947
+ *
2948
+ * @param options The options for the locale instance.
2949
+ * @template Z The type of the locale ticket.
2950
+ * @template E The type of the locale context.
2951
+ * @returns A new locale instance.
2952
+ *
2953
+ * @see https://0.vuetifyjs.com/composables/plugins/use-locale
2954
+ */
2955
+ function createLocale(_options = {}) {
2956
+ const { adapter = new Vuetify0LocaleAdapter(), messages = {}, ...options } = _options;
2957
+ const tokens = createTokens(messages);
2958
+ const registry = createSingle(options);
2959
+ for (const id in messages) {
2960
+ registry.register({ id });
2961
+ if (id === options.default && !registry.selectedId.value) registry.select(id);
2762
2962
  }
2763
- const total = computed(() => {
2764
- const g = toValue(gap);
2765
- let sum = 0;
2766
- let count = 0;
2767
- for (const w of widths.value.values()) {
2768
- sum += w + (count > 0 ? g : 0);
2769
- count++;
2963
+ function t(key, params, fallback) {
2964
+ const locale = registry.selectedId.value;
2965
+ const args = toArray(params);
2966
+ if (!locale) return adapter.t(fallback ?? key, ...args);
2967
+ const path = `${locale}.${key}`;
2968
+ const message = tokens.get(path)?.value;
2969
+ const template = /* @__PURE__ */ isString(message) ? resolve(locale, message) : fallback ?? key;
2970
+ return adapter.t(template, ...args);
2971
+ }
2972
+ function n(value, ...params) {
2973
+ return adapter.n(value, registry.selectedId.value, ...params);
2974
+ }
2975
+ function resolve(locale, str) {
2976
+ return str.replace(/{([a-zA-Z0-9.-_]+)}/g, (match, key) => {
2977
+ const [prefix, ...rest] = key.split(".");
2978
+ const target = registry.has(prefix) ? prefix : locale;
2979
+ const path = `${target}.${registry.has(prefix) ? rest.join(".") : key}`;
2980
+ const resolved = tokens.get(path)?.value;
2981
+ if (/* @__PURE__ */ isString(resolved)) return resolve(target, resolved);
2982
+ return match;
2983
+ });
2984
+ }
2985
+ return {
2986
+ ...registry,
2987
+ t,
2988
+ n,
2989
+ get size() {
2990
+ return registry.size;
2770
2991
  }
2771
- return sum;
2772
- });
2992
+ };
2993
+ }
2994
+ function createLocaleFallback() {
2773
2995
  return {
2774
- container,
2775
- width,
2776
- capacity: computed(() => {
2777
- const available = width.value - toValue(reserved);
2778
- if (width.value === 0) return Infinity;
2779
- if (available <= 0) return 0;
2780
- const g = toValue(gap);
2781
- const uniformWidth = toValue(itemWidth);
2782
- if (uniformWidth && uniformWidth > 0) {
2783
- const first = uniformWidth;
2784
- const subsequent = uniformWidth + g;
2785
- if (available < first) return 0;
2786
- return Math.max(1, Math.floor((available - first) / subsequent) + 1);
2787
- }
2788
- const entries = [...widths.value.entries()].toSorted((a, b) => a[0] - b[0]);
2789
- if (toValue(reverse)) entries.reverse();
2790
- let sum = 0;
2791
- let count = 0;
2792
- for (const [, w] of entries) {
2793
- const next = sum + w + (count > 0 ? g : 0);
2794
- if (next > available) break;
2795
- sum = next;
2796
- count++;
2797
- }
2798
- return count;
2799
- }),
2800
- total,
2801
- isOverflowing: toRef(() => {
2802
- return total.value > width.value - toValue(reserved);
2803
- }),
2804
- measure,
2805
- reset
2996
+ size: 0,
2997
+ t: (key, _params, fallback) => fallback ?? key,
2998
+ n: String
2806
2999
  };
2807
3000
  }
2808
3001
  /**
2809
- * Creates an overflow context with dependency injection support.
3002
+ * Creates a new locale context.
2810
3003
  *
2811
- * @param options Configuration options including namespace
2812
- * @returns Trinity tuple: [useContext, provideContext, defaultContext]
3004
+ * @param options The options for the locale context.
3005
+ * @template Z The type of the locale ticket.
3006
+ * @template E The type of the locale context.
3007
+ * @returns A new locale context.
3008
+ *
3009
+ * @see https://0.vuetifyjs.com/composables/plugins/use-locale
2813
3010
  *
2814
3011
  * @example
2815
3012
  * ```ts
2816
- * // Create injectable context
2817
- * const [useOverflow, provideOverflow, overflow] = createOverflowContext({
2818
- * namespace: 'my-overflow',
2819
- * gap: 8,
2820
- * reserved: 160,
3013
+ * import { createLocaleContext } from '@vuetify/v0'
3014
+ *
3015
+ * export const [useAppLocale, provideAppLocale, appLocale] = createLocaleContext({
3016
+ * namespace: 'app:locale',
3017
+ * messages: {
3018
+ * en: { hello: 'Hello' },
3019
+ * es: { hello: 'Hola' },
3020
+ * },
2821
3021
  * })
2822
3022
  *
2823
- * // In parent component
2824
- * provideOverflow()
3023
+ * // In a parent component:
3024
+ * provideAppLocale()
2825
3025
  *
2826
- * // In child component
2827
- * const overflow = useOverflow()
3026
+ * // In a child component:
3027
+ * const locale = useAppLocale()
3028
+ * locale.select('es')
2828
3029
  * ```
2829
3030
  */
2830
- function createOverflowContext(_options = {}) {
2831
- const { namespace = "v0:overflow",...options } = _options;
2832
- const [useOverflowContext, _provideOverflowContext] = createContext(namespace);
2833
- const context = createOverflow(options);
2834
- function provideOverflowContext(_context = context, app) {
2835
- return _provideOverflowContext(_context, app);
3031
+ function createLocaleContext(_options = {}) {
3032
+ const { namespace = "v0:locale", ...options } = _options;
3033
+ const [useLocaleContext, _provideLocaleContext] = createContext(namespace);
3034
+ const context = createLocale(options);
3035
+ function provideLocaleContext(_context = context, app) {
3036
+ return _provideLocaleContext(_context, app);
2836
3037
  }
2837
- return createTrinity(useOverflowContext, provideOverflowContext, context);
3038
+ return createTrinity(useLocaleContext, provideLocaleContext, context);
2838
3039
  }
2839
3040
  /**
2840
- * Returns the current overflow context from dependency injection.
3041
+ * Creates a new locale plugin.
2841
3042
  *
2842
- * @param namespace The namespace for the overflow context. Defaults to `v0:overflow`.
2843
- * @returns The current overflow context.
3043
+ * @param options The options for the locale plugin.
3044
+ * @template Z The type of the locale ticket.
3045
+ * @template E The type of the locale context.
3046
+ * @template R The type of the token ticket.
3047
+ * @template O The type of the token context.
3048
+ * @returns A new locale plugin.
2844
3049
  *
2845
- * @example
2846
- * ```vue
2847
- * <script lang="ts" setup>
2848
- * import { useOverflow } from '@vuetify/v0'
3050
+ * @see https://0.vuetifyjs.com/composables/plugins/use-locale
3051
+ */
3052
+ function createLocalePlugin(_options = {}) {
3053
+ const { namespace = "v0:locale", adapter = new Vuetify0LocaleAdapter(), messages = {}, ...options } = _options;
3054
+ const [, provideLocaleContext, context] = createLocaleContext({
3055
+ ...options,
3056
+ namespace,
3057
+ adapter,
3058
+ messages
3059
+ });
3060
+ return createPlugin({
3061
+ namespace,
3062
+ provide: (app) => {
3063
+ provideLocaleContext(context, app);
3064
+ }
3065
+ });
3066
+ }
3067
+ /**
3068
+ * Returns the current locale instance.
2849
3069
  *
2850
- * // Inject overflow context provided by parent
2851
- * const overflow = useOverflow()
2852
- * <\/script>
3070
+ * @returns The current locale instance.
2853
3071
  *
2854
- * <template>
2855
- * <div>
2856
- * <p>Capacity: {{ overflow.capacity.value }}</p>
2857
- * </div>
2858
- * </template>
2859
- * ```
3072
+ * @see https://0.vuetifyjs.com/composables/plugins/use-locale
2860
3073
  */
2861
- function useOverflow(namespace = "v0:overflow") {
2862
- return useContext(namespace);
3074
+ function useLocale(namespace = "v0:locale") {
3075
+ const fallback = createLocaleFallback();
3076
+ if (!getCurrentInstance()) return fallback;
3077
+ try {
3078
+ return useContext(namespace, fallback);
3079
+ } catch {
3080
+ return fallback;
3081
+ }
2863
3082
  }
2864
3083
 
2865
3084
  //#endregion
2866
- //#region src/composables/usePagination/index.ts
3085
+ //#region src/composables/useHydration/index.ts
2867
3086
  /**
2868
- * @module usePagination
2869
- *
2870
- * @remarks
2871
- * Lightweight pagination composable for navigating through pages.
3087
+ * Creates a new hydration instance.
2872
3088
  *
2873
- * Key features:
2874
- * - No registry overhead - just a bounded integer
2875
- * - Direct ref support for v-model compatibility
2876
- * - Navigation methods: next, prev, first, last
2877
- * - Computed visible items with ellipsis
2878
- * - Trinity pattern for dependency injection
2879
- *
2880
- * Unlike registry-based composables, pagination tracks a single number
2881
- * within a range, making it efficient for large page counts.
2882
- */
2883
- /**
2884
- * Creates a pagination instance.
3089
+ * @returns A new hydration instance.
2885
3090
  *
2886
- * @param options The options for the pagination instance.
2887
- * @returns A pagination context with navigation methods.
3091
+ * @see https://0.vuetifyjs.com/composables/plugins/use-hydration
2888
3092
  *
2889
3093
  * @example
2890
3094
  * ```ts
2891
- * import { createPagination } from '@vuetify/v0'
2892
- *
2893
- * // Basic usage
2894
- * const pagination = createPagination({ size: 100 })
2895
- * pagination.next()
2896
- * pagination.items.value // [{ type: 'page', value: 1 }, { type: 'page', value: 2 }, ...]
3095
+ * import { createHydration } from '@vuetify/v0'
2897
3096
  *
2898
- * // With v-model (pass a ref)
2899
- * const page = ref(1)
2900
- * const pagination = createPagination({ page, size: 100 })
2901
- * // Mutating pagination.page or the passed ref syncs both
3097
+ * const hydration = createHydration()
3098
+ * console.log(hydration.isHydrated.value) // false
3099
+ * hydration.hydrate()
3100
+ * console.log(hydration.isHydrated.value) // true
2902
3101
  * ```
2903
3102
  */
2904
- function createPagination(_options = {}) {
2905
- const { page: _page = 1, itemsPerPage: _itemsPerPage = 10, size: _size = 0, visible: _visible = 7, ellipsis = "..." } = _options;
2906
- const page = isRef(_page) ? _page : shallowRef(_page);
2907
- const pages = computed(() => {
2908
- const size = toValue(_size);
2909
- const perPage = toValue(_itemsPerPage);
2910
- if (size <= 0 || /* @__PURE__ */ isNaN(size)) return 0;
2911
- return Math.ceil(size / perPage);
2912
- });
2913
- function first() {
2914
- page.value = 1;
2915
- }
2916
- function last() {
2917
- page.value = Math.max(1, pages.value);
2918
- }
2919
- function next() {
2920
- if (page.value < pages.value) page.value++;
2921
- }
2922
- function prev() {
2923
- if (page.value > 1) page.value--;
2924
- }
2925
- function select(value) {
2926
- if (value < 1) page.value = 1;
2927
- else if (value > pages.value) page.value = Math.max(1, pages.value);
2928
- else page.value = value;
2929
- }
2930
- const isFirst = computed(() => page.value <= 1);
2931
- const isLast = computed(() => page.value >= pages.value);
2932
- const pageStart = computed(() => (page.value - 1) * toValue(_itemsPerPage));
2933
- const pageStop = computed(() => Math.min(pageStart.value + toValue(_itemsPerPage), toValue(_size)));
2934
- function toPage(value) {
2935
- return {
2936
- type: "page",
2937
- value
2938
- };
2939
- }
2940
- function toEllipsis() {
2941
- return ellipsis === false ? false : {
2942
- type: "ellipsis",
2943
- value: ellipsis
2944
- };
2945
- }
2946
- function filter(array) {
2947
- return array.filter(Boolean);
3103
+ function createHydration() {
3104
+ const isHydrated = shallowRef(false);
3105
+ function hydrate() {
3106
+ isHydrated.value = true;
2948
3107
  }
2949
3108
  return {
2950
- page,
2951
- ellipsis,
2952
- items: computed(() => {
2953
- const pageCount = pages.value;
2954
- const visible = toValue(_visible);
2955
- const current = page.value;
2956
- if (pageCount <= 0 || /* @__PURE__ */ isNaN(pageCount) || pageCount > Number.MAX_SAFE_INTEGER) return [];
2957
- if (visible <= 0) return [];
2958
- if (visible <= 2) return [toPage(current)];
2959
- if (pageCount <= visible) return (/* @__PURE__ */ range(pageCount, 1)).map(toPage);
2960
- if (visible === 3) {
2961
- const mid = current <= 1 ? 2 : current >= pageCount ? pageCount - 1 : current;
2962
- return [
2963
- toPage(1),
2964
- toPage(mid),
2965
- toPage(pageCount)
2966
- ];
2967
- }
2968
- const boundary = visible - 2;
2969
- const middle = visible - 4;
2970
- if (middle <= 0) {
2971
- if (current <= boundary) return filter([
2972
- ...(/* @__PURE__ */ range(boundary, 1)).map(toPage),
2973
- toEllipsis(),
2974
- toPage(pageCount)
2975
- ]);
2976
- if (current > pageCount - boundary) return filter([
2977
- toPage(1),
2978
- toEllipsis(),
2979
- ...(/* @__PURE__ */ range(boundary, pageCount - boundary + 1)).map(toPage)
2980
- ]);
2981
- return current <= Math.ceil(pageCount / 2) ? filter([
2982
- toPage(1),
2983
- toPage(current),
2984
- toEllipsis(),
2985
- toPage(pageCount)
2986
- ]) : filter([
2987
- toPage(1),
2988
- toEllipsis(),
2989
- toPage(current),
2990
- toPage(pageCount)
2991
- ]);
2992
- }
2993
- const leftThreshold = boundary - 1;
2994
- const rightThreshold = pageCount - boundary + 2;
2995
- if (current <= leftThreshold) return filter([
2996
- ...(/* @__PURE__ */ range(boundary, 1)).map(toPage),
2997
- toEllipsis(),
2998
- toPage(pageCount)
2999
- ]);
3000
- else if (current >= rightThreshold) return filter([
3001
- toPage(1),
3002
- toEllipsis(),
3003
- ...(/* @__PURE__ */ range(boundary, pageCount - boundary + 1)).map(toPage)
3004
- ]);
3005
- else {
3006
- const start = current - Math.floor(middle / 2);
3007
- return filter([
3008
- toPage(1),
3009
- toEllipsis(),
3010
- ...(/* @__PURE__ */ range(middle, start)).map(toPage),
3011
- toEllipsis(),
3012
- toPage(pageCount)
3013
- ]);
3014
- }
3015
- }),
3016
- pageStart,
3017
- pageStop,
3018
- isFirst,
3019
- isLast,
3020
- first,
3021
- last,
3022
- next,
3023
- prev,
3024
- select,
3025
- get itemsPerPage() {
3026
- return toValue(_itemsPerPage);
3027
- },
3028
- get size() {
3029
- return toValue(_size);
3030
- },
3031
- get pages() {
3032
- return pages.value;
3033
- }
3109
+ isHydrated: shallowReadonly(isHydrated),
3110
+ hydrate
3111
+ };
3112
+ }
3113
+ function createFallbackHydration() {
3114
+ return {
3115
+ isHydrated: shallowReadonly(shallowRef(true)),
3116
+ hydrate: () => {}
3034
3117
  };
3035
3118
  }
3036
3119
  /**
3037
- * Creates a pagination context for dependency injection.
3120
+ * Creates a new hydration context trinity.
3121
+ *
3122
+ * @param options Options for creating the hydration context.
3123
+ * @template E The type of the hydration context.
3124
+ * @returns A new hydration context trinity.
3125
+ *
3126
+ * @see https://0.vuetifyjs.com/composables/plugins/use-hydration
3127
+ *
3128
+ * @example
3129
+ * ```ts
3130
+ * import { createHydrationContext } from '@vuetify/v0'
3131
+ *
3132
+ * export const [useHydrationContext, provideHydrationContext, context] = createHydrationContext({
3133
+ * namespace: 'app:hydration',
3134
+ * })
3135
+ * ```
3136
+ */
3137
+ function createHydrationContext(_options = {}) {
3138
+ const { namespace = "v0:hydration" } = _options;
3139
+ const [useHydrationContext, _provideHydrationContext] = createContext(namespace);
3140
+ const context = createHydration();
3141
+ function provideHydrationContext(_context = context, app) {
3142
+ return _provideHydrationContext(_context, app);
3143
+ }
3144
+ return createTrinity(useHydrationContext, provideHydrationContext, context);
3145
+ }
3146
+ /**
3147
+ * Creates a new hydration plugin.
3038
3148
  *
3039
- * @param options The options including namespace.
3040
- * @returns A trinity: [usePagination, providePagination, defaultContext]
3149
+ * @param options The options for the hydration plugin.
3150
+ * @template E The type of the hydration context.
3151
+ * @returns A new hydration plugin.
3152
+ *
3153
+ * @see https://0.vuetifyjs.com/composables/plugins/use-hydration
3041
3154
  *
3042
3155
  * @example
3043
3156
  * ```ts
3044
- * // With default namespace 'v0:pagination'
3045
- * const [usePagination, providePaginationContext] = createPaginationContext({ size: 50 })
3157
+ * import { createApp } from 'vue'
3158
+ * import { createHydrationPlugin } from '@vuetify/v0'
3159
+ * import App from './App.vue'
3046
3160
  *
3047
- * // Or with custom namespace
3048
- * const [usePagination, providePaginationContext] = createPaginationContext({
3049
- * namespace: 'my-pagination',
3050
- * size: 50,
3051
- * })
3161
+ * const app = createApp(App)
3052
3162
  *
3053
- * // Parent component
3054
- * providePaginationContext()
3163
+ * app.use(createHydrationPlugin())
3055
3164
  *
3056
- * // Child component
3057
- * const pagination = usePagination()
3058
- * pagination.next()
3165
+ * app.mount('#app')
3059
3166
  * ```
3060
3167
  */
3061
- function createPaginationContext(_options = {}) {
3062
- const { namespace = "v0:pagination",...options } = _options;
3063
- const [usePaginationContext, _providePaginationContext] = createContext(namespace);
3064
- const context = createPagination(options);
3065
- function providePaginationContext(_context = context, app) {
3066
- return _providePaginationContext(_context, app);
3067
- }
3068
- return createTrinity(usePaginationContext, providePaginationContext, context);
3168
+ function createHydrationPlugin(_options = {}) {
3169
+ const { namespace = "v0:hydration", ...options } = _options;
3170
+ const [, provideHydrationContext, context] = createHydrationContext({
3171
+ ...options,
3172
+ namespace
3173
+ });
3174
+ return createPlugin({
3175
+ namespace,
3176
+ provide: (app) => {
3177
+ provideHydrationContext(context, app);
3178
+ },
3179
+ setup: (app) => {
3180
+ app.mixin({ mounted() {
3181
+ if (this.$parent !== null) return;
3182
+ context.hydrate();
3183
+ } });
3184
+ }
3185
+ });
3069
3186
  }
3070
3187
  /**
3071
- * Returns the current pagination instance from context.
3188
+ * Returns the current hydration instance.
3072
3189
  *
3073
- * @param namespace The namespace. @default 'v0:pagination'
3074
- * @returns The pagination context.
3190
+ * @param namespace The namespace for the hydration context. Defaults to `v0:hydration`.
3191
+ * @returns The current hydration instance.
3192
+ *
3193
+ * @see https://0.vuetifyjs.com/composables/plugins/use-hydration
3075
3194
  *
3076
3195
  * @example
3077
3196
  * ```vue
3078
- * <script setup>
3079
- * import { usePagination } from '@vuetify/v0'
3197
+ * <script setup lang="ts">
3198
+ * import { useHydration } from '@vuetify/v0'
3080
3199
  *
3081
- * const pagination = usePagination()
3200
+ * const hydration = useHydration()
3082
3201
  * <\/script>
3083
3202
  *
3084
3203
  * <template>
3085
- * <button @click="pagination.prev()" :disabled="pagination.isFirst.value">Prev</button>
3086
- * <button @click="pagination.next()" :disabled="pagination.isLast.value">Next</button>
3204
+ * <div>
3205
+ * <p>Is hydrated: {{ hydration.isHydrated.value }}</p>
3206
+ * </div>
3087
3207
  * </template>
3088
3208
  * ```
3089
3209
  */
3090
- function usePagination(namespace = "v0:pagination") {
3091
- return useContext(namespace);
3210
+ function useHydration(namespace = "v0:hydration") {
3211
+ const fallback = createFallbackHydration();
3212
+ if (!getCurrentInstance()) return fallback;
3213
+ try {
3214
+ return useContext(namespace, fallback);
3215
+ } catch {
3216
+ return fallback;
3217
+ }
3092
3218
  }
3093
3219
 
3094
3220
  //#endregion
3095
- //#region src/composables/useSingle/index.ts
3096
- /**
3097
- * @module useSingle
3098
- *
3099
- * @remarks
3100
- * Single-selection composable that extends useSelection to enforce only one selected item.
3101
- *
3102
- * Key features:
3103
- * - Auto-clears previous selection when selecting new item
3104
- * - Singular computed properties (selectedId, selectedItem, selectedIndex, selectedValue)
3105
- * - Perfect for tabs, radio buttons, theme selectors
3106
- *
3107
- * Inheritance chain: useRegistry → useSelection → useSingle
3108
- */
3221
+ //#region src/composables/useResizeObserver/index.ts
3109
3222
  /**
3110
- * Creates a new single selection instance that enforces only one selected item at a time.
3111
- *
3112
- * Extends `createSelection` by automatically clearing previous selections when a new item is selected.
3113
- * Adds computed singular properties: `selectedId`, `selectedItem`, `selectedIndex`, `selectedValue`.
3114
- *
3115
- * @param options The options for the single selection instance.
3116
- * @template Z The type of the single selection ticket.
3117
- * @template E The type of the single selection context.
3118
- * @returns A new single selection instance with single-selection enforcement.
3119
- *
3120
- * @remarks
3121
- * **Key Differences from `createSelection`:**
3122
- * - Automatically clears `selectedIds` before selecting a new item (enforces single selection)
3123
- * - Provides singular computed properties instead of plural sets
3124
- * - Perfect for tabs, radio buttons, theme selectors, and other single-choice UI components
3125
- *
3126
- * **Computed Properties:**
3127
- * - `selectedId`: The ID of the selected item (undefined if none selected)
3128
- * - `selectedItem`: The selected ticket object (undefined if none selected)
3129
- * - `selectedIndex`: The index of the selected item (-1 if none selected)
3130
- * - `selectedValue`: The value of the selected item (undefined if none selected)
3223
+ * A composable that uses the Resize Observer API to detect when an element's
3224
+ * size changes.
3131
3225
  *
3132
- * **Inheritance Chain:**
3133
- * `useRegistry` `createSelection` `createSingle` `createStep`
3226
+ * @param target The element to observe.
3227
+ * @param callback The callback to execute when the element's size changes.
3228
+ * @param options The options for the Resize Observer.
3229
+ * @returns An object with methods to control the observer.
3134
3230
  *
3135
- * @see https://0.vuetifyjs.com/composables/selection/use-single
3231
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver
3232
+ * @see https://0.vuetifyjs.com/composables/system/use-resize-observer
3136
3233
  *
3137
3234
  * @example
3138
3235
  * ```ts
3139
- * import { createSingle } from '@vuetify/v0'
3140
- *
3141
- * const tabs = createSingle({ mandatory: true })
3236
+ * import { ref } from 'vue'
3237
+ * import { useResizeObserver } from '@vuetify/v0'
3142
3238
  *
3143
- * tabs.onboard([
3144
- * { id: 'home', value: 'Home' },
3145
- * { id: 'about', value: 'About' },
3146
- * { id: 'contact', value: 'Contact' },
3147
- * ])
3239
+ * const el = ref<HTMLElement>()
3240
+ * const width = ref(0)
3241
+ * const height = ref(0)
3148
3242
  *
3149
- * tabs.first() // Select first tab
3243
+ * const { pause, resume, isPaused } = useResizeObserver(
3244
+ * el,
3245
+ * (entries) => {
3246
+ * const entry = entries[0]
3247
+ * if (entry) {
3248
+ * width.value = entry.contentRect.width
3249
+ * height.value = entry.contentRect.height
3250
+ * console.log('Size changed:', width.value, 'x', height.value)
3251
+ * }
3252
+ * },
3253
+ * { immediate: true }
3254
+ * )
3150
3255
  *
3151
- * console.log(tabs.selectedId.value) // 'home'
3152
- * console.log(tabs.selectedIndex.value) // 0
3256
+ * // Pause observation
3257
+ * pause()
3153
3258
  *
3154
- * tabs.select('about') // Switch to about tab
3155
- * console.log(tabs.selectedId.value) // 'about'
3156
- * console.log(tabs.selectedIds.size) // 1 (always enforces single selection)
3259
+ * // Resume observation
3260
+ * resume()
3157
3261
  * ```
3158
3262
  */
3159
- function createSingle(_options = {}) {
3160
- const { mandatory = false, multiple = false,...options } = _options;
3161
- const registry = createSelection({
3162
- ...options,
3163
- mandatory,
3164
- multiple
3263
+ function useResizeObserver(target, callback, options = {}) {
3264
+ const { isHydrated } = useHydration();
3265
+ const observer = shallowRef();
3266
+ const isPaused = shallowRef(false);
3267
+ const isActive = toRef(() => !!observer.value);
3268
+ function setup() {
3269
+ if (observer.value === null) return;
3270
+ if (!isHydrated.value || !SUPPORTS_OBSERVER || !target.value || isPaused.value) return;
3271
+ observer.value = new ResizeObserver((entries) => {
3272
+ callback(entries.map((entry) => ({
3273
+ contentRect: {
3274
+ width: entry.contentRect.width,
3275
+ height: entry.contentRect.height,
3276
+ top: entry.contentRect.top,
3277
+ left: entry.contentRect.left
3278
+ },
3279
+ target: entry.target
3280
+ })));
3281
+ if (options.once) stop();
3282
+ });
3283
+ observer.value.observe(target.value, { box: options.box || "content-box" });
3284
+ if (options.immediate) {
3285
+ const rect = target.value.getBoundingClientRect();
3286
+ callback([{
3287
+ contentRect: {
3288
+ width: rect.width,
3289
+ height: rect.height,
3290
+ top: rect.top,
3291
+ left: rect.left
3292
+ },
3293
+ target: target.value
3294
+ }]);
3295
+ }
3296
+ }
3297
+ watchEffect(() => {
3298
+ const hydrated = isHydrated.value;
3299
+ const el = target.value;
3300
+ cleanup();
3301
+ if (hydrated && el) setup();
3165
3302
  });
3166
- const selectedId = computed(() => registry.selectedIds.values().next().value);
3167
- const selectedItem = computed(() => registry.selectedItems.value.values().next().value);
3168
- const selectedIndex = computed(() => selectedItem.value?.index ?? -1);
3169
- const selectedValue = computed(() => selectedItem.value?.value);
3170
- function unselect(id) {
3171
- if (mandatory && registry.selectedIds.size === 1) return;
3172
- registry.selectedIds.delete(id);
3303
+ function cleanup() {
3304
+ if (observer.value) {
3305
+ observer.value.disconnect();
3306
+ observer.value = void 0;
3307
+ }
3173
3308
  }
3174
- function toggle(id) {
3175
- if (registry.selectedIds.has(id)) unselect(id);
3176
- else registry.select(id);
3309
+ function pause() {
3310
+ isPaused.value = true;
3311
+ observer.value?.disconnect();
3312
+ }
3313
+ function resume() {
3314
+ isPaused.value = false;
3315
+ setup();
3316
+ }
3317
+ function stop() {
3318
+ cleanup();
3319
+ observer.value = null;
3177
3320
  }
3321
+ onScopeDispose(stop, true);
3178
3322
  return {
3179
- ...registry,
3180
- selectedId,
3181
- selectedItem,
3182
- selectedIndex,
3183
- selectedValue,
3184
- unselect,
3185
- toggle,
3186
- get size() {
3187
- return registry.size;
3188
- }
3323
+ isActive: shallowReadonly(isActive),
3324
+ isPaused: shallowReadonly(isPaused),
3325
+ pause,
3326
+ resume,
3327
+ stop
3189
3328
  };
3190
3329
  }
3191
3330
  /**
3192
- * Creates a new single selection context.
3331
+ * A convenience composable that uses the Resize Observer API to track an
3332
+ * element's size.
3193
3333
  *
3194
- * @param options The options for the single selection context.
3195
- * @template Z The type of the single selection ticket.
3196
- * @template E The type of the single selection context.
3197
- * @returns A new single selection context.
3334
+ * @param target The element to observe.
3335
+ * @returns An object with the element's width and height.
3198
3336
  *
3199
- * @see https://0.vuetifyjs.com/composables/selection/use-single
3337
+ * @see https://0.vuetifyjs.com/composables/system/use-resize-observer#use-element-size
3200
3338
  *
3201
3339
  * @example
3202
3340
  * ```ts
3203
- * import { createSingleContext } from '@vuetify/v0'
3204
- *
3205
- * // With default namespace 'v0:single'
3206
- * export const [useSingle, provideSingle, context] = createSingleContext()
3341
+ * import { ref, watchEffect } from 'vue'
3342
+ * import { useElementSize } from '@vuetify/v0'
3207
3343
  *
3208
- * // In a parent component:
3209
- * provideSingle()
3344
+ * const box = ref<HTMLElement>()
3345
+ * const { width, height } = useElementSize(box)
3210
3346
  *
3211
- * // In a child component:
3212
- * const single = useSingle()
3213
- * single.select('tab-1')
3347
+ * // Width and height are reactive refs
3348
+ * watchEffect(() => {
3349
+ * console.log('Box size:', width.value, 'x', height.value)
3350
+ * })
3214
3351
  * ```
3215
3352
  */
3216
- function createSingleContext(_options = {}) {
3217
- const { namespace = "v0:single",...options } = _options;
3218
- const [useSingleContext, _provideSingleContext] = createContext(namespace);
3219
- const context = createSingle(options);
3220
- function provideSingleContext(_context = context, app) {
3221
- return _provideSingleContext(_context, app);
3353
+ function useElementSize(target) {
3354
+ const width = shallowRef(0);
3355
+ const height = shallowRef(0);
3356
+ const { pause: _pause, resume, stop, isActive, isPaused } = useResizeObserver(target, (entries) => {
3357
+ const entry = entries[0];
3358
+ if (entry) {
3359
+ width.value = entry.contentRect.width;
3360
+ height.value = entry.contentRect.height;
3361
+ }
3362
+ }, { immediate: true });
3363
+ function pause() {
3364
+ width.value = 0;
3365
+ height.value = 0;
3366
+ _pause();
3222
3367
  }
3223
- return createTrinity(useSingleContext, provideSingleContext, context);
3368
+ return {
3369
+ width,
3370
+ height,
3371
+ isActive,
3372
+ isPaused,
3373
+ pause,
3374
+ resume,
3375
+ stop
3376
+ };
3224
3377
  }
3378
+
3379
+ //#endregion
3380
+ //#region src/composables/useOverflow/index.ts
3225
3381
  /**
3226
- * Returns the current single selection instance.
3227
- *
3228
- * @param namespace The namespace for the single selection context. Defaults to `'v0:single'`.
3229
- * @returns The current single selection instance.
3382
+ * Creates a new overflow context for computing how many items fit in a container.
3230
3383
  *
3231
- * @see https://0.vuetifyjs.com/composables/selection/use-single
3384
+ * @param options Configuration options
3385
+ * @returns Overflow context with container ref, capacity, and measurement functions
3232
3386
  *
3233
- * @example
3387
+ * @example Variable-width mode (Breadcrumbs)
3234
3388
  * ```vue
3235
- * <script setup lang="ts">
3236
- * import { useSingle } from '@vuetify/v0'
3389
+ * <script lang="ts" setup>
3390
+ * import { useTemplateRef } from 'vue'
3391
+ * import { createOverflow } from '@vuetify/v0'
3237
3392
  *
3238
- * const tabs = useSingle()
3393
+ * const containerRef = useTemplateRef('container')
3394
+ * const overflow = createOverflow({
3395
+ * container: containerRef,
3396
+ * gap: 8,
3397
+ * reserved: 40,
3398
+ * })
3239
3399
  * <\/script>
3240
3400
  *
3241
3401
  * <template>
3242
- * <div>
3243
- * <p>Selected: {{ tabs.selectedId }}</p>
3402
+ * <div ref="container">
3403
+ * <span
3404
+ * v-for="(item, i) in items.slice(0, overflow.capacity.value)"
3405
+ * :key="i"
3406
+ * :ref="el => overflow.measure(i, el)"
3407
+ * >
3408
+ * {{ item }}
3409
+ * </span>
3410
+ * <span v-if="overflow.isOverflowing.value">...</span>
3244
3411
  * </div>
3245
3412
  * </template>
3246
3413
  * ```
3247
- */
3248
- function useSingle(namespace = "v0:single") {
3249
- return useContext(namespace);
3250
- }
3251
-
3252
- //#endregion
3253
- //#region src/composables/useTokens/index.ts
3254
- /**
3255
- * @module useTokens
3256
- *
3257
- * @see https://0.vuetifyjs.com/composables/registration/use-tokens
3258
3414
  *
3259
- * @remarks
3260
- * Design token registry with alias resolution and W3C Design Tokens format support.
3261
- *
3262
- * Key features:
3263
- * - Alias resolution with circular reference detection
3264
- * - Nested token flattening with dot notation
3265
- * - W3C Design Tokens format ($value, $type, $description, $extensions)
3266
- * - Path-based resolution (e.g., {colors}.blue.500)
3267
- * - Resolution caching for performance (~28,590 ops/sec)
3268
- *
3269
- * Used by useTheme, useLocale, and useFeatures for token-based configuration.
3270
- */
3271
- /**
3272
- * Creates a new token instance.
3273
- *
3274
- * @param tokens The tokens to use.
3275
- * @param options The options for the token instance.
3276
- * @template Z The type of the token ticket.
3277
- * @template E The type of the token context.
3278
- * @returns A new token instance.
3279
- *
3280
- * @see https://www.designtokens.org/tr/drafts/format/
3281
- * @see https://0.vuetifyjs.com/composables/registration/use-tokens
3282
- *
3283
- * @example
3415
+ * @example Uniform-width mode (Pagination)
3284
3416
  * ```ts
3285
- * import { useTokens } from '@vuetify/v0'
3286
- *
3287
- * const tokens = useTokens({
3288
- * colors: {
3289
- * primary: '#3b82f6',
3290
- * secondary: '{colors.primary}', // Alias reference
3291
- * },
3417
+ * const overflow = createOverflow({
3418
+ * container: () => atom.value?.element,
3419
+ * itemWidth: buttonWidth,
3420
+ * reserved: () => buttonWidth.value * 4,
3292
3421
  * })
3293
- *
3294
- * console.log(tokens.resolve('{colors.primary}')) // '#3b82f6'
3295
- * console.log(tokens.resolve('{colors.secondary}')) // '#3b82f6'
3296
3422
  * ```
3297
3423
  */
3298
- function createTokens(tokens = {}, options = {}) {
3299
- const logger = useLogger();
3300
- const registry = useRegistry(options);
3301
- const cache = /* @__PURE__ */ new Map();
3302
- registry.onboard(flatten(tokens, options.prefix, !!options.flat));
3303
- function isAlias(token) {
3304
- return /* @__PURE__ */ isString(token) && token.length > 2 && token[0] === "{" && token.at(-1) === "}";
3305
- }
3306
- function isTokenAlias(value) {
3307
- return /* @__PURE__ */ isObject(value) && "$value" in value;
3308
- }
3309
- function resolve(token, visited = /* @__PURE__ */ new Set()) {
3310
- const cacheKey = /* @__PURE__ */ isString(token) ? token : JSON.stringify(token);
3311
- const cached = cache.get(cacheKey);
3312
- if (!/* @__PURE__ */ isUndefined(cached)) return cached;
3313
- const reference = isTokenAlias(token) ? token.$value : token;
3314
- const isAliasReference = /* @__PURE__ */ isString(reference) && isAlias(reference);
3315
- const clean = isAliasReference ? reference.slice(1, -1) : String(reference);
3316
- if (visited.has(clean)) {
3317
- logger.warn(`Circular alias detected for "${clean}"`);
3318
- cache.set(cacheKey, void 0);
3319
- return;
3320
- }
3321
- visited.add(clean);
3322
- let found = registry.get(clean);
3323
- let segments = [];
3324
- if (!found && clean.includes(".")) {
3325
- const parts = clean.split(".");
3326
- for (let i = parts.length - 1; i > 0; i--) {
3327
- const prefix = parts.slice(0, i).join(".");
3328
- const suffix = parts.slice(i);
3329
- const candidate = registry.get(prefix);
3330
- if (!/* @__PURE__ */ isUndefined(candidate?.value)) {
3331
- found = candidate;
3332
- segments = suffix;
3333
- break;
3334
- }
3424
+ function createOverflow(options = {}) {
3425
+ const { container: _container, gap = 0, reserved = 0, itemWidth, reverse } = options;
3426
+ const container = /* @__PURE__ */ isUndefined(_container) ? shallowRef() : toRef(_container);
3427
+ const widths = shallowRef(/* @__PURE__ */ new Map());
3428
+ const { width } = useElementSize(container);
3429
+ function measure(index, el) {
3430
+ if (!el) {
3431
+ if (widths.value.has(index)) {
3432
+ const next = new Map(widths.value);
3433
+ next.delete(index);
3434
+ widths.value = next;
3335
3435
  }
3336
- }
3337
- if (/* @__PURE__ */ isUndefined(found?.value)) {
3338
- if (isAliasReference) logger.warn(`Alias not found for "${String(reference)}"`);
3339
- cache.set(cacheKey, void 0);
3340
3436
  return;
3341
3437
  }
3342
- let result;
3343
- let current = found.value;
3344
- if (segments.length > 0) {
3345
- if (isTokenAlias(current)) current = current.$value;
3346
- for (const segment of segments) {
3347
- if (!/* @__PURE__ */ isObject(current) || !(segment in current)) {
3348
- current = void 0;
3349
- break;
3350
- }
3351
- current = current[segment];
3352
- if (isTokenAlias(current)) current = current.$value;
3353
- }
3354
- if (/* @__PURE__ */ isUndefined(current)) {
3355
- logger.warn(`Path not found inside "${clean}": ${segments.join(".")}`);
3356
- cache.set(cacheKey, void 0);
3357
- return;
3358
- }
3359
- result = current;
3360
- } else if (isTokenAlias(current)) {
3361
- const inner = current.$value;
3362
- if (/* @__PURE__ */ isString(inner) && isAlias(inner)) return resolve(inner, visited);
3363
- result = inner;
3364
- } else if (/* @__PURE__ */ isString(current) && isAlias(current)) return resolve(current, visited);
3365
- else result = current;
3366
- cache.set(cacheKey, result);
3367
- return result;
3438
+ const style = getComputedStyle(el);
3439
+ const marginX = Number.parseFloat(style.marginLeft) + Number.parseFloat(style.marginRight);
3440
+ const w = el.offsetWidth + marginX;
3441
+ if (widths.value.get(index) !== w) widths.value = new Map(widths.value).set(index, w);
3368
3442
  }
3369
- return {
3370
- ...registry,
3371
- resolve,
3372
- isAlias,
3373
- get size() {
3374
- return registry.size;
3443
+ function reset() {
3444
+ widths.value = /* @__PURE__ */ new Map();
3445
+ }
3446
+ const total = computed(() => {
3447
+ const g = toValue(gap);
3448
+ let sum = 0;
3449
+ let count = 0;
3450
+ for (const w of widths.value.values()) {
3451
+ sum += w + (count > 0 ? g : 0);
3452
+ count++;
3375
3453
  }
3454
+ return sum;
3455
+ });
3456
+ return {
3457
+ container,
3458
+ width,
3459
+ capacity: computed(() => {
3460
+ const available = width.value - toValue(reserved);
3461
+ if (width.value === 0) return Infinity;
3462
+ if (available <= 0) return 0;
3463
+ const g = toValue(gap);
3464
+ const uniformWidth = toValue(itemWidth);
3465
+ if (uniformWidth && uniformWidth > 0) {
3466
+ const first = uniformWidth;
3467
+ const subsequent = uniformWidth + g;
3468
+ if (available < first) return 0;
3469
+ return Math.max(1, Math.floor((available - first) / subsequent) + 1);
3470
+ }
3471
+ const entries = [...widths.value.entries()].toSorted((a, b) => a[0] - b[0]);
3472
+ if (toValue(reverse)) entries.reverse();
3473
+ let sum = 0;
3474
+ let count = 0;
3475
+ for (const [, w] of entries) {
3476
+ const next = sum + w + (count > 0 ? g : 0);
3477
+ if (next > available) break;
3478
+ sum = next;
3479
+ count++;
3480
+ }
3481
+ return count;
3482
+ }),
3483
+ total,
3484
+ isOverflowing: toRef(() => {
3485
+ return total.value > width.value - toValue(reserved);
3486
+ }),
3487
+ measure,
3488
+ reset
3376
3489
  };
3377
3490
  }
3378
3491
  /**
3379
- * Creates a new token context.
3380
- *
3381
- * @param namespace The namespace for the token context.
3382
- * @param tokens The tokens to use.
3383
- * @template Z The type of the token ticket.
3384
- * @template E The type of the token context.
3385
- * @returns A new token context.
3492
+ * Creates an overflow context with dependency injection support.
3386
3493
  *
3387
- * @see https://0.vuetifyjs.com/composables/registration/use-tokens
3494
+ * @param options Configuration options including namespace
3495
+ * @returns Trinity tuple: [useContext, provideContext, defaultContext]
3388
3496
  *
3389
3497
  * @example
3390
3498
  * ```ts
3391
- * import { createTokensContext } from '@vuetify/v0'
3392
- *
3393
- * export const [useTokens, provideTokens, context] = createTokensContext({
3394
- * namespace: 'v0:tokens',
3395
- * tokens: {
3396
- * colors: {
3397
- * primary: '#3b82f6',
3398
- * secondary: '{colors.primary}', // Alias reference
3399
- * },
3400
- * },
3499
+ * // Create injectable context
3500
+ * const [useOverflow, provideOverflow, overflow] = createOverflowContext({
3501
+ * namespace: 'my-overflow',
3502
+ * gap: 8,
3503
+ * reserved: 160,
3401
3504
  * })
3505
+ *
3506
+ * // In parent component
3507
+ * provideOverflow()
3508
+ *
3509
+ * // In child component
3510
+ * const overflow = useOverflow()
3402
3511
  * ```
3403
3512
  */
3404
- function createTokensContext(_options) {
3405
- const { namespace = "v0:tokens", tokens = {},...options } = _options;
3406
- const [useTokensContext, _provideTokensContext] = createContext(namespace);
3407
- const context = createTokens(tokens, options);
3408
- function provideTokensContext(_context = context, app) {
3409
- return _provideTokensContext(_context, app);
3513
+ function createOverflowContext(_options = {}) {
3514
+ const { namespace = "v0:overflow", ...options } = _options;
3515
+ const [useOverflowContext, _provideOverflowContext] = createContext(namespace);
3516
+ const context = createOverflow(options);
3517
+ function provideOverflowContext(_context = context, app) {
3518
+ return _provideOverflowContext(_context, app);
3410
3519
  }
3411
- return createTrinity(useTokensContext, provideTokensContext, context);
3520
+ return createTrinity(useOverflowContext, provideOverflowContext, context);
3412
3521
  }
3413
3522
  /**
3414
- * Returns the current tokens instance.
3415
- *
3416
- * @param namespace The namespace for the tokens context. Defaults to `'v0:tokens'`.
3417
- * @returns The current tokens instance.
3523
+ * Returns the current overflow context from dependency injection.
3418
3524
  *
3419
- * @see https://0.vuetifyjs.com/composables/registration/use-tokens
3525
+ * @param namespace The namespace for the overflow context. Defaults to `v0:overflow`.
3526
+ * @returns The current overflow context.
3420
3527
  *
3421
3528
  * @example
3422
3529
  * ```vue
3423
- * <script setup lang="ts">
3424
- * import { useTokens } from '@vuetify/v0'
3530
+ * <script lang="ts" setup>
3531
+ * import { useOverflow } from '@vuetify/v0'
3425
3532
  *
3426
- * const tokens = useTokens()
3533
+ * // Inject overflow context provided by parent
3534
+ * const overflow = useOverflow()
3427
3535
  * <\/script>
3536
+ *
3537
+ * <template>
3538
+ * <div>
3539
+ * <p>Capacity: {{ overflow.capacity.value }}</p>
3540
+ * </div>
3541
+ * </template>
3428
3542
  * ```
3429
3543
  */
3430
- function useTokens(namespace = "v0:tokens") {
3544
+ function useOverflow(namespace = "v0:overflow") {
3431
3545
  return useContext(namespace);
3432
3546
  }
3433
- /**
3434
- * Flattens a nested collection of tokens into a flat array of tokens.
3435
- * Each token is represented by an object containing its ID & value.
3436
- * @param tokens The collection of tokens to flatten.
3437
- * @param prefix An optional prefix to prepend to each token ID.
3438
- * @returns An array of flattened tokens, each with an ID and value.
3439
- */
3440
- function flatten(tokens, prefix = "", flat = false) {
3441
- const flattened = [];
3442
- const stack = [{
3443
- tokens,
3444
- prefix,
3445
- flat
3446
- }];
3447
- while (stack.length > 0) {
3448
- const { tokens: currentTokens, prefix: currentPrefix, flat: flat$1 } = stack.pop();
3449
- const meta = {};
3450
- for (const k in currentTokens) if (k.startsWith("$")) meta[k] = currentTokens[k];
3451
- if (Object.keys(meta).length > 0 && currentPrefix) flattened.push({
3452
- id: currentPrefix,
3453
- value: meta
3454
- });
3455
- for (const key in currentTokens) {
3456
- if (key.startsWith("$")) continue;
3457
- const value = currentTokens[key];
3458
- const id = currentPrefix ? `${currentPrefix}.${key}` : key;
3459
- if (!/* @__PURE__ */ isObject(value)) {
3460
- flattened.push({
3461
- id,
3462
- value
3463
- });
3464
- continue;
3465
- }
3466
- if ("$value" in value) {
3467
- flattened.push({
3468
- id,
3469
- value
3470
- });
3471
- const inner = value.$value;
3472
- if (/* @__PURE__ */ isObject(inner) && !flat$1) for (const innerKey in inner) {
3473
- if (innerKey.startsWith("$")) continue;
3474
- const child = inner[innerKey];
3475
- const childId = `${id}.${innerKey}`;
3476
- if (!/* @__PURE__ */ isObject(child)) flattened.push({
3477
- id: childId,
3478
- value: child
3479
- });
3480
- else if ("$value" in child) flattened.push({
3481
- id: childId,
3482
- value: child
3483
- });
3484
- else stack.push({
3485
- tokens: child,
3486
- prefix: childId,
3487
- flat: flat$1
3488
- });
3489
- }
3490
- continue;
3491
- }
3492
- if (flat$1) {
3493
- flattened.push({
3494
- id,
3495
- value
3496
- });
3497
- continue;
3498
- }
3499
- stack.push({
3500
- tokens: value,
3501
- prefix: id,
3502
- flat: flat$1
3503
- });
3504
- }
3505
- }
3506
- return flattened;
3507
- }
3508
-
3509
- //#endregion
3510
- //#region src/composables/useLocale/adapters/v0.ts
3511
- /**
3512
- * Vuetify0.x locale adapter implementation
3513
- *
3514
- * This adapter provides translation and number formatting
3515
- * capabilities using the Intl API and supports both
3516
- * numbered ({0}, {1}) and named ({name}) variables in translation strings.
3517
- */
3518
- var Vuetify0LocaleAdapter = class {
3519
- t(message, ...params) {
3520
- let resolvedMessage = message;
3521
- if (params.length > 0 && /* @__PURE__ */ isObject(params[0])) {
3522
- const variables = params[0];
3523
- resolvedMessage = resolvedMessage.replace(/{([a-zA-Z][a-zA-Z0-9_]*)}/g, (match, name) => {
3524
- return /* @__PURE__ */ isUndefined(variables[name]) ? match : String(variables[name]);
3525
- });
3526
- params = params.slice(1);
3527
- }
3528
- resolvedMessage = resolvedMessage.replace(/\{(\d+)\}/g, (match, index) => {
3529
- const idx = Number.parseInt(index, 10);
3530
- if (!/* @__PURE__ */ isUndefined(params[idx])) return String(params[idx]);
3531
- return match;
3532
- });
3533
- return resolvedMessage;
3534
- }
3535
- n(value, locale, ...params) {
3536
- if (!IN_BROWSER || !locale) return value.toString();
3537
- const options = params[0];
3538
- return new Intl.NumberFormat(String(locale), options).format(value);
3539
- }
3540
- };
3541
3547
 
3542
3548
  //#endregion
3543
- //#region src/composables/useLocale/index.ts
3549
+ //#region src/composables/usePagination/index.ts
3544
3550
  /**
3545
- * @module useLocale
3546
- *
3547
- * @remarks
3548
- * Internationalization (i18n) composable with adapter pattern for message translation.
3551
+ * Creates a pagination instance.
3549
3552
  *
3550
- * Key features:
3551
- * - Locale selection with createSingle
3552
- * - Token-based message storage with useTokens
3553
- * - Numbered and named placeholder support ({0}, {name})
3554
- * - Number formatting with Intl.NumberFormat
3555
- * - Adapter pattern for integration with i18n providers
3553
+ * @param options The options for the pagination instance.
3554
+ * @returns A pagination context with navigation methods.
3556
3555
  *
3557
- * Integrates with createSingle for locale selection and useTokens for message resolution.
3558
- */
3559
- /**
3560
- * Creates a new locale instance.
3556
+ * @example
3557
+ * ```ts
3558
+ * import { createPagination } from '@vuetify/v0'
3561
3559
  *
3562
- * @param options The options for the locale instance.
3563
- * @template Z The type of the locale ticket.
3564
- * @template E The type of the locale context.
3565
- * @returns A new locale instance.
3560
+ * // Basic usage
3561
+ * const pagination = createPagination({ size: 100 })
3562
+ * pagination.next()
3563
+ * pagination.items.value // [{ type: 'page', value: 1 }, { type: 'page', value: 2 }, ...]
3566
3564
  *
3567
- * @see https://0.vuetifyjs.com/composables/plugins/use-locale
3565
+ * // With v-model (pass a ref)
3566
+ * const page = ref(1)
3567
+ * const pagination = createPagination({ page, size: 100 })
3568
+ * // Mutating pagination.page or the passed ref syncs both
3569
+ * ```
3568
3570
  */
3569
- function createLocale(_options = {}) {
3570
- const { adapter = new Vuetify0LocaleAdapter(), messages = {},...options } = _options;
3571
- const tokens = createTokens(messages);
3572
- const registry = createSingle(options);
3573
- for (const id in messages) {
3574
- registry.register({ id });
3575
- if (id === options.default && !registry.selectedId.value) registry.select(id);
3571
+ function createPagination(_options = {}) {
3572
+ const { page: _page = 1, itemsPerPage: _itemsPerPage = 10, size: _size = 0, visible: _visible = 7, ellipsis = "..." } = _options;
3573
+ const page = isRef(_page) ? _page : shallowRef(_page);
3574
+ const pages = computed(() => {
3575
+ const size = toValue(_size);
3576
+ const perPage = toValue(_itemsPerPage);
3577
+ if (size <= 0 || /* @__PURE__ */ isNaN(size)) return 0;
3578
+ return Math.ceil(size / perPage);
3579
+ });
3580
+ function first() {
3581
+ page.value = 1;
3576
3582
  }
3577
- function t(key, params, fallback) {
3578
- const locale = registry.selectedId.value;
3579
- const args = toArray(params);
3580
- if (!locale) return adapter.t(fallback ?? key, ...args);
3581
- const path = `${locale}.${key}`;
3582
- const message = tokens.get(path)?.value;
3583
- const template = /* @__PURE__ */ isString(message) ? resolve(locale, message) : fallback ?? key;
3584
- return adapter.t(template, ...args);
3583
+ function last() {
3584
+ page.value = Math.max(1, pages.value);
3585
+ }
3586
+ function next() {
3587
+ if (page.value < pages.value) page.value++;
3588
+ }
3589
+ function prev() {
3590
+ if (page.value > 1) page.value--;
3591
+ }
3592
+ function select(value) {
3593
+ if (value < 1) page.value = 1;
3594
+ else if (value > pages.value) page.value = Math.max(1, pages.value);
3595
+ else page.value = value;
3596
+ }
3597
+ const isFirst = computed(() => page.value <= 1);
3598
+ const isLast = computed(() => page.value >= pages.value);
3599
+ const pageStart = computed(() => (page.value - 1) * toValue(_itemsPerPage));
3600
+ const pageStop = computed(() => Math.min(pageStart.value + toValue(_itemsPerPage), toValue(_size)));
3601
+ function toPage(value) {
3602
+ return {
3603
+ type: "page",
3604
+ value
3605
+ };
3585
3606
  }
3586
- function n(value, ...params) {
3587
- return adapter.n(value, registry.selectedId.value, ...params);
3607
+ function toEllipsis() {
3608
+ return ellipsis === false ? false : {
3609
+ type: "ellipsis",
3610
+ value: ellipsis
3611
+ };
3588
3612
  }
3589
- function resolve(locale, str) {
3590
- return str.replace(/{([a-zA-Z0-9.-_]+)}/g, (match, key) => {
3591
- const [prefix, ...rest] = key.split(".");
3592
- const target = registry.has(prefix) ? prefix : locale;
3593
- const path = `${target}.${registry.has(prefix) ? rest.join(".") : key}`;
3594
- const resolved = tokens.get(path)?.value;
3595
- if (/* @__PURE__ */ isString(resolved)) return resolve(target, resolved);
3596
- return match;
3597
- });
3613
+ function filter(array) {
3614
+ return array.filter((item) => item !== false);
3598
3615
  }
3599
3616
  return {
3600
- ...registry,
3601
- t,
3602
- n,
3617
+ page,
3618
+ ellipsis,
3619
+ items: computed(() => {
3620
+ const pageCount = pages.value;
3621
+ const visible = toValue(_visible);
3622
+ const current = page.value;
3623
+ if (pageCount <= 0 || /* @__PURE__ */ isNaN(pageCount) || pageCount > Number.MAX_SAFE_INTEGER) return [];
3624
+ if (visible <= 0) return [];
3625
+ if (visible <= 2) return [toPage(current)];
3626
+ if (pageCount <= visible) return (/* @__PURE__ */ range(pageCount, 1)).map(toPage);
3627
+ if (visible === 3) {
3628
+ const mid = current <= 1 ? 2 : current >= pageCount ? pageCount - 1 : current;
3629
+ return [
3630
+ toPage(1),
3631
+ toPage(mid),
3632
+ toPage(pageCount)
3633
+ ];
3634
+ }
3635
+ const boundary = visible - 2;
3636
+ const middle = visible - 4;
3637
+ if (middle <= 0) {
3638
+ if (current <= boundary) return filter([
3639
+ ...(/* @__PURE__ */ range(boundary, 1)).map(toPage),
3640
+ toEllipsis(),
3641
+ toPage(pageCount)
3642
+ ]);
3643
+ if (current > pageCount - boundary) return filter([
3644
+ toPage(1),
3645
+ toEllipsis(),
3646
+ ...(/* @__PURE__ */ range(boundary, pageCount - boundary + 1)).map(toPage)
3647
+ ]);
3648
+ return current <= Math.ceil(pageCount / 2) ? filter([
3649
+ toPage(1),
3650
+ toPage(current),
3651
+ toEllipsis(),
3652
+ toPage(pageCount)
3653
+ ]) : filter([
3654
+ toPage(1),
3655
+ toEllipsis(),
3656
+ toPage(current),
3657
+ toPage(pageCount)
3658
+ ]);
3659
+ }
3660
+ const leftThreshold = boundary - 1;
3661
+ const rightThreshold = pageCount - boundary + 2;
3662
+ if (current <= leftThreshold) return filter([
3663
+ ...(/* @__PURE__ */ range(boundary, 1)).map(toPage),
3664
+ toEllipsis(),
3665
+ toPage(pageCount)
3666
+ ]);
3667
+ else if (current >= rightThreshold) return filter([
3668
+ toPage(1),
3669
+ toEllipsis(),
3670
+ ...(/* @__PURE__ */ range(boundary, pageCount - boundary + 1)).map(toPage)
3671
+ ]);
3672
+ else {
3673
+ const start = current - Math.floor(middle / 2);
3674
+ return filter([
3675
+ toPage(1),
3676
+ toEllipsis(),
3677
+ ...(/* @__PURE__ */ range(middle, start)).map(toPage),
3678
+ toEllipsis(),
3679
+ toPage(pageCount)
3680
+ ]);
3681
+ }
3682
+ }),
3683
+ pageStart,
3684
+ pageStop,
3685
+ isFirst,
3686
+ isLast,
3687
+ first,
3688
+ last,
3689
+ next,
3690
+ prev,
3691
+ select,
3692
+ get itemsPerPage() {
3693
+ return toValue(_itemsPerPage);
3694
+ },
3603
3695
  get size() {
3604
- return registry.size;
3696
+ return toValue(_size);
3697
+ },
3698
+ get pages() {
3699
+ return pages.value;
3605
3700
  }
3606
3701
  };
3607
3702
  }
3608
- function createLocaleFallback() {
3609
- return {
3610
- size: 0,
3611
- t: (key, _params, fallback) => fallback ?? key,
3612
- n: String
3613
- };
3614
- }
3615
3703
  /**
3616
- * Creates a new locale context.
3617
- *
3618
- * @param options The options for the locale context.
3619
- * @template Z The type of the locale ticket.
3620
- * @template E The type of the locale context.
3621
- * @returns A new locale context.
3704
+ * Creates a pagination context for dependency injection.
3622
3705
  *
3623
- * @see https://0.vuetifyjs.com/composables/plugins/use-locale
3706
+ * @param options The options including namespace.
3707
+ * @returns A trinity: [usePagination, providePagination, defaultContext]
3624
3708
  *
3625
3709
  * @example
3626
3710
  * ```ts
3627
- * import { createLocaleContext } from '@vuetify/v0'
3711
+ * // With default namespace 'v0:pagination'
3712
+ * const [usePagination, providePaginationContext] = createPaginationContext({ size: 50 })
3628
3713
  *
3629
- * export const [useAppLocale, provideAppLocale, appLocale] = createLocaleContext({
3630
- * namespace: 'app:locale',
3631
- * messages: {
3632
- * en: { hello: 'Hello' },
3633
- * es: { hello: 'Hola' },
3634
- * },
3714
+ * // Or with custom namespace
3715
+ * const [usePagination, providePaginationContext] = createPaginationContext({
3716
+ * namespace: 'my-pagination',
3717
+ * size: 50,
3635
3718
  * })
3636
3719
  *
3637
- * // In a parent component:
3638
- * provideAppLocale()
3720
+ * // Parent component
3721
+ * providePaginationContext()
3639
3722
  *
3640
- * // In a child component:
3641
- * const locale = useAppLocale()
3642
- * locale.select('es')
3723
+ * // Child component
3724
+ * const pagination = usePagination()
3725
+ * pagination.next()
3643
3726
  * ```
3644
3727
  */
3645
- function createLocaleContext(_options = {}) {
3646
- const { namespace = "v0:locale",...options } = _options;
3647
- const [useLocaleContext, _provideLocaleContext] = createContext(namespace);
3648
- const context = createLocale(options);
3649
- function provideLocaleContext(_context = context, app) {
3650
- return _provideLocaleContext(_context, app);
3728
+ function createPaginationContext(_options = {}) {
3729
+ const { namespace = "v0:pagination", ...options } = _options;
3730
+ const [usePaginationContext, _providePaginationContext] = createContext(namespace);
3731
+ const context = createPagination(options);
3732
+ function providePaginationContext(_context = context, app) {
3733
+ return _providePaginationContext(_context, app);
3651
3734
  }
3652
- return createTrinity(useLocaleContext, provideLocaleContext, context);
3735
+ return createTrinity(usePaginationContext, providePaginationContext, context);
3653
3736
  }
3654
3737
  /**
3655
- * Creates a new locale plugin.
3738
+ * Returns the current pagination instance from context.
3656
3739
  *
3657
- * @param options The options for the locale plugin.
3658
- * @template Z The type of the locale ticket.
3659
- * @template E The type of the locale context.
3660
- * @template R The type of the token ticket.
3661
- * @template O The type of the token context.
3662
- * @returns A new locale plugin.
3740
+ * @param namespace The namespace. @default 'v0:pagination'
3741
+ * @returns The pagination context.
3663
3742
  *
3664
- * @see https://0.vuetifyjs.com/composables/plugins/use-locale
3665
- */
3666
- function createLocalePlugin(_options = {}) {
3667
- const { namespace = "v0:locale", adapter = new Vuetify0LocaleAdapter(), messages = {},...options } = _options;
3668
- const [, provideLocaleContext, context] = createLocaleContext({
3669
- ...options,
3670
- namespace,
3671
- adapter,
3672
- messages
3673
- });
3674
- return createPlugin({
3675
- namespace,
3676
- provide: (app) => {
3677
- provideLocaleContext(context, app);
3678
- }
3679
- });
3680
- }
3681
- /**
3682
- * Returns the current locale instance.
3743
+ * @example
3744
+ * ```vue
3745
+ * <script setup lang="ts">
3746
+ * import { usePagination } from '@vuetify/v0'
3683
3747
  *
3684
- * @returns The current locale instance.
3748
+ * const pagination = usePagination()
3749
+ * <\/script>
3685
3750
  *
3686
- * @see https://0.vuetifyjs.com/composables/plugins/use-locale
3751
+ * <template>
3752
+ * <button @click="pagination.prev()" :disabled="pagination.isFirst.value">Prev</button>
3753
+ * <button @click="pagination.next()" :disabled="pagination.isLast.value">Next</button>
3754
+ * </template>
3755
+ * ```
3687
3756
  */
3688
- function useLocale(namespace = "v0:locale") {
3689
- const fallback = createLocaleFallback();
3690
- if (!getCurrentInstance()) return fallback;
3691
- try {
3692
- return useContext(namespace, fallback);
3693
- } catch {
3694
- return fallback;
3695
- }
3757
+ function usePagination(namespace = "v0:pagination") {
3758
+ return useContext(namespace);
3696
3759
  }
3697
3760
 
3698
3761
  //#endregion
@@ -3700,7 +3763,7 @@ function useLocale(namespace = "v0:locale") {
3700
3763
  const [usePaginationRoot, providePaginationRoot] = createContext();
3701
3764
  const [usePaginationControls, providePaginationControls] = createContext({ suffix: "controls" });
3702
3765
  const [usePaginationItems, providePaginationItems] = createContext({ suffix: "items" });
3703
- const _sfc_main$15 = /* @__PURE__ */ defineComponent({
3766
+ const _sfc_main$16 = /* @__PURE__ */ defineComponent({
3704
3767
  name: "PaginationRoot",
3705
3768
  __name: "PaginationRoot",
3706
3769
  props: /* @__PURE__ */ mergeModels({
@@ -3748,7 +3811,7 @@ const _sfc_main$15 = /* @__PURE__ */ defineComponent({
3748
3811
  page,
3749
3812
  visible: computed(() => {
3750
3813
  const totalCap = overflow.capacity.value;
3751
- if (totalCap === Infinity) return __props.totalVisible ?? Infinity;
3814
+ if (totalCap === Infinity) return __props.totalVisible ?? 7;
3752
3815
  const pageCap = Math.max(0, totalCap - controls.size);
3753
3816
  const noVisible = /* @__PURE__ */ isNullOrUndefined(__props.totalVisible);
3754
3817
  if (pageCap > 0) return noVisible ? pageCap : Math.min(__props.totalVisible, pageCap);
@@ -3773,7 +3836,10 @@ const _sfc_main$15 = /* @__PURE__ */ defineComponent({
3773
3836
  next: pagination.next,
3774
3837
  prev: pagination.prev,
3775
3838
  select: pagination.select,
3776
- attrs: { "aria-label": locale.t("Pagination.label", void 0, "Pagination") }
3839
+ attrs: {
3840
+ "aria-label": locale.t("Pagination.label", void 0, "Pagination"),
3841
+ "role": __props.as === "nav" ? void 0 : "navigation"
3842
+ }
3777
3843
  }));
3778
3844
  providePaginationRoot(__props.namespace, pagination);
3779
3845
  providePaginationControls(__props.namespace, controls);
@@ -3792,11 +3858,11 @@ const _sfc_main$15 = /* @__PURE__ */ defineComponent({
3792
3858
  };
3793
3859
  }
3794
3860
  });
3795
- var PaginationRoot_default = _sfc_main$15;
3861
+ var PaginationRoot_default = _sfc_main$16;
3796
3862
 
3797
3863
  //#endregion
3798
3864
  //#region src/components/Pagination/PaginationEllipsis.vue
3799
- const _sfc_main$14 = /* @__PURE__ */ defineComponent({
3865
+ const _sfc_main$15 = /* @__PURE__ */ defineComponent({
3800
3866
  name: "PaginationEllipsis",
3801
3867
  __name: "PaginationEllipsis",
3802
3868
  props: {
@@ -3837,11 +3903,11 @@ const _sfc_main$14 = /* @__PURE__ */ defineComponent({
3837
3903
  };
3838
3904
  }
3839
3905
  });
3840
- var PaginationEllipsis_default = _sfc_main$14;
3906
+ var PaginationEllipsis_default = _sfc_main$15;
3841
3907
 
3842
3908
  //#endregion
3843
3909
  //#region src/components/Pagination/PaginationFirst.vue
3844
- const _sfc_main$13 = /* @__PURE__ */ defineComponent({
3910
+ const _sfc_main$14 = /* @__PURE__ */ defineComponent({
3845
3911
  name: "PaginationFirst",
3846
3912
  __name: "PaginationFirst",
3847
3913
  props: {
@@ -3873,9 +3939,10 @@ const _sfc_main$13 = /* @__PURE__ */ defineComponent({
3873
3939
  first,
3874
3940
  attrs: {
3875
3941
  "aria-label": locale.t("Pagination.first", void 0, "Go to first page"),
3876
- "aria-disabled": __props.as === "button" ? void 0 : isDisabled.value,
3942
+ "aria-disabled": isDisabled.value,
3877
3943
  "data-disabled": isDisabled.value || void 0,
3878
3944
  "disabled": __props.as === "button" ? isDisabled.value : void 0,
3945
+ "tabindex": isDisabled.value ? -1 : 0,
3879
3946
  "type": __props.as === "button" ? "button" : void 0,
3880
3947
  "onClick": first
3881
3948
  }
@@ -3895,11 +3962,11 @@ const _sfc_main$13 = /* @__PURE__ */ defineComponent({
3895
3962
  };
3896
3963
  }
3897
3964
  });
3898
- var PaginationFirst_default = _sfc_main$13;
3965
+ var PaginationFirst_default = _sfc_main$14;
3899
3966
 
3900
3967
  //#endregion
3901
3968
  //#region src/components/Pagination/PaginationItem.vue
3902
- const _sfc_main$12 = /* @__PURE__ */ defineComponent({
3969
+ const _sfc_main$13 = /* @__PURE__ */ defineComponent({
3903
3970
  name: "PaginationItem",
3904
3971
  __name: "PaginationItem",
3905
3972
  props: {
@@ -3941,9 +4008,11 @@ const _sfc_main$12 = /* @__PURE__ */ defineComponent({
3941
4008
  attrs: {
3942
4009
  "aria-label": ariaLabel.value,
3943
4010
  "aria-current": isSelected.value ? "page" : void 0,
4011
+ "aria-disabled": __props.disabled,
3944
4012
  "data-selected": isSelected.value || void 0,
3945
4013
  "data-disabled": __props.disabled || void 0,
3946
4014
  "disabled": __props.as === "button" ? __props.disabled : void 0,
4015
+ "tabindex": __props.disabled ? -1 : 0,
3947
4016
  "type": __props.as === "button" ? "button" : void 0,
3948
4017
  "onClick": select
3949
4018
  }
@@ -3957,17 +4026,17 @@ const _sfc_main$12 = /* @__PURE__ */ defineComponent({
3957
4026
  as: __props.as,
3958
4027
  renderless: __props.renderless
3959
4028
  }), {
3960
- default: withCtx(() => [renderSlot(_ctx.$slots, "default", normalizeProps(guardReactiveProps(slotProps.value)))]),
4029
+ default: withCtx(() => [renderSlot(_ctx.$slots, "default", normalizeProps(guardReactiveProps(slotProps.value)), () => [createTextVNode(toDisplayString(__props.value), 1)])]),
3961
4030
  _: 3
3962
4031
  }, 16, ["as", "renderless"]);
3963
4032
  };
3964
4033
  }
3965
4034
  });
3966
- var PaginationItem_default = _sfc_main$12;
4035
+ var PaginationItem_default = _sfc_main$13;
3967
4036
 
3968
4037
  //#endregion
3969
4038
  //#region src/components/Pagination/PaginationLast.vue
3970
- const _sfc_main$11 = /* @__PURE__ */ defineComponent({
4039
+ const _sfc_main$12 = /* @__PURE__ */ defineComponent({
3971
4040
  name: "PaginationLast",
3972
4041
  __name: "PaginationLast",
3973
4042
  props: {
@@ -3999,9 +4068,10 @@ const _sfc_main$11 = /* @__PURE__ */ defineComponent({
3999
4068
  last,
4000
4069
  attrs: {
4001
4070
  "aria-label": locale.t("Pagination.last", void 0, "Go to last page"),
4002
- "aria-disabled": __props.as === "button" ? void 0 : isDisabled.value,
4071
+ "aria-disabled": isDisabled.value,
4003
4072
  "data-disabled": isDisabled.value || void 0,
4004
4073
  "disabled": __props.as === "button" ? isDisabled.value : void 0,
4074
+ "tabindex": isDisabled.value ? -1 : 0,
4005
4075
  "type": __props.as === "button" ? "button" : void 0,
4006
4076
  "onClick": last
4007
4077
  }
@@ -4021,11 +4091,11 @@ const _sfc_main$11 = /* @__PURE__ */ defineComponent({
4021
4091
  };
4022
4092
  }
4023
4093
  });
4024
- var PaginationLast_default = _sfc_main$11;
4094
+ var PaginationLast_default = _sfc_main$12;
4025
4095
 
4026
4096
  //#endregion
4027
4097
  //#region src/components/Pagination/PaginationNext.vue
4028
- const _sfc_main$10 = /* @__PURE__ */ defineComponent({
4098
+ const _sfc_main$11 = /* @__PURE__ */ defineComponent({
4029
4099
  name: "PaginationNext",
4030
4100
  __name: "PaginationNext",
4031
4101
  props: {
@@ -4057,9 +4127,10 @@ const _sfc_main$10 = /* @__PURE__ */ defineComponent({
4057
4127
  next,
4058
4128
  attrs: {
4059
4129
  "aria-label": locale.t("Pagination.next", void 0, "Go to next page"),
4060
- "aria-disabled": __props.as === "button" ? void 0 : isDisabled.value,
4130
+ "aria-disabled": isDisabled.value,
4061
4131
  "data-disabled": isDisabled.value || void 0,
4062
4132
  "disabled": __props.as === "button" ? isDisabled.value : void 0,
4133
+ "tabindex": isDisabled.value ? -1 : 0,
4063
4134
  "type": __props.as === "button" ? "button" : void 0,
4064
4135
  "onClick": next
4065
4136
  }
@@ -4079,11 +4150,11 @@ const _sfc_main$10 = /* @__PURE__ */ defineComponent({
4079
4150
  };
4080
4151
  }
4081
4152
  });
4082
- var PaginationNext_default = _sfc_main$10;
4153
+ var PaginationNext_default = _sfc_main$11;
4083
4154
 
4084
4155
  //#endregion
4085
4156
  //#region src/components/Pagination/PaginationPrev.vue
4086
- const _sfc_main$9 = /* @__PURE__ */ defineComponent({
4157
+ const _sfc_main$10 = /* @__PURE__ */ defineComponent({
4087
4158
  name: "PaginationPrev",
4088
4159
  __name: "PaginationPrev",
4089
4160
  props: {
@@ -4115,32 +4186,84 @@ const _sfc_main$9 = /* @__PURE__ */ defineComponent({
4115
4186
  prev,
4116
4187
  attrs: {
4117
4188
  "aria-label": locale.t("Pagination.prev", void 0, "Go to previous page"),
4118
- "aria-disabled": __props.as === "button" ? void 0 : isDisabled.value,
4189
+ "aria-disabled": isDisabled.value,
4119
4190
  "data-disabled": isDisabled.value || void 0,
4120
4191
  "disabled": __props.as === "button" ? isDisabled.value : void 0,
4192
+ "tabindex": isDisabled.value ? -1 : 0,
4121
4193
  "type": __props.as === "button" ? "button" : void 0,
4122
4194
  "onClick": prev
4123
4195
  }
4124
4196
  }));
4125
- onBeforeUnmount(() => controls.unregister(__props.id));
4197
+ onBeforeUnmount(() => controls.unregister(__props.id));
4198
+ return (_ctx, _cache) => {
4199
+ return openBlock(), createBlock(unref(Atom_default), mergeProps({
4200
+ ref_key: "atom",
4201
+ ref: atom
4202
+ }, slotProps.value.attrs, {
4203
+ as: __props.as,
4204
+ renderless: __props.renderless
4205
+ }), {
4206
+ default: withCtx(() => [renderSlot(_ctx.$slots, "default", normalizeProps(guardReactiveProps(slotProps.value)))]),
4207
+ _: 3
4208
+ }, 16, ["as", "renderless"]);
4209
+ };
4210
+ }
4211
+ });
4212
+ var PaginationPrev_default = _sfc_main$10;
4213
+
4214
+ //#endregion
4215
+ //#region src/components/Pagination/PaginationStatus.vue
4216
+ const _sfc_main$9 = /* @__PURE__ */ defineComponent({
4217
+ name: "PaginationStatus",
4218
+ __name: "PaginationStatus",
4219
+ props: {
4220
+ namespace: { default: "v0:pagination" },
4221
+ as: { default: "div" },
4222
+ renderless: { type: Boolean }
4223
+ },
4224
+ setup(__props) {
4225
+ const locale = useLocale();
4226
+ const pagination = usePaginationRoot(__props.namespace);
4227
+ const text = shallowRef("");
4228
+ watch(() => pagination.page.value, (page, prevPage) => {
4229
+ if (prevPage === void 0) return;
4230
+ setTimeout(() => {
4231
+ text.value = locale.t("Pagination.status", {
4232
+ page,
4233
+ pages: pagination.pages
4234
+ }, `Page ${page} of ${pagination.pages}`);
4235
+ }, 100);
4236
+ });
4237
+ const slotProps = toRef(() => ({
4238
+ page: pagination.page.value,
4239
+ pages: pagination.pages,
4240
+ text: text.value,
4241
+ attrs: {
4242
+ "aria-atomic": true,
4243
+ "aria-live": "polite",
4244
+ "role": "status"
4245
+ }
4246
+ }));
4126
4247
  return (_ctx, _cache) => {
4127
- return openBlock(), createBlock(unref(Atom_default), mergeProps({
4128
- ref_key: "atom",
4129
- ref: atom
4130
- }, slotProps.value.attrs, {
4248
+ return openBlock(), createBlock(unref(Atom_default), mergeProps(slotProps.value.attrs, {
4131
4249
  as: __props.as,
4132
4250
  renderless: __props.renderless
4133
4251
  }), {
4134
- default: withCtx(() => [renderSlot(_ctx.$slots, "default", normalizeProps(guardReactiveProps(slotProps.value)))]),
4252
+ default: withCtx(() => [renderSlot(_ctx.$slots, "default", normalizeProps(guardReactiveProps(slotProps.value)), () => [createTextVNode(toDisplayString(text.value), 1)])]),
4135
4253
  _: 3
4136
4254
  }, 16, ["as", "renderless"]);
4137
4255
  };
4138
4256
  }
4139
4257
  });
4140
- var PaginationPrev_default = _sfc_main$9;
4258
+ var PaginationStatus_default = _sfc_main$9;
4141
4259
 
4142
4260
  //#endregion
4143
4261
  //#region src/components/Pagination/index.ts
4262
+ /**
4263
+ * Pagination component with sub-components for building pagination controls.
4264
+ *
4265
+ * @see https://0.vuetifyjs.com/components/pagination
4266
+ */
4144
4267
  const Pagination = {
4145
4268
  Root: PaginationRoot_default,
4146
4269
  Item: PaginationItem_default,
@@ -4148,7 +4271,8 @@ const Pagination = {
4148
4271
  Prev: PaginationPrev_default,
4149
4272
  Ellipsis: PaginationEllipsis_default,
4150
4273
  Next: PaginationNext_default,
4151
- Last: PaginationLast_default
4274
+ Last: PaginationLast_default,
4275
+ Status: PaginationStatus_default
4152
4276
  };
4153
4277
 
4154
4278
  //#endregion
@@ -4295,6 +4419,11 @@ var PopoverContent_default = _sfc_main$6;
4295
4419
 
4296
4420
  //#endregion
4297
4421
  //#region src/components/Popover/index.ts
4422
+ /**
4423
+ * Popover component with sub-components for building popovers.
4424
+ *
4425
+ * @see https://0.vuetifyjs.com/components/popover
4426
+ */
4298
4427
  const Popover = {
4299
4428
  Root: PopoverRoot_default,
4300
4429
  Anchor: PopoverAnchor_default,
@@ -4329,7 +4458,7 @@ const _sfc_main$5 = /* @__PURE__ */ defineComponent({
4329
4458
  "modelValue": {},
4330
4459
  "modelModifiers": {}
4331
4460
  }),
4332
- emits: ["update:modelValue"],
4461
+ emits: /* @__PURE__ */ mergeModels(["update:model-value"], ["update:modelValue"]),
4333
4462
  setup(__props) {
4334
4463
  const model = useModel(__props, "modelValue");
4335
4464
  const selection = createSelection({
@@ -4404,6 +4533,11 @@ var SelectionItem_default = _sfc_main$4;
4404
4533
 
4405
4534
  //#endregion
4406
4535
  //#region src/components/Selection/index.ts
4536
+ /**
4537
+ * Selection component with sub-components for managing item selection state.
4538
+ *
4539
+ * @see https://0.vuetifyjs.com/components/selection
4540
+ */
4407
4541
  const Selection = {
4408
4542
  Root: SelectionRoot_default,
4409
4543
  Item: SelectionItem_default
@@ -4506,6 +4640,11 @@ var SingleItem_default = _sfc_main$2;
4506
4640
 
4507
4641
  //#endregion
4508
4642
  //#region src/components/Single/index.ts
4643
+ /**
4644
+ * Single component with sub-components for building single-selection interfaces.
4645
+ *
4646
+ * @see https://0.vuetifyjs.com/components/single
4647
+ */
4509
4648
  const Single = {
4510
4649
  Root: SingleRoot_default,
4511
4650
  Item: SingleItem_default
@@ -4514,20 +4653,6 @@ const Single = {
4514
4653
  //#endregion
4515
4654
  //#region src/composables/useStep/index.ts
4516
4655
  /**
4517
- * @module useStep
4518
- *
4519
- * @remarks
4520
- * Navigation composable that extends useSingle with first/last/next/prev/step methods.
4521
- *
4522
- * Key features:
4523
- * - Configurable circular or bounded navigation
4524
- * - Automatic disabled item skipping
4525
- * - Arbitrary step counts (positive/negative)
4526
- * - Perfect for wizards, carousels, pagination, onboarding flows
4527
- *
4528
- * Inheritance chain: useRegistry → useSelection → useSingle → useStep
4529
- */
4530
- /**
4531
4656
  * Creates a new step instance with navigation through items.
4532
4657
  *
4533
4658
  * Extends `createSingle` with `first()`, `last()`, `next()`, `prev()`, and `step(count)` methods
@@ -4596,7 +4721,7 @@ const Single = {
4596
4721
  * ```
4597
4722
  */
4598
4723
  function createStep(_options = {}) {
4599
- const { circular = false,...options } = _options;
4724
+ const { circular = false, ...options } = _options;
4600
4725
  const registry = createSingle(options);
4601
4726
  function first() {
4602
4727
  const ticket = registry.seek("first");
@@ -4672,7 +4797,7 @@ function createStep(_options = {}) {
4672
4797
  * ```
4673
4798
  */
4674
4799
  function createStepContext(_options = {}) {
4675
- const { namespace = "v0:step",...options } = _options;
4800
+ const { namespace = "v0:step", ...options } = _options;
4676
4801
  const [useStepContext, _provideStepContext] = createContext(namespace);
4677
4802
  const context = createStep(options);
4678
4803
  function provideStepContext(_context = context, app) {
@@ -4810,6 +4935,11 @@ var StepItem_default = _sfc_main;
4810
4935
 
4811
4936
  //#endregion
4812
4937
  //#region src/components/Step/index.ts
4938
+ /**
4939
+ * Step component with sub-components for building stepper navigation.
4940
+ *
4941
+ * @see https://0.vuetifyjs.com/components/step
4942
+ */
4813
4943
  const Step = {
4814
4944
  Root: StepRoot_default,
4815
4945
  Item: StepItem_default
@@ -4818,21 +4948,6 @@ const Step = {
4818
4948
  //#endregion
4819
4949
  //#region src/composables/toReactive/index.ts
4820
4950
  /**
4821
- * @module toReactive
4822
- *
4823
- * @remarks
4824
- * Utility function to convert values and refs into reactive proxies with ref unwrapping.
4825
- *
4826
- * Key features:
4827
- * - Automatic ref unwrapping
4828
- * - Deep reactive proxying
4829
- * - Map and Set support with ref unwrapping
4830
- * - Nested object/array reactivity
4831
- * - Type preservation
4832
- *
4833
- * Perfect for creating reactive versions of plain objects while automatically unwrapping refs.
4834
- */
4835
- /**
4836
4951
  * Converts a `MaybeRef` to a `UnwrapNestedRefs`.
4837
4952
  *
4838
4953
  * @param objectRef The object to convert.
@@ -4953,21 +5068,6 @@ function toReactive(objectRef) {
4953
5068
  //#endregion
4954
5069
  //#region src/composables/useEventListener/index.ts
4955
5070
  /**
4956
- * @module useEventListener
4957
- *
4958
- * @remarks
4959
- * Event listener composable with automatic cleanup on scope disposal.
4960
- *
4961
- * Key features:
4962
- * - Supports Window, Document, and HTMLElement targets
4963
- * - Reactive targets, events, and listeners
4964
- * - Event options support (capture, passive, once)
4965
- * - Automatic removeEventListener on unmount
4966
- * - Multiple overloads for type safety
4967
- *
4968
- * Perfect for safely managing event listeners in Vue components.
4969
- */
4970
- /**
4971
5071
  * Attaches an event listener to a target.
4972
5072
  *
4973
5073
  * @param target The target to attach the event listener to.
@@ -5022,7 +5122,7 @@ function useEventListener(target, event, listener, options) {
5022
5122
  * @see https://0.vuetifyjs.com/composables/system/use-event-listener
5023
5123
  */
5024
5124
  function useWindowEventListener(event, listener, options) {
5025
- return useEventListener(window, event, listener, options);
5125
+ return IN_BROWSER ? useEventListener(window, event, listener, options) : () => {};
5026
5126
  }
5027
5127
  /**
5028
5128
  * Attaches an event listener to the document.
@@ -5036,30 +5136,12 @@ function useWindowEventListener(event, listener, options) {
5036
5136
  * @see https://0.vuetifyjs.com/composables/system/use-event-listener
5037
5137
  */
5038
5138
  function useDocumentEventListener(event, listener, options) {
5039
- return useEventListener(document, event, listener, options);
5139
+ return IN_BROWSER ? useEventListener(document, event, listener, options) : () => {};
5040
5140
  }
5041
5141
 
5042
5142
  //#endregion
5043
5143
  //#region src/composables/useBreakpoints/index.ts
5044
5144
  /**
5045
- * @module useBreakpoints
5046
- *
5047
- * @see https://0.vuetifyjs.com/composables/plugins/use-breakpoints
5048
- *
5049
- * @remarks
5050
- * Responsive breakpoint detection composable with window resize handling.
5051
- *
5052
- * Key features:
5053
- * - Window matchMedia integration
5054
- * - Six built-in breakpoints (xs, sm, md, lg, xl, xxl)
5055
- * - Automatic resize listener with cleanup
5056
- * - SSR-safe (checks IN_BROWSER)
5057
- * - Hydration-aware
5058
- * - Custom breakpoint configuration
5059
- *
5060
- * Perfect for responsive layouts and conditional rendering based on screen size.
5061
- */
5062
- /**
5063
5145
  * Creates default breakpoint configuration.
5064
5146
  *
5065
5147
  * @returns The default breakpoint configuration object.
@@ -5203,7 +5285,7 @@ function createBreakpoints(_options = {}) {
5203
5285
  * ```
5204
5286
  */
5205
5287
  function createBreakpointsContext(_options = {}) {
5206
- const { namespace = "v0:breakpoints",...options } = _options;
5288
+ const { namespace = "v0:breakpoints", ...options } = _options;
5207
5289
  const [useBreakpointsContext, _provideBreakpointsContext] = createContext(namespace);
5208
5290
  const context = createBreakpoints(options);
5209
5291
  function provideBreakpointsContext(_context = context, app) {
@@ -5247,7 +5329,7 @@ function createBreakpointsContext(_options = {}) {
5247
5329
  * ```
5248
5330
  */
5249
5331
  function createBreakpointsPlugin(_options = {}) {
5250
- const { namespace = "v0:breakpoints",...options } = _options;
5332
+ const { namespace = "v0:breakpoints", ...options } = _options;
5251
5333
  const [, provideBreakpointsContext, context] = createBreakpointsContext({
5252
5334
  ...options,
5253
5335
  namespace
@@ -5305,25 +5387,217 @@ function useBreakpoints(namespace = "v0:breakpoints") {
5305
5387
  }
5306
5388
 
5307
5389
  //#endregion
5308
- //#region src/composables/useFeatures/index.ts
5390
+ //#region src/composables/useClickOutside/index.ts
5309
5391
  /**
5310
- * @module useFeatures
5392
+ * Detects clicks outside of the specified element(s).
5311
5393
  *
5312
- * @see https://0.vuetifyjs.com/composables/plugins/use-features
5394
+ * Uses two-phase detection (pointerdown → pointerup) to prevent false positives
5395
+ * when users drag from inside to outside an element.
5313
5396
  *
5314
- * @remarks
5315
- * Feature flag system with boolean and token-based features.
5397
+ * @param target Element ref(s) to detect clicks outside of. Accepts a single ref/getter or array of refs/getters.
5398
+ * @param handler Callback invoked when a click outside is detected.
5399
+ * @param options Configuration options.
5400
+ * @returns An object with methods to control the listener.
5316
5401
  *
5317
- * Key features:
5318
- * - Boolean features (true/false activation)
5319
- * - Token features with $variation support
5320
- * - Auto-selection of enabled features
5321
- * - Multi-select support for feature combinations
5322
- * - Perfect for A/B testing, progressive rollout, feature toggles
5323
- *
5324
- * Inheritance chain: useRegistry → createSelection → createGroup → createFeatures
5325
- * Integrates with useTokens for token-based features.
5402
+ * @see https://0.vuetifyjs.com/composables/system/use-click-outside
5403
+ *
5404
+ * @example Native element ref
5405
+ * ```ts
5406
+ * const menuRef = useTemplateRef<HTMLElement>('menu')
5407
+ *
5408
+ * useClickOutside(menuRef, () => { isOpen.value = false })
5409
+ * ```
5410
+ *
5411
+ * @example Component ref (e.g., Atom)
5412
+ * ```ts
5413
+ * const atomRef = useTemplateRef<AtomExpose>('atom')
5414
+ *
5415
+ * // Pass the exposed element TemplateRef via getter
5416
+ * useClickOutside(
5417
+ * () => atomRef.value?.element,
5418
+ * () => { isOpen.value = false }
5419
+ * )
5420
+ * ```
5421
+ *
5422
+ * @example Multiple targets
5423
+ * ```ts
5424
+ * const popoverRef = useTemplateRef<AtomExpose>('popover')
5425
+ * const anchorRef = useTemplateRef<HTMLElement>('anchor')
5426
+ *
5427
+ * useClickOutside(
5428
+ * [() => popoverRef.value?.element, anchorRef],
5429
+ * () => { isOpen.value = false }
5430
+ * )
5431
+ * ```
5432
+ *
5433
+ * @example Ignoring elements (CSS selectors or refs)
5434
+ * ```ts
5435
+ * useClickOutside(
5436
+ * () => navRef.value?.element,
5437
+ * () => { isOpen.value = false },
5438
+ * { ignore: ['[data-app-bar]'] }
5439
+ * )
5440
+ * ```
5326
5441
  */
5442
+ function useClickOutside(target, handler, options = {}) {
5443
+ const { capture = true, touchScrollThreshold = 30, detectIframe = false, ignore = [] } = options;
5444
+ const isPaused = shallowRef(false);
5445
+ const isActive = toRef(() => !isPaused.value);
5446
+ let initialTarget = null;
5447
+ let startPosition = {
5448
+ x: 0,
5449
+ y: 0
5450
+ };
5451
+ let cleanupPointerDown;
5452
+ let cleanupPointerUp;
5453
+ let cleanupBlur;
5454
+ /**
5455
+ * Resolve target(s) to an array of HTMLElements.
5456
+ */
5457
+ function getTargets() {
5458
+ return (Array.isArray(target) ? target : [target]).map((source) => toValue(source)).filter((el) => !/* @__PURE__ */ isNullOrUndefined(el));
5459
+ }
5460
+ /**
5461
+ * Resolve ignore targets to a tuple of [selectors, elements].
5462
+ * Called once per event to avoid repeated toValue() calls in hot path.
5463
+ */
5464
+ function resolveIgnoreTargets() {
5465
+ const ignoreTargets = toValue(ignore);
5466
+ if (ignoreTargets.length === 0) return [[], []];
5467
+ const selectors = [];
5468
+ const elements = [];
5469
+ for (const ignoreTarget of ignoreTargets) if (/* @__PURE__ */ isString(ignoreTarget)) selectors.push(ignoreTarget);
5470
+ else {
5471
+ const ignoreEl = toValue(ignoreTarget);
5472
+ if (ignoreEl) elements.push(ignoreEl);
5473
+ }
5474
+ return [selectors, elements];
5475
+ }
5476
+ /**
5477
+ * Check if an element matches resolved ignore targets.
5478
+ */
5479
+ function isIgnored(el, selectors, elements) {
5480
+ if (!el) return false;
5481
+ for (const selector of selectors) try {
5482
+ if (el.matches(selector) || !/* @__PURE__ */ isNull(el.closest(selector))) return true;
5483
+ } catch {}
5484
+ for (const ignoreEl of elements) if (ignoreEl === el || ignoreEl.contains(el)) return true;
5485
+ return false;
5486
+ }
5487
+ /**
5488
+ * Check if any element in the event path should be ignored.
5489
+ */
5490
+ function shouldIgnore(path) {
5491
+ const [selectors, elements] = resolveIgnoreTargets();
5492
+ if (selectors.length === 0 && elements.length === 0) return false;
5493
+ return path.some((node) => node instanceof Element && isIgnored(node, selectors, elements));
5494
+ }
5495
+ /**
5496
+ * Check if the event target is outside all target elements.
5497
+ */
5498
+ function isOutside(eventTarget) {
5499
+ if (!eventTarget) return false;
5500
+ if (!(eventTarget instanceof Node)) return false;
5501
+ const targets = getTargets();
5502
+ if (targets.length === 0) return false;
5503
+ return targets.every((el) => {
5504
+ return el !== eventTarget && !el.contains(eventTarget);
5505
+ });
5506
+ }
5507
+ /**
5508
+ * Validate that the target is still in the DOM.
5509
+ */
5510
+ function isValidTarget(eventTarget) {
5511
+ if (!(eventTarget instanceof Element)) return false;
5512
+ if (!eventTarget.isConnected) return false;
5513
+ return true;
5514
+ }
5515
+ /**
5516
+ * Handle pointerdown - store initial target and position.
5517
+ */
5518
+ function onPointerDown(event) {
5519
+ if (isPaused.value) return;
5520
+ if (event.defaultPrevented) return;
5521
+ initialTarget = event.composedPath()[0] ?? event.target;
5522
+ startPosition = {
5523
+ x: event.clientX,
5524
+ y: event.clientY
5525
+ };
5526
+ }
5527
+ /**
5528
+ * Handle pointerup - check if it's an outside click.
5529
+ */
5530
+ function onPointerUp(event) {
5531
+ if (isPaused.value) return;
5532
+ if (event.defaultPrevented) return;
5533
+ if (!initialTarget) return;
5534
+ const pointerdownTarget = initialTarget;
5535
+ initialTarget = null;
5536
+ if (!isValidTarget(pointerdownTarget)) return;
5537
+ const path = event.composedPath();
5538
+ const pointerupTarget = path[0] ?? event.target;
5539
+ if (event.pointerType === "touch") {
5540
+ const dx = Math.abs(event.clientX - startPosition.x);
5541
+ const dy = Math.abs(event.clientY - startPosition.y);
5542
+ if (dx >= touchScrollThreshold || dy >= touchScrollThreshold) return;
5543
+ }
5544
+ if (isOutside(pointerdownTarget) && isOutside(pointerupTarget) && !shouldIgnore(path)) handler(event);
5545
+ }
5546
+ /**
5547
+ * Handle window blur - detect focus moving to iframe.
5548
+ */
5549
+ function onBlur(event) {
5550
+ if (isPaused.value) return;
5551
+ if (event.defaultPrevented) return;
5552
+ if (document.activeElement instanceof HTMLIFrameElement) {
5553
+ const iframeIsOutside = getTargets().every((el) => !el.contains(document.activeElement));
5554
+ const [selectors, elements] = resolveIgnoreTargets();
5555
+ if (iframeIsOutside && !isIgnored(document.activeElement, selectors, elements)) handler(event);
5556
+ }
5557
+ }
5558
+ function setup() {
5559
+ cleanupPointerDown = useDocumentEventListener("pointerdown", onPointerDown, capture);
5560
+ cleanupPointerUp = useDocumentEventListener("pointerup", onPointerUp, capture);
5561
+ if (!detectIframe) return;
5562
+ cleanupBlur = useWindowEventListener("blur", onBlur, capture);
5563
+ }
5564
+ function cleanup() {
5565
+ cleanupPointerDown?.();
5566
+ cleanupPointerUp?.();
5567
+ cleanupBlur?.();
5568
+ cleanupPointerDown = void 0;
5569
+ cleanupPointerUp = void 0;
5570
+ cleanupBlur = void 0;
5571
+ }
5572
+ function pause() {
5573
+ if (isPaused.value) return;
5574
+ isPaused.value = true;
5575
+ initialTarget = null;
5576
+ cleanup();
5577
+ }
5578
+ function resume() {
5579
+ if (!isPaused.value) return;
5580
+ isPaused.value = false;
5581
+ setup();
5582
+ }
5583
+ function stop() {
5584
+ isPaused.value = true;
5585
+ initialTarget = null;
5586
+ cleanup();
5587
+ }
5588
+ setup();
5589
+ onScopeDispose(stop, true);
5590
+ return {
5591
+ isActive: shallowReadonly(isActive),
5592
+ isPaused: shallowReadonly(isPaused),
5593
+ pause,
5594
+ resume,
5595
+ stop
5596
+ };
5597
+ }
5598
+
5599
+ //#endregion
5600
+ //#region src/composables/useFeatures/index.ts
5327
5601
  /**
5328
5602
  * Creates a new features instance.
5329
5603
  *
@@ -5348,7 +5622,7 @@ function useBreakpoints(namespace = "v0:breakpoints") {
5348
5622
  * ```
5349
5623
  */
5350
5624
  function createFeatures(_options = {}) {
5351
- const { features,...options } = _options;
5625
+ const { features, ...options } = _options;
5352
5626
  const tokens = createTokens(features, { flat: true });
5353
5627
  const registry = createGroup(options);
5354
5628
  for (const [id, { value }] of tokens.entries()) register({
@@ -5402,7 +5676,7 @@ function createFeatures(_options = {}) {
5402
5676
  * ```
5403
5677
  */
5404
5678
  function createFeaturesContext(_options = {}) {
5405
- const { namespace = "v0:features",...options } = _options;
5679
+ const { namespace = "v0:features", ...options } = _options;
5406
5680
  const [useFeaturesContext, _provideFeaturesContext] = createContext(namespace);
5407
5681
  const context = createFeatures(options);
5408
5682
  function provideFeaturesContext(_context = context, app) {
@@ -5441,7 +5715,7 @@ function createFeaturesContext(_options = {}) {
5441
5715
  * ```
5442
5716
  */
5443
5717
  function createFeaturesPlugin(_options = {}) {
5444
- const { namespace = "v0:features",...options } = _options;
5718
+ const { namespace = "v0:features", ...options } = _options;
5445
5719
  const [, provideFeaturesContext, context] = createFeaturesContext({
5446
5720
  ...options,
5447
5721
  namespace
@@ -5484,21 +5758,6 @@ function useFeatures(namespace = "v0:features") {
5484
5758
 
5485
5759
  //#endregion
5486
5760
  //#region src/composables/useFilter/index.ts
5487
- /**
5488
- * @module useFilter
5489
- *
5490
- * @remarks
5491
- * Reactive array filtering composable with multiple filter modes.
5492
- *
5493
- * Key features:
5494
- * - Four filter modes: some, every, union, intersection
5495
- * - Case-insensitive filtering
5496
- * - Custom filter functions
5497
- * - Reactive updates
5498
- * - Perfect for search, multi-criteria filtering
5499
- *
5500
- * Filters arrays based on query strings with configurable matching strategies.
5501
- */
5502
5761
  function defaultFilter(query, item, keys, mode = "some") {
5503
5762
  const queries = Array.isArray(query) ? query.map((q) => String(q).toLowerCase()) : [String(query).toLowerCase()];
5504
5763
  function match(value, q) {
@@ -5512,6 +5771,89 @@ function defaultFilter(query, item, keys, mode = "some") {
5512
5771
  return false;
5513
5772
  }
5514
5773
  /**
5774
+ * Creates a filter context with pre-configured options.
5775
+ *
5776
+ * @param options The filter options
5777
+ * @template Z The type of the items
5778
+ * @template E The type of the filter context
5779
+ * @returns A filter context
5780
+ *
5781
+ * @see https://0.vuetifyjs.com/composables/utilities/use-filter
5782
+ *
5783
+ * @example
5784
+ * ```ts
5785
+ * import { createFilter } from '@vuetify/v0'
5786
+ *
5787
+ * const filter = createFilter({
5788
+ * mode: 'intersection',
5789
+ * keys: ['name', 'email'],
5790
+ * })
5791
+ *
5792
+ * const { items } = filter.apply(query, users)
5793
+ * ```
5794
+ */
5795
+ function createFilter(options = {}) {
5796
+ const { customFilter, keys, mode = "some" } = options;
5797
+ const filterFunction = customFilter ?? ((q, i) => defaultFilter(q, i, keys, mode));
5798
+ const query = toRef("");
5799
+ function apply(_query, items) {
5800
+ const itemsRef = isRef(items) ? items : toRef(() => items);
5801
+ const queryRef = toRef(_query);
5802
+ return { items: computed(() => {
5803
+ const q = toValue(queryRef);
5804
+ query.value = q;
5805
+ const queries = (Array.isArray(q) ? q : [q]).filter((q$1) => String(q$1).trim());
5806
+ if (queries.length === 0) return itemsRef.value;
5807
+ const queryParam = queries.length === 1 ? queries[0] : queries;
5808
+ return itemsRef.value.filter((item) => filterFunction(queryParam, item));
5809
+ }) };
5810
+ }
5811
+ return {
5812
+ mode,
5813
+ keys,
5814
+ customFilter,
5815
+ query,
5816
+ apply
5817
+ };
5818
+ }
5819
+ /**
5820
+ * Creates a filter context with dependency injection support.
5821
+ *
5822
+ * @param options The filter context options
5823
+ * @template Z The type of the items
5824
+ * @template E The type of the filter context
5825
+ * @returns A trinity tuple: [useContext, provideContext, defaultContext]
5826
+ *
5827
+ * @see https://0.vuetifyjs.com/composables/utilities/use-filter
5828
+ *
5829
+ * @example
5830
+ * ```ts
5831
+ * import { createFilterContext } from '@vuetify/v0'
5832
+ *
5833
+ * export const [useSearchFilter, provideSearchFilter, searchFilter] = createFilterContext({
5834
+ * namespace: 'app:search',
5835
+ * mode: 'union',
5836
+ * keys: ['title', 'description'],
5837
+ * })
5838
+ *
5839
+ * // In parent component
5840
+ * provideSearchFilter()
5841
+ *
5842
+ * // In child component
5843
+ * const filter = useSearchFilter()
5844
+ * const { items } = filter.apply(query, products)
5845
+ * ```
5846
+ */
5847
+ function createFilterContext(_options = {}) {
5848
+ const { namespace = "v0:filter", ...options } = _options;
5849
+ const [useFilterContext$1, _provideFilterContext] = createContext(namespace);
5850
+ const context = createFilter(options);
5851
+ function provideFilterContext(_context = context, app) {
5852
+ return _provideFilterContext(_context, app);
5853
+ }
5854
+ return createTrinity(useFilterContext$1, provideFilterContext, context);
5855
+ }
5856
+ /**
5515
5857
  * A reusable function for filtering an array of items.
5516
5858
  *
5517
5859
  * @param query The query to filter by.
@@ -5540,37 +5882,34 @@ function defaultFilter(query, item, keys, mode = "some") {
5540
5882
  * ```
5541
5883
  */
5542
5884
  function useFilter(query, items, options = {}) {
5543
- const { customFilter, keys, mode = "some" } = options;
5544
- const filterFunction = customFilter ?? ((q, i) => defaultFilter(q, i, keys, mode));
5545
- const itemsRef = isRef(items) ? items : toRef(() => items);
5546
- const queryRef = toRef(query);
5547
- return { items: computed(() => {
5548
- const q = toValue(queryRef);
5549
- const queries = (Array.isArray(q) ? q : [q]).filter((q$1) => String(q$1).trim());
5550
- if (queries.length === 0) return itemsRef.value;
5551
- const queryParam = queries.length === 1 ? queries[0] : queries;
5552
- return itemsRef.value.filter((item) => filterFunction(queryParam, item));
5553
- }) };
5885
+ return createFilter(options).apply(query, items);
5554
5886
  }
5555
-
5556
- //#endregion
5557
- //#region src/composables/useForm/index.ts
5558
5887
  /**
5559
- * @module useForm
5888
+ * Returns the current filter context from dependency injection.
5560
5889
  *
5561
- * @remarks
5562
- * Form validation composable with async rule support and multiple validation modes.
5890
+ * @param namespace The namespace for the filter context. Defaults to `'v0:filter'`.
5891
+ * @template Z The type of the items.
5892
+ * @template E The type of the filter context.
5893
+ * @returns The current filter context.
5563
5894
  *
5564
- * Key features:
5565
- * - Sync and async validation rules
5566
- * - Multiple validation modes (submit, change, combined)
5567
- * - Tri-state isValid (null/true/false)
5568
- * - isPristine tracking
5569
- * - Silent validation mode
5570
- * - Form-level validation and reset
5571
- *
5572
- * Each field is registered with validation rules and tracks its own state independently.
5895
+ * @see https://0.vuetifyjs.com/composables/utilities/use-filter
5896
+ *
5897
+ * @example
5898
+ * ```vue
5899
+ * <script setup lang="ts">
5900
+ * import { useFilterContext } from '@vuetify/v0'
5901
+ *
5902
+ * const filter = useFilterContext()
5903
+ * const { items } = filter.apply(query, products)
5904
+ * <\/script>
5905
+ * ```
5573
5906
  */
5907
+ function useFilterContext(namespace = "v0:filter") {
5908
+ return useContext(namespace);
5909
+ }
5910
+
5911
+ //#endregion
5912
+ //#region src/composables/useForm/index.ts
5574
5913
  /**
5575
5914
  * Creates a new form instance.
5576
5915
  *
@@ -5739,7 +6078,7 @@ function createForm(options) {
5739
6078
  * ```
5740
6079
  */
5741
6080
  function createFormContext(_options = {}) {
5742
- const { namespace = "v0:form",...options } = _options;
6081
+ const { namespace = "v0:form", ...options } = _options;
5743
6082
  const [useFormContext, _provideFormContext] = createContext(namespace);
5744
6083
  const context = createForm(options);
5745
6084
  function provideFormContext(_context = context, app) {
@@ -5777,22 +6116,6 @@ function useForm(namespace = "v0:form") {
5777
6116
  //#endregion
5778
6117
  //#region src/composables/useIntersectionObserver/index.ts
5779
6118
  /**
5780
- * @module useIntersectionObserver
5781
- *
5782
- * @remarks
5783
- * IntersectionObserver composable with lifecycle management.
5784
- *
5785
- * Key features:
5786
- * - IntersectionObserver API wrapper
5787
- * - Pause/resume/stop functionality
5788
- * - Automatic cleanup on unmount
5789
- * - SSR-safe (checks SUPPORTS_INTERSECTION_OBSERVER)
5790
- * - Hydration-aware
5791
- * - Immediate callback option
5792
- *
5793
- * Perfect for lazy loading, infinite scroll, and visibility detection.
5794
- */
5795
- /**
5796
6119
  * A composable that uses the Intersection Observer API to detect when an element
5797
6120
  * is visible in the viewport.
5798
6121
  *
@@ -5833,12 +6156,14 @@ function useForm(namespace = "v0:form") {
5833
6156
  */
5834
6157
  function useIntersectionObserver(target, callback, options = {}) {
5835
6158
  const { isHydrated } = useHydration();
6159
+ const targetRef = isRef(target) ? target : shallowRef(target);
5836
6160
  const observer = shallowRef();
5837
6161
  const isPaused = shallowRef(false);
5838
6162
  const isIntersecting = shallowRef(false);
5839
6163
  const isActive = toRef(() => !!observer.value);
5840
6164
  function setup() {
5841
- if (!isHydrated.value || !SUPPORTS_INTERSECTION_OBSERVER || !target.value || isPaused.value) return;
6165
+ if (observer.value === null) return;
6166
+ if (!isHydrated.value || !SUPPORTS_INTERSECTION_OBSERVER || !targetRef.value || isPaused.value) return;
5842
6167
  observer.value = new IntersectionObserver((entries) => {
5843
6168
  const transformedEntries = entries.map((entry) => ({
5844
6169
  boundingClientRect: entry.boundingClientRect,
@@ -5852,26 +6177,29 @@ function useIntersectionObserver(target, callback, options = {}) {
5852
6177
  const latestEntry = transformedEntries.at(-1);
5853
6178
  if (latestEntry) isIntersecting.value = latestEntry.isIntersecting;
5854
6179
  callback(transformedEntries);
6180
+ if (options.once && latestEntry?.isIntersecting) stop();
5855
6181
  }, {
5856
6182
  root: options.root || null,
5857
6183
  rootMargin: options.rootMargin || "0px",
5858
6184
  threshold: options.threshold || 0
5859
6185
  });
5860
- observer.value.observe(target.value);
6186
+ observer.value.observe(targetRef.value);
5861
6187
  if (options.immediate) callback([{
5862
- boundingClientRect: target.value.getBoundingClientRect(),
6188
+ boundingClientRect: targetRef.value.getBoundingClientRect(),
5863
6189
  intersectionRatio: 0,
5864
6190
  intersectionRect: new DOMRect(0, 0, 0, 0),
5865
6191
  isIntersecting: false,
5866
6192
  rootBounds: null,
5867
- target: target.value,
6193
+ target: targetRef.value,
5868
6194
  time: performance.now()
5869
6195
  }]);
5870
6196
  }
5871
- watch([isHydrated, target], () => {
6197
+ watchEffect(() => {
6198
+ const hydrated = isHydrated.value;
6199
+ const target$1 = targetRef.value;
5872
6200
  cleanup();
5873
- setup();
5874
- }, { immediate: true });
6201
+ if (hydrated && target$1) setup();
6202
+ });
5875
6203
  function cleanup() {
5876
6204
  if (observer.value) {
5877
6205
  observer.value.disconnect();
@@ -5889,6 +6217,7 @@ function useIntersectionObserver(target, callback, options = {}) {
5889
6217
  }
5890
6218
  function stop() {
5891
6219
  cleanup();
6220
+ observer.value = null;
5892
6221
  }
5893
6222
  onScopeDispose(stop, true);
5894
6223
  return {
@@ -5960,20 +6289,6 @@ function useElementIntersection(target, options = {}) {
5960
6289
  //#endregion
5961
6290
  //#region src/composables/useKeydown/index.ts
5962
6291
  /**
5963
- * @module useKeydown
5964
- *
5965
- * @remarks
5966
- * Keydown event listener composable with key filtering.
5967
- *
5968
- * Key features:
5969
- * - Key-specific event handling
5970
- * - preventDefault and stopPropagation options
5971
- * - Automatic cleanup on scope disposal
5972
- * - Built on useEventListener for consistent event handling
5973
- *
5974
- * Simplified wrapper around useEventListener for keyboard interactions.
5975
- */
5976
- /**
5977
6292
  * A composable that adds a keydown event listener to the document.
5978
6293
  *
5979
6294
  * @param handlers The key handlers to add.
@@ -5985,6 +6300,10 @@ function useElementIntersection(target, options = {}) {
5985
6300
  * ```ts
5986
6301
  * import { useKeydown } from '@vuetify/v0'
5987
6302
  *
6303
+ * // Single handler
6304
+ * useKeydown({ key: 'Escape', handler: () => console.log('Escape pressed') })
6305
+ *
6306
+ * // Multiple handlers
5988
6307
  * const { isActive, start, stop } = useKeydown([
5989
6308
  * { key: 'Enter', handler: () => console.log('Enter pressed') },
5990
6309
  * { key: 'Escape', handler: () => console.log('Escape pressed'), preventDefault: true },
@@ -6029,22 +6348,6 @@ function useKeydown(handlers) {
6029
6348
  //#endregion
6030
6349
  //#region src/composables/useMutationObserver/index.ts
6031
6350
  /**
6032
- * @module useMutationObserver
6033
- *
6034
- * @remarks
6035
- * MutationObserver composable with lifecycle management.
6036
- *
6037
- * Key features:
6038
- * - MutationObserver API wrapper
6039
- * - Pause/resume/stop functionality
6040
- * - Automatic cleanup on unmount
6041
- * - SSR-safe (checks SUPPORTS_MUTATION_OBSERVER)
6042
- * - Hydration-aware
6043
- * - Configurable observation options (childList, attributes, characterData, etc.)
6044
- *
6045
- * Perfect for detecting DOM changes and responding to mutations.
6046
- */
6047
- /**
6048
6351
  * A composable that uses the Mutation Observer API to detect changes in the DOM.
6049
6352
  *
6050
6353
  * @param target The element to observe.
@@ -6091,7 +6394,7 @@ function useMutationObserver(target, callback, options = {}) {
6091
6394
  const { isHydrated } = useHydration();
6092
6395
  const observer = shallowRef();
6093
6396
  const isPaused = shallowRef(false);
6094
- const isActive = computed(() => !!observer.value);
6397
+ const isActive = toRef(() => !!observer.value);
6095
6398
  const observerOptions = {
6096
6399
  childList: options.childList ?? true,
6097
6400
  attributes: options.attributes ?? false,
@@ -6102,6 +6405,7 @@ function useMutationObserver(target, callback, options = {}) {
6102
6405
  attributeFilter: options.attributeFilter
6103
6406
  };
6104
6407
  function setup() {
6408
+ if (observer.value === null) return;
6105
6409
  if (!isHydrated.value || !SUPPORTS_MUTATION_OBSERVER || !target.value || isPaused.value) return;
6106
6410
  observer.value = new MutationObserver((mutations) => {
6107
6411
  callback(mutations.map((mutation) => ({
@@ -6115,6 +6419,7 @@ function useMutationObserver(target, callback, options = {}) {
6115
6419
  attributeNamespace: mutation.attributeNamespace,
6116
6420
  oldValue: mutation.oldValue
6117
6421
  })));
6422
+ if (options.once) stop();
6118
6423
  });
6119
6424
  observer.value.observe(target.value, observerOptions);
6120
6425
  if (options.immediate) {
@@ -6135,12 +6440,15 @@ function useMutationObserver(target, callback, options = {}) {
6135
6440
  attributeNamespace: null,
6136
6441
  oldValue: null
6137
6442
  }]);
6443
+ if (options.once) stop();
6138
6444
  }
6139
6445
  }
6140
- watch([isHydrated, target], () => {
6446
+ watchEffect(() => {
6447
+ const hydrated = isHydrated.value;
6448
+ const el = target.value;
6141
6449
  cleanup();
6142
- setup();
6143
- }, { immediate: true });
6450
+ if (hydrated && el) setup();
6451
+ });
6144
6452
  function cleanup() {
6145
6453
  if (observer.value) {
6146
6454
  observer.value.disconnect();
@@ -6157,6 +6465,7 @@ function useMutationObserver(target, callback, options = {}) {
6157
6465
  }
6158
6466
  function stop() {
6159
6467
  cleanup();
6468
+ observer.value = null;
6160
6469
  }
6161
6470
  onScopeDispose(stop, true);
6162
6471
  return {
@@ -6189,23 +6498,6 @@ var Vuetify0PermissionAdapter = class extends PermissionAdapter {
6189
6498
  //#endregion
6190
6499
  //#region src/composables/usePermissions/index.ts
6191
6500
  /**
6192
- * @module usePermissions
6193
- *
6194
- * @see https://0.vuetifyjs.com/composables/plugins/use-permissions
6195
- *
6196
- * @remarks
6197
- * Permission management composable with support for RBAC and ABAC patterns.
6198
- *
6199
- * Key features:
6200
- * - Role-Based Access Control (RBAC) support
6201
- * - Attribute-Based Access Control (ABAC) with context
6202
- * - Functional permission conditions
6203
- * - Token-based permission storage
6204
- * - Adapter pattern for custom permission systems
6205
- *
6206
- * Built on useTokens for flexible permission configuration.
6207
- */
6208
- /**
6209
6501
  * Creates a new permissions instance.
6210
6502
  *
6211
6503
  * @param options The options for the permissions instance.
@@ -6229,7 +6521,7 @@ var Vuetify0PermissionAdapter = class extends PermissionAdapter {
6229
6521
  * ```
6230
6522
  */
6231
6523
  function createPermissions(_options = {}) {
6232
- const { adapter = new Vuetify0PermissionAdapter(), permissions = {},...options } = _options;
6524
+ const { adapter = new Vuetify0PermissionAdapter(), permissions = {}, ...options } = _options;
6233
6525
  const record = {};
6234
6526
  for (const role in permissions) {
6235
6527
  if (!record[role]) record[role] = {};
@@ -6271,7 +6563,7 @@ function createPermissions(_options = {}) {
6271
6563
  * ```
6272
6564
  */
6273
6565
  function createPermissionsContext(_options = {}) {
6274
- const { namespace = "v0:permissions",...options } = _options;
6566
+ const { namespace = "v0:permissions", ...options } = _options;
6275
6567
  const [usePermissionsContext, _providePermissionsContext] = createContext(namespace);
6276
6568
  const context = createPermissions(options);
6277
6569
  function providePermissionsContext(_context = context, app) {
@@ -6310,7 +6602,7 @@ function createPermissionsContext(_options = {}) {
6310
6602
  * ```
6311
6603
  */
6312
6604
  function createPermissionsPlugin(_options = {}) {
6313
- const { namespace = "v0:permissions",...options } = _options;
6605
+ const { namespace = "v0:permissions", ...options } = _options;
6314
6606
  const [, providePermissionContext, context] = createPermissionsContext({
6315
6607
  ...options,
6316
6608
  namespace
@@ -6352,21 +6644,6 @@ function usePermissions(namespace = "v0:permissions") {
6352
6644
  //#endregion
6353
6645
  //#region src/composables/useQueue/index.ts
6354
6646
  /**
6355
- * @module useQueue
6356
- *
6357
- * @remarks
6358
- * A queue composable for managing time-based collections with:
6359
- * - Automatic timeout-based removal
6360
- * - Pause/resume functionality
6361
- * - FIFO (First In, First Out) ordering
6362
- * - Manual dismissal support
6363
- * - Queue progression management
6364
- *
6365
- * Built on top of useRegistry, the queue automatically manages timeouts for tickets,
6366
- * ensuring only the first ticket in the queue is active at any time. When an ticket
6367
- * expires or is removed, the next ticket in the queue automatically becomes active.
6368
- */
6369
- /**
6370
6647
  * Creates a new queue instance
6371
6648
  *
6372
6649
  * @param options The options for the queue instance
@@ -6398,7 +6675,7 @@ function usePermissions(namespace = "v0:permissions") {
6398
6675
  * ```
6399
6676
  */
6400
6677
  function createQueue(_options = {}) {
6401
- const { timeout: _timeout = 3e3,...options } = _options;
6678
+ const { timeout: _timeout = 3e3, ...options } = _options;
6402
6679
  const registry = useRegistry({
6403
6680
  ...options,
6404
6681
  events: true
@@ -6493,7 +6770,6 @@ function createQueue(_options = {}) {
6493
6770
  /**
6494
6771
  * Creates a new queue context.
6495
6772
  *
6496
- * @param namespace The namespace for the queue context.
6497
6773
  * @param options The options for the queue context.
6498
6774
  * @template Z The type of the queue ticket.
6499
6775
  * @template E The type of the queue context.
@@ -6505,13 +6781,13 @@ function createQueue(_options = {}) {
6505
6781
  * ```ts
6506
6782
  * import { createQueueContext } from '@vuetify/v0'
6507
6783
  *
6508
- * export const [useQueue, provideQueue] = createQueueContext('v0:queue', {
6784
+ * export const [useQueue, provideQueue, context] = createQueueContext({
6509
6785
  * timeout: 5000,
6510
6786
  * })
6511
6787
  * ```
6512
6788
  */
6513
- function createQueueContext(_options) {
6514
- const { namespace,...options } = _options;
6789
+ function createQueueContext(_options = {}) {
6790
+ const { namespace = "v0:queue", ...options } = _options;
6515
6791
  const [useQueueContext, _provideQueueContext] = createContext(namespace);
6516
6792
  const context = createQueue(options);
6517
6793
  function provideQueueContext(_context = context, app) {
@@ -6569,21 +6845,6 @@ var MemoryAdapter = class {
6569
6845
  //#endregion
6570
6846
  //#region src/composables/useStorage/index.ts
6571
6847
  /**
6572
- * @module useStorage
6573
- *
6574
- * @remarks
6575
- * Reactive storage composable with adapter pattern for localStorage, sessionStorage, or memory.
6576
- *
6577
- * Key features:
6578
- * - Reactive refs that sync with storage
6579
- * - localStorage, sessionStorage, and memory adapters
6580
- * - Custom serialization support
6581
- * - SSR fallback to memory adapter
6582
- * - Automatic cleanup on remove/clear
6583
- *
6584
- * Uses adapter pattern to abstract storage implementation details.
6585
- */
6586
- /**
6587
6848
  * Creates a new storage instance.
6588
6849
  *
6589
6850
  * @param options The options for the storage instance.
@@ -6669,7 +6930,7 @@ function createStorage(options = {}) {
6669
6930
  };
6670
6931
  }
6671
6932
  function createStorageContext(_options = {}) {
6672
- const { namespace = "v0:storage",...options } = _options;
6933
+ const { namespace = "v0:storage", ...options } = _options;
6673
6934
  const [useStorageContext, _provideStorageContext] = createContext(namespace);
6674
6935
  const context = createStorage(options);
6675
6936
  function provideStorageContext(_context = context, app) {
@@ -6699,7 +6960,7 @@ function createStorageContext(_options = {}) {
6699
6960
  * ```
6700
6961
  */
6701
6962
  function createStoragePlugin(_options = {}) {
6702
- const { namespace = "v0:storage",...options } = _options;
6963
+ const { namespace = "v0:storage", ...options } = _options;
6703
6964
  const [, provideStorageContext, context] = createStorageContext({
6704
6965
  ...options,
6705
6966
  namespace
@@ -6820,24 +7081,6 @@ var Vuetify0ThemeAdapter = class extends ThemeAdapter {
6820
7081
  //#endregion
6821
7082
  //#region src/composables/useTheme/index.ts
6822
7083
  /**
6823
- * @module useTheme
6824
- *
6825
- * @see https://0.vuetifyjs.com/composables/plugins/use-theme
6826
- *
6827
- * @remarks
6828
- * Theme management composable with token resolution and CSS variable injection.
6829
- *
6830
- * Key features:
6831
- * - Single-selection theme switching (extends createSingle)
6832
- * - Token alias resolution via useTokens
6833
- * - Lazy theme loading (compute colors only when selected)
6834
- * - CSS variable generation via adapter pattern
6835
- * - SSR support with head integration
6836
- * - Theme cycling
6837
- *
6838
- * Integrates with createSingle for selection and useTokens for color resolution.
6839
- */
6840
- /**
6841
7084
  * Creates a new theme instance.
6842
7085
  *
6843
7086
  * @param options The options for the theme instance.
@@ -6872,14 +7115,14 @@ var Vuetify0ThemeAdapter = class extends ThemeAdapter {
6872
7115
  * ```
6873
7116
  */
6874
7117
  function createTheme(_options = {}) {
6875
- const { themes = {}, palette = {},...options } = _options;
7118
+ const { themes = {}, palette = {}, ...options } = _options;
6876
7119
  const tokens = createTokens({
6877
7120
  palette,
6878
7121
  ...themes
6879
7122
  }, { flat: true });
6880
7123
  const registry = createSingle(options);
6881
7124
  for (const id in themes) {
6882
- const { colors: value,...theme } = themes[id];
7125
+ const { colors: value, ...theme } = themes[id];
6883
7126
  register({
6884
7127
  id,
6885
7128
  value,
@@ -6961,7 +7204,7 @@ function createTheme(_options = {}) {
6961
7204
  * ```
6962
7205
  */
6963
7206
  function createThemeContext(_options = {}) {
6964
- const { namespace = "v0:theme",...options } = _options;
7207
+ const { namespace = "v0:theme", ...options } = _options;
6965
7208
  const [useThemeContext, _provideThemeContext] = createContext(namespace);
6966
7209
  const context = createTheme(options);
6967
7210
  function provideThemeContext(_context = context, app) {
@@ -7011,7 +7254,7 @@ function createThemeContext(_options = {}) {
7011
7254
  * ```
7012
7255
  */
7013
7256
  function createThemePlugin(_options = {}) {
7014
- const { adapter = new Vuetify0ThemeAdapter(), namespace = "v0:theme", palette = {}, themes = {}, target,...options } = _options;
7257
+ const { adapter = new Vuetify0ThemeAdapter(), namespace = "v0:theme", palette = {}, themes = {}, target, ...options } = _options;
7015
7258
  const [, provideThemeContext, context] = createThemeContext({
7016
7259
  ...options,
7017
7260
  namespace,
@@ -7058,21 +7301,6 @@ function useTheme(namespace = "v0:theme") {
7058
7301
  //#endregion
7059
7302
  //#region src/composables/useTimeline/index.ts
7060
7303
  /**
7061
- * @module useTimeline
7062
- *
7063
- * @remarks
7064
- * Bounded undo/redo system with overflow management.
7065
- *
7066
- * Key features:
7067
- * - Fixed-size history (default: 10 items)
7068
- * - Undo/redo stack management
7069
- * - Overflow queue (preserves oldest items)
7070
- * - Automatic reindexing after operations
7071
- * - Perfect for command pattern, history tracking
7072
- *
7073
- * Extends useRegistry with temporal navigation capabilities.
7074
- */
7075
- /**
7076
7304
  * Creates a new timeline instance.
7077
7305
  *
7078
7306
  * @param _options The options for the timeline instance.
@@ -7100,7 +7328,7 @@ function useTheme(namespace = "v0:theme") {
7100
7328
  * ```
7101
7329
  */
7102
7330
  function createTimeline(_options = {}) {
7103
- const { size = 10,...options } = _options;
7331
+ const { size = 10, ...options } = _options;
7104
7332
  const registry = useRegistry(options);
7105
7333
  const stack = [];
7106
7334
  const overflow = [];
@@ -7175,7 +7403,7 @@ function createTimeline(_options = {}) {
7175
7403
  * ```
7176
7404
  */
7177
7405
  function createTimelineContext(_options = {}) {
7178
- const { namespace = "v0:timeline",...options } = _options;
7406
+ const { namespace = "v0:timeline", ...options } = _options;
7179
7407
  const [useTimelineContext, _provideTimelineContext] = createContext(namespace);
7180
7408
  const context = createTimeline(options);
7181
7409
  function provideTimelineContext(_context = context, app) {
@@ -7207,24 +7435,6 @@ function useTimeline(namespace = "v0:timeline") {
7207
7435
  //#endregion
7208
7436
  //#region src/composables/useToggleScope/index.ts
7209
7437
  /**
7210
- * @module useToggleScope
7211
- *
7212
- * @remarks
7213
- * Conditionally manages an effect scope based on a reactive boolean condition.
7214
- * When the source becomes true, creates and runs an effect scope. When false, stops the scope.
7215
- * All reactive effects created within the scoped function are automatically cleaned up on deactivation.
7216
- *
7217
- * Key features:
7218
- * - Uses Vue's effectScope for efficient reactive effect lifecycle management
7219
- * - Automatic cleanup when condition becomes false
7220
- * - Supports optional reset callback for scope restart capability
7221
- * - Handles rapid toggling and parent scope disposal safely
7222
- * - SSR-safe (effectScope is part of Vue core)
7223
- *
7224
- * Perfect for conditional side effects, feature flags, and performance optimization
7225
- * by only running reactive effects when needed.
7226
- */
7227
- /**
7228
7438
  * Conditionally manages an effect scope based on a reactive boolean source.
7229
7439
  *
7230
7440
  * @param source A reactive boolean value or getter that controls the scope lifecycle
@@ -7306,24 +7516,6 @@ function useToggleScope(source, fn) {
7306
7516
  //#endregion
7307
7517
  //#region src/composables/useVirtual/index.ts
7308
7518
  /**
7309
- * @module useVirtual
7310
- *
7311
- * @remarks
7312
- * Virtual scrolling composable for efficiently rendering large lists.
7313
- *
7314
- * Key features:
7315
- * - Renders only visible items (viewport + overscan)
7316
- * - Dynamic or fixed item heights
7317
- * - SSR-safe (checks IN_BROWSER)
7318
- * - Bidirectional scrolling (forward/reverse for chat apps)
7319
- * - Scroll anchoring (maintains position across data changes)
7320
- * - Edge detection for infinite scroll
7321
- * - iOS momentum and elastic scrolling
7322
- * - Configurable overscan (extra items rendered for smooth scrolling)
7323
- *
7324
- * Perfect for large data sets, chat apps, and infinite scroll implementations.
7325
- */
7326
- /**
7327
7519
  * Virtual scrolling composable for efficiently rendering large lists
7328
7520
  *
7329
7521
  * @param items Reactive array of items to virtualize
@@ -7560,6 +7752,11 @@ function useVirtual(items, _options = {}) {
7560
7752
  element.value.scrollTop = totalHeight;
7561
7753
  }
7562
7754
  }
7755
+ onScopeDispose(() => {
7756
+ cancelAnimationFrame(raf);
7757
+ cancelAnimationFrame(rebuildRaf);
7758
+ cancelAnimationFrame(edgeRaf);
7759
+ }, true);
7563
7760
  return {
7564
7761
  element,
7565
7762
  items: computedItems,
@@ -7575,4 +7772,4 @@ function useVirtual(items, _options = {}) {
7575
7772
  }
7576
7773
 
7577
7774
  //#endregion
7578
- export { Atom_default as Atom, Avatar, COMMON_ELEMENTS, ConsolaLoggerAdapter, ExpansionPanel, Group, IN_BROWSER, MemoryAdapter, Pagination, PermissionAdapter, PinoLoggerAdapter, Popover, SELF_CLOSING_TAGS, SUPPORTS_INTERSECTION_OBSERVER, SUPPORTS_MATCH_MEDIA, SUPPORTS_MUTATION_OBSERVER, SUPPORTS_OBSERVER, SUPPORTS_TOUCH, Selection, Single, Step, Vuetify0LocaleAdapter, Vuetify0LoggerAdapter, Vuetify0ThemeAdapter, __LOGGER_ENABLED__, clamp, createBreakpoints, createBreakpointsContext, createBreakpointsPlugin, createContext, createFallbackHydration, createFeatures, createFeaturesContext, createFeaturesPlugin, createForm, createFormContext, createGroup, createGroupContext, createHydration, createHydrationContext, createHydrationPlugin, createLocale, createLocaleContext, createLocaleFallback, createLocalePlugin, createLogger, createLoggerContext, createLoggerPlugin, createOverflow, createOverflowContext, createPagination, createPaginationContext, createPermissions, createPermissionsContext, createPermissionsPlugin, createPlugin, createQueue, createQueueContext, createRegistryContext, createSelection, createSelectionContext, createSingle, createSingleContext, createStep, createStepContext, createStorage, createStorageContext, createStoragePlugin, createTheme, createThemeContext, createThemePlugin, createTimeline, createTimelineContext, createTokens, createTokensContext, createTrinity, debounce, genId, isArray, isBoolean, isFunction, isNaN, isNull, isNullOrUndefined, isNumber, isObject, isPrimitive, isSelfClosingTag, isString, isSymbol, isUndefined, mergeDeep, provideAvatarContext, provideContext, provideExpansionPanelItem, provideExpansionPanelSelection, provideGroupRoot, providePaginationControls, providePaginationItems, providePaginationRoot, providePopoverContext, provideSelectionRoot, provideSingleRoot, provideStepRoot, range, toArray, toReactive, useAvatarRoot, useBreakpoints, useContext, useDocumentEventListener, useElementIntersection, useElementSize, useEventListener, useExpansionPanelItem, useExpansionPanelRoot, useFeatures, useFilter, useForm, useGroup, useGroupRoot, useHydration, useIntersectionObserver, useKeydown, useLocale, useLogger, useMutationObserver, useOverflow, usePagination, usePaginationControls, usePaginationItems, usePaginationRoot, usePermissions, usePopoverContext, useProxyModel, useProxyRegistry, useQueue, useRegistry, useResizeObserver, useSelection, useSelectionRoot, useSingle, useSingleRoot, useStep, useStepRoot, useStorage, useTheme, useTimeline, useToggleScope, useTokens, useVirtual, useWindowEventListener, version };
7775
+ export { Atom_default as Atom, Avatar, AvatarFallback_default as AvatarFallback, AvatarImage_default as AvatarImage, AvatarRoot_default as AvatarRoot, COMMON_ELEMENTS, ConsolaLoggerAdapter, ExpansionPanel, ExpansionPanelActivator_default as ExpansionPanelActivator, ExpansionPanelContent_default as ExpansionPanelContent, ExpansionPanelHeader_default as ExpansionPanelHeader, ExpansionPanelItem_default as ExpansionPanelItem, ExpansionPanelRoot_default as ExpansionPanelRoot, Group, GroupItem_default as GroupItem, GroupRoot_default as GroupRoot, IN_BROWSER, MemoryAdapter, Pagination, PaginationEllipsis_default as PaginationEllipsis, PaginationFirst_default as PaginationFirst, PaginationItem_default as PaginationItem, PaginationLast_default as PaginationLast, PaginationNext_default as PaginationNext, PaginationPrev_default as PaginationPrev, PaginationRoot_default as PaginationRoot, PaginationStatus_default as PaginationStatus, PermissionAdapter, PinoLoggerAdapter, Popover, PopoverAnchor_default as PopoverAnchor, PopoverContent_default as PopoverContent, PopoverRoot_default as PopoverRoot, SELF_CLOSING_TAGS, SUPPORTS_INTERSECTION_OBSERVER, SUPPORTS_MATCH_MEDIA, SUPPORTS_MUTATION_OBSERVER, SUPPORTS_OBSERVER, SUPPORTS_TOUCH, Selection, SelectionItem_default as SelectionItem, SelectionRoot_default as SelectionRoot, Single, SingleItem_default as SingleItem, SingleRoot_default as SingleRoot, Step, StepItem_default as StepItem, StepRoot_default as StepRoot, Vuetify0LocaleAdapter, Vuetify0LoggerAdapter, Vuetify0ThemeAdapter, __LOGGER_ENABLED__, clamp, createBreakpoints, createBreakpointsContext, createBreakpointsPlugin, createContext, createFallbackHydration, createFeatures, createFeaturesContext, createFeaturesPlugin, createFilter, createFilterContext, createForm, createFormContext, createGroup, createGroupContext, createHydration, createHydrationContext, createHydrationPlugin, createLocale, createLocaleContext, createLocaleFallback, createLocalePlugin, createLogger, createLoggerContext, createLoggerPlugin, createOverflow, createOverflowContext, createPagination, createPaginationContext, createPermissions, createPermissionsContext, createPermissionsPlugin, createPlugin, createQueue, createQueueContext, createRegistryContext, createSelection, createSelectionContext, createSingle, createSingleContext, createStep, createStepContext, createStorage, createStorageContext, createStoragePlugin, createTheme, createThemeContext, createThemePlugin, createTimeline, createTimelineContext, createTokens, createTokensContext, createTrinity, debounce, genId, isArray, isBoolean, isFunction, isNaN, isNull, isNullOrUndefined, isNumber, isObject, isPrimitive, isSelfClosingTag, isString, isSymbol, isUndefined, mergeDeep, provideAvatarContext, provideContext, provideExpansionPanelItem, provideExpansionPanelSelection, provideGroupRoot, providePaginationControls, providePaginationItems, providePaginationRoot, providePopoverContext, provideSelectionRoot, provideSingleRoot, provideStepRoot, range, toArray, toReactive, useAvatarRoot, useBreakpoints, useClickOutside, useContext, useDocumentEventListener, useElementIntersection, useElementSize, useEventListener, useExpansionPanelItem, useExpansionPanelRoot, useFeatures, useFilter, useFilterContext, useForm, useGroup, useGroupRoot, useHydration, useIntersectionObserver, useKeydown, useLocale, useLogger, useMutationObserver, useOverflow, usePagination, usePaginationControls, usePaginationItems, usePaginationRoot, usePermissions, usePopoverContext, useProxyModel, useProxyRegistry, useQueue, useRegistry, useResizeObserver, useSelection, useSelectionRoot, useSingle, useSingleRoot, useStep, useStepRoot, useStorage, useTheme, useTimeline, useToggleScope, useTokens, useVirtual, useWindowEventListener, version };