@vuetify/v0 0.1.6 → 0.1.8

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 (162) hide show
  1. package/README.md +0 -1
  2. package/dist/{adapter-Bjs_Nx_J.mjs → adapter-B4zE-hA5.mjs} +5 -8
  3. package/dist/adapter-CqP9Z4JU.d.mts +1087 -0
  4. package/dist/{adapter-CLs-OrSN.d.mts → adapter-DIx4Rntl.d.mts} +5 -48
  5. package/dist/adapters-BjeDmKc6.mjs +1 -0
  6. package/dist/adapters-Bv5aRv3l.mjs +1 -0
  7. package/dist/adapters-C66XaKkw.mjs +1 -0
  8. package/dist/adapters-DkVblyML.mjs +1 -0
  9. package/dist/adapters-uJLWGQJl.mjs +1 -0
  10. package/dist/browser/index.js +2380 -1080
  11. package/dist/components/index.d.mts +2 -20
  12. package/dist/components/index.mjs +34 -39
  13. package/dist/{components-GiQh_RfQ.mjs → components-BbxKYAXs.mjs} +1129 -392
  14. package/dist/composables/index.d.mts +18 -17
  15. package/dist/composables/index.mjs +34 -37
  16. package/dist/{consola-DiUk9j3y.d.mts → consola-BVzYzeLH.d.mts} +1 -1
  17. package/dist/{consola-GBy8XRuL.mjs → consola-Ceox8BWi.mjs} +1 -2
  18. package/dist/constants/index.d.mts +1 -1
  19. package/dist/constants/index.mjs +3 -5
  20. package/dist/{createDataTable-lSofI5rU.mjs → createDataTable-DZouEhvH.mjs} +9 -11
  21. package/dist/{createGroup-CCb7Zfyw.mjs → createGroup-BpJFi41X.mjs} +5 -8
  22. package/dist/{createPagination-lagznd8i.mjs → createPagination-Bu8vE0JW.mjs} +3 -5
  23. package/dist/{createSelection-Zo4RQpYe.mjs → createSelection-8MX0OHXR.mjs} +9 -12
  24. package/dist/{createSingle-BH9wNDrS.mjs → createSingle-CbuOBb-E.mjs} +3 -5
  25. package/dist/{createTokens-Cu1efg9Z.mjs → createTokens-CXlT0Vc6.mjs} +25 -27
  26. package/dist/{createTrinity-Cii8-B2r.mjs → createTrinity-C_c8eedz.mjs} +10 -13
  27. package/dist/data-table/adapters/client/index.d.mts +1 -2
  28. package/dist/data-table/adapters/client/index.mjs +7 -9
  29. package/dist/data-table/adapters/index.d.mts +4 -4
  30. package/dist/data-table/adapters/index.mjs +10 -12
  31. package/dist/data-table/adapters/server/index.d.mts +1 -2
  32. package/dist/data-table/adapters/server/index.mjs +5 -7
  33. package/dist/data-table/adapters/virtual/index.d.mts +1 -2
  34. package/dist/data-table/adapters/virtual/index.mjs +7 -9
  35. package/dist/data-table/index.d.mts +5 -6
  36. package/dist/data-table/index.mjs +22 -25
  37. package/dist/date/index.d.mts +1 -3
  38. package/dist/date/index.mjs +3932 -3943
  39. package/dist/features/adapters/flagsmith/index.d.mts +2 -4
  40. package/dist/features/adapters/flagsmith/index.mjs +2 -3
  41. package/dist/features/adapters/launchdarkly/index.d.mts +1 -3
  42. package/dist/features/adapters/launchdarkly/index.mjs +2 -3
  43. package/dist/features/adapters/posthog/index.d.mts +1 -3
  44. package/dist/features/adapters/posthog/index.mjs +3 -4
  45. package/dist/features/index.d.mts +2 -16
  46. package/dist/features/index.mjs +13 -18
  47. package/dist/{flagsmith-CHmpPGR7.mjs → flagsmith-CrWUeIhT.mjs} +1 -2
  48. package/dist/{globals-D6FBsWDI.mjs → globals-ClSU6mqC.mjs} +2 -3
  49. package/dist/{htmlElements-d8iBCGpO.mjs → htmlElements-DcYtv0hg.mjs} +7 -10
  50. package/dist/{index-De0SQt1w.d.mts → index-63-0oJS8.d.mts} +381 -981
  51. package/dist/{index-DlUIZN-F.d.mts → index-B5NU2uB7.d.mts} +2754 -1642
  52. package/dist/index-CeNfBYuo.d.mts +46 -0
  53. package/dist/{index-DIK84tM4.d.mts → index-CmCMrlt3.d.mts} +3 -3
  54. package/dist/index-CxW4itj1.d.mts +858 -0
  55. package/dist/{index-BFBN5Zl3.d.mts → index-Dor6eAEc.d.mts} +0 -1
  56. package/dist/{index-UNwEBkQT.d.mts → index-MHkcqY_y.d.mts} +1 -2
  57. package/dist/{index-BuOz3Rgm.d.mts → index-dJKXAO5D.d.mts} +1 -2
  58. package/dist/index.d.mts +22 -20
  59. package/dist/index.mjs +38 -40
  60. package/dist/json/attributes.json +252 -0
  61. package/dist/json/importMap.json +60 -0
  62. package/dist/json/tags.json +128 -0
  63. package/dist/json/web-types.json +1023 -228
  64. package/dist/{launchdarkly-W8t8ZANX.mjs → launchdarkly-jF2KZGoH.mjs} +1 -2
  65. package/dist/locale/adapters/index.d.mts +1 -2
  66. package/dist/locale/adapters/index.mjs +4 -6
  67. package/dist/locale/adapters/v0/index.d.mts +1 -2
  68. package/dist/locale/adapters/v0/index.mjs +3 -5
  69. package/dist/locale/index.d.mts +2 -16
  70. package/dist/locale/index.mjs +14 -17
  71. package/dist/logger/adapters/consola/index.d.mts +1 -2
  72. package/dist/logger/adapters/consola/index.mjs +2 -3
  73. package/dist/logger/adapters/index.d.mts +4 -4
  74. package/dist/logger/adapters/index.mjs +6 -8
  75. package/dist/logger/adapters/pino/index.d.mts +1 -2
  76. package/dist/logger/adapters/pino/index.mjs +3 -5
  77. package/dist/logger/adapters/v0/index.d.mts +1 -2
  78. package/dist/logger/adapters/v0/index.mjs +3 -5
  79. package/dist/logger/index.d.mts +5 -16
  80. package/dist/logger/index.mjs +8 -10
  81. package/dist/{memory-BsZGbGnG.mjs → memory-XCMtkld1.mjs} +1 -2
  82. package/dist/palettes/ant/generate/index.d.mts +9 -0
  83. package/dist/palettes/ant/generate/index.mjs +98 -0
  84. package/dist/palettes/ant/index.d.mts +6 -0
  85. package/dist/palettes/ant/index.mjs +149 -0
  86. package/dist/palettes/index.d.mts +12 -0
  87. package/dist/palettes/index.mjs +1 -0
  88. package/dist/palettes/leonardo/generate/index.d.mts +10 -0
  89. package/dist/palettes/leonardo/generate/index.mjs +120 -0
  90. package/dist/palettes/material/generate/index.d.mts +10 -0
  91. package/dist/palettes/material/generate/index.mjs +103 -0
  92. package/dist/palettes/material/index.d.mts +6 -0
  93. package/dist/palettes/material/index.mjs +173 -0
  94. package/dist/palettes/md1/index.d.mts +6 -0
  95. package/dist/palettes/md1/index.mjs +261 -0
  96. package/dist/palettes/md2/index.d.mts +6 -0
  97. package/dist/palettes/md2/index.mjs +297 -0
  98. package/dist/palettes/radix/index.d.mts +6 -0
  99. package/dist/palettes/radix/index.mjs +439 -0
  100. package/dist/palettes/tailwind/index.d.mts +6 -0
  101. package/dist/palettes/tailwind/index.mjs +291 -0
  102. package/dist/permissions/adapters/index.d.mts +2 -17
  103. package/dist/permissions/adapters/index.mjs +4 -6
  104. package/dist/permissions/adapters/v0/index.d.mts +1 -17
  105. package/dist/permissions/adapters/v0/index.mjs +3 -5
  106. package/dist/permissions/index.d.mts +1 -16
  107. package/dist/permissions/index.mjs +12 -15
  108. package/dist/{pino-BD5PCzAF.mjs → pino-B7tJ3m18.mjs} +2 -4
  109. package/dist/{pino-p-jDkNQd.d.mts → pino-Bzighnkd.d.mts} +1 -2
  110. package/dist/{posthog-BxaG8sYi.mjs → posthog-BE7-t7cV.mjs} +2 -4
  111. package/dist/rules/index.d.mts +2 -0
  112. package/dist/rules/index.mjs +15 -0
  113. package/dist/{server-DgOdFYMU.mjs → server-CZ6ahbEH.mjs} +2 -4
  114. package/dist/{server-CGAeOGPC.d.mts → server-Ch9J86tb.d.mts} +1 -2
  115. package/dist/storage/adapters/index.d.mts +2 -2
  116. package/dist/storage/adapters/index.mjs +2 -3
  117. package/dist/storage/adapters/memory/index.d.mts +1 -1
  118. package/dist/storage/adapters/memory/index.mjs +2 -3
  119. package/dist/storage/index.d.mts +3 -16
  120. package/dist/storage/index.mjs +33 -37
  121. package/dist/theme/adapters/index.d.mts +1 -16
  122. package/dist/theme/adapters/index.mjs +4 -6
  123. package/dist/theme/adapters/v0/index.d.mts +1 -16
  124. package/dist/theme/adapters/v0/index.mjs +3 -5
  125. package/dist/theme/index.d.mts +1 -16
  126. package/dist/theme/index.mjs +13 -16
  127. package/dist/{toArray-BBZH-G2X.mjs → toArray-VdROPpy-.mjs} +2 -4
  128. package/dist/types/index.d.mts +1 -1
  129. package/dist/types/index.mjs +1 -1
  130. package/dist/{useClickOutside-Bm_3mbcT.mjs → useClickOutside-W0Sur1rC.mjs} +671 -211
  131. package/dist/{useFeatures-BS4mit8z.mjs → useFeatures-CUicSI-E.mjs} +5 -8
  132. package/dist/{useLocale-DJJmg-wv.mjs → useLocale-cQlPxbpV.mjs} +14 -12
  133. package/dist/{useLogger-C8G5jgNk.mjs → useLogger-DY1Hbcy1.mjs} +13 -16
  134. package/dist/{usePermissions-C5Mkotol.mjs → usePermissions-BSW59R4q.mjs} +5 -7
  135. package/dist/useRules-BbA6_gvs.mjs +144 -0
  136. package/dist/{useTheme-BBnASLr3.mjs → useTheme-Bdx2Lj5c.mjs} +11 -13
  137. package/dist/utilities/index.d.mts +1 -2
  138. package/dist/utilities/index.mjs +426 -4
  139. package/dist/{v0-BOxb3nD1.d.mts → v0-1xxC39wf.d.mts} +1 -2
  140. package/dist/{v0-DzvhDU1W.mjs → v0-2G2476h-.mjs} +3 -6
  141. package/dist/{v0-DtO_ICXr.mjs → v0-B1QQGE4O.mjs} +2 -5
  142. package/dist/{v0-lua6ffdk.mjs → v0-BFseIsBi.mjs} +3 -5
  143. package/dist/{v0-Bh8d1j_p.d.mts → v0-BZINNGoC.d.mts} +2 -2
  144. package/dist/{v0-DHMoZ7dS.d.mts → v0-CAKa6tzG.d.mts} +1 -1
  145. package/dist/{v0-BWBSVkew.mjs → v0-CHBrvw49.mjs} +3 -5
  146. package/dist/{v0-CVr15VcY.d.mts → v0-CdUL2eOn.d.mts} +1 -2
  147. package/dist/{v0-CWUF_HqP.mjs → v0-YAqbXudL.mjs} +3 -5
  148. package/dist/{virtual-CVb9hRUU.d.mts → virtual-DwBiFA25.d.mts} +1 -2
  149. package/dist/{virtual-BEOqkQvm.mjs → virtual-eDNVH1fz.mjs} +3 -5
  150. package/package.json +40 -11
  151. package/dist/adapter-DcwxFryd.d.mts +0 -97
  152. package/dist/adapters-BGJKsBrw.mjs +0 -1
  153. package/dist/adapters-BQ-Lr3PW.mjs +0 -1
  154. package/dist/adapters-DEXpW9If.mjs +0 -1
  155. package/dist/adapters-Q9WaOsJp.mjs +0 -1
  156. package/dist/adapters-SSDVth5e.mjs +0 -1
  157. package/dist/constants-B8pMSkcW.mjs +0 -1
  158. package/dist/utilities-CcJtp9Gx.mjs +0 -429
  159. /package/dist/{adapter-CJIj5ySf.d.mts → adapter-JTFG3Jn8.d.mts} +0 -0
  160. /package/dist/{index-Bv1VN_j5.d.mts → index-B5ZDDkXv.d.mts} +0 -0
  161. /package/dist/{index-BDTbJClL.d.mts → index-NsE5nARK.d.mts} +0 -0
  162. /package/dist/{memory-DVjquu_v.d.mts → memory-BTtRdnNn.d.mts} +0 -0
