@vuetify/v0 1.0.0-alpha.0 → 1.0.0-alpha.2

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 (160) hide show
  1. package/README.md +5 -1
  2. package/dist/{adapter-T7AedXkz.d.mts → adapter-58IvIfAZ.d.mts} +1 -1
  3. package/dist/{adapter-Drq1v5wV.mjs → adapter-Be9zUc-n.mjs} +6 -3
  4. package/dist/{adapter-CcHB7rs3.d.mts → adapter-BvWEd9w-.d.mts} +2 -2
  5. package/dist/{adapter-BZjmDNJF.d.mts → adapter-DlX3FA3A.d.mts} +2 -2
  6. package/dist/{adapter-CCIeOzqr.mjs → adapter-gQ2SNKZq.mjs} +31 -22
  7. package/dist/{adapters-D49L7m2R.mjs → adapters-BJ5n7rgh.mjs} +1 -1
  8. package/dist/adapters-BnKW0BF_.mjs +2 -0
  9. package/dist/adapters-CBrvizWb.mjs +4 -0
  10. package/dist/adapters-CMJGA1k7.mjs +2 -0
  11. package/dist/adapters-Dse4bPxk.mjs +5 -0
  12. package/dist/browser/index.js +4845 -3272
  13. package/dist/components/index.d.mts +3 -3
  14. package/dist/components/index.mjs +2 -2
  15. package/dist/{components-Dc7sUTsg.mjs → components-CqDewYTU.mjs} +1407 -411
  16. package/dist/composables/index.d.mts +19 -19
  17. package/dist/composables/index.mjs +28 -26
  18. package/dist/{consola-Byg0ybzh.d.mts → consola-BdgyPEfx.d.mts} +1 -1
  19. package/dist/constants/index.d.mts +2 -2
  20. package/dist/constants/index.mjs +3 -3
  21. package/dist/{createDataTable-BbUL9Vva.mjs → createDataTable-rXBqGglI.mjs} +105 -32
  22. package/dist/{createGroup-C2WCfYPB.mjs → createGroup-BU4olYtB.mjs} +29 -14
  23. package/dist/{createPagination-Tp4C4He8.mjs → createPagination-CHF7SmmK.mjs} +11 -7
  24. package/dist/{createTokens-qv02qq4_.mjs → createRegistry-Dl-bSSTr.mjs} +21 -302
  25. package/dist/{createSelection-AmMX6sjc.mjs → createSelection-Csaa-C8p.mjs} +28 -21
  26. package/dist/{createSingle-CffpxK__.mjs → createSingle-8xbHAIpY.mjs} +13 -17
  27. package/dist/createTokens-lNg2M_P_.mjs +302 -0
  28. package/dist/{createTrinity-vvXk0ARD.mjs → createTrinity-BTCs1pYx.mjs} +34 -31
  29. package/dist/data-table/adapters/client/index.d.mts +1 -1
  30. package/dist/data-table/adapters/client/index.mjs +1 -1
  31. package/dist/data-table/adapters/index.d.mts +4 -4
  32. package/dist/data-table/adapters/index.mjs +5 -5
  33. package/dist/data-table/adapters/server/index.d.mts +1 -1
  34. package/dist/data-table/adapters/server/index.mjs +1 -1
  35. package/dist/data-table/adapters/virtual/index.d.mts +1 -1
  36. package/dist/data-table/adapters/virtual/index.mjs +1 -1
  37. package/dist/data-table/index.d.mts +6 -6
  38. package/dist/data-table/index.mjs +6 -6
  39. package/dist/date/index.d.mts +2 -2
  40. package/dist/date/index.mjs +4 -4
  41. package/dist/features/adapters/flagsmith/index.d.mts +1 -1
  42. package/dist/features/adapters/flagsmith/index.mjs +1 -1
  43. package/dist/features/adapters/launchdarkly/index.d.mts +1 -1
  44. package/dist/features/adapters/launchdarkly/index.mjs +1 -1
  45. package/dist/features/adapters/posthog/index.d.mts +1 -1
  46. package/dist/features/adapters/posthog/index.mjs +1 -1
  47. package/dist/features/index.d.mts +2 -2
  48. package/dist/features/index.mjs +1 -1
  49. package/dist/{globals-CAv9vqkP.mjs → globals-CKdzjeLe.mjs} +1 -1
  50. package/dist/htmlElements-D4oMQZPJ.mjs +28 -0
  51. package/dist/{index-M8EpGjjA.d.mts → index-1XdASTjp.d.mts} +1 -1
  52. package/dist/{index-D26_u_WI.d.mts → index-B7cqgTBL.d.mts} +1599 -468
  53. package/dist/{index-DoGxDgdN.d.mts → index-BJGcVy7e.d.mts} +57 -6
  54. package/dist/index-BgCkepP_.d.mts +31 -0
  55. package/dist/{index-B_XLHftL.d.mts → index-BxKMMWnQ.d.mts} +301 -263
  56. package/dist/{index-tyzwWFHS.d.mts → index-BzFHTW59.d.mts} +1 -1
  57. package/dist/{index-CDcl4wPo.d.mts → index-CT5SCLzW.d.mts} +1 -1
  58. package/dist/{index-BUsrN1vL.d.mts → index-DE3bWw11.d.mts} +2 -2
  59. package/dist/{index-76fQGkkO.d.mts → index-DTvqw22G.d.mts} +8 -11
  60. package/dist/{index-F2Fmxnzi.d.mts → index-Dp1HjBxJ.d.mts} +1 -1
  61. package/dist/{index-B_AlCD7t.d.mts → index-DuddF-NR.d.mts} +2 -9
  62. package/dist/{index-Dxx0eMLi.d.mts → index-GOpjKzaJ.d.mts} +1 -1
  63. package/dist/index.d.mts +23 -23
  64. package/dist/index.mjs +31 -29
  65. package/dist/json/attributes.json +280 -4
  66. package/dist/json/importMap.json +60 -0
  67. package/dist/json/tags.json +136 -2
  68. package/dist/json/web-types.json +1186 -347
  69. package/dist/locale/adapters/index.d.mts +2 -2
  70. package/dist/locale/adapters/index.mjs +2 -2
  71. package/dist/locale/adapters/v0/index.d.mts +1 -1
  72. package/dist/locale/adapters/v0/index.mjs +1 -1
  73. package/dist/locale/adapters/vue-i18n/index.d.mts +1 -1
  74. package/dist/locale/index.d.mts +3 -3
  75. package/dist/locale/index.mjs +2 -2
  76. package/dist/logger/adapters/consola/index.d.mts +1 -1
  77. package/dist/logger/adapters/index.d.mts +4 -4
  78. package/dist/logger/adapters/index.mjs +2 -2
  79. package/dist/logger/adapters/pino/index.d.mts +1 -1
  80. package/dist/logger/adapters/v0/index.d.mts +1 -1
  81. package/dist/logger/adapters/v0/index.mjs +1 -1
  82. package/dist/logger/index.d.mts +5 -5
  83. package/dist/logger/index.mjs +2 -2
  84. package/dist/notifications/index.d.mts +2 -2
  85. package/dist/notifications/index.mjs +3 -54
  86. package/dist/palettes/ant/generate/index.mjs +1 -0
  87. package/dist/palettes/ant/index.d.mts +1 -1
  88. package/dist/palettes/index.d.mts +3 -3
  89. package/dist/palettes/leonardo/generate/index.mjs +1 -0
  90. package/dist/palettes/material/generate/index.mjs +1 -0
  91. package/dist/palettes/material/index.d.mts +1 -1
  92. package/dist/palettes/md1/index.d.mts +1 -1
  93. package/dist/palettes/md2/index.d.mts +1 -1
  94. package/dist/palettes/radix/index.d.mts +1 -1
  95. package/dist/palettes/tailwind/index.d.mts +1 -1
  96. package/dist/permissions/adapters/index.d.mts +1 -1
  97. package/dist/permissions/adapters/index.mjs +2 -2
  98. package/dist/permissions/adapters/v0/index.d.mts +1 -1
  99. package/dist/permissions/adapters/v0/index.mjs +1 -1
  100. package/dist/permissions/index.d.mts +1 -1
  101. package/dist/permissions/index.mjs +2 -2
  102. package/dist/{pino-BxddSW2l.d.mts → pino-DNfCEb0p.d.mts} +1 -1
  103. package/dist/{posthog-B8PEtlFr.mjs → posthog-DZNnPXxS.mjs} +1 -1
  104. package/dist/rules/index.d.mts +1 -1
  105. package/dist/rules/index.mjs +1 -1
  106. package/dist/{server-DNUTnISs.d.mts → server-3ilWFwqe.d.mts} +1 -1
  107. package/dist/{server-CIftA0pK.mjs → server-y7zLSCSx.mjs} +1 -1
  108. package/dist/storage/adapters/index.d.mts +2 -2
  109. package/dist/storage/adapters/index.mjs +1 -1
  110. package/dist/storage/adapters/memory/index.d.mts +1 -1
  111. package/dist/storage/adapters/memory/index.mjs +1 -1
  112. package/dist/storage/index.d.mts +3 -3
  113. package/dist/storage/index.mjs +2 -2
  114. package/dist/theme/adapters/index.d.mts +1 -1
  115. package/dist/theme/adapters/index.mjs +4 -4
  116. package/dist/theme/adapters/unhead/index.d.mts +1 -1
  117. package/dist/theme/adapters/unhead/index.mjs +1 -1
  118. package/dist/theme/adapters/v0/index.d.mts +1 -1
  119. package/dist/theme/adapters/v0/index.mjs +1 -1
  120. package/dist/theme/index.d.mts +1 -1
  121. package/dist/theme/index.mjs +3 -3
  122. package/dist/{toArray-doLQVI56.mjs → toArray-as9BWxBK.mjs} +10 -0
  123. package/dist/types/index.d.mts +2 -2
  124. package/dist/{unhead-BYw3a366.mjs → unhead-DZiD-4Tx.mjs} +2 -2
  125. package/dist/{useClickOutside-CnCQkh7M.mjs → useClickOutside-CmCUD_Pf.mjs} +577 -1024
  126. package/dist/{useFeatures-CMpkbU8Q.mjs → useFeatures-ZIvzzuEV.mjs} +16 -6
  127. package/dist/{useLocale-BYmoHpo6.mjs → useLocale-DTJx3aKR.mjs} +19 -7
  128. package/dist/{useLogger-BfaFH-Bi.mjs → useLogger-BBTcMN61.mjs} +33 -16
  129. package/dist/useNotifications-H4knpvNw.mjs +869 -0
  130. package/dist/{usePermissions-y3Uum3nO.mjs → usePermissions-B_G12Dwd.mjs} +14 -6
  131. package/dist/{useRules-eqSXpP9V.mjs → useRules--7Qoo60I.mjs} +15 -5
  132. package/dist/{useTheme-CFH6I91x.mjs → useTheme-Co05TEeD.mjs} +20 -8
  133. package/dist/utilities/index.d.mts +1 -1
  134. package/dist/utilities/index.mjs +14 -9
  135. package/dist/{v0-DXqYgj7J.mjs → v0-BrTEO5sv.mjs} +2 -2
  136. package/dist/{v0-BAG8p0si.d.mts → v0-CdusXjY_.d.mts} +1 -1
  137. package/dist/{v0-CFV8A5PF.mjs → v0-D0Mh3EVG.mjs} +1 -1
  138. package/dist/{v0-BpgPZ1qB.d.mts → v0-D7Fm2C3Y.d.mts} +1 -1
  139. package/dist/{v0-BqikIgl0.mjs → v0-DeiZuexg.mjs} +1 -1
  140. package/dist/{v0-DOq_Ia5H.mjs → v0-Dq3zhexO.mjs} +2 -2
  141. package/dist/{v0-C2UMaHUa.d.mts → v0-DrOub-e1.d.mts} +1 -1
  142. package/dist/{virtual-D1HwNBLS.mjs → virtual-C0yHf1DC.mjs} +2 -2
  143. package/dist/{virtual-BaQWQ9ji.d.mts → virtual-D4fckewC.d.mts} +1 -1
  144. package/package.json +10 -7
  145. package/SKILL.md +0 -95
  146. package/dist/adapters-BOVGPozf.mjs +0 -2
  147. package/dist/adapters-BbNfjyvY.mjs +0 -5
  148. package/dist/adapters-BhNTUuxE.mjs +0 -2
  149. package/dist/adapters-RwNU3wNj.mjs +0 -4
  150. package/dist/htmlElements-DcYtv0hg.mjs +0 -75
  151. package/dist/index-D6mQAEs2.d.mts +0 -79
  152. /package/dist/{adapter-DNKjooxI.d.mts → adapter-Dhq68tz0.d.mts} +0 -0
  153. /package/dist/{flagsmith-DQnnahG5.mjs → flagsmith-Dbh1h8WF.mjs} +0 -0
  154. /package/dist/{index-DxruGeVY.d.mts → index-C6rdXZ7j.d.mts} +0 -0
  155. /package/dist/{index-PWQavSPf.d.mts → index-CFhUdAHM.d.mts} +0 -0
  156. /package/dist/{index-c55Utzva.d.mts → index-CROz1VSV.d.mts} +0 -0
  157. /package/dist/{launchdarkly-2_48EJ1_.mjs → launchdarkly-BKtW-idu.mjs} +0 -0
  158. /package/dist/{memory-DUyWthic.d.mts → memory-CeSQE-QV.d.mts} +0 -0
  159. /package/dist/{memory-XCMtkld1.mjs → memory-oYBvtkgx.mjs} +0 -0
  160. /package/dist/{v0-4OQBCeda.mjs → v0-Bmow1q_x.mjs} +0 -0
