@vuetify/v0 0.2.1 → 1.0.0-alpha.1

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 (113) hide show
  1. package/README.md +5 -1
  2. package/dist/{adapter-CCIeOzqr.mjs → adapter-CDpOQ8sn.mjs} +29 -20
  3. package/dist/{adapter-CcHB7rs3.d.mts → adapter-DoziXEzS.d.mts} +1 -1
  4. package/dist/{adapter-Drq1v5wV.mjs → adapter-DtgIrQsG.mjs} +5 -2
  5. package/dist/{adapter-BZjmDNJF.d.mts → adapter-J7ude3gO.d.mts} +2 -2
  6. package/dist/adapters-CFjrKxA2.mjs +5 -0
  7. package/dist/adapters-CiCexgsk.mjs +4 -0
  8. package/dist/{adapters-Cd8NDs18.mjs → adapters-Da2twiUn.mjs} +1 -1
  9. package/dist/adapters-DegUcfkd.mjs +2 -0
  10. package/dist/browser/index.js +10113 -8547
  11. package/dist/components/index.d.mts +3 -3
  12. package/dist/components/index.mjs +2 -2
  13. package/dist/{components-C142GPl_.mjs → components-CaPQCjo5.mjs} +1356 -386
  14. package/dist/composables/index.d.mts +11 -11
  15. package/dist/composables/index.mjs +24 -24
  16. package/dist/constants/index.mjs +2 -2
  17. package/dist/{createDataTable-DKE5QsMe.mjs → createDataTable-B4UflKnT.mjs} +100 -30
  18. package/dist/{createGroup-CzRZ9COh.mjs → createGroup-BC2nfttd.mjs} +24 -9
  19. package/dist/{createPagination-Tp4C4He8.mjs → createPagination-qvJkcTUY.mjs} +11 -7
  20. package/dist/{createSelection-Dsb3I0zm.mjs → createSelection-BA9guLah.mjs} +28 -21
  21. package/dist/{createSingle-C7IGUjP6.mjs → createSingle-BHxHLZeg.mjs} +13 -17
  22. package/dist/{createTokens-CHTawmud.mjs → createTokens-oJAeh262.mjs} +27 -15
  23. package/dist/{createTrinity-vvXk0ARD.mjs → createTrinity-BTCs1pYx.mjs} +34 -31
  24. package/dist/data-table/adapters/client/index.d.mts +1 -1
  25. package/dist/data-table/adapters/client/index.mjs +1 -1
  26. package/dist/data-table/adapters/index.d.mts +4 -4
  27. package/dist/data-table/adapters/index.mjs +5 -5
  28. package/dist/data-table/adapters/server/index.d.mts +1 -1
  29. package/dist/data-table/adapters/server/index.mjs +1 -1
  30. package/dist/data-table/adapters/virtual/index.d.mts +1 -1
  31. package/dist/data-table/adapters/virtual/index.mjs +1 -1
  32. package/dist/data-table/index.d.mts +6 -6
  33. package/dist/data-table/index.mjs +6 -6
  34. package/dist/date/index.mjs +1 -1
  35. package/dist/features/adapters/posthog/index.mjs +1 -1
  36. package/dist/features/index.d.mts +1 -1
  37. package/dist/features/index.mjs +1 -1
  38. package/dist/{globals-BrRJkuSY.mjs → globals-Berkg6mP.mjs} +1 -1
  39. package/dist/{htmlElements-DcYtv0hg.mjs → htmlElements-CIePKaTX.mjs} +1 -1
  40. package/dist/{index-76fQGkkO.d.mts → index-D4odwkZg.d.mts} +8 -11
  41. package/dist/{index-B_XLHftL.d.mts → index-DFvLSoto.d.mts} +296 -258
  42. package/dist/{index-DoGxDgdN.d.mts → index-DVPq3_Fz.d.mts} +55 -4
  43. package/dist/{index-BFuSOgUi.d.mts → index-Gk3x_7zD.d.mts} +1570 -437
  44. package/dist/{index-BUsrN1vL.d.mts → index-TtSSvHY6.d.mts} +1 -1
  45. package/dist/index.d.mts +12 -12
  46. package/dist/index.mjs +27 -27
  47. package/dist/json/attributes.json +276 -0
  48. package/dist/json/importMap.json +60 -0
  49. package/dist/json/tags.json +136 -2
  50. package/dist/json/web-types.json +1183 -344
  51. package/dist/locale/adapters/index.d.mts +2 -2
  52. package/dist/locale/adapters/index.mjs +2 -2
  53. package/dist/locale/adapters/v0/index.d.mts +1 -1
  54. package/dist/locale/adapters/v0/index.mjs +1 -1
  55. package/dist/locale/adapters/vue-i18n/index.d.mts +1 -1
  56. package/dist/locale/index.d.mts +3 -3
  57. package/dist/locale/index.mjs +2 -2
  58. package/dist/logger/adapters/index.mjs +2 -2
  59. package/dist/logger/adapters/v0/index.mjs +1 -1
  60. package/dist/logger/index.d.mts +1 -1
  61. package/dist/logger/index.mjs +2 -2
  62. package/dist/notifications/index.d.mts +1 -1
  63. package/dist/notifications/index.mjs +1 -1
  64. package/dist/palettes/ant/index.d.mts +1 -1
  65. package/dist/palettes/index.d.mts +2 -2
  66. package/dist/palettes/material/index.d.mts +1 -1
  67. package/dist/palettes/md1/index.d.mts +1 -1
  68. package/dist/palettes/md2/index.d.mts +1 -1
  69. package/dist/palettes/radix/index.d.mts +1 -1
  70. package/dist/palettes/tailwind/index.d.mts +1 -1
  71. package/dist/permissions/adapters/index.d.mts +1 -1
  72. package/dist/permissions/adapters/v0/index.d.mts +1 -1
  73. package/dist/permissions/index.d.mts +1 -1
  74. package/dist/permissions/index.mjs +1 -1
  75. package/dist/{posthog-Ccm8FQfD.mjs → posthog-CPvNHMUb.mjs} +1 -1
  76. package/dist/rules/index.d.mts +1 -1
  77. package/dist/rules/index.mjs +1 -1
  78. package/dist/{server-CIftA0pK.mjs → server-B6OtHgBT.mjs} +1 -1
  79. package/dist/{server-DNUTnISs.d.mts → server-ZiHJ4tfq.d.mts} +1 -1
  80. package/dist/storage/index.d.mts +1 -1
  81. package/dist/storage/index.mjs +1 -1
  82. package/dist/theme/adapters/index.d.mts +1 -1
  83. package/dist/theme/adapters/index.mjs +4 -4
  84. package/dist/theme/adapters/unhead/index.d.mts +1 -1
  85. package/dist/theme/adapters/unhead/index.mjs +1 -1
  86. package/dist/theme/adapters/v0/index.d.mts +1 -1
  87. package/dist/theme/adapters/v0/index.mjs +1 -1
  88. package/dist/theme/index.d.mts +1 -1
  89. package/dist/theme/index.mjs +3 -3
  90. package/dist/{toArray-doLQVI56.mjs → toArray-BA_JxFPv.mjs} +9 -0
  91. package/dist/{unhead--58lO3Z-.mjs → unhead-D2YqAcmF.mjs} +2 -2
  92. package/dist/{useClickOutside-BjO3Nty9.mjs → useClickOutside-B9a6Jext.mjs} +572 -160
  93. package/dist/{useFeatures-D9bGOvh4.mjs → useFeatures-wgMwaQ5W.mjs} +14 -5
  94. package/dist/{useLocale-BRQTt3Ka.mjs → useLocale-qMmVnAwS.mjs} +14 -5
  95. package/dist/{useLogger-Daz-Zr0z.mjs → useLogger-DFIRqm-N.mjs} +33 -16
  96. package/dist/{usePermissions-Yp3guoLH.mjs → usePermissions-tZhkBJmq.mjs} +11 -3
  97. package/dist/{useRules-BFPH7q8w.mjs → useRules-D3UXEtu7.mjs} +10 -2
  98. package/dist/{useTheme-zRa0Nh_g.mjs → useTheme-BeD__R8t.mjs} +14 -5
  99. package/dist/utilities/index.mjs +5 -5
  100. package/dist/{v0-CcV0VwYd.mjs → v0-6XptGYVx.mjs} +2 -2
  101. package/dist/{v0-DOq_Ia5H.mjs → v0-BG7RhKBv.mjs} +2 -2
  102. package/dist/{v0-Bno8FQ_F.mjs → v0-CNitYI9N.mjs} +1 -1
  103. package/dist/{v0-BpgPZ1qB.d.mts → v0-CWXUkMY0.d.mts} +1 -1
  104. package/dist/{v0-BAG8p0si.d.mts → v0-Dzw5OwNo.d.mts} +1 -1
  105. package/dist/{v0-D-AEQbvj.mjs → v0-I2mHxD9T.mjs} +1 -1
  106. package/dist/{virtual-BaQWQ9ji.d.mts → virtual-BCOfxnRS.d.mts} +1 -1
  107. package/dist/{virtual-D1HwNBLS.mjs → virtual-To-dSw2_.mjs} +2 -2
  108. package/package.json +10 -7
  109. package/SKILL.md +0 -95
  110. package/dist/adapters-BbNfjyvY.mjs +0 -5
  111. package/dist/adapters-BzRMo72Y.mjs +0 -4
  112. package/dist/adapters-_DyP1X4U.mjs +0 -2
  113. /package/dist/{index-c55Utzva.d.mts → index-DvuJXuAN.d.mts} +0 -0