@@ -1,16 +1,16 @@
1
- import { a as SUPPORTS_OBSERVER, i as SUPPORTS_MUTATION_OBSERVER, n as SUPPORTS_INTERSECTION_OBSERVER, r as SUPPORTS_MATCH_MEDIA, t as IN_BROWSER } from "./globals-D6FBsWDI.mjs";
2
- import { a as isElement, c as isNull, d as isObject, g as mergeDeep, h as isUndefined, l as isNullOrUndefined, o as isFunction, p as isString, t as clamp, u as isNumber, v as useId$1, y as instanceExists } from "./utilities-CcJtp9Gx.mjs";
3
- import { i as useContext, n as createContext, t as createTrinity } from "./createTrinity-Cii8-B2r.mjs";
4
- import { a as createPlugin, i as useLogger, o as createPluginContext } from "./useLogger-C8G5jgNk.mjs";
5
- import { i as createRegistry } from "./createTokens-Cu1efg9Z.mjs";
6
- import { i as createModel, t as createSelection } from "./createSelection-Zo4RQpYe.mjs";
7
- import { t as createSingle } from "./createSingle-BH9wNDrS.mjs";
8
- import { t as createGroup } from "./createGroup-CCb7Zfyw.mjs";
9
- import { t as toArray } from "./toArray-BBZH-G2X.mjs";
10
- import { a as useLocale } from "./useLocale-DJJmg-wv.mjs";
11
- import { t as MemoryAdapter } from "./memory-BsZGbGnG.mjs";
12
- import { computed, effectScope, isRef, nextTick, onScopeDispose, reactive, readonly, ref, shallowReactive, shallowReadonly, shallowRef, toRef, toValue, unref, watch, watchEffect } from "vue";
13
-
1
+ import { a as SUPPORTS_OBSERVER, i as SUPPORTS_MUTATION_OBSERVER, n as SUPPORTS_INTERSECTION_OBSERVER, r as SUPPORTS_MATCH_MEDIA, t as IN_BROWSER } from "./globals-ClSU6mqC.mjs";
2
+ import { clamp, instanceExists, isElement, isFunction, isNull, isNullOrUndefined, isNumber, isObject, isString, isUndefined, mergeDeep, useId as useId$1 } from "./utilities/index.mjs";
3
+ import { i as useContext, n as createContext, t as createTrinity } from "./createTrinity-C_c8eedz.mjs";
4
+ import { a as createPlugin, i as useLogger, o as createPluginContext } from "./useLogger-DY1Hbcy1.mjs";
5
+ import { i as createRegistry } from "./createTokens-CXlT0Vc6.mjs";
6
+ import { i as createModel, t as createSelection } from "./createSelection-8MX0OHXR.mjs";
7
+ import { t as createSingle } from "./createSingle-CbuOBb-E.mjs";
8
+ import { t as createGroup } from "./createGroup-BpJFi41X.mjs";
9
+ import { t as toArray } from "./toArray-VdROPpy-.mjs";
10
+ import { a as useLocale } from "./useLocale-cQlPxbpV.mjs";
11
+ import { a as useRules, o as isStandardSchema } from "./useRules-BbA6_gvs.mjs";
12
+ import { t as MemoryAdapter } from "./memory-XCMtkld1.mjs";
13
+ import { computed, effectScope, isRef, nextTick, onMounted, onScopeDispose, reactive, readonly, ref, shallowReactive, shallowReadonly, shallowRef, toRef, toValue, unref, watch, watchEffect } from "vue";
14
14
  //#region src/composables/createBreadcrumbs/index.ts