@@ -1,22 +1,24 @@
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-CAv9vqkP.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-CKdzjeLe.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-BfaFH-Bi.mjs";
5
- import { a as createRegistry } from "./createTokens-qv02qq4_.mjs";
6
- import { i as createModel, t as createSelection } from "./createSelection-AmMX6sjc.mjs";
7
- import { t as createSingle } from "./createSingle-CffpxK__.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-C2WCfYPB.mjs";
11
- import { a as useLocale } from "./useLocale-BYmoHpo6.mjs";
12
- import "./createPagination-Tp4C4He8.mjs";
13
- import "./createDataTable-BbUL9Vva.mjs";
14
- import { a as useRules, o as isStandardSchema } from "./useRules-eqSXpP9V.mjs";
15
- import "./useFeatures-CMpkbU8Q.mjs";
16
- import "./usePermissions-y3Uum3nO.mjs";
17
- import { t as MemoryAdapter } from "./memory-XCMtkld1.mjs";
18
- import "./useTheme-CFH6I91x.mjs";
19
- import { computed, effectScope, isRef, nextTick, onMounted, onScopeDispose, reactive, readonly, ref, shallowReactive, shallowReadonly, shallowRef, toRef, toValue, unref, watch, watchEffect } from "vue";
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-BBTcMN61.mjs";
5
+ import { t as createRegistry } from "./createRegistry-Dl-bSSTr.mjs";
6
+ import { i as createModel, t as createSelection } from "./createSelection-Csaa-C8p.mjs";
7
+ import { t as createSingle } from "./createSingle-8xbHAIpY.mjs";
8
+ import "./createTokens-lNg2M_P_.mjs";
9
+ import { a as useLocale } from "./useLocale-DTJx3aKR.mjs";
10
+ import { c as useTimer } from "./useNotifications-H4knpvNw.mjs";
11
+ import { t as toArray } from "./toArray-as9BWxBK.mjs";
12
+ import { n as createFilter } from "./adapter-gQ2SNKZq.mjs";
13
+ import { t as createGroup } from "./createGroup-BU4olYtB.mjs";
14
+ import "./createPagination-CHF7SmmK.mjs";
15
+ import "./createDataTable-rXBqGglI.mjs";
16
+ import { a as useRules, o as isStandardSchema } from "./useRules--7Qoo60I.mjs";
17
+ import "./useFeatures-ZIvzzuEV.mjs";
18
+ import "./usePermissions-B_G12Dwd.mjs";
19
+ import { t as MemoryAdapter } from "./memory-oYBvtkgx.mjs";
20
+ import "./useTheme-Co05TEeD.mjs";
21
+ import { computed, effectScope, hasInjectionContext, isRef, nextTick, onMounted, onScopeDispose, reactive, readonly, ref, shallowReactive, shallowReadonly, shallowRef, toRef, toValue, unref, watch, watchEffect } from "vue";
20
22
  //#region src/composables/createBreadcrumbs/index.ts
21
23
  /**
22
24
  * @module createBreadcrumbs
@@ -33,6 +35,16 @@ import { computed, effectScope, isRef, nextTick, onMounted, onScopeDispose, reac
33
35
  * - Trinity pattern for dependency injection
34
36
  *
35
37
  * Inheritance chain: createRegistry → createSelection → createSingle → createBreadcrumbs
38
+ *
39
+ * @example
40
+ * ```ts
41
+ * import { createBreadcrumbs } from '@vuetify/v0'
42
+ *
43
+ * const crumbs = createBreadcrumbs()
44
+ * crumbs.register({ text: 'Home' })
45
+ * crumbs.register({ text: 'Docs' })
46
+ * console.log(crumbs.depth.value) // 2
47
+ * ```
36
48
  */
37
49
  /**
38
50
  * Creates a breadcrumbs navigation model.
@@ -63,6 +75,7 @@ function createBreadcrumbs(options = {}) {
63
75
  const single = createSingle({
64
76
  ...options,
65
77
  reactive: true,
78
+ events: true,
66
79
  enroll: true
67
80
  });
68
81
  const depth = toRef(() => single.size);
@@ -129,12 +142,7 @@ function createBreadcrumbs(options = {}) {
129
142
  */
130
143
  function createBreadcrumbsContext(_options = {}) {
131
144
  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);
145
+ return createTrinity(namespace, createBreadcrumbs(options));
138
146
  }
139
147
  /**
140
148
  * Returns the current breadcrumbs instance from context.
@@ -163,134 +171,6 @@ function useBreadcrumbs(namespace = "v0:breadcrumbs") {
163
171
  return useContext(namespace);
164
172
  }
165
173
  //#endregion
166
- //#region src/composables/useTimer/index.ts
167
- /**
168
- * @module useTimer
169
- *
170
- * @see https://0.vuetifyjs.com/composables/system/use-timer
171
- *
172
- * @remarks
173
- * A reactive timer composable with pause/resume support.
174
- *
175
- * Key features:
176
- * - Start/stop/pause/resume controls
177
- * - Reactive remaining time tracking
178
- * - One-shot (default) or repeating mode
179
- * - Automatic cleanup on scope disposal
180
- * - SSR-safe
181
- */
182
- /**
183
- * Creates a reactive timer with pause/resume support.
184
- *
185
- * @param handler Callback invoked when the timer fires.
186
- * @param options Timer configuration.
187
- * @returns Timer controls and reactive state.
188
- *
189
- * @see https://0.vuetifyjs.com/composables/system/use-timer
190
- *
191
- * @example
192
- * ```ts
193
- * const timer = useTimer(() => console.log('fired'), { duration: 5000 })
194
- *
195
- * timer.start()
196
- * timer.pause()
197
- * timer.resume()
198
- * timer.stop()
199
- * ```
200
- */
201
- function useTimer(handler, options = {}) {
202
- const { duration = 1e3, repeat = false } = options;
203
- const remaining = shallowRef(duration);
204
- const isActive = shallowRef(false);
205
- const isPaused = shallowRef(false);
206
- let timeoutId;
207
- let trackingId;
208
- let startedAt = 0;
209
- let budget = duration;
210
- function clearTimer() {
211
- if (!/* @__PURE__ */ isUndefined(timeoutId)) {
212
- globalThis.clearTimeout(timeoutId);
213
- timeoutId = void 0;
214
- }
215
- }
216
- function startTracking() {
217
- stopTracking();
218
- if (!IN_BROWSER) return;
219
- trackingId = globalThis.setInterval(() => {
220
- if (!isActive.value || isPaused.value) return;
221
- const elapsed = Date.now() - startedAt;
222
- remaining.value = Math.max(0, budget - elapsed);
223
- }, 100);
224
- }
225
- function stopTracking() {
226
- if (!/* @__PURE__ */ isUndefined(trackingId)) {
227
- globalThis.clearInterval(trackingId);
228
- trackingId = void 0;
229
- }
230
- }
231
- function fire() {
232
- clearTimer();
233
- stopTracking();
234
- handler();
235
- if (repeat) begin(duration);
236
- else {
237
- isActive.value = false;
238
- remaining.value = 0;
239
- }
240
- }
241
- function begin(ms) {
242
- clearTimer();
243
- stopTracking();
244
- budget = ms;
245
- startedAt = Date.now();
246
- remaining.value = ms;
247
- isActive.value = true;
248
- isPaused.value = false;
249
- timeoutId = globalThis.setTimeout(fire, ms);
250
- startTracking();
251
- }
252
- function start() {
253
- if (duration < 0) return;
254
- begin(duration);
255
- }
256
- function stop() {
257
- clearTimer();
258
- stopTracking();
259
- isActive.value = false;
260
- isPaused.value = false;
261
- remaining.value = duration;
262
- }
263
- function pause() {
264
- if (!isActive.value || isPaused.value) return;
265
- const elapsed = Date.now() - startedAt;
266
- budget = Math.max(0, budget - elapsed);
267
- remaining.value = budget;
268
- clearTimer();
269
- stopTracking();
270
- isPaused.value = true;
271
- }
272
- function resume() {
273
- if (!isPaused.value) return;
274
- isPaused.value = false;
275
- startedAt = Date.now();
276
- timeoutId = globalThis.setTimeout(fire, budget);
277
- startTracking();
278
- }
279
- onScopeDispose(() => {
280
- clearTimer();
281
- stopTracking();
282
- }, true);
283
- return {
284
- start,
285
- stop,
286
- pause,
287
- resume,
288
- remaining,
289
- isActive,
290
- isPaused
291
- };
292
- }
293
- //#endregion
294
174
  //#region src/composables/usePopover/index.ts
295
175
  /**
296
176
  * @module usePopover
@@ -311,6 +191,15 @@ function useTimer(handler, options = {}) {
311
191
  *
312
192
  * Perfect for building select, combobox, tooltip, and menu components
313
193
  * without wrapping the Popover compound component.
194
+ *
195
+ * @example
196
+ * ```ts
197
+ * import { usePopover } from '@vuetify/v0'
198
+ *
199
+ * const popover = usePopover()
200
+ * popover.open()
201
+ * popover.toggle()
202
+ * ```
314
203
  */