@@ -1,22 +1,22 @@
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-BrRJkuSY.mjs";
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-Berkg6mP.mjs";
2
2
  import { clamp, instanceExists, isArray, isElement, isFunction, isNull, isNullOrUndefined, isNumber, isObject, isString, isUndefined, mergeDeep, range, resolveIds, resolveIndexes, useId as useId$1 } from "./utilities/index.mjs";
3
- import { i as useContext, n as createContext, t as createTrinity } from "./createTrinity-vvXk0ARD.mjs";
4
- import { a as createPlugin, i as useLogger, o as createPluginContext } from "./useLogger-Daz-Zr0z.mjs";
5
- import { a as createRegistry } from "./createTokens-CHTawmud.mjs";
6
- import { i as createModel, t as createSelection } from "./createSelection-Dsb3I0zm.mjs";
7
- import { t as createSingle } from "./createSingle-C7IGUjP6.mjs";
8
- import { t as toArray } from "./toArray-doLQVI56.mjs";
9
- import { n as createFilter } from "./adapter-CCIeOzqr.mjs";
10
- import { t as createGroup } from "./createGroup-CzRZ9COh.mjs";
11
- import { a as useLocale } from "./useLocale-BRQTt3Ka.mjs";
12
- import "./createPagination-Tp4C4He8.mjs";
13
- import "./createDataTable-DKE5QsMe.mjs";
14
- import { a as useRules, o as isStandardSchema } from "./useRules-BFPH7q8w.mjs";
15
- import "./useFeatures-D9bGOvh4.mjs";
16
- import "./usePermissions-Yp3guoLH.mjs";
3
+ import { i as useContext, t as createTrinity } from "./createTrinity-BTCs1pYx.mjs";
4
+ import { a as createPlugin, i as useLogger, o as createPluginContext } from "./useLogger-DFIRqm-N.mjs";
5
+ import { a as createRegistry } from "./createTokens-oJAeh262.mjs";
6
+ import { i as createModel, t as createSelection } from "./createSelection-BA9guLah.mjs";
7
+ import { t as createSingle } from "./createSingle-BHxHLZeg.mjs";
8
+ import { a as useLocale } from "./useLocale-qMmVnAwS.mjs";
9
+ import { t as toArray } from "./toArray-BA_JxFPv.mjs";
10
+ import { n as createFilter } from "./adapter-CDpOQ8sn.mjs";
11
+ import { t as createGroup } from "./createGroup-BC2nfttd.mjs";
12
+ import "./createPagination-qvJkcTUY.mjs";
13
+ import "./createDataTable-B4UflKnT.mjs";
14
+ import { a as useRules, o as isStandardSchema } from "./useRules-D3UXEtu7.mjs";
15
+ import "./useFeatures-wgMwaQ5W.mjs";
16
+ import "./usePermissions-tZhkBJmq.mjs";
17
17
  import { t as MemoryAdapter } from "./memory-XCMtkld1.mjs";
18
- import "./useTheme-zRa0Nh_g.mjs";
19
- import { computed, effectScope, isRef, nextTick, onMounted, onScopeDispose, reactive, readonly, ref, shallowReactive, shallowReadonly, shallowRef, toRef, toValue, unref, watch, watchEffect } from "vue";
18
+ import "./useTheme-BeD__R8t.mjs";
19
+ import { computed, effectScope, hasInjectionContext, isRef, nextTick, onMounted, onScopeDispose, reactive, readonly, ref, shallowReactive, shallowReadonly, shallowRef, toRef, toValue, unref, watch, watchEffect } from "vue";
20
20
  //#region src/composables/createBreadcrumbs/index.ts
21
21
  /**
22
22
  * @module createBreadcrumbs
@@ -33,6 +33,16 @@ import { computed, effectScope, isRef, nextTick, onMounted, onScopeDispose, reac
33
33
  * - Trinity pattern for dependency injection
34
34
  *
35
35
  * Inheritance chain: createRegistry → createSelection → createSingle → createBreadcrumbs
36
+ *
37
+ * @example
38
+ * ```ts
39
+ * import { createBreadcrumbs } from '@vuetify/v0'
40
+ *
41
+ * const crumbs = createBreadcrumbs()
42
+ * crumbs.register({ text: 'Home' })
43
+ * crumbs.register({ text: 'Docs' })
44
+ * console.log(crumbs.depth.value) // 2
45
+ * ```
36
46
  */
37
47
  /**
38
48
  * Creates a breadcrumbs navigation model.
@@ -63,6 +73,7 @@ function createBreadcrumbs(options = {}) {
63
73
  const single = createSingle({
64
74
  ...options,
65
75
  reactive: true,
76
+ events: true,
66
77
  enroll: true
67
78
  });
68
79
  const depth = toRef(() => single.size);
@@ -129,12 +140,7 @@ function createBreadcrumbs(options = {}) {
129
140
  */
130
141
  function createBreadcrumbsContext(_options = {}) {
131
142
  const { namespace = "v0:breadcrumbs", ...options } = _options;
132
- const [useBreadcrumbsContext, _provideBreadcrumbsContext] = createContext(namespace);
133
- const context = createBreadcrumbs(options);
134
- function provideBreadcrumbsContext(_context = context, app) {
135
- return _provideBreadcrumbsContext(_context, app);
136
- }
137
- return createTrinity(useBreadcrumbsContext, provideBreadcrumbsContext, context);
143
+ return createTrinity(namespace, createBreadcrumbs(options));
138
144
  }
139
145
  /**
140
146
  * Returns the current breadcrumbs instance from context.
@@ -178,6 +184,14 @@ function useBreadcrumbs(namespace = "v0:breadcrumbs") {
178
184
  * - One-shot (default) or repeating mode
179
185
  * - Automatic cleanup on scope disposal
180
186
  * - SSR-safe
187
+ *
188
+ * @example
189
+ * ```ts
190
+ * import { useTimer } from '@vuetify/v0'
191
+ *
192
+ * const timer = useTimer(() => console.log('fired'), { duration: 5000 })
193
+ * timer.start()
194
+ * ```
181
195
  */
182
196
  /**
183
197
  * Creates a reactive timer with pause/resume support.
@@ -311,6 +325,15 @@ function useTimer(handler, options = {}) {
311
325
  *
312
326
  * Perfect for building select, combobox, tooltip, and menu components
313
327
  * without wrapping the Popover compound component.
328
+ *
329
+ * @example
330
+ * ```ts
331
+ * import { usePopover } from '@vuetify/v0'
332
+ *
333
+ * const popover = usePopover()
334
+ * popover.open()
335
+ * popover.toggle()
336
+ * ```
314
337
  */