15
15
  /**
16
16
  * @module createBreadcrumbs
@@ -154,7 +154,6 @@ function createBreadcrumbsContext(_options = {}) {
154
154
  function useBreadcrumbs(namespace = "v0:breadcrumbs") {
155
155
  return useContext(namespace);
156
156
  }
157
-
158
157
  //#endregion
159
158
  //#region src/composables/useHydration/index.ts
160
159
  /**
@@ -244,7 +243,6 @@ const [createHydrationContext, createHydrationPlugin, useHydration] = createPlug
244
243
  } });
245
244
  }
246
245
  });
247
-
248
246
  //#endregion
249
247
  //#region src/composables/toElement/index.ts
250
248
  /**
@@ -279,7 +277,6 @@ function toElement(target) {
279
277
  if (raw instanceof Element) return raw;
280
278
  if ("$el" in raw) return raw.$el;
281
279
  }
282
-
283
280
  //#endregion
284
281
  //#region src/composables/createObserver/index.ts
285
282
  /**
@@ -365,7 +362,6 @@ function createObserver(target, userCallback, config) {
365
362
  stop
366
363
  };
367
364
  }
368
-
369
365
  //#endregion
370
366
  //#region src/composables/useResizeObserver/index.ts
371
367
  /**
@@ -503,7 +499,6 @@ function useElementSize(target) {
503
499
  stop
504
500
  };
505
501
  }
506
-
507
502
  //#endregion
508
503
  //#region src/composables/createOverflow/index.ts
509
504
  /**
@@ -696,7 +691,6 @@ function createOverflowContext(_options = {}) {
696
691
  function useOverflow(namespace = "v0:overflow") {
697
692
  return useContext(namespace);
698
693
  }
699
-
700
694
  //#endregion
701
695
  //#region src/composables/useProxyModel/index.ts
702
696
  /**
@@ -786,7 +780,6 @@ function useProxyModel(context, model, options) {
786
780
  onScopeDispose(stop, true);
787
781
  return stop;
788
782
  }
789
-
790
783
  //#endregion
791
784
  //#region src/composables/toReactive/index.ts
792
785
  /**
@@ -921,7 +914,6 @@ function toReactive(objectRef) {
921
914
  }
922
915
  }));
923
916
  }
924
-
925
917
  //#endregion
926
918
  //#region src/composables/useBreakpoints/index.ts
927
919
  /**
@@ -1055,6 +1047,7 @@ function createBreakpoints(_options = {}) {
1055
1047
  }
1056
1048
  return {
1057
1049
  breakpoints,
1050
+ mobileBreakpoint,
1058
1051
  name: readonly(name),
1059
1052
  width: readonly(width),
1060
1053
  height: readonly(height),
@@ -1081,8 +1074,10 @@ function createBreakpoints(_options = {}) {
1081
1074
  }
1082
1075
  function createBreakpointsFallback(options = {}) {
1083
1076
  if (options.ssr) return createBreakpoints(options);
1077
+ const defaults = createDefaultBreakpoints();
1084
1078
  return {
1085
- breakpoints: createDefaultBreakpoints().breakpoints,
1079
+ breakpoints: defaults.breakpoints,
1080
+ mobileBreakpoint: defaults.mobileBreakpoint,
1086
1081
  name: readonly(shallowRef("xs")),
1087
1082
  width: readonly(shallowRef(0)),
1088
1083
  height: readonly(shallowRef(0)),
@@ -1128,7 +1123,6 @@ const [createBreakpointsContext, createBreakpointsPlugin, useBreakpoints] = crea
1128
1123
  } });
1129
1124
  }
1130
1125
  });
1131
-
1132
1126
  //#endregion
1133
1127
  //#region src/composables/useDate/index.ts
1134
1128
  /**
@@ -1338,160 +1332,98 @@ function useDate(namespace = "v0:date") {
1338
1332
  if (!instanceExists()) throw new Error("[v0] useDate() must be called inside a Vue component with createDatePlugin installed.\n\nExample:\n import { Vuetify0DateAdapter } from '@vuetify/v0/date'\n import { createDatePlugin } from '@vuetify/v0'\n\n app.use(createDatePlugin({ adapter: new Vuetify0DateAdapter() }))");
1339
1333
  return useContext(namespace);
1340
1334
  }
1341
-
1342
1335
  //#endregion
1343
1336
  //#region src/composables/createForm/index.ts
1344
1337
  /**
1345
1338
  * @module createForm
1346
1339
  *
1347
1340
  * @remarks
1348
- * Form validation composable with async rule support and multiple validation modes.
1341
+ * Form composable that coordinates validation across multiple fields.
1349
1342
  *
1350
1343
  * Key features:
1351
- * - Sync and async validation rules
1352
- * - Multiple validation modes (submit, change, combined)
1353
- * - Tri-state isValid (null/true/false)
1354
- * - isPristine tracking
1355
- * - Silent validation mode
1356
- * - Form-level validation and reset
1357
- *
1358
- * Each field is registered with validation rules and tracks its own state independently.
1344
+ * - Pure registry of ValidationContext instances
1345
+ * - Validations auto-register via useForm() injection
1346
+ * - Form-level submit, reset, and aggregate state
1347
+ * - Exposes disabled/readonly refs for component consumption
1348
+ * - Trinity pattern for DI
1349
+ *
1350
+ * Per-field validation logic lives in createValidation.
1351
+ * createForm is the mothership it coordinates, not creates.
1359
1352
  */
1360
1353
  /**
1361
1354
  * Creates a new form instance.
1362
1355
  *
1356
+ * A form is a pure registry of validation contexts. Validations register
1357
+ * themselves via `useForm()` injection. The form coordinates submit, reset,
1358
+ * and aggregate state across all registered validations.
1359
+ *
1363
1360
  * @param options The options for the form instance.
1364
- * @template Z The type of the form ticket.
1365
- * @template E The type of the form context.
1366
- * @returns A new form instance.
1361
+ * @returns A new form context.
1367
1362
  *
1368
1363
  * @see https://0.vuetifyjs.com/composables/forms/create-form
1369
1364
  *
1370
1365
  * @example
1371
1366
  * ```ts
1372
- * import { createForm } from '@vuetify/v0'
1367
+ * import { createForm, createValidation } from '@vuetify/v0'
1368
+ * import { shallowRef } from 'vue'
1373
1369
  *
1374
1370
  * const form = createForm()
1375
1371
  *
1376
- * const username = form.register({
1377
- * id: 'username',
1378
- * value: '',
1379
- * rules: [(v) => v.length > 0 || 'Username is required'],
1372
+ * // Each validation is one input — form is just the coordinator
1373
+ * const email = shallowRef('')
1374
+ * const validation = createValidation({
1375
+ * value: email,
1376
+ * rules: ['required', 'email'],
1380
1377
  * })
1381
1378
  *
1382
- * await form.submit()
1383
- *
1384
- * console.log(username.errors.value) // ['Username is required']
1379
+ * form.register({ value: validation })
1385
1380
  *
1381
+ * await form.submit()
1386
1382
  * form.reset()
1387
1383
  * ```
1388
1384
  */