315
204
  function usePopover(options = {}) {
316
205
  const { id: _id, positionArea = "bottom", positionTry = "most-width bottom", showDelay = 0, hideDelay = 0 } = options;
@@ -392,6 +281,15 @@ function usePopover(options = {}) {
392
281
  * useRovingFocus and useVirtualFocus.
393
282
  *
394
283
  * Not exported from the package barrel — consumed only by sibling composables.
284
+ *
285
+ * @example
286
+ * ```ts
287
+ * import { createFocusTraversal } from '#v0/composables/createFocusTraversal'
288
+ *
289
+ * const items = () => [{ id: 'a' }, { id: 'b' }, { id: 'c' }]
290
+ * const traversal = createFocusTraversal(items, id => console.log(id))
291
+ * traversal.next()
292
+ * ```
395
293
  */
396
294
  function mod(length, index) {
397
295
  return (index % length + length) % length;
@@ -574,6 +472,15 @@ function createFocusTraversal(items, activate, options = {}) {
574
472
  *
575
473
  * Perfect for comboboxes, autocompletes, listboxes, and other widgets
576
474
  * where DOM focus must remain on the control element.
475
+ *
476
+ * @example
477
+ * ```ts
478
+ * import { useVirtualFocus } from '@vuetify/v0'
479
+ *
480
+ * const items = () => [{ id: 'a' }, { id: 'b' }, { id: 'c' }]
481
+ * const cursor = useVirtualFocus(items)
482
+ * cursor.next()
483
+ * ```
577
484
  */
578
485
  function useVirtualFocus(items, options) {
579
486
  const { control, target, orientation, circular, columns, onHighlight } = options;
@@ -616,6 +523,9 @@ function useVirtualFocus(items, options) {
616
523
  }
617
524
  const listener = target ?? control;
618
525
  if (listener) useEventListener(listener, "keydown", traversal.onKeydown);
526
+ onScopeDispose(() => {
527
+ clear();
528
+ });
619
529
  return {
620
530
  highlightedId: traversal.activeId,
621
531
  highlight,
@@ -709,6 +619,16 @@ var ServerAdapter = class {
709
619
  * - Strict mode: reverts query to selected value on close if no match
710
620
  * - Popover-based dropdown positioning
711
621
  * - Context DI via createComboboxContext / useCombobox
622
+ *
623
+ * @example
624
+ * ```ts
625
+ * import { createCombobox } from '@vuetify/v0'
626
+ *
627
+ * const combobox = createCombobox({ strict: true })
628
+ * combobox.selection.register({ value: 'Apple' })
629
+ * combobox.selection.register({ value: 'Banana' })
630
+ * combobox.open()
631
+ * ```
712
632
  */
713
633
  /**
714
634
  * Creates a combobox context that orchestrates selection, popover, virtual
@@ -743,7 +663,7 @@ function createCombobox(options = {}) {
743
663
  const hasError = shallowRef(false);
744
664
  const errors = computed(() => {
745
665
  const messages = toValue(errorMessages);
746
- return messages ? toArray(messages) : [];
666
+ return messages ? /* @__PURE__ */ toArray(messages) : [];
747
667
  });
748
668
  const isValid = toRef(() => {
749
669
  if (toValue(error)) return false;
@@ -778,7 +698,7 @@ function createCombobox(options = {}) {
778
698
  const isOpen = popover.isOpen;
779
699
  const cursor = useVirtualFocus(() => selection.values().filter((ticket) => filtered.value.has(ticket.id) && !toValue(ticket.disabled)).map((ticket) => ({
780
700
  id: ticket.id,
781
- el: () => document.querySelector(`#${CSS.escape(`${id}-option-${ticket.id}`)}`),
701
+ el: () => IN_BROWSER ? document.querySelector(`#${CSS.escape(`${id}-option-${ticket.id}`)}`) : null,
782
702
  disabled: ticket.disabled
783
703
  })), {
784
704
  control: inputEl,
@@ -879,12 +799,7 @@ function createCombobox(options = {}) {
879
799
  */
880
800
  function createComboboxContext(options = {}) {
881
801
  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);
802
+ return createTrinity(namespace, createCombobox(rest));
888
803
  }
889
804
  /**
890
805
  * Injects the current combobox context from a parent provider.
@@ -924,6 +839,15 @@ function useCombobox(namespace = "v0:combobox") {
924
839
  *
925
840
  * Per-field validation logic lives in createValidation.
926
841
  * createForm is the mothership — it coordinates, not creates.
842
+ *
843
+ * @example
844
+ * ```ts
845
+ * import { createForm } from '@vuetify/v0'
846
+ *
847
+ * const form = createForm()
848
+ * const isValid = await form.validate()
849
+ * if (isValid) form.submit()
850
+ * ```
927
851
  */
928
852
  /**
929
853
  * Creates a new form instance.
@@ -985,7 +909,7 @@ function createForm(options = {}) {
985
909
  for (const ticket of registry.values()) ticket.value.reset();
986
910
  }
987
911
  async function submit(id) {
988
- const ids = id ? toArray(id) : [...registry.keys()];
912
+ const ids = id ? /* @__PURE__ */ toArray(id) : [...registry.keys()];
989
913
  return (await Promise.all(ids.map(async (key) => {
990
914
  const ticket = registry.get(key);
991
915
  if (!ticket) return true;
@@ -1023,12 +947,7 @@ function createForm(options = {}) {
1023
947
  */
1024
948
  function createFormContext(_options = {}) {
1025
949
  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);
950
+ return createTrinity(namespace, createForm(options));
1032
951
  }
1033
952
  /**
1034
953
  * Returns the current form instance.
@@ -1048,6 +967,7 @@ function createFormContext(_options = {}) {
1048
967
  * ```
1049
968
  */
1050
969
  function useForm(namespace = "v0:form") {
970
+ if (!hasInjectionContext()) return void 0;
1051
971
  try {
1052
972
  return useContext(namespace);
1053
973
  } catch {
@@ -1073,8 +993,18 @@ function useForm(namespace = "v0:form") {
1073
993
  * - Tri-state isValid (null/true/false)
1074
994
  *
1075
995
  * Uses useRules() to resolve alias strings via shared context.
996
+ *
997
+ * @example
998
+ * ```ts
999
+ * import { createValidation } from '@vuetify/v0'
1000
+ *
1001
+ * const validation = createValidation({
1002
+ * rules: [v => !!v || 'Required'],
1003
+ * })
1004
+ * await validation.validate('hello')
1005
+ * ```
1076
1006
  */
1077
- const UNSET = Symbol("unset");
1007
+ const UNSET = /* @__PURE__ */ Symbol("unset");
1078
1008
  /**
1079
1009
  * Creates a per-input validation instance.
1080
1010
  *
@@ -1118,7 +1048,7 @@ function createValidation(_options = {}) {
1118
1048
  const isValidating = shallowRef(false);
1119
1049
  let generation = 0;
1120
1050
  function register(input) {
1121
- if (/* @__PURE__ */ isFunction(input) || /* @__PURE__ */ isString(input) || isStandardSchema(input)) {
1051
+ if (/* @__PURE__ */ isFunction(input) || /* @__PURE__ */ isString(input) || /* @__PURE__ */ isStandardSchema(input)) {
1122
1052
  const resolved = rulesContext.resolve([input]);
1123
1053
  return group.register({ value: resolved[0] ?? (() => true) });
1124
1054
  }
@@ -1146,6 +1076,13 @@ function createValidation(_options = {}) {
1146
1076
  isValid.value = errorMessages.length === 0;
1147
1077
  }
1148
1078
  return errorMessages.length === 0;
1079
+ } catch (error) {
1080
+ if (gen !== generation) return isValid.value ?? false;
1081
+ if (!silent) {
1082
+ errors.value = [error instanceof Error ? error.message : "Validation error"];
1083
+ isValid.value = false;
1084
+ }
1085
+ return false;
1149
1086
  } finally {
1150
1087
  if (gen === generation && !silent) isValidating.value = false;
1151
1088
  }
@@ -1191,6 +1128,16 @@ function createValidation(_options = {}) {
1191
1128
  *
1192
1129
  * No event handling — composables never bind DOM events. Components call
1193
1130
  * validate() and write isFocused/isTouched when they choose.
1131
+ *
1132
+ * @example
1133
+ * ```ts
1134
+ * import { shallowRef } from 'vue'
1135
+ * import { createInput } from '@vuetify/v0'
1136
+ *
1137
+ * const value = shallowRef('')
1138
+ * const input = createInput({ value, label: 'Name', rules: ['required'] })
1139
+ * await input.validate()
1140
+ * ```
1194
1141
  */
1195
1142
  function createInput(options) {
1196
1143
  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;
@@ -1219,7 +1166,7 @@ function createInput(options) {
1219
1166
  }, { flush: "sync" });
1220
1167
  const errors = computed(() => {
1221
1168
  const manual = toValue(errorMessages);
1222
- return [...manual ? toArray(manual) : [], ...validation.errors.value];
1169
+ return [...manual ? /* @__PURE__ */ toArray(manual) : [], ...validation.errors.value];
1223
1170
  });
1224
1171
  const isValid = toRef(() => {
1225
1172
  if (toValue(error)) return false;
@@ -1268,48 +1215,6 @@ function createInput(options) {
1268
1215
  };
1269
1216
  }
1270
1217
  //#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
1218
  //#region src/composables/createNested/index.ts
1314
1219
  /**
1315
1220
  * @module createNested
@@ -1323,17 +1228,20 @@ const singleOpenStrategy = {
1323
1228
  * - Tree traversal utilities (getPath, getDescendants, etc.)
1324
1229
  * - Cascade selection propagation through nested registers
1325
1230
  * - `rootIds` tracking for top-level item detection
1326
- * - Pluggable open strategies
1327
1231
  *
1328
1232
  * Inheritance chain: createSelection → createGroup → createNested
1233
+ *
1234
+ * @example
1235
+ * ```ts
1236
+ * import { createNested } from '@vuetify/v0'
1237
+ *
1238
+ * const tree = createNested()
1239
+ * const root = tree.register({ value: 'root' })
1240
+ * tree.register({ value: 'child', parentId: root.id })
1241
+ * tree.open(root.id)
1242
+ * ```
1329
1243
  */
1330
1244
  /**
1331
- * Resolves open mode to an OpenStrategy.
1332
- */
1333
- function resolveOpenStrategy(open = "multiple") {
1334
- return open === "single" ? singleOpenStrategy : multipleOpenStrategy;
1335
- }
1336
- /**
1337
1245
  * Creates a new nested tree instance with hierarchical management.
1338
1246
  *
1339
1247
  * Extends `createGroup` to support parent-child relationships, tree traversal,
@@ -1372,10 +1280,9 @@ function resolveOpenStrategy(open = "multiple") {
1372
1280
  * ```
1373
1281
  */
1374
1282
  function createNested(_options = {}) {
1375
- const { open: openMode = "multiple", openAll = false, reveal: revealOnOpen = false, selection: selectionMode = "cascade", active: activeMode = "single", openStrategy, ...options } = _options;
1283
+ const { open: openMode = "multiple", openAll = false, reveal: revealOnOpen = false, selection: selectionMode = "cascade", active: activeMode = "single", ...options } = _options;
1376
1284
  const mandatoryOption = _options.mandatory ?? false;
1377
1285
  const multipleOption = _options.multiple ?? true;
1378
- const resolvedOpenStrategy = openStrategy ?? resolveOpenStrategy(openMode);
1379
1286
  const group = createGroup(options);
1380
1287
  const logger = useLogger();
1381
1288
  const children = shallowReactive(/* @__PURE__ */ new Map());
@@ -1402,12 +1309,14 @@ function createNested(_options = {}) {
1402
1309
  }
1403
1310
  function open(ids) {
1404
1311
  if (toValue(group.disabled)) return;
1405
- for (const id of toArray(ids)) {
1312
+ for (const id of /* @__PURE__ */ toArray(ids)) {
1406
1313
  if (!group.has(id)) continue;
1407
1314
  const item = group.get(id);
1408
1315
  if (!item || toValue(item.disabled)) continue;
1409
1316
  openedIds.add(id);
1410
- resolvedOpenStrategy.onOpen?.(id, context);
1317
+ if (openMode === "single") {
1318
+ for (const openedId of openedIds) if (openedId !== id) openedIds.delete(openedId);
1319
+ }
1411
1320
  if (revealOnOpen) {
1412
1321
  let parentId = parents.get(id);
1413
1322
  while (!/* @__PURE__ */ isUndefined(parentId)) {
@@ -1419,17 +1328,16 @@ function createNested(_options = {}) {
1419
1328
  }
1420
1329
  function close(ids) {
1421
1330
  if (toValue(group.disabled)) return;
1422
- for (const id of toArray(ids)) {
1331
+ for (const id of /* @__PURE__ */ toArray(ids)) {
1423
1332
  if (!group.has(id)) continue;
1424
1333
  const item = group.get(id);
1425
1334
  if (!item || toValue(item.disabled)) continue;
1426
1335
  openedIds.delete(id);
1427
- resolvedOpenStrategy.onClose?.(id, context);
1428
1336
  }
1429
1337
  }
1430
1338
  function flip(ids) {
1431
1339
  if (toValue(group.disabled)) return;
1432
- for (const id of toArray(ids)) {
1340
+ for (const id of /* @__PURE__ */ toArray(ids)) {
1433
1341
  if (!group.has(id)) continue;
1434
1342
  const item = group.get(id);
1435
1343
  if (!item || toValue(item.disabled)) continue;
@@ -1442,7 +1350,7 @@ function createNested(_options = {}) {
1442
1350
  * Useful for expanding a section with its immediate subcategories.
1443
1351
  */
1444
1352
  function unfold(ids) {
1445
- for (const id of toArray(ids)) {
1353
+ for (const id of /* @__PURE__ */ toArray(ids)) {
1446
1354
  if (!group.has(id)) continue;
1447
1355
  open(id);
1448
1356
  const childIds = children.get(id) ?? [];
@@ -1454,7 +1362,7 @@ function createNested(_options = {}) {
1454
1362
  * Makes the node visible in a collapsed tree without opening the node itself.
1455
1363
  */
1456
1364
  function reveal(ids) {
1457
- for (const id of toArray(ids)) {
1365
+ for (const id of /* @__PURE__ */ toArray(ids)) {
1458
1366
  if (!group.has(id)) continue;
1459
1367
  const ancestorIds = getAncestors(id);
1460
1368
  if (ancestorIds.length > 0) open(ancestorIds);
@@ -1465,7 +1373,7 @@ function createNested(_options = {}) {
1465
1373
  * Opens the entire subtree rooted at the given node.
1466
1374
  */
1467
1375
  function expand(ids) {
1468
- for (const id of toArray(ids)) {
1376
+ for (const id of /* @__PURE__ */ toArray(ids)) {
1469
1377
  if (!group.has(id)) continue;
1470
1378
  if (!isLeaf(id)) open(id);
1471
1379
  for (const descendantId of getDescendants(id)) if (!isLeaf(descendantId)) open(descendantId);
@@ -1491,7 +1399,7 @@ function createNested(_options = {}) {
1491
1399
  return activeIds.has(id);
1492
1400
  }
1493
1401
  function activate(ids) {
1494
- for (const id of toArray(ids)) {
1402
+ for (const id of /* @__PURE__ */ toArray(ids)) {
1495
1403
  if (!group.has(id)) continue;
1496
1404
  if (activeMode === "single") {
1497
1405
  for (const activeId of activeIds) if (activeId !== id) activeIds.delete(activeId);
@@ -1500,7 +1408,7 @@ function createNested(_options = {}) {
1500
1408
  }
1501
1409
  }
1502
1410
  function deactivate(ids) {
1503
- for (const id of toArray(ids)) activeIds.delete(id);
1411
+ for (const id of /* @__PURE__ */ toArray(ids)) activeIds.delete(id);
1504
1412
  }
1505
1413
  function deactivateAll() {
1506
1414
  activeIds.clear();
@@ -1508,7 +1416,13 @@ function createNested(_options = {}) {
1508
1416
  function getPath(id) {
1509
1417
  const path = [];
1510
1418
  let currentId = id;
1419
+ const visited = /* @__PURE__ */ new Set();
1511
1420
  while (!/* @__PURE__ */ isUndefined(currentId)) {
1421
+ if (visited.has(currentId)) {
1422
+ logger.warn(`Circular parent reference detected at "${currentId}".`);
1423
+ break;
1424
+ }
1425
+ visited.add(currentId);
1512
1426
  path.unshift(currentId);
1513
1427
  currentId = parents.get(currentId);
1514
1428
  }
@@ -1626,7 +1540,7 @@ function createNested(_options = {}) {
1626
1540
  }
1627
1541
  function select(ids) {
1628
1542
  if (toValue(group.disabled)) return;
1629
- for (const id of toArray(ids)) {
1543
+ for (const id of /* @__PURE__ */ toArray(ids)) {
1630
1544
  if (!group.has(id)) continue;
1631
1545
  const item = group.get(id);
1632
1546
  if (!item || toValue(item.disabled)) continue;
@@ -1653,7 +1567,7 @@ function createNested(_options = {}) {
1653
1567
  }
1654
1568
  function unselect(ids) {
1655
1569
  if (toValue(group.disabled)) return;
1656
- for (const id of toArray(ids)) {
1570
+ for (const id of /* @__PURE__ */ toArray(ids)) {
1657
1571
  if (!group.has(id)) continue;
1658
1572
  const item = group.get(id);
1659
1573
  if (!item || toValue(item.disabled)) continue;
@@ -1680,7 +1594,7 @@ function createNested(_options = {}) {
1680
1594
  }
1681
1595
  function toggle(ids) {
1682
1596
  if (toValue(group.disabled)) return;
1683
- for (const id of toArray(ids)) {
1597
+ for (const id of /* @__PURE__ */ toArray(ids)) {
1684
1598
  const item = group.get(id);
1685
1599
  if (!item || toValue(item.disabled)) continue;
1686
1600
  if (selectionMode === "independent") group.toggle(id);
@@ -1867,7 +1781,7 @@ function createNested(_options = {}) {
1867
1781
  rootIds.clear();
1868
1782
  group.reset();
1869
1783
  }
1870
- const context = {
1784
+ return {
1871
1785
  ...group,
1872
1786
  children,
1873
1787
  parents,
@@ -1903,7 +1817,6 @@ function createNested(_options = {}) {
1903
1817
  deactivateAll,
1904
1818
  toFlat,
1905
1819
  multiple: toValue(multipleOption),
1906
- openStrategy: resolvedOpenStrategy,
1907
1820
  select,
1908
1821
  unselect,
1909
1822
  toggle,
@@ -1920,7 +1833,6 @@ function createNested(_options = {}) {
1920
1833
  return group.size;
1921
1834
  }
1922
1835
  };
1923
- return context;
1924
1836
  }
1925
1837
  /**
1926
1838
  * Creates a new nested context with provide/inject pattern.
@@ -1942,12 +1854,7 @@ function createNested(_options = {}) {
1942
1854
  */
1943
1855
  function createNestedContext(_options = {}) {
1944
1856
  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);
1857
+ return createTrinity(namespace, createNested(options));
1951
1858
  }
1952
1859
  /**
1953
1860
  * Returns the current nested instance from context.
@@ -1973,6 +1880,15 @@ function useNested(namespace = "v0:nested") {
1973
1880
  *
1974
1881
  * Used by createSlider, createNumberField, and other numeric composables.
1975
1882
  * Handles floating-point precision correction internally.
1883
+ *
1884
+ * @example
1885
+ * ```ts
1886
+ * import { createNumeric } from '@vuetify/v0'
1887
+ *
1888
+ * const numeric = createNumeric({ min: 0, max: 10, step: 1 })
1889
+ * console.log(numeric.snap(3.7)) // 4
1890
+ * console.log(numeric.toPercent(5)) // 0.5
1891
+ * ```
1976
1892
  */
1977
1893
  function decimalPlaces(n) {
1978
1894
  const s = String(n);
@@ -1984,6 +1900,7 @@ function createNumeric(options = {}) {
1984
1900
  const extent = max - min;
1985
1901
  const decimals = Math.max(decimalPlaces(step), Number.isFinite(min) ? decimalPlaces(min) : 0);
1986
1902
  function snap(value) {
1903
+ if (!Number.isFinite(value)) return min;
1987
1904
  if (step <= 0 || !Number.isFinite(min)) return /* @__PURE__ */ clamp(value, min, max);
1988
1905
  const result = min + Math.round((/* @__PURE__ */ clamp(value, min, max) - min) / step) * step;
1989
1906
  return /* @__PURE__ */ clamp(decimals > 0 ? +result.toFixed(decimals) : result, min, max);
@@ -2046,6 +1963,15 @@ function createNumeric(options = {}) {
2046
1963
  * @remarks
2047
1964
  * Orchestrator composable that composes createInput + createNumeric + Intl.NumberFormat.
2048
1965
  * Manages a numeric value with formatting, parsing, stepping, and field state.
1966
+ *
1967
+ * @example
1968
+ * ```ts
1969
+ * import { createNumberField } from '@vuetify/v0'
1970
+ *
1971
+ * const field = createNumberField({ min: 0, max: 100, step: 5 })
1972
+ * field.increment()
1973
+ * console.log(field.value.value) // 5
1974
+ * ```
2049
1975
  */
2050
1976
  function createNumberField(options = {}) {
2051
1977
  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 +2096,16 @@ function createNumberField(options = {}) {
2170
2096
  * - Perfect for hydration-safe rendering
2171
2097
  *
2172
2098
  * Essential for composables that need to behave differently during SSR vs client-side.
2099
+ *
2100
+ * @example
2101
+ * ```ts
2102
+ * import { useHydration } from '@vuetify/v0'
2103
+ *
2104
+ * const { isHydrated } = useHydration()
2105
+ * if (isHydrated.value) {
2106
+ * // safe for client-only logic
2107
+ * }
2108
+ * ```
2173
2109
  */
2174
2110
  /**
2175
2111
  * Creates a new hydration instance.
@@ -2258,6 +2194,15 @@ const [createHydrationContext, createHydrationPlugin, useHydration] = createPlug
2258
2194
  * Accepts refs, getters, raw DOM elements, or Vue component instances
2259
2195
  * and normalizes them to a plain Element. Uses structural typing to
2260
2196
  * avoid cross-version Vue Ref incompatibilities.
2197
+ *
2198
+ * @example
2199
+ * ```ts
2200
+ * import { shallowRef } from 'vue'
2201
+ * import { toElement } from '@vuetify/v0'
2202
+ *
2203
+ * const el = shallowRef<HTMLElement | null>(null)
2204
+ * const resolved = toElement(el) // HTMLElement | undefined
2205
+ * ```
2261
2206
  */
2262
2207
  /**
2263
2208
  * Resolves a {@link MaybeElementRef} to a DOM Element or undefined.
@@ -2305,6 +2250,19 @@ function toElement(target) {
2305
2250
  * - `undefined` — not yet created
2306
2251
  * - `null` — permanently stopped (`stop()` was called; `setup()` is a no-op)
2307
2252
  * - instance — active observer
2253
+ *
2254
+ * @example
2255
+ * ```ts
2256
+ * import { createObserver } from '#v0/composables/createObserver'
2257
+ *
2258
+ * const observer = createObserver(target, entries => {
2259
+ * console.log(entries)
2260
+ * }, {
2261
+ * supports: true,
2262
+ * create: cb => new ResizeObserver(cb),
2263
+ * observe: (o, el) => o.observe(el),
2264
+ * })
2265
+ * ```
2308
2266
  */
2309
2267
  function createObserver(target, userCallback, config) {
2310
2268
  const { isHydrated } = useHydration();
@@ -2397,6 +2355,17 @@ function createObserver(target, userCallback, config) {
2397
2355
  * - Box model options (content-box/border-box)
2398
2356
  *
2399
2357
  * Perfect for responsive components and size-based rendering.
2358
+ *
2359
+ * @example
2360
+ * ```ts
2361
+ * import { useTemplateRef } from 'vue'
2362
+ * import { useResizeObserver } from '@vuetify/v0'
2363
+ *
2364
+ * const target = useTemplateRef('target')
2365
+ * useResizeObserver(target, entries => {
2366
+ * console.log(entries[0].contentRect.width)
2367
+ * })
2368
+ * ```
2400
2369
  */
2401
2370
  /**
2402
2371
  * A composable that uses the Resize Observer API to detect when an element's
@@ -2508,8 +2477,8 @@ function useElementSize(target) {
2508
2477
  _pause();
2509
2478
  }
2510
2479
  return {
2511
- width,
2512
- height,
2480
+ width: shallowReadonly(width),
2481
+ height: shallowReadonly(height),
2513
2482
  isActive,
2514
2483
  isPaused: shallowReadonly(isPaused),
2515
2484
  pause,
@@ -2537,6 +2506,16 @@ function useElementSize(target) {
2537
2506
  *
2538
2507
  * Use variable mode (default) for items with different widths like Breadcrumbs.
2539
2508
  * Use uniform mode (itemWidth option) for same-width items like Pagination buttons.
2509
+ *
2510
+ * @example
2511
+ * ```ts
2512
+ * import { useTemplateRef } from 'vue'
2513
+ * import { createOverflow } from '@vuetify/v0'
2514
+ *
2515
+ * const el = useTemplateRef('container')
2516
+ * const overflow = createOverflow({ container: el })
2517
+ * console.log(overflow.capacity.value) // number of items that fit
2518
+ * ```
2540
2519
  */
2541
2520
  /**
2542
2521
  * Creates a new overflow context for computing how many items fit in a container.
@@ -2625,7 +2604,7 @@ function createOverflow(options = {}) {
2625
2604
  if (available <= 0) return 0;
2626
2605
  const g = toValue(gap);
2627
2606
  const uniformWidth = toValue(itemWidth) ?? 0;
2628
- if (itemWidth !== void 0 && uniformWidth <= 0) return Infinity;
2607
+ if (!/* @__PURE__ */ isUndefined(itemWidth) && uniformWidth <= 0) return Infinity;
2629
2608
  if (uniformWidth > 0) {
2630
2609
  const subsequent = uniformWidth + g;
2631
2610
  if (available < uniformWidth) return 0;
@@ -2676,12 +2655,7 @@ function createOverflow(options = {}) {
2676
2655
  */
2677
2656
  function createOverflowContext(_options = {}) {
2678
2657
  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);
2658
+ return createTrinity(namespace, createOverflow(options));
2685
2659
  }
2686
2660
  /**
2687
2661
  * Returns the current overflow context from dependency injection.
@@ -2725,6 +2699,15 @@ function useOverflow(namespace = "v0:overflow") {
2725
2699
  * All segments stay selected (multiple: true, enroll: true) so
2726
2700
  * selectedValues always reflects the full set of segment values.
2727
2701
  * Compatible with useProxyModel for v-model bridging.
2702
+ *
2703
+ * @example
2704
+ * ```ts
2705
+ * import { createProgress } from '@vuetify/v0'
2706
+ *
2707
+ * const progress = createProgress({ min: 0, max: 100, value: 25 })
2708
+ * progress.register({ value: 50 })
2709
+ * console.log(progress.percent.value)
2710
+ * ```
2728
2711
  */
2729
2712
  /**
2730
2713
  * Creates a progress instance with model-based segment tracking.
@@ -2818,12 +2801,7 @@ function createProgress(options = {}) {
2818
2801
  */
2819
2802
  function createProgressContext(_options = {}) {
2820
2803
  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);
2804
+ return createTrinity(namespace, createProgress(options));
2827
2805
  }
2828
2806
  /**
2829
2807
  * Returns the current progress instance from context.
@@ -2835,201 +2813,6 @@ function useProgress(namespace = "v0:progress") {
2835
2813
  return useContext(namespace);
2836
2814
  }
2837
2815
  //#endregion
2838
- //#region src/composables/createQueue/index.ts
2839
- /**
2840
- * @module createQueue
2841
- *
2842
- * @see https://0.vuetifyjs.com/composables/registration/create-queue
2843
- *
2844
- * @remarks
2845
- * A queue composable for managing time-based collections with:
2846
- * - Automatic timeout-based removal
2847
- * - Pause/resume functionality
2848
- * - FIFO (First In, First Out) ordering
2849
- * - Manual dismissal support
2850
- * - Queue progression management
2851
- *
2852
- * Built on top of createRegistry, the queue automatically manages timeouts for tickets,
2853
- * ensuring only the first ticket in the queue is active at any time. When a ticket
2854
- * expires or is removed, the next ticket in the queue automatically becomes active.
2855
- */
2856
- /**
2857
- * Creates a new queue instance
2858
- *
2859
- * @param options The options for the queue instance
2860
- * @returns A new queue instance
2861
- *
2862
- * @see https://0.vuetifyjs.com/composables/registration/create-queue
2863
- *
2864
- * @example
2865
- * ```ts
2866
- * import { useQueue } from '@vuetify/v0'
2867
- *
2868
- * const queue = useQueue()
2869
- *
2870
- * // Register an ticket with default timeout (3000ms)
2871
- * const ticket1 = queue.register({ value: 'Ticket 1' })
2872
- *
2873
- * // Register an ticket with custom timeout
2874
- * const ticket2 = queue.register({ value: 'Ticket 2', timeout: 5000 })
2875
- *
2876
- * // Register a persistent ticket that must be manually dismissed
2877
- * const ticket3 = queue.register({ value: 'Ticket 3', timeout: -1 })
2878
- *
2879
- * // Dismiss an ticket using the convenience method
2880
- * ticket3.dismiss()
2881
- *
2882
- * console.log(queue.size) // 2
2883
- * ```
2884
- */
2885
- function createQueue(_options = {}) {
2886
- const { timeout: _timeout = 3e3, ...options } = _options;
2887
- const registry = createRegistry({
2888
- ...options,
2889
- events: true
2890
- });
2891
- const timers = /* @__PURE__ */ new Map();
2892
- function createTicketTimer(ticket) {
2893
- if (/* @__PURE__ */ isUndefined(ticket.timeout) || ticket.timeout < 0 || ticket.isPaused) return;
2894
- const timer = useTimer(() => {
2895
- timers.delete(ticket.id);
2896
- registry.unregister(ticket.id);
2897
- resume();
2898
- }, { duration: ticket.timeout });
2899
- timers.set(ticket.id, timer);
2900
- timer.start();
2901
- }
2902
- function stopTimer(id) {
2903
- const timer = timers.get(id);
2904
- if (timer) {
2905
- timer.stop();
2906
- timers.delete(id);
2907
- }
2908
- }
2909
- function register(registration = {}) {
2910
- const id = registration.id ?? /* @__PURE__ */ useId$1();
2911
- const timeout = Object.prototype.hasOwnProperty.call(registration, "timeout") ? registration.timeout : _timeout;
2912
- const ticket = {
2913
- ...registration,
2914
- id,
2915
- timeout,
2916
- isPaused: registry.size > 0,
2917
- dismiss: () => unregister(id)
2918
- };
2919
- const registered = registry.register(ticket);
2920
- createTicketTimer(registered);
2921
- return registered;
2922
- }
2923
- function unregister(id) {
2924
- const ticket = /* @__PURE__ */ isUndefined(id) ? registry.seek("first") : registry.get(id);
2925
- if (!ticket) return void 0;
2926
- const wasFirst = ticket.index === 0;
2927
- stopTimer(ticket.id);
2928
- registry.unregister(ticket.id);
2929
- if (wasFirst) resume();
2930
- return ticket;
2931
- }
2932
- function offboard(ids) {
2933
- let hadFirst = false;
2934
- for (const id of ids) {
2935
- const ticket = registry.get(id);
2936
- if (!ticket) continue;
2937
- if (ticket.index === 0) hadFirst = true;
2938
- stopTimer(ticket.id);
2939
- }
2940
- registry.offboard(ids);
2941
- if (hadFirst) resume();
2942
- }
2943
- function pause() {
2944
- const ticket = registry.seek("first");
2945
- if (!ticket || ticket.isPaused) return void 0;
2946
- timers.get(ticket.id)?.pause();
2947
- return registry.upsert(ticket.id, { isPaused: true });
2948
- }
2949
- function resume() {
2950
- const ticket = registry.seek("first");
2951
- if (!ticket || ticket.index !== 0 || !ticket.isPaused) return void 0;
2952
- const updated = registry.upsert(ticket.id, { isPaused: false });
2953
- const timer = timers.get(updated.id);
2954
- if (timer) timer.start();
2955
- else createTicketTimer(updated);
2956
- return updated;
2957
- }
2958
- function clear() {
2959
- for (const timer of timers.values()) timer.stop();
2960
- timers.clear();
2961
- registry.clear();
2962
- }
2963
- function dispose() {
2964
- clear();
2965
- registry.dispose();
2966
- }
2967
- onScopeDispose(dispose, true);
2968
- function onboard(registrations) {
2969
- return registry.batch(() => registrations.map((registration) => register(registration)));
2970
- }
2971
- return {
2972
- ...registry,
2973
- register,
2974
- unregister,
2975
- onboard,
2976
- offboard,
2977
- pause,
2978
- resume,
2979
- clear,
2980
- dispose,
2981
- get size() {
2982
- return registry.size;
2983
- }
2984
- };
2985
- }
2986
- /**
2987
- * Creates a new queue context.
2988
- *
2989
- * @param options The options for the queue context.
2990
- * @returns A new queue context.
2991
- *
2992
- * @see https://0.vuetifyjs.com/composables/registration/create-queue
2993
- *
2994
- * @example
2995
- * ```ts
2996
- * import { createQueueContext } from '@vuetify/v0'
2997
- *
2998
- * export const [useQueue, provideQueue, context] = createQueueContext({
2999
- * timeout: 5000,
3000
- * })
3001
- * ```
3002
- */
3003
- function createQueueContext(_options = {}) {
3004
- 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);
3011
- }
3012
- /**
3013
- * Returns the current queue instance.
3014
- *
3015
- * @param namespace The namespace for the queue context. Defaults to `'v0:queue'`.
3016
- * @returns The current queue instance.
3017
- *
3018
- * @see https://0.vuetifyjs.com/composables/registration/create-queue
3019
- *
3020
- * @example
3021
- * ```vue
3022
- * <script setup lang="ts">
3023
- * import { useQueue } from '@vuetify/v0'
3024
- *
3025
- * const queue = useQueue()
3026
- * <\/script>
3027
- * ```
3028
- */
3029
- function useQueue(namespace = "v0:queue") {
3030
- return useContext(namespace);
3031
- }
3032
- //#endregion
3033
2816
  //#region src/composables/createRating/index.ts
3034
2817
  /**
3035
2818
  * @module createRating
@@ -3050,6 +2833,15 @@ function useQueue(namespace = "v0:queue") {
3050
2833
  * Unlike registry-based composables, rating tracks a single number
3051
2834
  * within a range with computed item states, making it efficient
3052
2835
  * for any star/icon rating use case.
2836
+ *
2837
+ * @example
2838
+ * ```ts
2839
+ * import { createRating } from '@vuetify/v0'
2840
+ *
2841
+ * const rating = createRating({ size: 5, value: 3 })
2842
+ * rating.select(4)
2843
+ * console.log(rating.value.value) // 4
2844
+ * ```
3053
2845
  */
3054
2846
  /**
3055
2847
  * Creates a rating instance.
@@ -3147,12 +2939,7 @@ function createRating(_options = {}) {
3147
2939
  */
3148
2940
  function createRatingContext(_options = {}) {
3149
2941
  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);
2942
+ return createTrinity(namespace, createRating(options));
3156
2943
  }
3157
2944
  /**
3158
2945
  * Returns the current rating instance from context.
@@ -3198,6 +2985,16 @@ function useRating(namespace = "v0:rating") {
3198
2985
  * Designed for single-thumb, range, and multi-thumb sliders.
3199
2986
  * Also reusable for color picker tracks, media scrubbers,
3200
2987
  * gradient editors, and other 1D value-on-track controls.
2988
+ *
2989
+ * @example
2990
+ * ```ts
2991
+ * import { shallowRef } from 'vue'
2992
+ * import { createSlider } from '@vuetify/v0'
2993
+ *
2994
+ * const slider = createSlider({ min: 0, max: 100, step: 5 })
2995
+ * slider.register({ value: shallowRef(25) })
2996
+ * slider.set(0, 60)
2997
+ * ```
3201
2998
  */
3202
2999
  /**
3203
3000
  * Creates slider state with value math, step snapping, and multi-thumb support.
@@ -3385,6 +3182,16 @@ function createSlider(options = {}) {
3385
3182
  * - Perfect for wizards, carousels, pagination, onboarding flows
3386
3183
  *
3387
3184
  * Inheritance chain: createRegistry → createSelection → createSingle → createStep
3185
+ *
3186
+ * @example
3187
+ * ```ts
3188
+ * import { createStep } from '@vuetify/v0'
3189
+ *
3190
+ * const wizard = createStep({ circular: false })
3191
+ * wizard.register({ value: 'step-1' })
3192
+ * wizard.register({ value: 'step-2' })
3193
+ * wizard.next()
3194
+ * ```
3388
3195
  */
3389
3196
  /**
3390
3197
  * Creates a new step instance with navigation through items.
@@ -3533,12 +3340,7 @@ function createStep(_options = {}) {
3533
3340
  */
3534
3341
  function createStepContext(_options = {}) {
3535
3342
  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);
3343
+ return createTrinity(namespace, createStep(options));
3542
3344
  }
3543
3345
  /**
3544
3346
  * Returns the current step instance.
@@ -3587,7 +3389,17 @@ function useStep(namespace = "v0:step") {
3587
3389
  * - Automatic reindexing after operations
3588
3390
  * - Perfect for command pattern, history tracking
3589
3391
  *
3590
- * Extends createRegistry with temporal navigation capabilities.
3392
+ * Extends createRegistry with temporal navigation capabilities.
3393
+ *
3394
+ * @example
3395
+ * ```ts
3396
+ * import { createTimeline } from '@vuetify/v0'
3397
+ *
3398
+ * const timeline = createTimeline({ size: 5 })
3399
+ * timeline.register({ value: 'action-1' })
3400
+ * timeline.register({ value: 'action-2' })
3401
+ * timeline.undo()
3402
+ * ```
3591
3403
  */
3592
3404
  /**
3593
3405
  * Creates a new timeline instance.
@@ -3699,12 +3511,7 @@ function createTimeline(_options = {}) {
3699
3511
  */
3700
3512
  function createTimelineContext(_options = {}) {
3701
3513
  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);
3514
+ return createTrinity(namespace, createTimeline(options));
3708
3515
  }
3709
3516
  /**
3710
3517
  * Returns the current timeline instance.
@@ -3748,6 +3555,16 @@ function useTimeline(namespace = "v0:timeline") {
3748
3555
  * - Configurable overscan (extra items rendered for smooth scrolling)
3749
3556
  *
3750
3557
  * Perfect for large data sets, chat apps, and infinite scroll implementations.
3558
+ *
3559
+ * @example
3560
+ * ```ts
3561
+ * import { shallowRef } from 'vue'
3562
+ * import { createVirtual } from '@vuetify/v0'
3563
+ *
3564
+ * const items = shallowRef(Array.from({ length: 10000 }, (_, i) => ({ id: i })))
3565
+ * const virtual = createVirtual(items, { itemHeight: 40 })
3566
+ * console.log(virtual.items.value)
3567
+ * ```
3751
3568
  */
3752
3569
  /**
3753
3570
  * Virtual scrolling composable for efficiently rendering large lists
@@ -4040,12 +3857,7 @@ function createVirtual(items, _options = {}) {
4040
3857
  */
4041
3858
  function createVirtualContext(items, _options = {}) {
4042
3859
  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);
3860
+ return createTrinity(namespace, createVirtual(items, options));
4049
3861
  }
4050
3862
  /**
4051
3863
  * Returns the current virtual context from dependency injection.
@@ -4095,6 +3907,16 @@ function useVirtual(namespace = "v0:virtual") {
4095
3907
  * - Type preservation
4096
3908
  *
4097
3909
  * Perfect for creating reactive versions of plain objects while automatically unwrapping refs.
3910
+ *
3911
+ * @example
3912
+ * ```ts
3913
+ * import { shallowRef } from 'vue'
3914
+ * import { toReactive } from '@vuetify/v0'
3915
+ *
3916
+ * const source = { name: shallowRef('Alice'), age: 30 }
3917
+ * const reactive = toReactive(source)
3918
+ * console.log(reactive.name) // 'Alice' (auto-unwrapped)
3919
+ * ```
4098
3920
  */
4099
3921
  function createMapProxy(refObject) {
4100
3922
  let mapProxy;
@@ -4252,6 +4074,14 @@ function toReactive(objectRef) {
4252
4074
  * - Custom breakpoint configuration
4253
4075
  *
4254
4076
  * Perfect for responsive layouts and conditional rendering based on screen size.
4077
+ *
4078
+ * @example
4079
+ * ```ts
4080
+ * import { useBreakpoints } from '@vuetify/v0'
4081
+ *
4082
+ * const { current, isMobile, smAndUp } = useBreakpoints()
4083
+ * console.log(current.value) // 'md'
4084
+ * ```
4255
4085
  */
4256
4086
  /**
4257
4087
  * Creates default breakpoint configuration.
@@ -4534,7 +4364,7 @@ function createDate(options) {
4534
4364
  const { locales = defaultLocales, adapter, locale: initialLocale, firstDayOfWeek: explicitFirstDay } = options;
4535
4365
  let selectedId;
4536
4366
  try {
4537
- if (instanceExists()) selectedId = useLocale().selectedId;
4367
+ if (/* @__PURE__ */ instanceExists()) selectedId = useLocale().selectedId;
4538
4368
  } catch {}
4539
4369
  const locale = computed(() => {
4540
4370
  const selected = selectedId?.value;
@@ -4550,7 +4380,7 @@ function createDate(options) {
4550
4380
  const loc = locale.value;
4551
4381
  return loc ? deriveFirstDayOfWeek(loc) : 0;
4552
4382
  });
4553
- if (instanceExists()) onScopeDispose(watchEffect(() => {
4383
+ if (/* @__PURE__ */ instanceExists()) onScopeDispose(watchEffect(() => {
4554
4384
  const loc = locale.value;
4555
4385
  if (loc && adapter.locale !== loc) adapter.locale = loc;
4556
4386
  const fdow = firstDayOfWeek.value;
@@ -4590,12 +4420,7 @@ function createDate(options) {
4590
4420
  */
4591
4421
  function createDateContext(options) {
4592
4422
  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);
4423
+ return createTrinity(namespace, createDate(dateOptions));
4599
4424
  }
4600
4425
  /**
4601
4426
  * Creates a new date plugin.
@@ -4667,7 +4492,7 @@ function createDatePlugin(options) {
4667
4492
  * ```
4668
4493
  */
4669
4494
  function useDate(namespace = "v0:date") {
4670
- 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() }))");
4495
+ if (!/* @__PURE__ */ 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() }))");
4671
4496
  return useContext(namespace);
4672
4497
  }
4673
4498
  //#endregion
@@ -4697,13 +4522,14 @@ const keyAliasMap = {
4697
4522
  minus: "-",
4698
4523
  hyphen: "-"
4699
4524
  };
4525
+ /* @__NO_SIDE_EFFECTS__ */
4700
4526
  function normalizeKey(key) {
4701
4527
  const lowerKey = key.toLowerCase();
4702
4528
  return keyAliasMap[lowerKey] ?? lowerKey;
4703
4529
  }
4704
4530
  //#endregion
4705
4531
  //#region src/composables/useHotkey/parsing.ts
4706
- const logger = useLogger();
4532
+ const logger = /* @__PURE__ */ useLogger();
4707
4533
  const MODIFIERS = [
4708
4534
  "ctrl",
4709
4535
  "shift",
@@ -4748,7 +4574,7 @@ function splitKeyCombination(combination, isInternal = false) {
4748
4574
  function flushBuffer(separator) {
4749
4575
  if (buffer) {
4750
4576
  if (separator) separators.push(separator);
4751
- keys.push(normalizeKey(buffer));
4577
+ keys.push(/* @__PURE__ */ normalizeKey(buffer));
4752
4578
  buffer = "";
4753
4579
  }
4754
4580
  }
@@ -4781,7 +4607,7 @@ function splitKeyCombination(combination, isInternal = false) {
4781
4607
  return emptyResult;
4782
4608
  }
4783
4609
  if (keys.length === 0 && combination) return {
4784
- keys: [normalizeKey(combination)],
4610
+ keys: [/* @__PURE__ */ normalizeKey(combination)],
4785
4611
  separators
4786
4612
  };
4787
4613
  /* v8 ignore stop */
@@ -4879,6 +4705,14 @@ function splitKeySequence(str) {
4879
4705
  * - SSR-safe (no-op when not in browser)
4880
4706
  *
4881
4707
  * Builds on useEventListener for lifecycle-managed keyboard events.
4708
+ *
4709
+ * @example
4710
+ * ```ts
4711
+ * import { useHotkey } from '@vuetify/v0'
4712
+ *
4713
+ * useHotkey('ctrl+k', () => console.log('opened palette'))
4714
+ * useHotkey('g-h', () => console.log('go home'))
4715
+ * ```
4882
4716
  */
4883
4717
  const isMac = IN_BROWSER && /mac|iphone|ipad|ipod/i.test(navigator?.userAgent ?? "");
4884
4718
  /**
@@ -4922,6 +4756,7 @@ function useHotkey(keys, callback, options = {}, _platform) {
4922
4756
  let isSequence = false;
4923
4757
  let groupIndex = 0;
4924
4758
  function isInputFocused() {
4759
+ if (!IN_BROWSER) return false;
4925
4760
  if (toValue(inputs)) return false;
4926
4761
  const activeElement = document.activeElement;
4927
4762
  if (!activeElement) return false;
@@ -5050,6 +4885,115 @@ function matchesKeyGroup(e, group, platformIsMac) {
5050
4885
  return modifiersMatch && e.key.toLowerCase() === actualKey.toLowerCase();
5051
4886
  }
5052
4887
  //#endregion
4888
+ //#region src/composables/useImage/index.ts
4889
+ /**
4890
+ * @module useImage
4891
+ *
4892
+ * @see https://0.vuetifyjs.com/composables/system/use-image
4893
+ *
4894
+ * @remarks
4895
+ * Image loading state machine with deferred loading support.
4896
+ *
4897
+ * Key features:
4898
+ * - State machine: idle → loading → loaded | error
4899
+ * - Reactive `eager` gate withholds the source until ready
4900
+ * - Automatic reset when `src` changes
4901
+ * - Manual `retry()` to re-attempt after error
4902
+ * - Bind-ready handlers and gated source
4903
+ * - SSR-safe
4904
+ *
4905
+ * Perfect for image components, lightboxes, lazy-loaded galleries,
4906
+ * and any UI that needs to react to image load state.
4907
+ *
4908
+ * @example
4909
+ * ```ts
4910
+ * import { useImage } from '@vuetify/v0'
4911
+ *
4912
+ * const { status, source, onLoad, onError } = useImage({
4913
+ * src: 'https://example.com/img.png',
4914
+ * })
4915
+ * ```
4916
+ */
4917
+ /**
4918
+ * Tracks image loading state as a reactive state machine.
4919
+ *
4920
+ * @param options Configuration options
4921
+ * @returns Image context with state refs and event handlers
4922
+ *
4923
+ * @see https://0.vuetifyjs.com/composables/system/use-image
4924
+ *
4925
+ * @example
4926
+ * ```ts
4927
+ * import { toRef } from 'vue'
4928
+ * import { useImage } from '@vuetify/v0'
4929
+ *
4930
+ * const props = defineProps<{ src: string }>()
4931
+ *
4932
+ * const { source, isLoaded, onLoad, onError, retry } = useImage({
4933
+ * src: toRef(() => props.src),
4934
+ * })
4935
+ * ```
4936
+ *
4937
+ * @example
4938
+ * Composed with `useIntersectionObserver` for lazy loading:
4939
+ * ```ts
4940
+ * const target = shallowRef<HTMLElement>()
4941
+ * const { isIntersecting } = useIntersectionObserver(target, () => {}, {
4942
+ * once: true,
4943
+ * rootMargin: '200px',
4944
+ * })
4945
+ *
4946
+ * const { source, onLoad, onError } = useImage({
4947
+ * src: toRef(() => props.src),
4948
+ * eager: isIntersecting,
4949
+ * })
4950
+ * ```
4951
+ */
4952
+ function useImage(options) {
4953
+ const { src, eager = true } = options;
4954
+ const status = shallowRef(toValue(eager) ? "loading" : "idle");
4955
+ const isIdle = toRef(() => status.value === "idle");
4956
+ const isLoading = toRef(() => status.value === "loading");
4957
+ const isLoaded = toRef(() => status.value === "loaded");
4958
+ const isError = toRef(() => status.value === "error");
4959
+ const source = toRef(() => status.value === "idle" ? void 0 : toValue(src));
4960
+ function onLoad() {
4961
+ status.value = "loaded";
4962
+ }
4963
+ function onError() {
4964
+ status.value = "error";
4965
+ }
4966
+ function retry() {
4967
+ const resumeAs = toValue(eager) ? "loading" : "idle";
4968
+ status.value = "idle";
4969
+ nextTick(() => {
4970
+ status.value = resumeAs;
4971
+ });
4972
+ }
4973
+ const stopEager = watch(() => toValue(eager), (value) => {
4974
+ if (value && status.value === "idle") status.value = "loading";
4975
+ else if (!value && status.value !== "loaded" && status.value !== "error") status.value = "idle";
4976
+ });
4977
+ const stopSrc = watch(() => toValue(src), () => {
4978
+ status.value = toValue(eager) ? "loading" : "idle";
4979
+ });
4980
+ onScopeDispose(() => {
4981
+ stopEager();
4982
+ stopSrc();
4983
+ }, true);
4984
+ return {
4985
+ status: shallowReadonly(status),
4986
+ isIdle,
4987
+ isLoading,
4988
+ isLoaded,
4989
+ isError,
4990
+ source,
4991
+ onLoad,
4992
+ onError,
4993
+ retry
4994
+ };
4995
+ }
4996
+ //#endregion
5053
4997
  //#region src/composables/useIntersectionObserver/index.ts
5054
4998
  /**
5055
4999
  * @module useIntersectionObserver
@@ -5070,6 +5014,17 @@ function matchesKeyGroup(e, group, platformIsMac) {
5070
5014
  * - Immediate callback option
5071
5015
  *
5072
5016
  * Perfect for lazy loading, infinite scroll, and visibility detection.
5017
+ *
5018
+ * @example
5019
+ * ```ts
5020
+ * import { useTemplateRef } from 'vue'
5021
+ * import { useIntersectionObserver } from '@vuetify/v0'
5022
+ *
5023
+ * const target = useTemplateRef('target')
5024
+ * useIntersectionObserver(target, entries => {
5025
+ * console.log(entries[0].isIntersecting)
5026
+ * })
5027
+ * ```
5073
5028
  */
5074
5029
  /**
5075
5030
  * A composable that uses the Intersection Observer API to detect when an element
@@ -5230,6 +5185,15 @@ function useElementIntersection(target, options = {}) {
5230
5185
  *
5231
5186
  * Perfect for dialogs, menus, tooltips, and any component with
5232
5187
  * conditionally rendered content.
5188
+ *
5189
+ * @example
5190
+ * ```ts
5191
+ * import { shallowRef } from 'vue'
5192
+ * import { useLazy } from '@vuetify/v0'
5193
+ *
5194
+ * const isOpen = shallowRef(false)
5195
+ * const { hasContent, onAfterLeave } = useLazy(isOpen)
5196
+ * ```
5233
5197
  */
5234
5198
  /**
5235
5199
  * Deferred content rendering for performance optimization.
@@ -5320,6 +5284,14 @@ function useLazy(active, options = {}) {
5320
5284
  * - Supports both static and dynamic queries
5321
5285
  *
5322
5286
  * Perfect for responsive conditionals beyond breakpoint detection.
5287
+ *
5288
+ * @example
5289
+ * ```ts
5290
+ * import { useMediaQuery } from '@vuetify/v0'
5291
+ *
5292
+ * const { matches } = useMediaQuery('(prefers-color-scheme: dark)')
5293
+ * console.log(matches.value) // true/false
5294
+ * ```
5323
5295
  */
5324
5296
  /**
5325
5297
  * Reactive media query matching.
@@ -5440,6 +5412,17 @@ function usePrefersContrast() {
5440
5412
  * - Configurable observation options (childList, attributes, characterData, etc.)
5441
5413
  *
5442
5414
  * Perfect for detecting DOM changes and responding to mutations.
5415
+ *
5416
+ * @example
5417
+ * ```ts
5418
+ * import { useTemplateRef } from 'vue'
5419
+ * import { useMutationObserver } from '@vuetify/v0'
5420
+ *
5421
+ * const target = useTemplateRef('target')
5422
+ * useMutationObserver(target, records => {
5423
+ * console.log(records)
5424
+ * }, { childList: true })
5425
+ * ```
5443
5426
  */
5444
5427
  /**
5445
5428
  * A composable that uses the Mutation Observer API to detect changes in the DOM.
@@ -5534,525 +5517,6 @@ function useMutationObserver(target, callback, options = {}) {
5534
5517
  });
5535
5518
  }
5536
5519
  //#endregion
5537
- //#region src/composables/useNotifications/index.ts
5538
- /**
5539
- * @module useNotifications
5540
- * @see https://0.vuetifyjs.com/composables/plugins/use-notifications
5541
- *
5542
- * @remarks
5543
- * Notification management composable built on createRegistry and createQueue.
5544
- * Registry stores the full notification lifecycle (permanent record).
5545
- * Queue manages the display surface (toasts) with FIFO ordering and auto-dismiss.
5546
- *
5547
- * Supports:
5548
- * - Push notifications with severity levels and configurable timeouts
5549
- * - State mutations: read, seen, archived, snoozed
5550
- * - Bulk operations: readAll, archiveAll, clear
5551
- * - Toast queue with pause/resume and auto-dismiss
5552
- * - Adapter integration via event system
5553
- * - Plugin installation via createNotificationsPlugin
5554
- */
5555
- function createNotifications(options = {}) {
5556
- const { timeout = 3e3, ...registryOptions } = options;
5557
- const registry = createRegistry({
5558
- ...registryOptions,
5559
- events: true,
5560
- reactive: true
5561
- });
5562
- const queue = createQueue({
5563
- timeout,
5564
- events: true,
5565
- reactive: true
5566
- });
5567
- registry.on("unregister:ticket", (ticket) => {
5568
- if (queue.has(ticket.id)) queue.unregister(ticket.id);
5569
- });
5570
- /**
5571
- * Build a full {@link NotificationTicket} from raw input
5572
- *
5573
- * @param input The notification input to hydrate.
5574
- * @returns A partial ticket with timestamps, lifecycle methods, and an ID.
5575
- * @internal Used by {@link send}, {@link register}, and {@link onboard}.
5576
- */
5577
- function hydrate(input) {
5578
- const id = input.id ?? /* @__PURE__ */ useId$1();
5579
- const now = /* @__PURE__ */ new Date();
5580
- return {
5581
- ...input,
5582
- id,
5583
- createdAt: now,
5584
- readAt: null,
5585
- seenAt: null,
5586
- archivedAt: null,
5587
- snoozedUntil: null,
5588
- read: () => read(id),
5589
- unread: () => unread(id),
5590
- seen: () => seen(id),
5591
- archive: () => archive(id),
5592
- unarchive: () => unarchive(id),
5593
- snooze: (until) => snooze(id, until),
5594
- wake: () => wake(id),
5595
- dismiss: () => queue.unregister(id)
5596
- };
5597
- }
5598
- /**
5599
- * Create a notification and enqueue it for toast display
5600
- *
5601
- * @param input The notification input to create.
5602
- * @returns The hydrated notification ticket.
5603
- * @remarks Hydrates the input with timestamps and lifecycle methods, registers
5604
- * it in the registry, adds it to the display queue, and emits
5605
- * `notification:received`. The ticket auto-dismisses after the configured
5606
- * timeout unless paused.
5607
- *
5608
- * @see https://0.vuetifyjs.com/composables/plugins/use-notifications
5609
- *
5610
- * @example
5611
- * ```ts
5612
- * import { useNotifications } from '@vuetify/v0'
5613
- *
5614
- * const notifications = useNotifications()
5615
- *
5616
- * // Basic toast
5617
- * notifications.send({ subject: 'Changes saved', severity: 'success' })
5618
- *
5619
- * // With custom timeout
5620
- * const ticket = notifications.send({ subject: 'Connection lost', severity: 'error', timeout: 10000 })
5621
- *
5622
- * console.log(ticket.id) // 'generated-id'
5623
- * console.log(ticket.createdAt) // Date
5624
- * console.log(ticket.readAt) // null
5625
- *
5626
- * // Ticket convenience methods
5627
- * ticket.read() // marks as read
5628
- * ticket.dismiss() // removes from toast queue, keeps in registry
5629
- * ```
5630
- */
5631
- function send(input) {
5632
- const ticket = registry.register(hydrate(input));
5633
- queue.register(/* @__PURE__ */ isUndefined(input.timeout) ? { id: ticket.id } : {
5634
- id: ticket.id,
5635
- timeout: input.timeout
5636
- });
5637
- registry.emit("notification:received", ticket);
5638
- return ticket;
5639
- }
5640
- /**
5641
- * Register a notification in the registry without adding it to the toast queue
5642
- *
5643
- * @param input The notification input to register.
5644
- * @returns The hydrated notification ticket.
5645
- * @remarks Overrides the base registry `register` to hydrate the input with
5646
- * timestamps and lifecycle methods. Use for historical or pre-existing items
5647
- * that should appear in an inbox but not pop up as toasts.
5648
- *
5649
- * @see https://0.vuetifyjs.com/composables/plugins/use-notifications
5650
- *
5651
- * @example
5652
- * ```ts
5653
- * import { useNotifications } from '@vuetify/v0'
5654
- *
5655
- * const notifications = useNotifications()
5656
- *
5657
- * // Register a historical item (appears in inbox, not as toast)
5658
- * const ticket = notifications.register({ id: 'old-1', subject: 'Deployed v2.1' })
5659
- *
5660
- * console.log(ticket.createdAt) // Date
5661
- * console.log(ticket.readAt) // null
5662
- *
5663
- * // Lifecycle methods work the same as send()
5664
- * ticket.read()
5665
- * ticket.archive()
5666
- * ```
5667
- */
5668
- function register(input) {
5669
- return registry.register(hydrate(input));
5670
- }
5671
- /**
5672
- * Bulk version of {@link register}
5673
- *
5674
- * @param inputs Array of notification inputs to register.
5675
- * @returns Array of hydrated notification tickets.
5676
- * @remarks Registers multiple notifications into the registry without toast
5677
- * display. Wraps all registrations in a single `registry.batch()` call so
5678
- * reactive updates are deferred until the entire batch completes.
5679
- *
5680
- * @see https://0.vuetifyjs.com/composables/plugins/use-notifications
5681
- *
5682
- * @example
5683
- * ```ts
5684
- * import { useNotifications } from '@vuetify/v0'
5685
- *
5686
- * const notifications = useNotifications()
5687
- *
5688
- * // Load historical items on mount
5689
- * const tickets = notifications.onboard([
5690
- * { id: 'n1', subject: 'Welcome to the team' },
5691
- * { id: 'n2', subject: 'Setup complete', severity: 'success' },
5692
- * ])
5693
- *
5694
- * console.log(tickets.length) // 2
5695
- * console.log(notifications.queue.values()) // [] (no toasts)
5696
- * console.log(notifications.values().length) // 2 (in registry)
5697
- * ```
5698
- */
5699
- function onboard(inputs) {
5700
- return registry.batch(() => inputs.map((input) => register(input)));
5701
- }
5702
- /**
5703
- * Mark a notification as read
5704
- *
5705
- * @param id The ID of the notification to mark as read.
5706
- * @remarks Sets `readAt` to the current time and emits `notification:read`.
5707
- * Adapters listen to this event for outbound sync.
5708
- *
5709
- * @see https://0.vuetifyjs.com/composables/plugins/use-notifications
5710
- *
5711
- * @example
5712
- * ```ts
5713
- * import { useNotifications } from '@vuetify/v0'
5714
- *
5715
- * const notifications = useNotifications()
5716
- *
5717
- * const ticket = notifications.send({ subject: 'New message' })
5718
- *
5719
- * notifications.read(ticket.id)
5720
- * console.log(ticket.readAt) // Date
5721
- *
5722
- * // Or via ticket convenience method
5723
- * ticket.read()
5724
- * ```
5725
- */
5726
- function read(id) {
5727
- registry.upsert(id, { readAt: /* @__PURE__ */ new Date() }, "notification:read");
5728
- }
5729
- /**
5730
- * Mark a notification as unread
5731
- *
5732
- * @param id The ID of the notification to mark as unread.
5733
- * @remarks Clears `readAt` and emits `notification:unread`.
5734
- *
5735
- * @see https://0.vuetifyjs.com/composables/plugins/use-notifications
5736
- *
5737
- * @example
5738
- * ```ts
5739
- * import { useNotifications } from '@vuetify/v0'
5740
- *
5741
- * const notifications = useNotifications()
5742
- *
5743
- * notifications.unread('notif-1')
5744
- * ```
5745
- */
5746
- function unread(id) {
5747
- registry.upsert(id, { readAt: null }, "notification:unread");
5748
- }
5749
- /**
5750
- * Mark a notification as seen
5751
- *
5752
- * @param id The ID of the notification to mark as seen.
5753
- * @remarks Sets `seenAt` to the current time and emits `notification:seen`.
5754
- * Distinct from read — seen tracks whether the notification appeared in the
5755
- * user's viewport, while read indicates the user actively engaged with it.
5756
- *
5757
- * @see https://0.vuetifyjs.com/composables/plugins/use-notifications
5758
- *
5759
- * @example
5760
- * ```ts
5761
- * import { useNotifications } from '@vuetify/v0'
5762
- *
5763
- * const notifications = useNotifications()
5764
- *
5765
- * // Mark as seen when visible in inbox viewport
5766
- * notifications.seen('notif-1')
5767
- * ```
5768
- */
5769
- function seen(id) {
5770
- registry.upsert(id, { seenAt: /* @__PURE__ */ new Date() }, "notification:seen");
5771
- }
5772
- /**
5773
- * Archive a notification
5774
- *
5775
- * @param id The ID of the notification to archive.
5776
- * @remarks Sets `archivedAt` to the current time and emits `notification:archived`.
5777
- *
5778
- * @see https://0.vuetifyjs.com/composables/plugins/use-notifications
5779
- *
5780
- * @example
5781
- * ```ts
5782
- * import { useNotifications } from '@vuetify/v0'
5783
- *
5784
- * const notifications = useNotifications()
5785
- *
5786
- * notifications.archive('notif-1')
5787
- * ```
5788
- */
5789
- function archive(id) {
5790
- registry.upsert(id, { archivedAt: /* @__PURE__ */ new Date() }, "notification:archived");
5791
- }
5792
- /**
5793
- * Restore an archived notification
5794
- *
5795
- * @param id The ID of the notification to unarchive.
5796
- * @remarks Clears `archivedAt` and emits `notification:unarchived`.
5797
- *
5798
- * @see https://0.vuetifyjs.com/composables/plugins/use-notifications
5799
- *
5800
- * @example
5801
- * ```ts
5802
- * import { useNotifications } from '@vuetify/v0'
5803
- *
5804
- * const notifications = useNotifications()
5805
- *
5806
- * notifications.unarchive('notif-1')
5807
- * ```
5808
- */
5809
- function unarchive(id) {
5810
- registry.upsert(id, { archivedAt: null }, "notification:unarchived");
5811
- }
5812
- /**
5813
- * Snooze a notification until a given time
5814
- *
5815
- * @param id The ID of the notification to snooze.
5816
- * @param until The time at which the snooze expires.
5817
- * @remarks Sets `snoozedUntil` and emits `notification:snoozed`. The composable
5818
- * does not auto-wake — consumers are responsible for calling {@link wake} when
5819
- * the snooze expires (e.g., via a timer or server push).
5820
- *
5821
- * @see https://0.vuetifyjs.com/composables/plugins/use-notifications
5822
- *
5823
- * @example
5824
- * ```ts
5825
- * import { useNotifications } from '@vuetify/v0'
5826
- *
5827
- * const notifications = useNotifications()
5828
- *
5829
- * const tomorrow = new Date(Date.now() + 86_400_000)
5830
- * notifications.snooze('notif-1', tomorrow)
5831
- * ```
5832
- */
5833
- function snooze(id, until) {
5834
- registry.upsert(id, { snoozedUntil: until }, "notification:snoozed");
5835
- }
5836
- /**
5837
- * Cancel a snooze
5838
- *
5839
- * @param id The ID of the notification to wake.
5840
- * @remarks Clears `snoozedUntil` and emits `notification:unsnoozed`.
5841
- *
5842
- * @see https://0.vuetifyjs.com/composables/plugins/use-notifications
5843
- *
5844
- * @example
5845
- * ```ts
5846
- * import { useNotifications } from '@vuetify/v0'
5847
- *
5848
- * const notifications = useNotifications()
5849
- *
5850
- * notifications.wake('notif-1')
5851
- * ```
5852
- */
5853
- function wake(id) {
5854
- registry.upsert(id, { snoozedUntil: null }, "notification:unsnoozed");
5855
- }
5856
- /**
5857
- * Mark all unread notifications as read
5858
- *
5859
- * @remarks Iterates all notifications and marks unread ones as read in a single
5860
- * batch. Skips already-read notifications to preserve their original `readAt`
5861
- * timestamp. Emits `notification:read` for each affected notification.
5862
- *
5863
- * @see https://0.vuetifyjs.com/composables/plugins/use-notifications
5864
- *
5865
- * @example
5866
- * ```ts
5867
- * import { useNotifications } from '@vuetify/v0'
5868
- *
5869
- * const notifications = useNotifications()
5870
- *
5871
- * notifications.send({ subject: 'Message 1' })
5872
- * notifications.send({ subject: 'Message 2' })
5873
- *
5874
- * notifications.readAll()
5875
- *
5876
- * console.log(notifications.values().every(t => t.readAt !== null)) // true
5877
- * ```
5878
- */
5879
- function readAll() {
5880
- const now = /* @__PURE__ */ new Date();
5881
- registry.batch(() => {
5882
- for (const ticket of registry.values()) if (/* @__PURE__ */ isNull(ticket.readAt)) registry.upsert(ticket.id, { readAt: now }, "notification:read");
5883
- });
5884
- }
5885
- /**
5886
- * Archive all unarchived notifications
5887
- *
5888
- * @remarks Iterates all notifications and archives unarchived ones in a single
5889
- * batch. Skips already-archived notifications to preserve their original
5890
- * `archivedAt` timestamp. Emits `notification:archived` for each affected notification.
5891
- *
5892
- * @see https://0.vuetifyjs.com/composables/plugins/use-notifications
5893
- *
5894
- * @example
5895
- * ```ts
5896
- * import { useNotifications } from '@vuetify/v0'
5897
- *
5898
- * const notifications = useNotifications()
5899
- *
5900
- * notifications.send({ subject: 'Alert 1' })
5901
- * notifications.send({ subject: 'Alert 2' })
5902
- *
5903
- * notifications.archiveAll()
5904
- *
5905
- * console.log(notifications.values().every(t => t.archivedAt !== null)) // true
5906
- * ```
5907
- */
5908
- function archiveAll() {
5909
- const now = /* @__PURE__ */ new Date();
5910
- registry.batch(() => {
5911
- for (const ticket of registry.values()) if (/* @__PURE__ */ isNull(ticket.archivedAt)) registry.upsert(ticket.id, { archivedAt: now }, "notification:archived");
5912
- });
5913
- }
5914
- return {
5915
- ...registry,
5916
- send,
5917
- register,
5918
- onboard,
5919
- queue,
5920
- read,
5921
- unread,
5922
- seen,
5923
- archive,
5924
- unarchive,
5925
- snooze,
5926
- wake,
5927
- readAll,
5928
- archiveAll,
5929
- get size() {
5930
- return registry.size;
5931
- }
5932
- };
5933
- }
5934
- function noop() {}
5935
- const EMPTY = [];
5936
- function createNotificationsFallback() {
5937
- const stub = {
5938
- id: "",
5939
- index: 0,
5940
- value: 0,
5941
- valueIsIndex: true,
5942
- createdAt: /* @__PURE__ */ new Date(0),
5943
- readAt: null,
5944
- seenAt: null,
5945
- archivedAt: null,
5946
- snoozedUntil: null,
5947
- read: noop,
5948
- unread: noop,
5949
- seen: noop,
5950
- archive: noop,
5951
- unarchive: noop,
5952
- snooze: noop,
5953
- wake: noop,
5954
- dismiss: noop,
5955
- unregister: noop
5956
- };
5957
- return {
5958
- collection: /* @__PURE__ */ new Map(),
5959
- size: 0,
5960
- send: () => stub,
5961
- queue: {
5962
- collection: /* @__PURE__ */ new Map(),
5963
- size: 0,
5964
- register: () => ({}),
5965
- unregister: () => void 0,
5966
- has: () => false,
5967
- get: () => void 0,
5968
- keys: () => EMPTY,
5969
- values: () => EMPTY,
5970
- entries: () => EMPTY,
5971
- browse: () => void 0,
5972
- lookup: () => void 0,
5973
- upsert: () => ({}),
5974
- seek: () => void 0,
5975
- move: () => void 0,
5976
- on: noop,
5977
- off: noop,
5978
- emit: noop,
5979
- dispose: noop,
5980
- clear: noop,
5981
- reindex: noop,
5982
- batch: (fn) => fn(),
5983
- onboard: () => EMPTY,
5984
- offboard: noop,
5985
- pause: () => void 0,
5986
- resume: () => void 0
5987
- },
5988
- read: noop,
5989
- unread: noop,
5990
- seen: noop,
5991
- archive: noop,
5992
- unarchive: noop,
5993
- snooze: noop,
5994
- wake: noop,
5995
- readAll: noop,
5996
- archiveAll: noop,
5997
- clear: noop,
5998
- has: () => false,
5999
- get: () => void 0,
6000
- keys: () => EMPTY,
6001
- values: () => EMPTY,
6002
- entries: () => EMPTY,
6003
- browse: () => void 0,
6004
- lookup: () => void 0,
6005
- upsert: () => stub,
6006
- register: () => stub,
6007
- unregister: noop,
6008
- reindex: noop,
6009
- move: () => void 0,
6010
- seek: () => void 0,
6011
- on: noop,
6012
- off: noop,
6013
- emit: noop,
6014
- dispose: noop,
6015
- batch: (fn) => fn(),
6016
- onboard: () => EMPTY,
6017
- offboard: noop
6018
- };
6019
- }
6020
- /**
6021
- * Notification management with registry, event system, and optional adapters.
6022
- *
6023
- * @see https://0.vuetifyjs.com/composables/plugins/use-notifications
6024
- *
6025
- * @example
6026
- * ```ts
6027
- * import { createNotificationsPlugin, useNotifications } from '@vuetify/v0'
6028
- *
6029
- * // Install as plugin
6030
- * app.use(createNotificationsPlugin())
6031
- *
6032
- * // Use in components
6033
- * const notifications = useNotifications()
6034
- * notifications.send({ subject: 'Saved', severity: 'success' })
6035
- * ```
6036
- */
6037
- const [createNotificationsContext, createNotificationsPlugin, useNotifications] = createPluginContext("v0:notifications", (options) => createNotifications(options), {
6038
- fallback: () => createNotificationsFallback(),
6039
- setup: (context, app, options) => {
6040
- app.onUnmount(() => {
6041
- context.dispose();
6042
- context.queue.dispose();
6043
- });
6044
- const { adapter } = options;
6045
- if (!adapter) return;
6046
- adapter.setup({
6047
- send: context.send,
6048
- register: context.register,
6049
- on: context.on,
6050
- off: context.off
6051
- });
6052
- if (/* @__PURE__ */ isFunction(adapter.dispose)) app.onUnmount(() => adapter.dispose());
6053
- }
6054
- });
6055
- //#endregion
6056
5520
  //#region src/composables/usePresence/index.ts
6057
5521
  /**
6058
5522
  * @module usePresence
@@ -6072,6 +5536,15 @@ const [createNotificationsContext, createNotificationsPlugin, useNotifications]
6072
5536
  * - Re-entry during leave: cancels exit, stays mounted
6073
5537
  * - Immediate mode: auto-unmounts if done() not called (fast path)
6074
5538
  * - SSR-safe: starts unmounted
5539
+ *
5540
+ * @example
5541
+ * ```ts
5542
+ * import { shallowRef } from 'vue'
5543
+ * import { usePresence } from '@vuetify/v0'
5544
+ *
5545
+ * const isOpen = shallowRef(false)
5546
+ * const { isMounted, state, done } = usePresence({ present: isOpen })
5547
+ * ```
6075
5548
  */
6076
5549
  /**
6077
5550
  * Animation-agnostic mount lifecycle management.
@@ -6183,6 +5656,16 @@ function usePresence(options) {
6183
5656
  * - Works with any ModelContext (Selection, Slider, etc.)
6184
5657
  *
6185
5658
  * Bridges the gap between model composables and Vue's v-model.
5659
+ *
5660
+ * @example
5661
+ * ```ts
5662
+ * import { shallowRef } from 'vue'
5663
+ * import { createSelection, useProxyModel } from '@vuetify/v0'
5664
+ *
5665
+ * const selection = createSelection({ events: true })
5666
+ * const model = shallowRef<string[]>([])
5667
+ * useProxyModel(selection, model, { multiple: true })
5668
+ * ```
6186
5669
  */
6187
5670
  /**
6188
5671
  * Syncs a ref with a model context bidirectionally.
@@ -6214,7 +5697,7 @@ function useProxyModel(context, model, options) {
6214
5697
  const _transformOut = options?.transformOut;
6215
5698
  function transformIn(val) {
6216
5699
  const value = toValue(val);
6217
- return toArray(/* @__PURE__ */ isFunction(_transformIn) ? _transformIn(value) : value);
5700
+ return /* @__PURE__ */ toArray(/* @__PURE__ */ isFunction(_transformIn) ? _transformIn(value) : value);
6218
5701
  }
6219
5702
  function transformOut(val) {
6220
5703
  if (/* @__PURE__ */ isFunction(_transformOut)) return _transformOut(val);
@@ -6287,6 +5770,16 @@ function useProxyModel(context, model, options) {
6287
5770
  * - Callable function with cancel method
6288
5771
  *
6289
5772
  * Perfect for throttling updates to the next animation frame.
5773
+ *
5774
+ * @example
5775
+ * ```ts
5776
+ * import { useRaf } from '@vuetify/v0'
5777
+ *
5778
+ * const update = useRaf(timestamp => {
5779
+ * // runs on next animation frame
5780
+ * })
5781
+ * update()
5782
+ * ```
6290
5783
  */
6291
5784
  /**
6292
5785
  * Scope-disposed safe requestAnimationFrame.
@@ -6355,6 +5848,15 @@ function useRaf(callback) {
6355
5848
  * - Auto-attaches keydown listener when target is provided
6356
5849
  *
6357
5850
  * Perfect for toolbars, menus, tree items, grids, and other composite widgets.
5851
+ *
5852
+ * @example
5853
+ * ```ts
5854
+ * import { useRovingFocus } from '@vuetify/v0'
5855
+ *
5856
+ * const items = () => [{ id: 'a' }, { id: 'b' }, { id: 'c' }]
5857
+ * const focus = useRovingFocus(items, { orientation: 'horizontal' })
5858
+ * focus.next()
5859
+ * ```
6358
5860
  */
6359
5861
  function useRovingFocus(items, options = {}) {
6360
5862
  const { orientation, circular, columns, onFocus, target } = options;
@@ -6432,6 +5934,14 @@ var Vuetify0RtlAdapter = class {
6432
5934
  * - Subtree overrides via context provision
6433
5935
  *
6434
5936
  * Independent from useLocale — Vuetify connects them via adapter.
5937
+ *
5938
+ * @example
5939
+ * ```ts
5940
+ * import { useRtl } from '@vuetify/v0'
5941
+ *
5942
+ * const { isRtl, toggle } = useRtl()
5943
+ * toggle() // flip direction
5944
+ * ```
6435
5945
  */
6436
5946
  /**
6437
5947
  * Creates a new RTL direction instance.
@@ -6483,6 +5993,15 @@ const [createRtlContext, createRtlPlugin, useRtl] = createPluginContext("v0:rtl"
6483
5993
  * - Auto-cleanup when registered within component setup
6484
5994
  *
6485
5995
  * Built on createSelection for consistent ticket-based management.
5996
+ *
5997
+ * @example
5998
+ * ```ts
5999
+ * import { useStack } from '@vuetify/v0'
6000
+ *
6001
+ * const stack = useStack()
6002
+ * const ticket = stack.register({ onDismiss: () => console.log('dismissed') })
6003
+ * ticket.select()
6004
+ * ```
6486
6005
  */
6487
6006
  /**
6488
6007
  * Creates a new stack instance for managing overlay z-indexes.
@@ -6557,7 +6076,7 @@ function createStack(_options = {}) {
6557
6076
  ...input,
6558
6077
  id
6559
6078
  });
6560
- if (instanceExists()) onScopeDispose(() => {
6079
+ if (/* @__PURE__ */ instanceExists()) onScopeDispose(() => {
6561
6080
  selection.unregister(id);
6562
6081
  }, true);
6563
6082
  return ticket;
@@ -6600,12 +6119,7 @@ function createStack(_options = {}) {
6600
6119
  */
6601
6120
  function createStackContext(_options = {}) {
6602
6121
  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);
6122
+ return createTrinity(namespace, createStack(options));
6609
6123
  }
6610
6124
  /**
6611
6125
  * Creates a Vue plugin to provide stack context at app level.
@@ -6686,7 +6200,7 @@ function getStackFallback() {
6686
6200
  */
6687
6201
  function useStack(namespace = "v0:stack") {
6688
6202
  const fallback = getStackFallback();
6689
- if (!instanceExists()) return fallback;
6203
+ if (!/* @__PURE__ */ instanceExists()) return fallback;
6690
6204
  try {
6691
6205
  return useContext(namespace);
6692
6206
  } catch {
@@ -6712,6 +6226,15 @@ function useStack(namespace = "v0:stack") {
6712
6226
  * - Automatic cleanup on remove/clear
6713
6227
  *
6714
6228
  * Uses adapter pattern to abstract storage implementation details.
6229
+ *
6230
+ * @example
6231
+ * ```ts
6232
+ * import { useStorage } from '@vuetify/v0'
6233
+ *
6234
+ * const storage = useStorage()
6235
+ * const theme = storage.get('theme', 'light')
6236
+ * theme.value = 'dark' // persists automatically
6237
+ * ```
6715
6238
  */
6716
6239
  /**
6717
6240
  * Creates a new storage instance.
@@ -6753,7 +6276,7 @@ function createStorage(options = {}) {
6753
6276
  if (/* @__PURE__ */ isNullOrUndefined(raw)) return void 0;
6754
6277
  try {
6755
6278
  const parsed = serializer.read(raw);
6756
- if (ttl && /* @__PURE__ */ isObject(parsed) && "__ttl" in parsed && "__v" in parsed) {
6279
+ if (ttl && /* @__PURE__ */ isObject(parsed) && "__v0" in parsed && "__v" in parsed) {
6757
6280
  const envelope = parsed;
6758
6281
  if (Date.now() - envelope.__t > ttl) {
6759
6282
  adapter?.removeItem(prefixedKey);
@@ -6769,7 +6292,7 @@ function createStorage(options = {}) {
6769
6292
  }
6770
6293
  function writeStored(prefixedKey, value) {
6771
6294
  const wrapped = ttl ? {
6772
- __ttl: 1,
6295
+ __v0: 1,
6773
6296
  __v: value,
6774
6297
  __t: Date.now()
6775
6298
  } : value;
@@ -6859,6 +6382,17 @@ const [createStorageContext, createStoragePlugin, useStorage] = createPluginCont
6859
6382
  *
6860
6383
  * Perfect for conditional side effects, feature flags, and performance optimization
6861
6384
  * by only running reactive effects when needed.
6385
+ *
6386
+ * @example
6387
+ * ```ts
6388
+ * import { shallowRef } from 'vue'
6389
+ * import { useToggleScope } from '@vuetify/v0'
6390
+ *
6391
+ * const isEnabled = shallowRef(false)
6392
+ * const { isActive } = useToggleScope(isEnabled, () => {
6393
+ * // effects run while isEnabled is true
6394
+ * })
6395
+ * ```
6862
6396
  */
6863
6397
  /**
6864
6398
  * Conditionally manages an effect scope based on a reactive boolean source.
@@ -6954,6 +6488,15 @@ function useToggleScope(source, fn) {
6954
6488
  * - Multiple overloads for type safety
6955
6489
  *
6956
6490
  * Perfect for safely managing event listeners in Vue components.
6491
+ *
6492
+ * @example
6493
+ * ```ts
6494
+ * import { useEventListener } from '@vuetify/v0'
6495
+ *
6496
+ * useEventListener(window, 'resize', () => {
6497
+ * console.log('window resized')
6498
+ * })
6499
+ * ```
6957
6500
  */
6958
6501
  /**
6959
6502
  * Attaches an event listener to a target.
@@ -6984,8 +6527,8 @@ function useEventListener(target, event, listener, options) {
6984
6527
  ], ([el, events, listeners, opts]) => {
6985
6528
  cleanup();
6986
6529
  if (!el) return;
6987
- const eventList = toArray(events);
6988
- const listenerList = toArray(listeners);
6530
+ const eventList = /* @__PURE__ */ toArray(events);
6531
+ const listenerList = /* @__PURE__ */ toArray(listeners);
6989
6532
  for (const event of eventList) for (const listenerFn of listenerList) cleanups.push(register(el, event, listenerFn, opts));
6990
6533
  }, {
6991
6534
  immediate: true,
@@ -7050,6 +6593,15 @@ function useDocumentEventListener(event, listener, options) {
7050
6593
  * Accessibility: This composable handles pointer interactions only. For accessible
7051
6594
  * components (dialogs, popovers, menus), pair with `useHotkey` for Escape key
7052
6595
  * dismissal per WCAG/APG requirements.
6596
+ *
6597
+ * @example
6598
+ * ```ts
6599
+ * import { useTemplateRef } from 'vue'
6600
+ * import { useClickOutside } from '@vuetify/v0'
6601
+ *
6602
+ * const target = useTemplateRef('popover')
6603
+ * useClickOutside(target, () => console.log('clicked outside'))
6604
+ * ```
7053
6605
  */
7054
6606
  /**
7055
6607
  * Detects clicks outside of the specified element(s).
@@ -7130,7 +6682,7 @@ function useClickOutside(target, handler, options = {}) {
7130
6682
  * Resolve target(s) to an array of HTMLElements.
7131
6683
  */
7132
6684
  function getTargets() {
7133
- return toArray(target).map((source) => toValue(source)).filter((el) => !!el && /* @__PURE__ */ isFunction(el.contains));
6685
+ return (/* @__PURE__ */ toArray(target)).map((source) => toValue(source)).filter((el) => !!el && /* @__PURE__ */ isFunction(el.contains));
7134
6686
  }
7135
6687
  /**
7136
6688
  * Resolve ignore targets to a tuple of [selectors, elements].
@@ -7237,6 +6789,7 @@ function useClickOutside(target, handler, options = {}) {
7237
6789
  * Handle window blur - detect focus moving to iframe.
7238
6790
  */
7239
6791
  function onBlur(event) {
6792
+ if (!IN_BROWSER) return;
7240
6793
  if (isPaused.value) return;
7241
6794
  if (event.defaultPrevented) return;
7242
6795
  if (document.activeElement instanceof HTMLIFrameElement) {
@@ -7287,4 +6840,4 @@ function useClickOutside(target, handler, options = {}) {
7287
6840
  };
7288
6841
  }
7289
6842
  //#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 };
6843
+ export { createRating as $, useElementIntersection as A, ClientAdapter as At, createBreakpointsPlugin as B, usePresence as C, createForm as Ct, usePrefersDark as D, createComboboxContext as Dt, usePrefersContrast as E, createCombobox as Et, createDateContext as F, useBreadcrumbs as Ft, useVirtual as G, toReactive as H, createDatePlugin as I, useTimeline as J, createTimeline as K, useDate as L, useImage as M, usePopover as Mt, useHotkey as N, createBreadcrumbs as Nt, usePrefersReducedMotion as O, useCombobox as Ot, createDate as P, createBreadcrumbsContext as Pt, createSlider as Q, createBreakpoints as R, useProxyModel as S, createValidation as St, useMediaQuery as T, useForm as Tt, createVirtual as U, useBreakpoints as V, createVirtualContext as W, createStepContext as X, createStep as Y, useStep as Z, createRtlPlugin as _, createNumeric as _t, useToggleScope as a, createOverflow as at, useRovingFocus as b, useNested as bt, createStoragePlugin as c, useElementSize as ct, createStackContext as d, createFallbackHydration as dt, createRatingContext as et, createStackPlugin as f, createHydration as ft, createRtlFallback as g, createNumberField as gt, createRtlContext as h, useHydration as ht, useWindowEventListener as i, useProgress as it, useIntersectionObserver as j, useVirtualFocus as jt, useLazy as k, ServerAdapter as kt, useStorage as l, useResizeObserver as lt, createRtl as m, createHydrationPlugin as mt, useDocumentEventListener as n, createProgress as nt, createStorage as o, createOverflowContext as ot, useStack as p, createHydrationContext as pt, createTimelineContext as q, useEventListener as r, createProgressContext as rt, createStorageContext as s, useOverflow as st, useClickOutside as t, useRating as tt, createStack as u, toElement as ut, useRtl as v, createNested as vt, useMutationObserver as w, createFormContext as wt, useRaf as x, createInput as xt, Vuetify0RtlAdapter as y, createNestedContext as yt, createBreakpointsContext as z };