315
338
  function usePopover(options = {}) {
316
339
  const { id: _id, positionArea = "bottom", positionTry = "most-width bottom", showDelay = 0, hideDelay = 0 } = options;
@@ -392,6 +415,15 @@ function usePopover(options = {}) {
392
415
  * useRovingFocus and useVirtualFocus.
393
416
  *
394
417
  * Not exported from the package barrel — consumed only by sibling composables.
418
+ *
419
+ * @example
420
+ * ```ts
421
+ * import { createFocusTraversal } from '#v0/composables/createFocusTraversal'
422
+ *
423
+ * const items = () => [{ id: 'a' }, { id: 'b' }, { id: 'c' }]
424
+ * const traversal = createFocusTraversal(items, id => console.log(id))
425
+ * traversal.next()
426
+ * ```
395
427
  */
396
428
  function mod(length, index) {
397
429
  return (index % length + length) % length;
@@ -574,6 +606,15 @@ function createFocusTraversal(items, activate, options = {}) {
574
606
  *
575
607
  * Perfect for comboboxes, autocompletes, listboxes, and other widgets
576
608
  * where DOM focus must remain on the control element.
609
+ *
610
+ * @example
611
+ * ```ts
612
+ * import { useVirtualFocus } from '@vuetify/v0'
613
+ *
614
+ * const items = () => [{ id: 'a' }, { id: 'b' }, { id: 'c' }]
615
+ * const cursor = useVirtualFocus(items)
616
+ * cursor.next()
617
+ * ```
577
618
  */
578
619
  function useVirtualFocus(items, options) {
579
620
  const { control, target, orientation, circular, columns, onHighlight } = options;
@@ -616,6 +657,9 @@ function useVirtualFocus(items, options) {
616
657
  }
617
658
  const listener = target ?? control;
618
659
  if (listener) useEventListener(listener, "keydown", traversal.onKeydown);
660
+ onScopeDispose(() => {
661
+ clear();
662
+ });
619
663
  return {
620
664
  highlightedId: traversal.activeId,
621
665
  highlight,
@@ -709,6 +753,16 @@ var ServerAdapter = class {
709
753
  * - Strict mode: reverts query to selected value on close if no match
710
754
  * - Popover-based dropdown positioning
711
755
  * - Context DI via createComboboxContext / useCombobox
756
+ *
757
+ * @example
758
+ * ```ts
759
+ * import { createCombobox } from '@vuetify/v0'
760
+ *
761
+ * const combobox = createCombobox({ strict: true })
762
+ * combobox.selection.register({ value: 'Apple' })
763
+ * combobox.selection.register({ value: 'Banana' })
764
+ * combobox.open()
765
+ * ```
712
766
  */
713
767
  /**
714
768
  * Creates a combobox context that orchestrates selection, popover, virtual
@@ -778,7 +832,7 @@ function createCombobox(options = {}) {
778
832
  const isOpen = popover.isOpen;
779
833
  const cursor = useVirtualFocus(() => selection.values().filter((ticket) => filtered.value.has(ticket.id) && !toValue(ticket.disabled)).map((ticket) => ({
780
834
  id: ticket.id,
781
- el: () => document.querySelector(`#${CSS.escape(`${id}-option-${ticket.id}`)}`),
835
+ el: () => IN_BROWSER ? document.querySelector(`#${CSS.escape(`${id}-option-${ticket.id}`)}`) : null,
782
836
  disabled: ticket.disabled
783
837
  })), {
784
838
  control: inputEl,
@@ -879,12 +933,7 @@ function createCombobox(options = {}) {
879
933
  */
880
934
  function createComboboxContext(options = {}) {
881
935
  const { namespace = "v0:combobox", ...rest } = options;
882
- const [useCombobox, _provideCombobox] = createContext(namespace);
883
- const context = createCombobox(rest);
884
- function provideCombobox(_context = context, app) {
885
- return _provideCombobox(_context, app);
886
- }
887
- return createTrinity(useCombobox, provideCombobox, context);
936
+ return createTrinity(namespace, createCombobox(rest));
888
937
  }
889
938
  /**
890
939
  * Injects the current combobox context from a parent provider.
@@ -924,6 +973,15 @@ function useCombobox(namespace = "v0:combobox") {
924
973
  *
925
974
  * Per-field validation logic lives in createValidation.
926
975
  * createForm is the mothership — it coordinates, not creates.
976
+ *
977
+ * @example
978
+ * ```ts
979
+ * import { createForm } from '@vuetify/v0'
980
+ *
981
+ * const form = createForm()
982
+ * const isValid = await form.validate()
983
+ * if (isValid) form.submit()
984
+ * ```
927
985
  */
928
986
  /**
929
987
  * Creates a new form instance.
@@ -1023,12 +1081,7 @@ function createForm(options = {}) {
1023
1081
  */
1024
1082
  function createFormContext(_options = {}) {
1025
1083
  const { namespace = "v0:form", ...options } = _options;
1026
- const [useFormContext, _provideFormContext] = createContext(namespace);
1027
- const context = createForm(options);
1028
- function provideFormContext(_context = context, app) {
1029
- return _provideFormContext(_context, app);
1030
- }
1031
- return createTrinity(useFormContext, provideFormContext, context);
1084
+ return createTrinity(namespace, createForm(options));
1032
1085
  }
1033
1086
  /**
1034
1087
  * Returns the current form instance.
@@ -1048,6 +1101,7 @@ function createFormContext(_options = {}) {
1048
1101
  * ```
1049
1102
  */
1050
1103
  function useForm(namespace = "v0:form") {
1104
+ if (!hasInjectionContext()) return void 0;
1051
1105
  try {
1052
1106
  return useContext(namespace);
1053
1107
  } catch {
@@ -1073,8 +1127,18 @@ function useForm(namespace = "v0:form") {
1073
1127
  * - Tri-state isValid (null/true/false)
1074
1128
  *
1075
1129
  * Uses useRules() to resolve alias strings via shared context.
1130
+ *
1131
+ * @example
1132
+ * ```ts
1133
+ * import { createValidation } from '@vuetify/v0'
1134
+ *
1135
+ * const validation = createValidation({
1136
+ * rules: [v => !!v || 'Required'],
1137
+ * })
1138
+ * await validation.validate('hello')
1139
+ * ```
1076
1140
  */
1077
- const UNSET = Symbol("unset");
1141
+ const UNSET = /* @__PURE__ */ Symbol("unset");
1078
1142
  /**
1079
1143
  * Creates a per-input validation instance.
1080
1144
  *
@@ -1146,6 +1210,13 @@ function createValidation(_options = {}) {
1146
1210
  isValid.value = errorMessages.length === 0;
1147
1211
  }
1148
1212
  return errorMessages.length === 0;
1213
+ } catch (error) {
1214
+ if (gen !== generation) return isValid.value ?? false;
1215
+ if (!silent) {
1216
+ errors.value = [error instanceof Error ? error.message : "Validation error"];
1217
+ isValid.value = false;
1218
+ }
1219
+ return false;
1149
1220
  } finally {
1150
1221
  if (gen === generation && !silent) isValidating.value = false;
1151
1222
  }
@@ -1191,6 +1262,16 @@ function createValidation(_options = {}) {
1191
1262
  *
1192
1263
  * No event handling — composables never bind DOM events. Components call
1193
1264
  * validate() and write isFocused/isTouched when they choose.
1265
+ *
1266
+ * @example
1267
+ * ```ts
1268
+ * import { shallowRef } from 'vue'
1269
+ * import { createInput } from '@vuetify/v0'
1270
+ *
1271
+ * const value = shallowRef('')
1272
+ * const input = createInput({ value, label: 'Name', rules: ['required'] })
1273
+ * await input.validate()
1274
+ * ```
1194
1275
  */
1195
1276
  function createInput(options) {
1196
1277
  const { value, id = /* @__PURE__ */ useId$1(), label, name, form, required, disabled = false, readonly: _readonly = false, rules = [], error = false, errorMessages, dirty: dirtyFn, equals = (a, b) => a === b } = options;
@@ -1268,48 +1349,6 @@ function createInput(options) {
1268
1349
  };
1269
1350
  }
1270
1351
  //#endregion
1271
- //#region src/composables/createNested/strategies.ts
1272
- /**
1273
- * Multiple open strategy: allows multiple nodes to be open simultaneously.
1274
- *
1275
- * @remarks
1276
- * Perfect for tree views, file explorers, and nested menus where users expect
1277
- * to keep multiple sections expanded at once.
1278
- *
1279
- * @example
1280
- * ```ts
1281
- * const tree = createNested({ openStrategy: multipleOpenStrategy })
1282
- * tree.open('node-1')
1283
- * tree.open('node-2')
1284
- * // Both nodes are now open
1285
- * ```
1286
- */
1287
- const multipleOpenStrategy = {
1288
- onOpen: void 0,
1289
- onClose: void 0
1290
- };
1291
- /**
1292
- * Single open strategy: only one node can be open at a time (accordion behavior).
1293
- *
1294
- * @remarks
1295
- * Perfect for accordions, single-select navigation, and contexts where only
1296
- * one section should be visible at a time.
1297
- *
1298
- * @example
1299
- * ```ts
1300
- * const tree = createNested({ openStrategy: singleOpenStrategy })
1301
- * tree.open('node-1') // node-1 opens
1302
- * tree.open('node-2') // node-1 closes, node-2 opens
1303
- * ```
1304
- */
1305
- const singleOpenStrategy = {
1306
- onOpen: (id, context) => {
1307
- const toClose = [...context.openedIds].filter((openedId) => openedId !== id);
1308
- for (const openedId of toClose) context.openedIds.delete(openedId);
1309
- },
1310
- onClose: void 0
1311
- };
1312
- //#endregion
1313
1352
  //#region src/composables/createNested/index.ts
1314
1353
  /**
1315
1354
  * @module createNested
@@ -1323,17 +1362,20 @@ const singleOpenStrategy = {
1323
1362
  * - Tree traversal utilities (getPath, getDescendants, etc.)
1324
1363
  * - Cascade selection propagation through nested registers
1325
1364
  * - `rootIds` tracking for top-level item detection
1326
- * - Pluggable open strategies
1327
1365
  *
1328
1366
  * Inheritance chain: createSelection → createGroup → createNested
1367
+ *
1368
+ * @example
1369
+ * ```ts
1370
+ * import { createNested } from '@vuetify/v0'
1371
+ *
1372
+ * const tree = createNested()
1373
+ * const root = tree.register({ value: 'root' })
1374
+ * tree.register({ value: 'child', parentId: root.id })
1375
+ * tree.open(root.id)
1376
+ * ```
1329
1377
  */
1330
1378
  /**
1331
- * Resolves open mode to an OpenStrategy.
1332
- */
1333
- function resolveOpenStrategy(open = "multiple") {
1334
- return open === "single" ? singleOpenStrategy : multipleOpenStrategy;
1335
- }
1336
- /**
1337
1379
  * Creates a new nested tree instance with hierarchical management.
1338
1380
  *
1339
1381
  * Extends `createGroup` to support parent-child relationships, tree traversal,
@@ -1372,10 +1414,9 @@ function resolveOpenStrategy(open = "multiple") {
1372
1414
  * ```
1373
1415
  */
1374
1416
  function createNested(_options = {}) {
1375
- const { open: openMode = "multiple", openAll = false, reveal: revealOnOpen = false, selection: selectionMode = "cascade", active: activeMode = "single", openStrategy, ...options } = _options;
1417
+ const { open: openMode = "multiple", openAll = false, reveal: revealOnOpen = false, selection: selectionMode = "cascade", active: activeMode = "single", ...options } = _options;
1376
1418
  const mandatoryOption = _options.mandatory ?? false;
1377
1419
  const multipleOption = _options.multiple ?? true;
1378
- const resolvedOpenStrategy = openStrategy ?? resolveOpenStrategy(openMode);
1379
1420
  const group = createGroup(options);
1380
1421
  const logger = useLogger();
1381
1422
  const children = shallowReactive(/* @__PURE__ */ new Map());
@@ -1407,7 +1448,9 @@ function createNested(_options = {}) {
1407
1448
  const item = group.get(id);
1408
1449
  if (!item || toValue(item.disabled)) continue;
1409
1450
  openedIds.add(id);
1410
- resolvedOpenStrategy.onOpen?.(id, context);
1451
+ if (openMode === "single") {
1452
+ for (const openedId of openedIds) if (openedId !== id) openedIds.delete(openedId);
1453
+ }
1411
1454
  if (revealOnOpen) {
1412
1455
  let parentId = parents.get(id);
1413
1456
  while (!/* @__PURE__ */ isUndefined(parentId)) {
@@ -1424,7 +1467,6 @@ function createNested(_options = {}) {
1424
1467
  const item = group.get(id);
1425
1468
  if (!item || toValue(item.disabled)) continue;
1426
1469
  openedIds.delete(id);
1427
- resolvedOpenStrategy.onClose?.(id, context);
1428
1470
  }
1429
1471
  }
1430
1472
  function flip(ids) {
@@ -1508,7 +1550,13 @@ function createNested(_options = {}) {
1508
1550
  function getPath(id) {
1509
1551
  const path = [];
1510
1552
  let currentId = id;
1553
+ const visited = /* @__PURE__ */ new Set();
1511
1554
  while (!/* @__PURE__ */ isUndefined(currentId)) {
1555
+ if (visited.has(currentId)) {
1556
+ logger.warn(`Circular parent reference detected at "${currentId}".`);
1557
+ break;
1558
+ }
1559
+ visited.add(currentId);
1512
1560
  path.unshift(currentId);
1513
1561
  currentId = parents.get(currentId);
1514
1562
  }
@@ -1867,7 +1915,7 @@ function createNested(_options = {}) {
1867
1915
  rootIds.clear();
1868
1916
  group.reset();
1869
1917
  }
1870
- const context = {
1918
+ return {
1871
1919
  ...group,
1872
1920
  children,
1873
1921
  parents,
@@ -1903,7 +1951,6 @@ function createNested(_options = {}) {
1903
1951
  deactivateAll,
1904
1952
  toFlat,
1905
1953
  multiple: toValue(multipleOption),
1906
- openStrategy: resolvedOpenStrategy,
1907
1954
  select,
1908
1955
  unselect,
1909
1956
  toggle,
@@ -1920,7 +1967,6 @@ function createNested(_options = {}) {
1920
1967
  return group.size;
1921
1968
  }
1922
1969
  };
1923
- return context;
1924
1970
  }
1925
1971
  /**
1926
1972
  * Creates a new nested context with provide/inject pattern.
@@ -1942,12 +1988,7 @@ function createNested(_options = {}) {
1942
1988
  */
1943
1989
  function createNestedContext(_options = {}) {
1944
1990
  const { namespace = "v0:nested", ...options } = _options;
1945
- const [useNestedContext, _provideNestedContext] = createContext(namespace);
1946
- const context = createNested(options);
1947
- function provideNestedContext(_context = context, app) {
1948
- return _provideNestedContext(_context, app);
1949
- }
1950
- return createTrinity(useNestedContext, provideNestedContext, context);
1991
+ return createTrinity(namespace, createNested(options));
1951
1992
  }
1952
1993
  /**
1953
1994
  * Returns the current nested instance from context.
@@ -1973,6 +2014,15 @@ function useNested(namespace = "v0:nested") {
1973
2014
  *
1974
2015
  * Used by createSlider, createNumberField, and other numeric composables.
1975
2016
  * Handles floating-point precision correction internally.
2017
+ *
2018
+ * @example
2019
+ * ```ts
2020
+ * import { createNumeric } from '@vuetify/v0'
2021
+ *
2022
+ * const numeric = createNumeric({ min: 0, max: 10, step: 1 })
2023
+ * console.log(numeric.snap(3.7)) // 4
2024
+ * console.log(numeric.toPercent(5)) // 0.5
2025
+ * ```
1976
2026
  */
1977
2027
  function decimalPlaces(n) {
1978
2028
  const s = String(n);
@@ -1984,6 +2034,7 @@ function createNumeric(options = {}) {
1984
2034
  const extent = max - min;
1985
2035
  const decimals = Math.max(decimalPlaces(step), Number.isFinite(min) ? decimalPlaces(min) : 0);
1986
2036
  function snap(value) {
2037
+ if (!Number.isFinite(value)) return min;
1987
2038
  if (step <= 0 || !Number.isFinite(min)) return /* @__PURE__ */ clamp(value, min, max);
1988
2039
  const result = min + Math.round((/* @__PURE__ */ clamp(value, min, max) - min) / step) * step;
1989
2040
  return /* @__PURE__ */ clamp(decimals > 0 ? +result.toFixed(decimals) : result, min, max);
@@ -2046,6 +2097,15 @@ function createNumeric(options = {}) {
2046
2097
  * @remarks
2047
2098
  * Orchestrator composable that composes createInput + createNumeric + Intl.NumberFormat.
2048
2099
  * Manages a numeric value with formatting, parsing, stepping, and field state.
2100
+ *
2101
+ * @example
2102
+ * ```ts
2103
+ * import { createNumberField } from '@vuetify/v0'
2104
+ *
2105
+ * const field = createNumberField({ min: 0, max: 100, step: 5 })
2106
+ * field.increment()
2107
+ * console.log(field.value.value) // 5
2108
+ * ```
2049
2109
  */
2050
2110
  function createNumberField(options = {}) {
2051
2111
  const { value = ref(null), locale = "en-US", format: formatOptions, clamp: shouldClamp = true, disabled = false, readonly: _readonly = false, min, max, step, leap, wrap, id, label, name, rules, error, errorMessages } = options;
@@ -2170,6 +2230,16 @@ function createNumberField(options = {}) {
2170
2230
  * - Perfect for hydration-safe rendering
2171
2231
  *
2172
2232
  * Essential for composables that need to behave differently during SSR vs client-side.
2233
+ *
2234
+ * @example
2235
+ * ```ts
2236
+ * import { useHydration } from '@vuetify/v0'
2237
+ *
2238
+ * const { isHydrated } = useHydration()
2239
+ * if (isHydrated.value) {
2240
+ * // safe for client-only logic
2241
+ * }
2242
+ * ```
2173
2243
  */
2174
2244
  /**
2175
2245
  * Creates a new hydration instance.
@@ -2258,6 +2328,15 @@ const [createHydrationContext, createHydrationPlugin, useHydration] = createPlug
2258
2328
  * Accepts refs, getters, raw DOM elements, or Vue component instances
2259
2329
  * and normalizes them to a plain Element. Uses structural typing to
2260
2330
  * avoid cross-version Vue Ref incompatibilities.
2331
+ *
2332
+ * @example
2333
+ * ```ts
2334
+ * import { shallowRef } from 'vue'
2335
+ * import { toElement } from '@vuetify/v0'
2336
+ *
2337
+ * const el = shallowRef<HTMLElement | null>(null)
2338
+ * const resolved = toElement(el) // HTMLElement | undefined
2339
+ * ```
2261
2340
  */
2262
2341
  /**
2263
2342
  * Resolves a {@link MaybeElementRef} to a DOM Element or undefined.
@@ -2305,6 +2384,19 @@ function toElement(target) {
2305
2384
  * - `undefined` — not yet created
2306
2385
  * - `null` — permanently stopped (`stop()` was called; `setup()` is a no-op)
2307
2386
  * - instance — active observer
2387
+ *
2388
+ * @example
2389
+ * ```ts
2390
+ * import { createObserver } from '#v0/composables/createObserver'
2391
+ *
2392
+ * const observer = createObserver(target, entries => {
2393
+ * console.log(entries)
2394
+ * }, {
2395
+ * supports: true,
2396
+ * create: cb => new ResizeObserver(cb),
2397
+ * observe: (o, el) => o.observe(el),
2398
+ * })
2399
+ * ```
2308
2400
  */
2309
2401
  function createObserver(target, userCallback, config) {
2310
2402
  const { isHydrated } = useHydration();
@@ -2397,6 +2489,17 @@ function createObserver(target, userCallback, config) {
2397
2489
  * - Box model options (content-box/border-box)
2398
2490
  *
2399
2491
  * Perfect for responsive components and size-based rendering.
2492
+ *
2493
+ * @example
2494
+ * ```ts
2495
+ * import { useTemplateRef } from 'vue'
2496
+ * import { useResizeObserver } from '@vuetify/v0'
2497
+ *
2498
+ * const target = useTemplateRef('target')
2499
+ * useResizeObserver(target, entries => {
2500
+ * console.log(entries[0].contentRect.width)
2501
+ * })
2502
+ * ```
2400
2503
  */
2401
2504
  /**
2402
2505
  * A composable that uses the Resize Observer API to detect when an element's
@@ -2508,8 +2611,8 @@ function useElementSize(target) {
2508
2611
  _pause();
2509
2612
  }
2510
2613
  return {
2511
- width,
2512
- height,
2614
+ width: shallowReadonly(width),
2615
+ height: shallowReadonly(height),
2513
2616
  isActive,
2514
2617
  isPaused: shallowReadonly(isPaused),
2515
2618
  pause,
@@ -2537,6 +2640,16 @@ function useElementSize(target) {
2537
2640
  *
2538
2641
  * Use variable mode (default) for items with different widths like Breadcrumbs.
2539
2642
  * Use uniform mode (itemWidth option) for same-width items like Pagination buttons.
2643
+ *
2644
+ * @example
2645
+ * ```ts
2646
+ * import { useTemplateRef } from 'vue'
2647
+ * import { createOverflow } from '@vuetify/v0'
2648
+ *
2649
+ * const el = useTemplateRef('container')
2650
+ * const overflow = createOverflow({ container: el })
2651
+ * console.log(overflow.capacity.value) // number of items that fit
2652
+ * ```
2540
2653
  */
2541
2654
  /**
2542
2655
  * Creates a new overflow context for computing how many items fit in a container.
@@ -2625,7 +2738,7 @@ function createOverflow(options = {}) {
2625
2738
  if (available <= 0) return 0;
2626
2739
  const g = toValue(gap);
2627
2740
  const uniformWidth = toValue(itemWidth) ?? 0;
2628
- if (itemWidth !== void 0 && uniformWidth <= 0) return Infinity;
2741
+ if (!/* @__PURE__ */ isUndefined(itemWidth) && uniformWidth <= 0) return Infinity;
2629
2742
  if (uniformWidth > 0) {
2630
2743
  const subsequent = uniformWidth + g;
2631
2744
  if (available < uniformWidth) return 0;
@@ -2676,12 +2789,7 @@ function createOverflow(options = {}) {
2676
2789
  */
2677
2790
  function createOverflowContext(_options = {}) {
2678
2791
  const { namespace = "v0:overflow", ...options } = _options;
2679
- const [useOverflowContext, _provideOverflowContext] = createContext(namespace);
2680
- const context = createOverflow(options);
2681
- function provideOverflowContext(_context = context, app) {
2682
- return _provideOverflowContext(_context, app);
2683
- }
2684
- return createTrinity(useOverflowContext, provideOverflowContext, context);
2792
+ return createTrinity(namespace, createOverflow(options));
2685
2793
  }
2686
2794
  /**
2687
2795
  * Returns the current overflow context from dependency injection.
@@ -2725,6 +2833,15 @@ function useOverflow(namespace = "v0:overflow") {
2725
2833
  * All segments stay selected (multiple: true, enroll: true) so
2726
2834
  * selectedValues always reflects the full set of segment values.
2727
2835
  * Compatible with useProxyModel for v-model bridging.
2836
+ *
2837
+ * @example
2838
+ * ```ts
2839
+ * import { createProgress } from '@vuetify/v0'
2840
+ *
2841
+ * const progress = createProgress({ min: 0, max: 100, value: 25 })
2842
+ * progress.register({ value: 50 })
2843
+ * console.log(progress.percent.value)
2844
+ * ```
2728
2845
  */
2729
2846
  /**
2730
2847
  * Creates a progress instance with model-based segment tracking.
@@ -2818,12 +2935,7 @@ function createProgress(options = {}) {
2818
2935
  */
2819
2936
  function createProgressContext(_options = {}) {
2820
2937
  const { namespace = "v0:progress", ...options } = _options;
2821
- const [use, _provide] = createContext(namespace);
2822
- const context = createProgress(options);
2823
- function provide(_context = context, app) {
2824
- return _provide(_context, app);
2825
- }
2826
- return createTrinity(use, provide, context);
2938
+ return createTrinity(namespace, createProgress(options));
2827
2939
  }
2828
2940
  /**
2829
2941
  * Returns the current progress instance from context.
@@ -2852,6 +2964,15 @@ function useProgress(namespace = "v0:progress") {
2852
2964
  * Built on top of createRegistry, the queue automatically manages timeouts for tickets,
2853
2965
  * ensuring only the first ticket in the queue is active at any time. When a ticket
2854
2966
  * expires or is removed, the next ticket in the queue automatically becomes active.
2967
+ *
2968
+ * @example
2969
+ * ```ts
2970
+ * import { createQueue } from '@vuetify/v0'
2971
+ *
2972
+ * const queue = createQueue()
2973
+ * queue.register({ value: 'Notification 1', timeout: 3000 })
2974
+ * queue.register({ value: 'Notification 2', timeout: 3000 })
2975
+ * ```
2855
2976
  */
2856
2977
  /**
2857
2978
  * Creates a new queue instance
@@ -3002,12 +3123,7 @@ function createQueue(_options = {}) {
3002
3123
  */
3003
3124
  function createQueueContext(_options = {}) {
3004
3125
  const { namespace = "v0:queue", ...options } = _options;
3005
- const [useQueueContext, _provideQueueContext] = createContext(namespace);
3006
- const context = createQueue(options);
3007
- function provideQueueContext(_context = context, app) {
3008
- return _provideQueueContext(_context, app);
3009
- }
3010
- return createTrinity(useQueueContext, provideQueueContext, context);
3126
+ return createTrinity(namespace, createQueue(options));
3011
3127
  }
3012
3128
  /**
3013
3129
  * Returns the current queue instance.
@@ -3050,6 +3166,15 @@ function useQueue(namespace = "v0:queue") {
3050
3166
  * Unlike registry-based composables, rating tracks a single number
3051
3167
  * within a range with computed item states, making it efficient
3052
3168
  * for any star/icon rating use case.
3169
+ *
3170
+ * @example
3171
+ * ```ts
3172
+ * import { createRating } from '@vuetify/v0'
3173
+ *
3174
+ * const rating = createRating({ size: 5, value: 3 })
3175
+ * rating.select(4)
3176
+ * console.log(rating.value.value) // 4
3177
+ * ```
3053
3178
  */
3054
3179
  /**
3055
3180
  * Creates a rating instance.
@@ -3147,12 +3272,7 @@ function createRating(_options = {}) {
3147
3272
  */
3148
3273
  function createRatingContext(_options = {}) {
3149
3274
  const { namespace = "v0:rating", ...options } = _options;
3150
- const [useRatingContext, _provideRatingContext] = createContext(namespace);
3151
- const context = createRating(options);
3152
- function provideRatingContext(_context = context, app) {
3153
- return _provideRatingContext(_context, app);
3154
- }
3155
- return createTrinity(useRatingContext, provideRatingContext, context);
3275
+ return createTrinity(namespace, createRating(options));
3156
3276
  }
3157
3277
  /**
3158
3278
  * Returns the current rating instance from context.
@@ -3198,6 +3318,16 @@ function useRating(namespace = "v0:rating") {
3198
3318
  * Designed for single-thumb, range, and multi-thumb sliders.
3199
3319
  * Also reusable for color picker tracks, media scrubbers,
3200
3320
  * gradient editors, and other 1D value-on-track controls.
3321
+ *
3322
+ * @example
3323
+ * ```ts
3324
+ * import { shallowRef } from 'vue'
3325
+ * import { createSlider } from '@vuetify/v0'
3326
+ *
3327
+ * const slider = createSlider({ min: 0, max: 100, step: 5 })
3328
+ * slider.register({ value: shallowRef(25) })
3329
+ * slider.set(0, 60)
3330
+ * ```
3201
3331
  */
3202
3332
  /**
3203
3333
  * Creates slider state with value math, step snapping, and multi-thumb support.
@@ -3385,6 +3515,16 @@ function createSlider(options = {}) {
3385
3515
  * - Perfect for wizards, carousels, pagination, onboarding flows
3386
3516
  *
3387
3517
  * Inheritance chain: createRegistry → createSelection → createSingle → createStep
3518
+ *
3519
+ * @example
3520
+ * ```ts
3521
+ * import { createStep } from '@vuetify/v0'
3522
+ *
3523
+ * const wizard = createStep({ circular: false })
3524
+ * wizard.register({ value: 'step-1' })
3525
+ * wizard.register({ value: 'step-2' })
3526
+ * wizard.next()
3527
+ * ```
3388
3528
  */
3389
3529
  /**
3390
3530
  * Creates a new step instance with navigation through items.
@@ -3533,12 +3673,7 @@ function createStep(_options = {}) {
3533
3673
  */
3534
3674
  function createStepContext(_options = {}) {
3535
3675
  const { namespace = "v0:step", ...options } = _options;
3536
- const [useStepContext, _provideStepContext] = createContext(namespace);
3537
- const context = createStep(options);
3538
- function provideStepContext(_context = context, app) {
3539
- return _provideStepContext(_context, app);
3540
- }
3541
- return createTrinity(useStepContext, provideStepContext, context);
3676
+ return createTrinity(namespace, createStep(options));
3542
3677
  }
3543
3678
  /**
3544
3679
  * Returns the current step instance.
@@ -3588,6 +3723,16 @@ function useStep(namespace = "v0:step") {
3588
3723
  * - Perfect for command pattern, history tracking
3589
3724
  *
3590
3725
  * Extends createRegistry with temporal navigation capabilities.
3726
+ *
3727
+ * @example
3728
+ * ```ts
3729
+ * import { createTimeline } from '@vuetify/v0'
3730
+ *
3731
+ * const timeline = createTimeline({ size: 5 })
3732
+ * timeline.register({ value: 'action-1' })
3733
+ * timeline.register({ value: 'action-2' })
3734
+ * timeline.undo()
3735
+ * ```
3591
3736
  */
3592
3737
  /**
3593
3738
  * Creates a new timeline instance.
@@ -3699,12 +3844,7 @@ function createTimeline(_options = {}) {
3699
3844
  */
3700
3845
  function createTimelineContext(_options = {}) {
3701
3846
  const { namespace = "v0:timeline", ...options } = _options;
3702
- const [useTimelineContext, _provideTimelineContext] = createContext(namespace);
3703
- const context = createTimeline(options);
3704
- function provideTimelineContext(_context = context, app) {
3705
- return _provideTimelineContext(_context, app);
3706
- }
3707
- return createTrinity(useTimelineContext, provideTimelineContext, context);
3847
+ return createTrinity(namespace, createTimeline(options));
3708
3848
  }
3709
3849
  /**
3710
3850
  * Returns the current timeline instance.
@@ -3748,6 +3888,16 @@ function useTimeline(namespace = "v0:timeline") {
3748
3888
  * - Configurable overscan (extra items rendered for smooth scrolling)
3749
3889
  *
3750
3890
  * Perfect for large data sets, chat apps, and infinite scroll implementations.
3891
+ *
3892
+ * @example
3893
+ * ```ts
3894
+ * import { shallowRef } from 'vue'
3895
+ * import { createVirtual } from '@vuetify/v0'
3896
+ *
3897
+ * const items = shallowRef(Array.from({ length: 10000 }, (_, i) => ({ id: i })))
3898
+ * const virtual = createVirtual(items, { itemHeight: 40 })
3899
+ * console.log(virtual.items.value)
3900
+ * ```
3751
3901
  */
3752
3902
  /**
3753
3903
  * Virtual scrolling composable for efficiently rendering large lists
@@ -4040,12 +4190,7 @@ function createVirtual(items, _options = {}) {
4040
4190
  */
4041
4191
  function createVirtualContext(items, _options = {}) {
4042
4192
  const { namespace = "v0:virtual", ...options } = _options;
4043
- const [useVirtualContext, _provideVirtualContext] = createContext(namespace);
4044
- const context = createVirtual(items, options);
4045
- function provideVirtualContext(_context = context, app) {
4046
- return _provideVirtualContext(_context, app);
4047
- }
4048
- return createTrinity(useVirtualContext, provideVirtualContext, context);
4193
+ return createTrinity(namespace, createVirtual(items, options));
4049
4194
  }
4050
4195
  /**
4051
4196
  * Returns the current virtual context from dependency injection.
@@ -4095,6 +4240,16 @@ function useVirtual(namespace = "v0:virtual") {
4095
4240
  * - Type preservation
4096
4241
  *
4097
4242
  * Perfect for creating reactive versions of plain objects while automatically unwrapping refs.
4243
+ *
4244
+ * @example
4245
+ * ```ts
4246
+ * import { shallowRef } from 'vue'
4247
+ * import { toReactive } from '@vuetify/v0'
4248
+ *
4249
+ * const source = { name: shallowRef('Alice'), age: 30 }
4250
+ * const reactive = toReactive(source)
4251
+ * console.log(reactive.name) // 'Alice' (auto-unwrapped)
4252
+ * ```
4098
4253
  */
4099
4254
  function createMapProxy(refObject) {
4100
4255
  let mapProxy;
@@ -4252,6 +4407,14 @@ function toReactive(objectRef) {
4252
4407
  * - Custom breakpoint configuration
4253
4408
  *
4254
4409
  * Perfect for responsive layouts and conditional rendering based on screen size.
4410
+ *
4411
+ * @example
4412
+ * ```ts
4413
+ * import { useBreakpoints } from '@vuetify/v0'
4414
+ *
4415
+ * const { current, isMobile, smAndUp } = useBreakpoints()
4416
+ * console.log(current.value) // 'md'
4417
+ * ```
4255
4418
  */
4256
4419
  /**
4257
4420
  * Creates default breakpoint configuration.
@@ -4590,12 +4753,7 @@ function createDate(options) {
4590
4753
  */
4591
4754
  function createDateContext(options) {
4592
4755
  const { namespace = "v0:date", ...dateOptions } = options;
4593
- const [useDateContext, _provideDateContext] = createContext(namespace);
4594
- const context = createDate(dateOptions);
4595
- function provideDateContext(_context = context, app) {
4596
- return _provideDateContext(_context, app);
4597
- }
4598
- return createTrinity(useDateContext, provideDateContext, context);
4756
+ return createTrinity(namespace, createDate(dateOptions));
4599
4757
  }
4600
4758
  /**
4601
4759
  * Creates a new date plugin.
@@ -4703,7 +4861,7 @@ function normalizeKey(key) {
4703
4861
  }
4704
4862
  //#endregion
4705
4863
  //#region src/composables/useHotkey/parsing.ts
4706
- const logger = useLogger();
4864
+ const logger = /* @__PURE__ */ useLogger();
4707
4865
  const MODIFIERS = [
4708
4866
  "ctrl",
4709
4867
  "shift",
@@ -4879,6 +5037,14 @@ function splitKeySequence(str) {
4879
5037
  * - SSR-safe (no-op when not in browser)
4880
5038
  *
4881
5039
  * Builds on useEventListener for lifecycle-managed keyboard events.
5040
+ *
5041
+ * @example
5042
+ * ```ts
5043
+ * import { useHotkey } from '@vuetify/v0'
5044
+ *
5045
+ * useHotkey('ctrl+k', () => console.log('opened palette'))
5046
+ * useHotkey('g-h', () => console.log('go home'))
5047
+ * ```
4882
5048
  */
4883
5049
  const isMac = IN_BROWSER && /mac|iphone|ipad|ipod/i.test(navigator?.userAgent ?? "");
4884
5050
  /**
@@ -4922,6 +5088,7 @@ function useHotkey(keys, callback, options = {}, _platform) {
4922
5088
  let isSequence = false;
4923
5089
  let groupIndex = 0;
4924
5090
  function isInputFocused() {
5091
+ if (!IN_BROWSER) return false;
4925
5092
  if (toValue(inputs)) return false;
4926
5093
  const activeElement = document.activeElement;
4927
5094
  if (!activeElement) return false;
@@ -5050,6 +5217,115 @@ function matchesKeyGroup(e, group, platformIsMac) {
5050
5217
  return modifiersMatch && e.key.toLowerCase() === actualKey.toLowerCase();
5051
5218
  }
5052
5219
  //#endregion
5220
+ //#region src/composables/useImage/index.ts
5221
+ /**
5222
+ * @module useImage
5223
+ *
5224
+ * @see https://0.vuetifyjs.com/composables/system/use-image
5225
+ *
5226
+ * @remarks
5227
+ * Image loading state machine with deferred loading support.
5228
+ *
5229
+ * Key features:
5230
+ * - State machine: idle → loading → loaded | error
5231
+ * - Reactive `eager` gate withholds the source until ready
5232
+ * - Automatic reset when `src` changes
5233
+ * - Manual `retry()` to re-attempt after error
5234
+ * - Bind-ready handlers and gated source
5235
+ * - SSR-safe
5236
+ *
5237
+ * Perfect for image components, lightboxes, lazy-loaded galleries,
5238
+ * and any UI that needs to react to image load state.
5239
+ *
5240
+ * @example
5241
+ * ```ts
5242
+ * import { useImage } from '@vuetify/v0'
5243
+ *
5244
+ * const { status, source, onLoad, onError } = useImage({
5245
+ * src: 'https://example.com/img.png',
5246
+ * })
5247
+ * ```
5248
+ */
5249
+ /**
5250
+ * Tracks image loading state as a reactive state machine.
5251
+ *
5252
+ * @param options Configuration options
5253
+ * @returns Image context with state refs and event handlers
5254
+ *
5255
+ * @see https://0.vuetifyjs.com/composables/system/use-image
5256
+ *
5257
+ * @example
5258
+ * ```ts
5259
+ * import { toRef } from 'vue'
5260
+ * import { useImage } from '@vuetify/v0'
5261
+ *
5262
+ * const props = defineProps<{ src: string }>()
5263
+ *
5264
+ * const { source, isLoaded, onLoad, onError, retry } = useImage({
5265
+ * src: toRef(() => props.src),
5266
+ * })
5267
+ * ```
5268
+ *
5269
+ * @example
5270
+ * Composed with `useIntersectionObserver` for lazy loading:
5271
+ * ```ts
5272
+ * const target = shallowRef<HTMLElement>()
5273
+ * const { isIntersecting } = useIntersectionObserver(target, () => {}, {
5274
+ * once: true,
5275
+ * rootMargin: '200px',
5276
+ * })
5277
+ *
5278
+ * const { source, onLoad, onError } = useImage({
5279
+ * src: toRef(() => props.src),
5280
+ * eager: isIntersecting,
5281
+ * })
5282
+ * ```
5283
+ */
5284
+ function useImage(options) {
5285
+ const { src, eager = true } = options;
5286
+ const status = shallowRef(toValue(eager) ? "loading" : "idle");
5287
+ const isIdle = toRef(() => status.value === "idle");
5288
+ const isLoading = toRef(() => status.value === "loading");
5289
+ const isLoaded = toRef(() => status.value === "loaded");
5290
+ const isError = toRef(() => status.value === "error");
5291
+ const source = toRef(() => status.value === "idle" ? void 0 : toValue(src));
5292
+ function onLoad() {
5293
+ status.value = "loaded";
5294
+ }
5295
+ function onError() {
5296
+ status.value = "error";
5297
+ }
5298
+ function retry() {
5299
+ const resumeAs = toValue(eager) ? "loading" : "idle";
5300
+ status.value = "idle";
5301
+ nextTick(() => {
5302
+ status.value = resumeAs;
5303
+ });
5304
+ }
5305
+ const stopEager = watch(() => toValue(eager), (value) => {
5306
+ if (value && status.value === "idle") status.value = "loading";
5307
+ else if (!value && status.value !== "loaded" && status.value !== "error") status.value = "idle";
5308
+ });
5309
+ const stopSrc = watch(() => toValue(src), () => {
5310
+ status.value = toValue(eager) ? "loading" : "idle";
5311
+ });
5312
+ onScopeDispose(() => {
5313
+ stopEager();
5314
+ stopSrc();
5315
+ }, true);
5316
+ return {
5317
+ status: shallowReadonly(status),
5318
+ isIdle,
5319
+ isLoading,
5320
+ isLoaded,
5321
+ isError,
5322
+ source,
5323
+ onLoad,
5324
+ onError,
5325
+ retry
5326
+ };
5327
+ }
5328
+ //#endregion
5053
5329
  //#region src/composables/useIntersectionObserver/index.ts
5054
5330
  /**
5055
5331
  * @module useIntersectionObserver
@@ -5070,6 +5346,17 @@ function matchesKeyGroup(e, group, platformIsMac) {
5070
5346
  * - Immediate callback option
5071
5347
  *
5072
5348
  * Perfect for lazy loading, infinite scroll, and visibility detection.
5349
+ *
5350
+ * @example
5351
+ * ```ts
5352
+ * import { useTemplateRef } from 'vue'
5353
+ * import { useIntersectionObserver } from '@vuetify/v0'
5354
+ *
5355
+ * const target = useTemplateRef('target')
5356
+ * useIntersectionObserver(target, entries => {
5357
+ * console.log(entries[0].isIntersecting)
5358
+ * })
5359
+ * ```
5073
5360
  */
5074
5361
  /**
5075
5362
  * A composable that uses the Intersection Observer API to detect when an element
@@ -5230,6 +5517,15 @@ function useElementIntersection(target, options = {}) {
5230
5517
  *
5231
5518
  * Perfect for dialogs, menus, tooltips, and any component with
5232
5519
  * conditionally rendered content.
5520
+ *
5521
+ * @example
5522
+ * ```ts
5523
+ * import { shallowRef } from 'vue'
5524
+ * import { useLazy } from '@vuetify/v0'
5525
+ *
5526
+ * const isOpen = shallowRef(false)
5527
+ * const { hasContent, onAfterLeave } = useLazy(isOpen)
5528
+ * ```
5233
5529
  */
5234
5530
  /**
5235
5531
  * Deferred content rendering for performance optimization.
@@ -5320,6 +5616,14 @@ function useLazy(active, options = {}) {
5320
5616
  * - Supports both static and dynamic queries
5321
5617
  *
5322
5618
  * Perfect for responsive conditionals beyond breakpoint detection.
5619
+ *
5620
+ * @example
5621
+ * ```ts
5622
+ * import { useMediaQuery } from '@vuetify/v0'
5623
+ *
5624
+ * const { matches } = useMediaQuery('(prefers-color-scheme: dark)')
5625
+ * console.log(matches.value) // true/false
5626
+ * ```
5323
5627
  */
5324
5628
  /**
5325
5629
  * Reactive media query matching.
@@ -5440,6 +5744,17 @@ function usePrefersContrast() {
5440
5744
  * - Configurable observation options (childList, attributes, characterData, etc.)
5441
5745
  *
5442
5746
  * Perfect for detecting DOM changes and responding to mutations.
5747
+ *
5748
+ * @example
5749
+ * ```ts
5750
+ * import { useTemplateRef } from 'vue'
5751
+ * import { useMutationObserver } from '@vuetify/v0'
5752
+ *
5753
+ * const target = useTemplateRef('target')
5754
+ * useMutationObserver(target, records => {
5755
+ * console.log(records)
5756
+ * }, { childList: true })
5757
+ * ```
5443
5758
  */
5444
5759
  /**
5445
5760
  * A composable that uses the Mutation Observer API to detect changes in the DOM.
@@ -5551,6 +5866,14 @@ function useMutationObserver(target, callback, options = {}) {
5551
5866
  * - Toast queue with pause/resume and auto-dismiss
5552
5867
  * - Adapter integration via event system
5553
5868
  * - Plugin installation via createNotificationsPlugin
5869
+ *
5870
+ * @example
5871
+ * ```ts
5872
+ * import { useNotifications } from '@vuetify/v0'
5873
+ *
5874
+ * const notifications = useNotifications()
5875
+ * notifications.send({ subject: 'Saved', severity: 'success' })
5876
+ * ```
5554
5877
  */
5555
5878
  function createNotifications(options = {}) {
5556
5879
  const { timeout = 3e3, ...registryOptions } = options;
@@ -6072,6 +6395,15 @@ const [createNotificationsContext, createNotificationsPlugin, useNotifications]
6072
6395
  * - Re-entry during leave: cancels exit, stays mounted
6073
6396
  * - Immediate mode: auto-unmounts if done() not called (fast path)
6074
6397
  * - SSR-safe: starts unmounted
6398
+ *
6399
+ * @example
6400
+ * ```ts
6401
+ * import { shallowRef } from 'vue'
6402
+ * import { usePresence } from '@vuetify/v0'
6403
+ *
6404
+ * const isOpen = shallowRef(false)
6405
+ * const { isMounted, state, done } = usePresence({ present: isOpen })
6406
+ * ```
6075
6407
  */
6076
6408
  /**
6077
6409
  * Animation-agnostic mount lifecycle management.
@@ -6183,6 +6515,16 @@ function usePresence(options) {
6183
6515
  * - Works with any ModelContext (Selection, Slider, etc.)
6184
6516
  *
6185
6517
  * Bridges the gap between model composables and Vue's v-model.
6518
+ *
6519
+ * @example
6520
+ * ```ts
6521
+ * import { shallowRef } from 'vue'
6522
+ * import { createSelection, useProxyModel } from '@vuetify/v0'
6523
+ *
6524
+ * const selection = createSelection({ events: true })
6525
+ * const model = shallowRef<string[]>([])
6526
+ * useProxyModel(selection, model, { multiple: true })
6527
+ * ```
6186
6528
  */
6187
6529
  /**
6188
6530
  * Syncs a ref with a model context bidirectionally.
@@ -6287,6 +6629,16 @@ function useProxyModel(context, model, options) {
6287
6629
  * - Callable function with cancel method
6288
6630
  *
6289
6631
  * Perfect for throttling updates to the next animation frame.
6632
+ *
6633
+ * @example
6634
+ * ```ts
6635
+ * import { useRaf } from '@vuetify/v0'
6636
+ *
6637
+ * const update = useRaf(timestamp => {
6638
+ * // runs on next animation frame
6639
+ * })
6640
+ * update()
6641
+ * ```
6290
6642
  */
6291
6643
  /**
6292
6644
  * Scope-disposed safe requestAnimationFrame.
@@ -6355,6 +6707,15 @@ function useRaf(callback) {
6355
6707
  * - Auto-attaches keydown listener when target is provided
6356
6708
  *
6357
6709
  * Perfect for toolbars, menus, tree items, grids, and other composite widgets.
6710
+ *
6711
+ * @example
6712
+ * ```ts
6713
+ * import { useRovingFocus } from '@vuetify/v0'
6714
+ *
6715
+ * const items = () => [{ id: 'a' }, { id: 'b' }, { id: 'c' }]
6716
+ * const focus = useRovingFocus(items, { orientation: 'horizontal' })
6717
+ * focus.next()
6718
+ * ```
6358
6719
  */
6359
6720
  function useRovingFocus(items, options = {}) {
6360
6721
  const { orientation, circular, columns, onFocus, target } = options;
@@ -6432,6 +6793,14 @@ var Vuetify0RtlAdapter = class {
6432
6793
  * - Subtree overrides via context provision
6433
6794
  *
6434
6795
  * Independent from useLocale — Vuetify connects them via adapter.
6796
+ *
6797
+ * @example
6798
+ * ```ts
6799
+ * import { useRtl } from '@vuetify/v0'
6800
+ *
6801
+ * const { isRtl, toggle } = useRtl()
6802
+ * toggle() // flip direction
6803
+ * ```
6435
6804
  */
6436
6805
  /**
6437
6806
  * Creates a new RTL direction instance.
@@ -6483,6 +6852,15 @@ const [createRtlContext, createRtlPlugin, useRtl] = createPluginContext("v0:rtl"
6483
6852
  * - Auto-cleanup when registered within component setup
6484
6853
  *
6485
6854
  * Built on createSelection for consistent ticket-based management.
6855
+ *
6856
+ * @example
6857
+ * ```ts
6858
+ * import { useStack } from '@vuetify/v0'
6859
+ *
6860
+ * const stack = useStack()
6861
+ * const ticket = stack.register({ onDismiss: () => console.log('dismissed') })
6862
+ * ticket.select()
6863
+ * ```
6486
6864
  */
6487
6865
  /**
6488
6866
  * Creates a new stack instance for managing overlay z-indexes.
@@ -6600,12 +6978,7 @@ function createStack(_options = {}) {
6600
6978
  */
6601
6979
  function createStackContext(_options = {}) {
6602
6980
  const { namespace = "v0:stack", ...options } = _options;
6603
- const [useStackContext, _provideStackContext] = createContext(namespace);
6604
- const context = createStack(options);
6605
- function provideStackContext(_context = context, app) {
6606
- return _provideStackContext(_context, app);
6607
- }
6608
- return createTrinity(useStackContext, provideStackContext, context);
6981
+ return createTrinity(namespace, createStack(options));
6609
6982
  }
6610
6983
  /**
6611
6984
  * Creates a Vue plugin to provide stack context at app level.
@@ -6712,6 +7085,15 @@ function useStack(namespace = "v0:stack") {
6712
7085
  * - Automatic cleanup on remove/clear
6713
7086
  *
6714
7087
  * Uses adapter pattern to abstract storage implementation details.
7088
+ *
7089
+ * @example
7090
+ * ```ts
7091
+ * import { useStorage } from '@vuetify/v0'
7092
+ *
7093
+ * const storage = useStorage()
7094
+ * const theme = storage.get('theme', 'light')
7095
+ * theme.value = 'dark' // persists automatically
7096
+ * ```
6715
7097
  */
6716
7098
  /**
6717
7099
  * Creates a new storage instance.
@@ -6753,7 +7135,7 @@ function createStorage(options = {}) {
6753
7135
  if (/* @__PURE__ */ isNullOrUndefined(raw)) return void 0;
6754
7136
  try {
6755
7137
  const parsed = serializer.read(raw);
6756
- if (ttl && /* @__PURE__ */ isObject(parsed) && "__ttl" in parsed && "__v" in parsed) {
7138
+ if (ttl && /* @__PURE__ */ isObject(parsed) && "__v0" in parsed && "__v" in parsed) {
6757
7139
  const envelope = parsed;
6758
7140
  if (Date.now() - envelope.__t > ttl) {
6759
7141
  adapter?.removeItem(prefixedKey);
@@ -6769,7 +7151,7 @@ function createStorage(options = {}) {
6769
7151
  }
6770
7152
  function writeStored(prefixedKey, value) {
6771
7153
  const wrapped = ttl ? {
6772
- __ttl: 1,
7154
+ __v0: 1,
6773
7155
  __v: value,
6774
7156
  __t: Date.now()
6775
7157
  } : value;
@@ -6859,6 +7241,17 @@ const [createStorageContext, createStoragePlugin, useStorage] = createPluginCont
6859
7241
  *
6860
7242
  * Perfect for conditional side effects, feature flags, and performance optimization
6861
7243
  * by only running reactive effects when needed.
7244
+ *
7245
+ * @example
7246
+ * ```ts
7247
+ * import { shallowRef } from 'vue'
7248
+ * import { useToggleScope } from '@vuetify/v0'
7249
+ *
7250
+ * const isEnabled = shallowRef(false)
7251
+ * const { isActive } = useToggleScope(isEnabled, () => {
7252
+ * // effects run while isEnabled is true
7253
+ * })
7254
+ * ```
6862
7255
  */
6863
7256
  /**
6864
7257
  * Conditionally manages an effect scope based on a reactive boolean source.
@@ -6954,6 +7347,15 @@ function useToggleScope(source, fn) {
6954
7347
  * - Multiple overloads for type safety
6955
7348
  *
6956
7349
  * Perfect for safely managing event listeners in Vue components.
7350
+ *
7351
+ * @example
7352
+ * ```ts
7353
+ * import { useEventListener } from '@vuetify/v0'
7354
+ *
7355
+ * useEventListener(window, 'resize', () => {
7356
+ * console.log('window resized')
7357
+ * })
7358
+ * ```
6957
7359
  */
6958
7360
  /**
6959
7361
  * Attaches an event listener to a target.
@@ -7050,6 +7452,15 @@ function useDocumentEventListener(event, listener, options) {
7050
7452
  * Accessibility: This composable handles pointer interactions only. For accessible
7051
7453
  * components (dialogs, popovers, menus), pair with `useHotkey` for Escape key
7052
7454
  * dismissal per WCAG/APG requirements.
7455
+ *
7456
+ * @example
7457
+ * ```ts
7458
+ * import { useTemplateRef } from 'vue'
7459
+ * import { useClickOutside } from '@vuetify/v0'
7460
+ *
7461
+ * const target = useTemplateRef('popover')
7462
+ * useClickOutside(target, () => console.log('clicked outside'))
7463
+ * ```
7053
7464
  */
7054
7465
  /**
7055
7466
  * Detects clicks outside of the specified element(s).
@@ -7237,6 +7648,7 @@ function useClickOutside(target, handler, options = {}) {
7237
7648
  * Handle window blur - detect focus moving to iframe.
7238
7649
  */
7239
7650
  function onBlur(event) {
7651
+ if (!IN_BROWSER) return;
7240
7652
  if (isPaused.value) return;
7241
7653
  if (event.defaultPrevented) return;
7242
7654
  if (document.activeElement instanceof HTMLIFrameElement) {
@@ -7287,4 +7699,4 @@ function useClickOutside(target, handler, options = {}) {
7287
7699
  };
7288
7700
  }
7289
7701
  //#endregion
7290
- export { createStepContext as $, usePrefersContrast as A, createValidation as At, useDate as B, usePopover as Bt, usePresence as C, createNumeric as Ct, useNotifications as D, multipleOpenStrategy as Dt, createNotificationsPlugin as E, useNested as Et, useIntersectionObserver as F, createComboboxContext as Ft, toReactive as G, createBreakpointsContext as H, createBreadcrumbs as Ht, useHotkey as I, useCombobox as It, useVirtual as J, createVirtual as K, createDate as L, ServerAdapter as Lt, usePrefersReducedMotion as M, createFormContext as Mt, useLazy as N, useForm as Nt, useMutationObserver as O, singleOpenStrategy as Ot, useElementIntersection as P, createCombobox as Pt, createStep as Q, createDateContext as R, ClientAdapter as Rt, useProxyModel as S, createNumberField as St, createNotificationsContext as T, createNestedContext as Tt, createBreakpointsPlugin as U, createBreadcrumbsContext as Ut, createBreakpoints as V, useTimer as Vt, useBreakpoints as W, useBreadcrumbs as Wt, createTimelineContext as X, createTimeline as Y, useTimeline as Z, createRtlPlugin as _, createFallbackHydration as _t, useToggleScope as a, createQueue as at, useRovingFocus as b, createHydrationPlugin as bt, createStoragePlugin as c, createProgress as ct, createStackContext as d, createOverflow as dt, useStep as et, createStackPlugin as f, createOverflowContext as ft, createRtlFallback as g, toElement as gt, createRtlContext as h, useResizeObserver as ht, useWindowEventListener as i, useRating as it, usePrefersDark as j, createForm as jt, useMediaQuery as k, createInput as kt, useStorage as l, createProgressContext as lt, createRtl as m, useElementSize as mt, useDocumentEventListener as n, createRating as nt, createStorage as o, createQueueContext as ot, useStack as p, useOverflow as pt, createVirtualContext as q, useEventListener as r, createRatingContext as rt, createStorageContext as s, useQueue as st, useClickOutside as t, createSlider as tt, createStack as u, useProgress as ut, useRtl as v, createHydration as vt, createNotifications as w, createNested as wt, useRaf as x, useHydration as xt, Vuetify0RtlAdapter as y, createHydrationContext as yt, createDatePlugin as z, useVirtualFocus as zt };
7702
+ export { createStep as $, usePrefersContrast as A, createForm as At, createDatePlugin as B, useTimer as Bt, usePresence as C, createNumberField as Ct, useNotifications as D, useNested as Dt, createNotificationsPlugin as E, createNestedContext as Et, useIntersectionObserver as F, useCombobox as Ft, useBreakpoints as G, createBreakpoints as H, createBreadcrumbsContext as Ht, useImage as I, ServerAdapter as It, createVirtualContext as J, toReactive as K, useHotkey as L, ClientAdapter as Lt, usePrefersReducedMotion as M, useForm as Mt, useLazy as N, createCombobox as Nt, useMutationObserver as O, createInput as Ot, useElementIntersection as P, createComboboxContext as Pt, useTimeline as Q, createDate as R, useVirtualFocus as Rt, useProxyModel as S, useHydration as St, createNotificationsContext as T, createNested as Tt, createBreakpointsContext as U, useBreadcrumbs as Ut, useDate as V, createBreadcrumbs as Vt, createBreakpointsPlugin as W, createTimeline as X, useVirtual as Y, createTimelineContext as Z, createRtlPlugin as _, toElement as _t, useToggleScope as a, useRating as at, useRovingFocus as b, createHydrationContext as bt, createStoragePlugin as c, useQueue as ct, createStackContext as d, useProgress as dt, createStepContext as et, createStackPlugin as f, createOverflow as ft, createRtlFallback as g, useResizeObserver as gt, createRtlContext as h, useElementSize as ht, useWindowEventListener as i, createRatingContext as it, usePrefersDark as j, createFormContext as jt, useMediaQuery as k, createValidation as kt, useStorage as l, createProgress as lt, createRtl as m, useOverflow as mt, useDocumentEventListener as n, createSlider as nt, createStorage as o, createQueue as ot, useStack as p, createOverflowContext as pt, createVirtual as q, useEventListener as r, createRating as rt, createStorageContext as s, createQueueContext as st, useClickOutside as t, useStep as tt, createStack as u, createProgressContext as ut, useRtl as v, createFallbackHydration as vt, createNotifications as w, createNumeric as wt, useRaf as x, createHydrationPlugin as xt, Vuetify0RtlAdapter as y, createHydration as yt, createDateContext as z, usePopover as zt };