1389
- function createForm(options) {
1390
- const registry = createRegistry(options);
1391
- const validateOn = options?.validateOn || "submit";
1392
- function parse(value) {
1393
- return value.toLowerCase().split(/\s+/);
1394
- }
1385
+ function createForm(options = {}) {
1386
+ const { disabled = false, readonly = false, ..._options } = options;
1387
+ const registry = createRegistry({
1388
+ ..._options,
1389
+ reactive: true
1390
+ });
1395
1391
  const isValidating = computed(() => {
1396
- for (const ticket of registry.values()) if (ticket.isValidating.value) return true;
1392
+ for (const ticket of registry.values()) if (ticket.value.isValidating.value) return true;
1397
1393
  return false;
1398
1394
  });
1399
1395
  const isValid = computed(() => {
1396
+ let hasNull = false;
1400
1397
  let hasFields = false;
1401
1398
  for (const ticket of registry.values()) {
1402
1399
  hasFields = true;
1403
- if (ticket.isValid.value === false) return false;
1404
- if (/* @__PURE__ */ isNull(ticket.isValid.value)) return null;
1400
+ if (ticket.value.isValid.value === false) return false;
1401
+ if (/* @__PURE__ */ isNull(ticket.value.isValid.value)) hasNull = true;
1405
1402
  }
1406
- return hasFields ? true : null;
1403
+ if (!hasFields) return null;
1404
+ return hasNull ? null : true;
1407
1405
  });
1408
- function reset() {
1409
- for (const ticket of registry.values()) ticket.reset();
1410
- }
1411
- async function submit() {
1412
- return validate([...registry.keys()]);
1413
- }
1414
- async function validate(id) {
1415
- const validating = toArray(id);
1416
- return (await Promise.all(validating.map(async (id$1) => await registry.get(id$1)?.validate() ?? true))).every(Boolean);
1417
- }
1418
1406
  function register(registration) {
1419
- const model = shallowRef(/* @__PURE__ */ isNullOrUndefined(registration.value) ? "" : toValue(registration.value));
1420
- const rules = registration.rules || [];
1421
- const errors = shallowRef([]);
1422
- const isValidating$1 = shallowRef(false);
1423
- const initialValue = model.value;
1424
- const triggers = registration.validateOn || validateOn;
1425
- const isPristine = shallowRef(true);
1426
- const isValid$1 = shallowRef(null);
1427
- function _validatesOn(event) {
1428
- return parse(triggers).includes(event);
1429
- }
1430
- function _reset() {
1431
- model.value = initialValue;
1432
- errors.value = [];
1433
- isPristine.value = true;
1434
- isValid$1.value = null;
1435
- isValidating$1.value = false;
1436
- validationGeneration++;
1437
- }
1438
- let validationGeneration = 0;
1439
- async function validate$1(silent = false) {
1440
- if (rules.length === 0) return isValid$1.value = true;
1441
- const generation = ++validationGeneration;
1442
- isValidating$1.value = true;
1443
- try {
1444
- const results = await Promise.all(rules.map((rule) => rule(model.value)));
1445
- if (generation !== validationGeneration) return isValid$1.value ?? false;
1446
- const errorMessages = results.filter((result) => /* @__PURE__ */ isString(result));
1447
- if (!silent) {
1448
- errors.value = errorMessages;
1449
- isValid$1.value = errorMessages.length === 0;
1450
- isPristine.value = toValue(model) === initialValue;
1451
- }
1452
- return errorMessages.length === 0;
1453
- } finally {
1454
- if (generation === validationGeneration) isValidating$1.value = false;
1455
- }
1456
- }
1457
- const item = {
1458
- ...registration,
1459
- rules,
1460
- errors,
1461
- disabled: registration.disabled || false,
1462
- validateOn: triggers,
1463
- isValidating: isValidating$1,
1464
- isPristine,
1465
- isValid: isValid$1,
1466
- reset: _reset,
1467
- validate: validate$1
1468
- };
1469
- const ticket = registry.register(item);
1470
- Object.defineProperty(ticket, "value", {
1471
- get() {
1472
- return model.value;
1473
- },
1474
- set(val) {
1475
- model.value = val;
1476
- isPristine.value = val === initialValue;
1477
- isValid$1.value = null;
1478
- if (_validatesOn("change")) validate$1();
1479
- },
1480
- enumerable: true,
1481
- configurable: true
1482
- });
1483
- return ticket;
1407
+ return registry.register(registration);
1484
1408
  }
1485
- function onboard(registrations) {
1486
- return registry.batch(() => registrations.map((r) => register(r)));
1409
+ function reset() {
1410
+ for (const ticket of registry.values()) ticket.value.reset();
1411
+ }
1412
+ async function submit(id) {
1413
+ const ids = id ? toArray(id) : [...registry.keys()];
1414
+ return (await Promise.all(ids.map(async (key) => {
1415
+ const ticket = registry.get(key);
1416
+ if (!ticket) return true;
1417
+ return ticket.value.validate();
1418
+ }))).every(Boolean);
1487
1419
  }
1488
1420
  return {
1489
1421
  ...registry,
1490
1422
  register,
1491
- onboard,
1492
- reset,
1493
1423
  submit,
1494
- validateOn,
1424
+ reset,
1425
+ disabled,
1426
+ readonly,
1495
1427
  isValid,
1496
1428
  isValidating,
1497
1429
  get size() {
@@ -1500,12 +1432,10 @@ function createForm(options) {
1500
1432
  };
1501
1433
  }
1502
1434
  /**
1503
- * Creates a new form context.
1435
+ * Creates a new form context using the Trinity pattern.
1504
1436
  *
1505
1437
  * @param options The options for the form context.
1506
- * @template Z The type of the form ticket.
1507
- * @template E The type of the form context.
1508
- * @returns A new form context.
1438
+ * @returns A Trinity tuple: [useFormContext, provideFormContext, formContext]
1509
1439
  *
1510
1440
  * @see https://0.vuetifyjs.com/composables/forms/create-form
1511
1441
  *
@@ -1513,21 +1443,7 @@ function createForm(options) {
1513
1443
  * ```ts
1514
1444
  * import { createFormContext } from '@vuetify/v0'
1515
1445
  *
1516
- * // With default namespace 'v0:form'
1517
- * export const [useMyForm, provideMyForm, myForm] = createFormContext({ validateOn: 'change' })
1518
- *
1519
- * // Or with custom namespace
1520
- * export const [useMyForm, provideMyForm, myForm] = createFormContext({
1521
- * namespace: 'my-form',
1522
- * validateOn: 'change',
1523
- * })
1524
- *
1525
- * // In a parent component:
1526
- * provideMyForm()
1527
- *
1528
- * // In a child component:
1529
- * const form = useMyForm()
1530
- * form.register({ id: 'field', value: ref(''), rules: [...] })
1446
+ * export const [useMyForm, provideMyForm, myForm] = createFormContext()
1531
1447
  * ```
1532
1448
  */
1533
1449
  function createFormContext(_options = {}) {
@@ -1543,7 +1459,7 @@ function createFormContext(_options = {}) {
1543
1459
  * Returns the current form instance.
1544
1460
  *
1545
1461
  * @param namespace The namespace for the form context. Defaults to `'v0:form'`.
1546
- * @returns The current form instance.
1462
+ * @returns The current form instance, or undefined if not provided.
1547
1463
  *
1548
1464
  * @see https://0.vuetifyjs.com/composables/forms/create-form
1549
1465
  *
@@ -1554,18 +1470,15 @@ function createFormContext(_options = {}) {
1554
1470
  *
1555
1471
  * const form = useForm()
1556
1472
  * <\/script>
1557
- *
1558
- * <template>
1559
- * <div>
1560
- * <p>Form is {{ form.isValid.value ? 'valid' : 'invalid' }}</p>
1561
- * </div>
1562
- * </template>
1563
1473
  * ```
1564
1474
  */
1565
1475
  function useForm(namespace = "v0:form") {
1566
- return useContext(namespace);
1476
+ try {
1477
+ return useContext(namespace);
1478
+ } catch {
1479
+ return;
1480
+ }
1567
1481
  }
1568
-
1569
1482
  //#endregion
1570
1483
  //#region src/composables/useHotkey/aliases.ts
1571
1484
  /**
@@ -1597,7 +1510,6 @@ function normalizeKey(key) {
1597
1510
  const lowerKey = key.toLowerCase();
1598
1511
  return keyAliasMap[lowerKey] ?? lowerKey;
1599
1512
  }
1600
-
1601
1513
  //#endregion
1602
1514
  //#region src/composables/useHotkey/parsing.ts
1603
1515
  const logger = useLogger();
@@ -1754,7 +1666,6 @@ function splitKeySequence(str) {
1754
1666
  /* v8 ignore stop */
1755
1667
  return collapsed;
1756
1668
  }
1757
-
1758
1669
  //#endregion
1759
1670
  //#region src/composables/useHotkey/index.ts
1760
1671
  /**
@@ -1945,7 +1856,6 @@ function matchesKeyGroup(e, group, platformIsMac) {
1945
1856
  if (/* @__PURE__ */ isUndefined(actualKey)) return modifiersMatch;
1946
1857
  return modifiersMatch && e.key.toLowerCase() === actualKey.toLowerCase();
1947
1858
  }
1948
-
1949
1859
  //#endregion
1950
1860
  //#region src/composables/useIntersectionObserver/index.ts
1951
1861
  /**
@@ -2104,7 +2014,6 @@ function useElementIntersection(target, options = {}) {
2104
2014
  stop
2105
2015
  };
2106
2016
  }
2107
-
2108
2017
  //#endregion
2109
2018
  //#region src/composables/useLazy/index.ts
2110
2019
  /**
@@ -2189,7 +2098,6 @@ function useLazy(active, options = {}) {
2189
2098
  onAfterLeave
2190
2099
  };
2191
2100
  }
2192
-
2193
2101
  //#endregion
2194
2102
  //#region src/composables/useMediaQuery/index.ts
2195
2103
  /**
@@ -2306,7 +2214,6 @@ function usePrefersReducedMotion() {
2306
2214
  function usePrefersContrast() {
2307
2215
  return useMediaQuery("(prefers-contrast: more)");
2308
2216
  }
2309
-
2310
2217
  //#endregion
2311
2218
  //#region src/composables/useMutationObserver/index.ts
2312
2219
  /**
@@ -2417,7 +2324,6 @@ function useMutationObserver(target, callback, options = {}) {
2417
2324
  onceIncludesImmediate: true
2418
2325
  });
2419
2326
  }
2420
-
2421
2327
  //#endregion
2422
2328
  //#region src/composables/createNested/strategies.ts
2423
2329
  /**
@@ -2459,7 +2365,6 @@ const singleOpenStrategy = {
2459
2365
  },
2460
2366
  onClose: void 0
2461
2367
  };
2462
-
2463
2368
  //#endregion
2464
2369
  //#region src/composables/createNested/index.ts
2465
2370
  /**
@@ -2526,7 +2431,7 @@ function createNested(_options = {}) {
2526
2431
  const multipleOption = _options.multiple ?? true;
2527
2432
  const resolvedOpenStrategy = openStrategy ?? resolveOpenStrategy(openMode);
2528
2433
  const group = createGroup(options);
2529
- const logger$1 = useLogger();
2434
+ const logger = useLogger();
2530
2435
  const children = shallowReactive(/* @__PURE__ */ new Map());
2531
2436
  const parents = shallowReactive(/* @__PURE__ */ new Map());
2532
2437
  const openedIds = shallowReactive(/* @__PURE__ */ new Set());
@@ -2810,7 +2715,7 @@ function createNested(_options = {}) {
2810
2715
  const id = registration.id ?? /* @__PURE__ */ useId$1();
2811
2716
  const parentId = registration.parentId;
2812
2717
  const nested = registration.children;
2813
- if (!/* @__PURE__ */ isUndefined(parentId) && !group.has(parentId)) logger$1.warn(`Parent with id "${parentId}" does not exist. Registering "${id}" without parent.`);
2718
+ if (!/* @__PURE__ */ isUndefined(parentId) && !group.has(parentId)) logger.warn(`Parent with id "${parentId}" does not exist. Registering "${id}" without parent.`);
2814
2719
  if (!/* @__PURE__ */ isUndefined(parentId) && group.has(parentId)) {
2815
2720
  if (batching) {
2816
2721
  pendingParents.set(id, parentId);
@@ -2869,9 +2774,9 @@ function createNested(_options = {}) {
2869
2774
  if (!group.has(id)) return;
2870
2775
  const parentId = parents.get(id);
2871
2776
  if (!/* @__PURE__ */ isUndefined(parentId)) {
2872
- const siblings$1 = children.get(parentId);
2873
- if (siblings$1) {
2874
- const filtered = siblings$1.filter((sid) => sid !== id);
2777
+ const siblings = children.get(parentId);
2778
+ if (siblings) {
2779
+ const filtered = siblings.filter((sid) => sid !== id);
2875
2780
  if (filtered.length === 0) children.delete(parentId);
2876
2781
  else children.set(parentId, filtered);
2877
2782
  }
@@ -3029,7 +2934,83 @@ function createNestedContext(_options = {}) {
3029
2934
  function useNested(namespace = "v0:nested") {
3030
2935
  return useContext(namespace);
3031
2936
  }
3032
-
2937
+ //#endregion
2938
+ //#region src/composables/usePopover/index.ts
2939
+ /**
2940
+ * @module usePopover
2941
+ *
2942
+ * @remarks
2943
+ * Composable for native popover API behavior with CSS anchor positioning.
2944
+ * Manages open/close state, anchor styles, content attributes, and
2945
+ * bidirectional sync between reactive state and native popover events.
2946
+ *
2947
+ * Key features:
2948
+ * - Native popover API (showPopover/hidePopover)
2949
+ * - CSS anchor positioning (position-area, position-try-fallbacks)
2950
+ * - Toggle event sync for native state changes
2951
+ * - SSR-safe (no DOM ops outside browser)
2952
+ * - Optional external isOpen ref for v-model integration
2953
+ *
2954
+ * Perfect for building select, combobox, tooltip, and menu components
2955
+ * without wrapping the Popover compound component.
2956
+ */
2957
+ function usePopover(options = {}) {
2958
+ const { id: _id, positionArea = "bottom", positionTry = "most-width bottom" } = options;
2959
+ const id = _id ?? /* @__PURE__ */ useId$1();
2960
+ const isOpen = options.isOpen ?? shallowRef(false);
2961
+ function open() {
2962
+ isOpen.value = true;
2963
+ }
2964
+ function close() {
2965
+ isOpen.value = false;
2966
+ }
2967
+ function toggle() {
2968
+ isOpen.value = !isOpen.value;
2969
+ }
2970
+ const anchorStyles = toRef(() => ({ anchorName: `--${id}` }));
2971
+ const contentAttrs = toRef(() => ({
2972
+ id,
2973
+ popover: ""
2974
+ }));
2975
+ const contentStyles = toRef(() => ({
2976
+ "position": "fixed",
2977
+ "margin": "unset",
2978
+ "inset-area": positionArea,
2979
+ "position-area": positionArea,
2980
+ "position-anchor": `--${id}`,
2981
+ "position-try-fallbacks": positionTry
2982
+ }));
2983
+ /* v8 ignore start -- browser popover API */
2984
+ function attach(el) {
2985
+ onMounted(() => {
2986
+ const element = toValue(el);
2987
+ if (isOpen.value) element?.showPopover();
2988
+ });
2989
+ watch(isOpen, (value) => {
2990
+ const element = toValue(el);
2991
+ if (!element?.isConnected) return;
2992
+ if (value === element.matches?.(":popover-open")) return;
2993
+ if (value) element.showPopover?.();
2994
+ else element.hidePopover?.();
2995
+ });
2996
+ useEventListener(el, "toggle", (e) => {
2997
+ if (!toValue(el)?.isConnected) return;
2998
+ isOpen.value = e.newState === "open";
2999
+ });
3000
+ }
3001
+ /* v8 ignore stop */
3002
+ return {
3003
+ isOpen,
3004
+ id,
3005
+ open,
3006
+ close,
3007
+ toggle,
3008
+ anchorStyles,
3009
+ contentAttrs,
3010
+ contentStyles,
3011
+ attach
3012
+ };
3013
+ }
3033
3014
  //#endregion
3034
3015
  //#region src/composables/createQueue/index.ts
3035
3016
  /**
@@ -3094,7 +3075,7 @@ function createQueue(_options = {}) {
3094
3075
  }, ticket.timeout);
3095
3076
  timeouts.set(ticket.id, timeout);
3096
3077
  }
3097
- function clearTimeout$1(id) {
3078
+ function clearTimeout(id) {
3098
3079
  const timeout = timeouts.get(id);
3099
3080
  if (timeout) {
3100
3081
  globalThis.clearTimeout(timeout);
@@ -3119,7 +3100,7 @@ function createQueue(_options = {}) {
3119
3100
  const ticket = /* @__PURE__ */ isUndefined(id) ? registry.seek("first") : registry.get(id);
3120
3101
  if (!ticket) return void 0;
3121
3102
  const wasFirst = ticket.index === 0;
3122
- clearTimeout$1(ticket.id);
3103
+ clearTimeout(ticket.id);
3123
3104
  registry.unregister(ticket.id);
3124
3105
  if (wasFirst) resume();
3125
3106
  return ticket;
@@ -3130,7 +3111,7 @@ function createQueue(_options = {}) {
3130
3111
  const ticket = registry.get(id);
3131
3112
  if (!ticket) continue;
3132
3113
  if (ticket.index === 0) hadFirst = true;
3133
- clearTimeout$1(ticket.id);
3114
+ clearTimeout(ticket.id);
3134
3115
  }
3135
3116
  registry.offboard(ids);
3136
3117
  if (hadFirst) resume();
@@ -3138,7 +3119,7 @@ function createQueue(_options = {}) {
3138
3119
  function pause() {
3139
3120
  const ticket = registry.seek("first");
3140
3121
  if (!ticket || ticket.isPaused) return void 0;
3141
- clearTimeout$1(ticket.id);
3122
+ clearTimeout(ticket.id);
3142
3123
  return registry.upsert(ticket.id, { isPaused: true });
3143
3124
  }
3144
3125
  function resume() {
@@ -3149,7 +3130,7 @@ function createQueue(_options = {}) {
3149
3130
  return updated;
3150
3131
  }
3151
3132
  function clear() {
3152
- for (const id of timeouts.keys()) clearTimeout$1(id);
3133
+ for (const id of timeouts.keys()) clearTimeout(id);
3153
3134
  registry.clear();
3154
3135
  }
3155
3136
  function dispose() {
@@ -3223,7 +3204,300 @@ function createQueueContext(_options = {}) {
3223
3204
  function useQueue(namespace = "v0:queue") {
3224
3205
  return useContext(namespace);
3225
3206
  }
3226
-
3207
+ //#endregion
3208
+ //#region src/composables/createFocusTraversal/index.ts
3209
+ /**
3210
+ * @module createFocusTraversal
3211
+ *
3212
+ * @remarks
3213
+ * Internal factory for keyboard-driven traversal of ordered item lists.
3214
+ * Encapsulates stride-based navigation, disabled-item skipping, circular/bounded
3215
+ * movement, grid row scoping, and key-to-action mapping shared by
3216
+ * useRovingFocus and useVirtualFocus.
3217
+ *
3218
+ * Not exported from the package barrel — consumed only by sibling composables.
3219
+ */
3220
+ function mod(length, index) {
3221
+ return (index % length + length) % length;
3222
+ }
3223
+ function isRtl(e) {
3224
+ if (!IN_BROWSER) return false;
3225
+ const el = e.currentTarget;
3226
+ return el ? getComputedStyle(el).direction === "rtl" : false;
3227
+ }
3228
+ function createFocusTraversal(items, activate, options = {}) {
3229
+ const { orientation = "vertical", circular = false, columns: _columns } = options;
3230
+ const activeId = shallowRef();
3231
+ function enabled() {
3232
+ return items().filter((item) => !toValue(item.disabled));
3233
+ }
3234
+ function indexOf(id) {
3235
+ return items().findIndex((item) => item.id === id);
3236
+ }
3237
+ function go(id) {
3238
+ activeId.value = id;
3239
+ activate(id);
3240
+ }
3241
+ function step(stride) {
3242
+ const all = items();
3243
+ const length = all.length;
3244
+ if (!length) return;
3245
+ const current = /* @__PURE__ */ isUndefined(activeId.value) ? -1 : indexOf(activeId.value);
3246
+ const direction = stride > 0 ? 1 : -1;
3247
+ const absStride = Math.abs(stride);
3248
+ let index = current + stride;
3249
+ const maxHops = Math.ceil(length / absStride);
3250
+ let hops = 0;
3251
+ if (circular) index = mod(length, index);
3252
+ else if (index < 0 || index >= length) return;
3253
+ while (hops < maxHops) {
3254
+ const item = all[index];
3255
+ if (item && !toValue(item.disabled)) {
3256
+ go(item.id);
3257
+ return;
3258
+ }
3259
+ hops++;
3260
+ index = circular ? mod(length, index + stride) : index + direction * absStride;
3261
+ if (!circular && (index < 0 || index >= length)) return;
3262
+ }
3263
+ }
3264
+ function next() {
3265
+ step(1);
3266
+ }
3267
+ function prev() {
3268
+ step(-1);
3269
+ }
3270
+ function first() {
3271
+ const list = enabled();
3272
+ if (list.length > 0) go(list[0].id);
3273
+ }
3274
+ function last() {
3275
+ const list = enabled();
3276
+ if (list.length > 0) go(list.at(-1).id);
3277
+ }
3278
+ /** Focus first non-disabled item in the current row (grid mode) */
3279
+ function rowFirst() {
3280
+ const cols = toValue(_columns) ?? 0;
3281
+ if (!cols) return first();
3282
+ const all = items();
3283
+ const current = /* @__PURE__ */ isUndefined(activeId.value) ? 0 : indexOf(activeId.value);
3284
+ const rowStart = current - current % cols;
3285
+ const rowEnd = Math.min(rowStart + cols, all.length);
3286
+ for (let i = rowStart; i < rowEnd; i++) {
3287
+ const item = all[i];
3288
+ if (item && !toValue(item.disabled)) {
3289
+ go(item.id);
3290
+ return;
3291
+ }
3292
+ }
3293
+ }
3294
+ /** Focus last non-disabled item in the current row (grid mode) */
3295
+ function rowLast() {
3296
+ const cols = toValue(_columns) ?? 0;
3297
+ if (!cols) return last();
3298
+ const all = items();
3299
+ const current = /* @__PURE__ */ isUndefined(activeId.value) ? 0 : indexOf(activeId.value);
3300
+ const rowStart = current - current % cols;
3301
+ const rowEnd = Math.min(rowStart + cols, all.length);
3302
+ for (let i = rowEnd - 1; i >= rowStart; i--) {
3303
+ const item = all[i];
3304
+ if (item && !toValue(item.disabled)) {
3305
+ go(item.id);
3306
+ return;
3307
+ }
3308
+ }
3309
+ }
3310
+ function onKeydown(e) {
3311
+ const cols = toValue(_columns);
3312
+ const rtl = isRtl(e);
3313
+ if (cols) {
3314
+ switch (e.key) {
3315
+ case "ArrowRight":
3316
+ e.preventDefault();
3317
+ step(rtl ? -1 : 1);
3318
+ break;
3319
+ case "ArrowLeft":
3320
+ e.preventDefault();
3321
+ step(rtl ? 1 : -1);
3322
+ break;
3323
+ case "ArrowDown":
3324
+ e.preventDefault();
3325
+ step(cols);
3326
+ break;
3327
+ case "ArrowUp":
3328
+ e.preventDefault();
3329
+ step(-cols);
3330
+ break;
3331
+ case "Home":
3332
+ e.preventDefault();
3333
+ if (e.ctrlKey) first();
3334
+ else rowFirst();
3335
+ break;
3336
+ case "End":
3337
+ e.preventDefault();
3338
+ if (e.ctrlKey) last();
3339
+ else rowLast();
3340
+ break;
3341
+ }
3342
+ return;
3343
+ }
3344
+ const prevKeys = [];
3345
+ const nextKeys = [];
3346
+ if (orientation === "vertical" || orientation === "both") {
3347
+ prevKeys.push("ArrowUp");
3348
+ nextKeys.push("ArrowDown");
3349
+ }
3350
+ if (orientation === "horizontal" || orientation === "both") {
3351
+ prevKeys.push(rtl ? "ArrowRight" : "ArrowLeft");
3352
+ nextKeys.push(rtl ? "ArrowLeft" : "ArrowRight");
3353
+ }
3354
+ if (prevKeys.includes(e.key)) {
3355
+ e.preventDefault();
3356
+ prev();
3357
+ } else if (nextKeys.includes(e.key)) {
3358
+ e.preventDefault();
3359
+ next();
3360
+ } else if (e.key === "Home") {
3361
+ e.preventDefault();
3362
+ first();
3363
+ } else if (e.key === "End") {
3364
+ e.preventDefault();
3365
+ last();
3366
+ }
3367
+ }
3368
+ return {
3369
+ activeId,
3370
+ step,
3371
+ next,
3372
+ prev,
3373
+ first,
3374
+ last,
3375
+ onKeydown
3376
+ };
3377
+ }
3378
+ //#endregion
3379
+ //#region src/composables/useRovingFocus/index.ts
3380
+ /**
3381
+ * @module useRovingFocus
3382
+ *
3383
+ * @remarks
3384
+ * Roving tabindex composable for keyboard navigation within composite widgets.
3385
+ *
3386
+ * Key features:
3387
+ * - Arrow key navigation with orientation support
3388
+ * - Grid mode for 2D navigation (data tables, calendars)
3389
+ * - Automatic disabled item skipping
3390
+ * - Optional circular navigation
3391
+ * - Home/End key support (row-scoped in grid mode)
3392
+ * - Auto-attaches keydown listener when target is provided
3393
+ *
3394
+ * Perfect for toolbars, menus, tree items, grids, and other composite widgets.
3395
+ */
3396
+ function useRovingFocus(items, options = {}) {
3397
+ const { orientation, circular, columns, onFocus, target } = options;
3398
+ function applyFocus(id) {
3399
+ const item = items().find((i) => i.id === id);
3400
+ if (!item?.el) return false;
3401
+ onFocus?.(id);
3402
+ nextTick(() => {
3403
+ toValue(item.el)?.focus();
3404
+ });
3405
+ return true;
3406
+ }
3407
+ const traversal = createFocusTraversal(items, (id) => applyFocus(id), {
3408
+ orientation,
3409
+ circular,
3410
+ columns
3411
+ });
3412
+ function focus(id) {
3413
+ const prev = traversal.activeId.value;
3414
+ traversal.activeId.value = id;
3415
+ if (!applyFocus(id)) traversal.activeId.value = prev;
3416
+ }
3417
+ function enabled() {
3418
+ return items().filter((item) => !toValue(item.disabled));
3419
+ }
3420
+ function isTabbable(id) {
3421
+ if (!/* @__PURE__ */ isUndefined(traversal.activeId.value)) return traversal.activeId.value === id;
3422
+ const list = enabled();
3423
+ return list.length > 0 && list[0]?.id === id;
3424
+ }
3425
+ if (target) useEventListener(target, "keydown", traversal.onKeydown);
3426
+ return {
3427
+ focusedId: traversal.activeId,
3428
+ isTabbable,
3429
+ focus,
3430
+ next: traversal.next,
3431
+ prev: traversal.prev,
3432
+ first: traversal.first,
3433
+ last: traversal.last,
3434
+ onKeydown: traversal.onKeydown
3435
+ };
3436
+ }
3437
+ //#endregion
3438
+ //#region src/composables/useRtl/adapters/v0.ts
3439
+ var Vuetify0RtlAdapter = class {
3440
+ setup(app, context, target) {
3441
+ if (IN_BROWSER) {
3442
+ if (/* @__PURE__ */ isNull(target)) return;
3443
+ const targetEl = target instanceof HTMLElement ? target : /* @__PURE__ */ isString(target) ? document.querySelector(target) : document.documentElement;
3444
+ if (!targetEl) return;
3445
+ targetEl.dir = context.isRtl.value ? "rtl" : "ltr";
3446
+ onScopeDispose(watch(context.isRtl, (value) => {
3447
+ targetEl.dir = value ? "rtl" : "ltr";
3448
+ }), true);
3449
+ } else {
3450
+ const head = app._context?.provides?.usehead ?? app._context?.provides?.head;
3451
+ if (head?.push) head.push({ htmlAttrs: { dir: context.isRtl.value ? "rtl" : "ltr" } });
3452
+ }
3453
+ }
3454
+ };
3455
+ //#endregion
3456
+ //#region src/composables/useRtl/index.ts
3457
+ /**
3458
+ * @module useRtl
3459
+ *
3460
+ * @remarks
3461
+ * RTL (right-to-left) direction composable with adapter pattern.
3462
+ *
3463
+ * Key features:
3464
+ * - Reactive boolean direction state
3465
+ * - Plugin trinity pattern (createRtlContext, createRtlPlugin, useRtl)
3466
+ * - Adapter pattern for DOM integration (dir attribute)
3467
+ * - Subtree overrides via context provision
3468
+ *
3469
+ * Independent from useLocale — Vuetify connects them via adapter.
3470
+ */
3471
+ /**
3472
+ * Creates a new RTL direction instance.
3473
+ *
3474
+ * @param options The options for the RTL instance.
3475
+ * @returns A new RTL context with reactive direction state.
3476
+ *
3477
+ * @see https://0.vuetifyjs.com/composables/plugins/use-rtl
3478
+ */
3479
+ function createRtl(options = {}) {
3480
+ const isRtl = shallowRef(options.default ?? false);
3481
+ function toggle() {
3482
+ isRtl.value = !isRtl.value;
3483
+ }
3484
+ return {
3485
+ isRtl,
3486
+ toggle
3487
+ };
3488
+ }
3489
+ function createRtlFallback() {
3490
+ return {
3491
+ isRtl: shallowRef(false),
3492
+ toggle: () => {}
3493
+ };
3494
+ }
3495
+ const [createRtlContext, createRtlPlugin, useRtl] = createPluginContext("v0:rtl", (options) => createRtl(options), {
3496
+ fallback: () => createRtlFallback(),
3497
+ setup: (context, app, { adapter = new Vuetify0RtlAdapter(), target }) => {
3498
+ adapter.setup(app, context, target);
3499
+ }
3500
+ });
3227
3501
  //#endregion
3228
3502
  //#region src/composables/createSlider/index.ts
3229
3503
  /**
@@ -3300,7 +3574,7 @@ function createSlider(options = {}) {
3300
3574
  events: true
3301
3575
  });
3302
3576
  const disabled = toRef(() => toValue(disabledProp));
3303
- const readonly$1 = toRef(() => toValue(readonlyProp));
3577
+ const readonly = toRef(() => toValue(readonlyProp));
3304
3578
  const orientation = toRef(() => toValue(orientationProp));
3305
3579
  const inverted = toRef(() => toValue(invertedProp));
3306
3580
  const extent = max - min;
@@ -3352,7 +3626,7 @@ function createSlider(options = {}) {
3352
3626
  }
3353
3627
  }
3354
3628
  function set(index, value) {
3355
- if (readonly$1.value) return;
3629
+ if (readonly.value) return;
3356
3630
  const snapped = snap(value);
3357
3631
  const current = values.value;
3358
3632
  let constrained = snapped;
@@ -3391,7 +3665,7 @@ function createSlider(options = {}) {
3391
3665
  minStepsBetweenThumbs,
3392
3666
  crossover,
3393
3667
  disabled,
3394
- readonly: readonly$1,
3668
+ readonly,
3395
3669
  orientation,
3396
3670
  inverted,
3397
3671
  register,
@@ -3408,7 +3682,6 @@ function createSlider(options = {}) {
3408
3682
  }
3409
3683
  };
3410
3684
  }
3411
-
3412
3685
  //#endregion
3413
3686
  //#region src/composables/useStack/index.ts
3414
3687
  /**
@@ -3459,9 +3732,9 @@ function createStack(_options = {}) {
3459
3732
  });
3460
3733
  const isActive = toRef(() => selection.selectedIds.size > 0);
3461
3734
  const top = toRef(() => {
3462
- const ids$1 = Array.from(selection.selectedIds);
3463
- if (ids$1.length === 0) return void 0;
3464
- return selection.get(ids$1.at(-1));
3735
+ const ids = Array.from(selection.selectedIds);
3736
+ if (ids.length === 0) return void 0;
3737
+ return selection.get(ids.at(-1));
3465
3738
  });
3466
3739
  const scrimZIndex = toRef(() => {
3467
3740
  const ticket = top.value;
@@ -3635,7 +3908,6 @@ function useStack(namespace = "v0:stack") {
3635
3908
  return fallback;
3636
3909
  }
3637
3910
  }
3638
-
3639
3911
  //#endregion
3640
3912
  //#region src/composables/createStep/index.ts
3641
3913
  /**
@@ -3836,7 +4108,6 @@ function createStepContext(_options = {}) {
3836
4108
  function useStep(namespace = "v0:step") {
3837
4109
  return useContext(namespace);
3838
4110
  }
3839
-
3840
4111
  //#endregion
3841
4112
  //#region src/composables/useStorage/index.ts
3842
4113
  /**
@@ -3894,7 +4165,7 @@ function createStorage(options = {}) {
3894
4165
  if (!raw) return void 0;
3895
4166
  try {
3896
4167
  const parsed = serializer.read(raw);
3897
- if (ttl && parsed && typeof parsed === "object" && "__ttl" in parsed && "__v" in parsed) {
4168
+ if (ttl && /* @__PURE__ */ isObject(parsed) && "__ttl" in parsed && "__v" in parsed) {
3898
4169
  if (Date.now() - parsed.__t > ttl) {
3899
4170
  adapter?.removeItem(prefixedKey);
3900
4171
  return;
@@ -3959,7 +4230,7 @@ function createStorage(options = {}) {
3959
4230
  const valueRef = cache.get(e.key);
3960
4231
  if (!valueRef) return;
3961
4232
  watchers.get(e.key)?.();
3962
- valueRef.value = e.newValue == null ? void 0 : readStored(e.key);
4233
+ valueRef.value = /* @__PURE__ */ isNullOrUndefined(e.newValue) ? void 0 : readStored(e.key);
3963
4234
  const stop = watch(valueRef, (newValue) => {
3964
4235
  if (/* @__PURE__ */ isNullOrUndefined(newValue)) adapter?.removeItem(e.key);
3965
4236
  else writeStored(e.key, newValue);
@@ -3978,7 +4249,6 @@ function createStorageFallback() {
3978
4249
  return createStorage({ adapter: new MemoryAdapter() });
3979
4250
  }
3980
4251
  const [createStorageContext, createStoragePlugin, useStorage] = createPluginContext("v0:storage", (options) => createStorage(options), { fallback: () => createStorageFallback() });
3981
-
3982
4252
  //#endregion
3983
4253
  //#region src/composables/createTimeline/index.ts
3984
4254
  /**
@@ -4127,7 +4397,127 @@ function createTimelineContext(_options = {}) {
4127
4397
  function useTimeline(namespace = "v0:timeline") {
4128
4398
  return useContext(namespace);
4129
4399
  }
4130
-
4400
+ //#endregion
4401
+ //#region src/composables/createValidation/index.ts
4402
+ /**
4403
+ * @module createValidation
4404
+ *
4405
+ * @remarks
4406
+ * Per-input validation composable built on createGroup.
4407
+ *
4408
+ * Key features:
4409
+ * - Each ticket is a rule — enable/disable via select/unselect
4410
+ * - Auto-register with parent form via useForm() injection
4411
+ * - Async rule support with generation-based race safety
4412
+ * - Silent validation mode
4413
+ * - Tri-state isValid (null/true/false)
4414
+ *
4415
+ * Uses useRules() to resolve alias strings via shared context.
4416
+ */
4417
+ const UNSET = Symbol("unset");
4418
+ /**
4419
+ * Creates a per-input validation instance.
4420
+ *
4421
+ * Built on `createGroup` — each registered rule becomes a ticket that can be
4422
+ * enabled/disabled via selection methods (`select`, `unselect`, `toggle`).
4423
+ * Only selected (active) rules run during validation.
4424
+ *
4425
+ * @param options The options for the validation instance.
4426
+ * @returns A new validation context.
4427
+ *
4428
+ * @see https://0.vuetifyjs.com/composables/forms/create-validation
4429
+ *
4430
+ * @example
4431
+ * ```ts
4432
+ * import { createValidation } from '@vuetify/v0'
4433
+ *
4434
+ * const validation = createValidation({
4435
+ * rules: [
4436
+ * v => !!v || 'Required',
4437
+ * v => /^.+@\S+\.\S+$/.test(String(v)) || 'Invalid email',
4438
+ * ],
4439
+ * })
4440
+ *
4441
+ * await validation.validate('')
4442
+ *
4443
+ * console.log(validation.errors.value) // ['Required', 'Invalid email']
4444
+ *
4445
+ * validation.reset()
4446
+ * ```
4447
+ */
4448
+ function createValidation(_options = {}) {
4449
+ const { rules: initialRules = [], value: valueSource, enroll = true, ...options } = _options;
4450
+ const group = createGroup({
4451
+ ...options,
4452
+ enroll,
4453
+ multiple: true
4454
+ });
4455
+ const rulesContext = useRules();
4456
+ const errors = shallowRef([]);
4457
+ const isValid = shallowRef(null);
4458
+ const isValidating = shallowRef(false);
4459
+ let generation = 0;
4460
+ function register(input) {
4461
+ if (/* @__PURE__ */ isFunction(input) || /* @__PURE__ */ isString(input) || isStandardSchema(input)) {
4462
+ const resolved = rulesContext.resolve([input]);
4463
+ return group.register({ value: resolved[0] ?? (() => true) });
4464
+ }
4465
+ return group.register(input);
4466
+ }
4467
+ function onboard(rules) {
4468
+ return group.batch(() => rules.map((r) => register(r)));
4469
+ }
4470
+ async function validate(_value = UNSET, silent = false) {
4471
+ const val = _value === UNSET ? toValue(valueSource) : _value;
4472
+ const activeRules = [];
4473
+ for (const ticket of group.selectedItems.value) activeRules.push(ticket.value);
4474
+ if (activeRules.length === 0) {
4475
+ if (!silent) isValid.value = true;
4476
+ return true;
4477
+ }
4478
+ const gen = ++generation;
4479
+ if (!silent) isValidating.value = true;
4480
+ try {
4481
+ const results = await Promise.all(activeRules.map((rule) => rule(val)));
4482
+ if (gen !== generation) return isValid.value ?? false;
4483
+ const errorMessages = results.filter((result) => /* @__PURE__ */ isString(result) || result === false).map((result) => result === false ? "Validation failed" : result);
4484
+ if (!silent) {
4485
+ errors.value = errorMessages;
4486
+ isValid.value = errorMessages.length === 0;
4487
+ }
4488
+ return errorMessages.length === 0;
4489
+ } finally {
4490
+ if (gen === generation && !silent) isValidating.value = false;
4491
+ }
4492
+ }
4493
+ function reset() {
4494
+ errors.value = [];
4495
+ isValid.value = null;
4496
+ isValidating.value = false;
4497
+ generation++;
4498
+ }
4499
+ if (initialRules.length > 0) onboard(initialRules);
4500
+ const context = {
4501
+ ...group,
4502
+ register,
4503
+ onboard,
4504
+ validate,
4505
+ reset,
4506
+ errors,
4507
+ isValid,
4508
+ isValidating,
4509
+ get size() {
4510
+ return group.size;
4511
+ }
4512
+ };
4513
+ const form = useForm();
4514
+ const ticket = form?.register({ value: context });
4515
+ onScopeDispose(() => {
4516
+ if (!ticket || !form) return;
4517
+ form.unregister(ticket.id);
4518
+ }, true);
4519
+ return context;
4520
+ }
4131
4521
  //#endregion
4132
4522
  //#region src/composables/useToggleScope/index.ts
4133
4523
  /**
@@ -4224,7 +4614,6 @@ function useToggleScope(source, fn) {
4224
4614
  onScopeDispose(stop, true);
4225
4615
  return controls;
4226
4616
  }
4227
-
4228
4617
  //#endregion
4229
4618
  //#region src/composables/createVirtual/index.ts
4230
4619
  /**
@@ -4368,10 +4757,10 @@ function createVirtual(items, _options = {}) {
4368
4757
  function rebuild() {
4369
4758
  const length = items.value.length;
4370
4759
  const newOffsets = offsets.value.length === length ? offsets.value : Array.from({ length });
4371
- let offset$1 = 0;
4760
+ let offset = 0;
4372
4761
  for (let i = 0; i < length; i++) {
4373
- newOffsets[i] = offset$1;
4374
- offset$1 += heights.value[i] || itemHeight.value;
4762
+ newOffsets[i] = offset;
4763
+ offset += heights.value[i] || itemHeight.value;
4375
4764
  }
4376
4765
  if (offsets.value !== newOffsets) offsets.value = newOffsets;
4377
4766
  update();
@@ -4425,10 +4814,10 @@ function createVirtual(items, _options = {}) {
4425
4814
  }
4426
4815
  /* v8 ignore stop */
4427
4816
  }
4428
- function resize(index, height$1) {
4429
- if (heights.value[index] === height$1) return;
4430
- heights.value[index] = height$1;
4431
- if (!itemHeight.value) itemHeight.value = height$1;
4817
+ function resize(index, height) {
4818
+ if (heights.value[index] === height) return;
4819
+ heights.value[index] = height;
4820
+ if (!itemHeight.value) itemHeight.value = height;
4432
4821
  if (IN_BROWSER) {
4433
4822
  cancelAnimationFrame(rebuildRaf);
4434
4823
  rebuildRaf = requestAnimationFrame(rebuild);
@@ -4572,7 +4961,80 @@ function createVirtualContext(items, _options = {}) {
4572
4961
  function useVirtual(namespace = "v0:virtual") {
4573
4962
  return useContext(namespace);
4574
4963
  }
4575
-
4964
+ //#endregion
4965
+ //#region src/composables/useVirtualFocus/index.ts
4966
+ /**
4967
+ * @module useVirtualFocus
4968
+ *
4969
+ * @remarks
4970
+ * Virtual focus composable for aria-activedescendant keyboard navigation.
4971
+ * DOM focus stays on a control element while a virtual cursor highlights
4972
+ * items in a list.
4973
+ *
4974
+ * Key features:
4975
+ * - Arrow key navigation with orientation support
4976
+ * - Grid mode for 2D navigation
4977
+ * - Automatic disabled item skipping
4978
+ * - Optional circular navigation
4979
+ * - Home/End key support (row-scoped in grid mode)
4980
+ * - Auto-attaches keydown listener when target is provided
4981
+ * - Sets aria-activedescendant and data-highlighted attributes
4982
+ *
4983
+ * Perfect for comboboxes, autocompletes, listboxes, and other widgets
4984
+ * where DOM focus must remain on the control element.
4985
+ */
4986
+ function useVirtualFocus(items, options) {
4987
+ const { control, target, orientation, circular, columns, onHighlight } = options;
4988
+ let previousEl = null;
4989
+ function applyHighlight(id) {
4990
+ const item = items().find((i) => i.id === id);
4991
+ if (!item?.el) return false;
4992
+ const el = toValue(item.el);
4993
+ if (!el) return false;
4994
+ const controlEl = toValue(control);
4995
+ if (controlEl) {
4996
+ const itemId = el.getAttribute("id");
4997
+ if (itemId) controlEl.setAttribute("aria-activedescendant", itemId);
4998
+ }
4999
+ if (previousEl) delete previousEl.dataset.highlighted;
5000
+ el.dataset.highlighted = "";
5001
+ previousEl = el;
5002
+ el.scrollIntoView({ block: "nearest" });
5003
+ onHighlight?.(id);
5004
+ return true;
5005
+ }
5006
+ const traversal = createFocusTraversal(items, (id) => applyHighlight(id), {
5007
+ orientation,
5008
+ circular,
5009
+ columns
5010
+ });
5011
+ function highlight(id) {
5012
+ const prev = traversal.activeId.value;
5013
+ traversal.activeId.value = id;
5014
+ if (!applyHighlight(id)) traversal.activeId.value = prev;
5015
+ }
5016
+ function clear() {
5017
+ traversal.activeId.value = void 0;
5018
+ const controlEl = toValue(control);
5019
+ if (controlEl) controlEl.removeAttribute("aria-activedescendant");
5020
+ if (previousEl) {
5021
+ delete previousEl.dataset.highlighted;
5022
+ previousEl = null;
5023
+ }
5024
+ }
5025
+ const listener = target ?? control;
5026
+ if (listener) useEventListener(listener, "keydown", traversal.onKeydown);
5027
+ return {
5028
+ highlightedId: traversal.activeId,
5029
+ highlight,
5030
+ clear,
5031
+ next: traversal.next,
5032
+ prev: traversal.prev,
5033
+ first: traversal.first,
5034
+ last: traversal.last,
5035
+ onKeydown: traversal.onKeydown
5036
+ };
5037
+ }
4576
5038
  //#endregion
4577
5039
  //#region src/composables/useEventListener/index.ts
4578
5040
  /**
@@ -4607,9 +5069,9 @@ function useEventListener(target, event, listener, options) {
4607
5069
  for (const fn of cleanups) fn();
4608
5070
  cleanups.length = 0;
4609
5071
  }
4610
- function register(el, event$1, listener$1, options$1) {
4611
- el.addEventListener(event$1, listener$1, options$1);
4612
- return () => el.removeEventListener(event$1, listener$1, options$1);
5072
+ function register(el, event, listener, options) {
5073
+ el.addEventListener(event, listener, options);
5074
+ return () => el.removeEventListener(event, listener, options);
4613
5075
  }
4614
5076
  const stopWatcher = watch(() => [
4615
5077
  toValue(target),
@@ -4621,7 +5083,7 @@ function useEventListener(target, event, listener, options) {
4621
5083
  if (!el) return;
4622
5084
  const eventList = toArray(events);
4623
5085
  const listenerList = toArray(listeners);
4624
- for (const event$1 of eventList) for (const listenerFn of listenerList) cleanups.push(register(el, event$1, listenerFn, opts));
5086
+ for (const event of eventList) for (const listenerFn of listenerList) cleanups.push(register(el, event, listenerFn, opts));
4625
5087
  }, {
4626
5088
  immediate: true,
4627
5089
  flush: "post"
@@ -4661,7 +5123,6 @@ function useWindowEventListener(event, listener, options) {
4661
5123
  function useDocumentEventListener(event, listener, options) {
4662
5124
  return IN_BROWSER ? useEventListener(document, event, listener, options) : () => {};
4663
5125
  }
4664
-
4665
5126
  //#endregion
4666
5127
  //#region src/composables/useClickOutside/index.ts
4667
5128
  /**
@@ -4919,6 +5380,5 @@ function useClickOutside(target, handler, options = {}) {
4919
5380
  stop
4920
5381
  };
4921
5382
  }
4922
-
4923
5383
  //#endregion
4924
- export { useProxyModel as $, multipleOpenStrategy as A, useHotkey as B, createSlider as C, createNested as D, useQueue as E, usePrefersDark as F, createDateContext as G, createFormContext as H, usePrefersReducedMotion as I, createBreakpoints as J, createDatePlugin as K, useLazy as L, useMutationObserver as M, useMediaQuery as N, createNestedContext as O, usePrefersContrast as P, toReactive as Q, useElementIntersection as R, useStack as S, createQueueContext as T, useForm as U, createForm as V, createDate as W, createBreakpointsPlugin as X, createBreakpointsContext as Y, useBreakpoints as Z, createStepContext as _, createVirtual as a, toElement as at, createStackContext as b, useToggleScope as c, createHydrationContext as ct, useTimeline as d, createBreadcrumbs as dt, createOverflow as et, createStorage as f, createBreadcrumbsContext as ft, createStep as g, useStorage as h, useWindowEventListener as i, useResizeObserver as it, singleOpenStrategy as j, useNested as k, createTimeline as l, createHydrationPlugin as lt, createStoragePlugin as m, useDocumentEventListener as n, useOverflow as nt, createVirtualContext as o, createFallbackHydration as ot, createStorageContext as p, useBreadcrumbs as pt, useDate as q, useEventListener as r, useElementSize as rt, useVirtual as s, createHydration as st, useClickOutside as t, createOverflowContext as tt, createTimelineContext as u, useHydration as ut, useStep as v, createQueue as w, createStackPlugin as x, createStack as y, useIntersectionObserver as z };
5384
+ export { useForm as $, useRtl as A, multipleOpenStrategy as B, createStackPlugin as C, useBreadcrumbs as Ct, createRtlContext as D, createRtl as E, useQueue as F, usePrefersDark as G, useMutationObserver as H, usePopover as I, useElementIntersection as J, usePrefersReducedMotion as K, createNested as L, useRovingFocus as M, createQueue as N, createRtlFallback as O, createQueueContext as P, createFormContext as Q, createNestedContext as R, createStackContext as S, createBreadcrumbsContext as St, createSlider as T, useMediaQuery as U, singleOpenStrategy as V, usePrefersContrast as W, useHotkey as X, useIntersectionObserver as Y, createForm as Z, useStorage as _, createHydration as _t, useVirtualFocus as a, createBreakpointsContext as at, useStep as b, useHydration as bt, useVirtual as c, toReactive as ct, createTimeline as d, createOverflowContext as dt, createDate as et, createTimelineContext as f, useOverflow as ft, createStoragePlugin as g, createFallbackHydration as gt, createStorageContext as h, toElement as ht, useWindowEventListener as i, createBreakpoints as it, Vuetify0RtlAdapter as j, createRtlPlugin as k, useToggleScope as l, useProxyModel as lt, createStorage as m, useResizeObserver as mt, useDocumentEventListener as n, createDatePlugin as nt, createVirtual as o, createBreakpointsPlugin as ot, useTimeline as p, useElementSize as pt, useLazy as q, useEventListener as r, useDate as rt, createVirtualContext as s, useBreakpoints as st, useClickOutside as t, createDateContext as tt, createValidation as u, createOverflow as ut, createStep as v, createHydrationContext as vt, useStack as w, createStack as x, createBreadcrumbs as xt, createStepContext as y, createHydrationPlugin as yt, useNested as z };