@vuetify/v0 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (162) hide show
  1. package/README.md +8 -0
  2. package/dist/{adapter-Butx_2UU.d.mts → adapter-BXunW_mw.d.mts} +1 -1
  3. package/dist/{createPagination-B5dfqY-a.mjs → adapter-BiQV5j8B.mjs} +98 -3
  4. package/dist/adapter-ClB-53_F.d.mts +62 -0
  5. package/dist/{adapter-hq9YlPOF.d.mts → adapter-CqS8xexO.d.mts} +2 -2
  6. package/dist/adapter-CrRJuxRk.mjs +21 -0
  7. package/dist/{adapter-_srNCBEi.d.mts → adapter-PDTe5nFT.d.mts} +6 -7
  8. package/dist/browser/index.d.ts +15101 -12955
  9. package/dist/browser/index.js +16553 -14035
  10. package/dist/components/index.d.mts +2 -2
  11. package/dist/components/index.mjs +2 -2
  12. package/dist/{components-B2BZ1B3K.mjs → components-DBhVg-t1.mjs} +8210 -6301
  13. package/dist/composables/index.d.mts +22 -20
  14. package/dist/composables/index.mjs +37 -34
  15. package/dist/{composables-DONBl_c9.mjs → composables-ZGhVN2EJ.mjs} +32 -1061
  16. package/dist/{consola-BPGkJp_q.d.mts → consola-CdMU53rU.d.mts} +1 -1
  17. package/dist/constants/index.d.mts +1 -1
  18. package/dist/constants/index.mjs +1 -1
  19. package/dist/{createDataTable-DgyHBfAr.mjs → createDataTable-VmQEDn-7.mjs} +23 -7
  20. package/dist/{createGroup-BXKKcb9-.mjs → createGroup-B_LL7xRr.mjs} +2 -2
  21. package/dist/createPlugin-Oo6t-vBw.mjs +157 -0
  22. package/dist/{createRegistry-B9cOWny2.mjs → createRegistry-DVdvep0v.mjs} +1 -1
  23. package/dist/{createSelection-CWE554_g.mjs → createSelection-BNdDz8oY.mjs} +1 -1
  24. package/dist/{createSingle-Dz-1Iv7u.mjs → createSingle-DHyIQ9Cj.mjs} +1 -1
  25. package/dist/{createTokens-C4qcW2Kv.mjs → createTokens-DoISbwd7.mjs} +2 -2
  26. package/dist/data-table/adapters/client/index.d.mts +1 -1
  27. package/dist/data-table/adapters/client/index.mjs +1 -1
  28. package/dist/data-table/adapters/index.d.mts +4 -4
  29. package/dist/data-table/adapters/index.mjs +4 -4
  30. package/dist/data-table/adapters/server/index.d.mts +1 -1
  31. package/dist/data-table/adapters/server/index.mjs +1 -1
  32. package/dist/data-table/adapters/virtual/index.d.mts +1 -1
  33. package/dist/data-table/adapters/virtual/index.mjs +1 -1
  34. package/dist/data-table/index.d.mts +5 -5
  35. package/dist/data-table/index.mjs +5 -5
  36. package/dist/date/index.d.mts +1 -1
  37. package/dist/date/index.mjs +2 -2
  38. package/dist/features/adapters/flagsmith/index.d.mts +1 -1
  39. package/dist/features/adapters/flagsmith/index.mjs +1 -1
  40. package/dist/features/adapters/launchdarkly/index.d.mts +1 -1
  41. package/dist/features/adapters/launchdarkly/index.mjs +1 -1
  42. package/dist/features/adapters/posthog/index.d.mts +1 -1
  43. package/dist/features/adapters/posthog/index.mjs +2 -2
  44. package/dist/features/index.d.mts +2 -2
  45. package/dist/features/index.mjs +2 -2
  46. package/dist/{flagsmith-DA2GCyGv.d.mts → flagsmith-DcIDrI7_.d.mts} +1 -1
  47. package/dist/{globals-CtaXlEOI.mjs → globals-DaoKtIGF.mjs} +1 -1
  48. package/dist/{index-CTl0cGH6.d.mts → index-Cm6CbqI6.d.mts} +7258 -5609
  49. package/dist/{index-Dc7lKT6q.d.mts → index-Cx0cWGlx.d.mts} +461 -130
  50. package/dist/{index-QnpcDsV7.d.mts → index-D0ub61GV.d.mts} +2 -2
  51. package/dist/{index-RGiSdjYt.d.mts → index-DSPkZ0ql.d.mts} +2 -2
  52. package/dist/{index-DCtHbY0a.d.mts → index-Di9e8sOm.d.mts} +24 -19
  53. package/dist/{index-DF0tMI2_.d.mts → index-DjRE4lLl.d.mts} +108 -2
  54. package/dist/index.d.mts +25 -24
  55. package/dist/index.mjs +40 -37
  56. package/dist/json/attributes.json +488 -0
  57. package/dist/json/importMap.json +92 -0
  58. package/dist/json/tags.json +234 -0
  59. package/dist/json/web-types.json +1540 -113
  60. package/dist/{launchdarkly-Bp8p9PMD.d.mts → launchdarkly-CUzunYol.d.mts} +1 -1
  61. package/dist/locale/adapters/index.d.mts +2 -2
  62. package/dist/locale/adapters/index.mjs +2 -2
  63. package/dist/locale/adapters/v0/index.d.mts +1 -1
  64. package/dist/locale/adapters/v0/index.mjs +1 -1
  65. package/dist/locale/adapters/vue-i18n/index.d.mts +1 -1
  66. package/dist/locale/adapters/vue-i18n/index.mjs +1 -1
  67. package/dist/locale/index.d.mts +3 -3
  68. package/dist/locale/index.mjs +3 -3
  69. package/dist/locale/messages/en/index.d.mts +3 -0
  70. package/dist/locale/messages/en/index.mjs +1 -0
  71. package/dist/logger/adapters/consola/index.d.mts +1 -1
  72. package/dist/logger/adapters/index.d.mts +4 -4
  73. package/dist/logger/adapters/index.mjs +1 -1
  74. package/dist/logger/adapters/pino/index.d.mts +1 -1
  75. package/dist/logger/adapters/v0/index.d.mts +1 -1
  76. package/dist/logger/adapters/v0/index.mjs +1 -1
  77. package/dist/logger/index.d.mts +5 -5
  78. package/dist/logger/index.mjs +2 -2
  79. package/dist/notifications/index.d.mts +1 -1
  80. package/dist/notifications/index.mjs +2 -2
  81. package/dist/palettes/ant/index.d.mts +1 -1
  82. package/dist/palettes/index.d.mts +3 -3
  83. package/dist/palettes/material/index.d.mts +1 -1
  84. package/dist/palettes/md1/index.d.mts +1 -1
  85. package/dist/palettes/md2/index.d.mts +1 -1
  86. package/dist/palettes/radix/index.d.mts +1 -1
  87. package/dist/palettes/tailwind/index.d.mts +1 -1
  88. package/dist/permissions/adapters/index.d.mts +1 -1
  89. package/dist/permissions/adapters/index.mjs +1 -1
  90. package/dist/permissions/adapters/v0/index.d.mts +1 -1
  91. package/dist/permissions/adapters/v0/index.mjs +1 -1
  92. package/dist/permissions/index.d.mts +1 -1
  93. package/dist/permissions/index.mjs +2 -2
  94. package/dist/{pino-B6BI1AOK.d.mts → pino-DjeWBFnj.d.mts} +1 -1
  95. package/dist/popover/adapters/floating-ui/index.d.mts +25 -0
  96. package/dist/popover/adapters/floating-ui/index.mjs +98 -0
  97. package/dist/popover/index.d.mts +3 -0
  98. package/dist/popover/index.mjs +3 -0
  99. package/dist/{posthog-sFqk0bGy.d.mts → posthog-CJAYssdr.d.mts} +1 -1
  100. package/dist/rules/index.d.mts +1 -1
  101. package/dist/rules/index.mjs +1 -1
  102. package/dist/{server-DbtTGb67.d.mts → server-5vbJ7GGs.d.mts} +2 -2
  103. package/dist/{server-D5BJBjB0.mjs → server-m7iD1vOr.mjs} +1 -2
  104. package/dist/storage/adapters/index.d.mts +2 -2
  105. package/dist/storage/adapters/index.mjs +1 -1
  106. package/dist/storage/adapters/memory/index.d.mts +1 -1
  107. package/dist/storage/adapters/memory/index.mjs +1 -1
  108. package/dist/storage/index.d.mts +3 -3
  109. package/dist/storage/index.mjs +2 -2
  110. package/dist/theme/adapters/index.d.mts +1 -1
  111. package/dist/theme/adapters/index.mjs +3 -3
  112. package/dist/theme/adapters/unhead/index.d.mts +1 -1
  113. package/dist/theme/adapters/unhead/index.mjs +1 -1
  114. package/dist/theme/adapters/v0/index.d.mts +1 -1
  115. package/dist/theme/adapters/v0/index.mjs +1 -1
  116. package/dist/theme/index.d.mts +2 -2
  117. package/dist/theme/index.mjs +4 -4
  118. package/dist/types/index.d.mts +1 -1
  119. package/dist/{unhead-BAWCwNOF.mjs → unhead-C8zbWr45.mjs} +2 -2
  120. package/dist/{useEventListener-DSOeDtC-.mjs → useEventListener-2eAMwUdw.mjs} +2 -2
  121. package/dist/useFeatures-DLafCOWt.mjs +221 -0
  122. package/dist/{useLocale-D-V0DENN.mjs → useLocale-K_45ulPt.mjs} +4 -4
  123. package/dist/{useLogger-CbvzXCWb.mjs → useLogger-YyWuYvrH.mjs} +5 -159
  124. package/dist/{useNotifications-Cqg3uDz0.mjs → useNotifications-Kh_KvM7j.mjs} +57 -154
  125. package/dist/{usePermissions-BTdUVyQe.mjs → usePermissions-BCGwsOES.mjs} +4 -4
  126. package/dist/usePopover-BTo0AGIQ.mjs +420 -0
  127. package/dist/{useRovingFocus-g6ifibLg.mjs → useRovingFocus-CkRnVmJ1.mjs} +1122 -531
  128. package/dist/{useRules-DEiHd_eY.mjs → useRules-BuE5ffOJ.mjs} +3 -2
  129. package/dist/{useStorage-BSfQfDbg.mjs → useStorage-BT8-mjVs.mjs} +5 -4
  130. package/dist/useTheme-DkK6tPqY.mjs +445 -0
  131. package/dist/useTimer-CGVXk397.mjs +151 -0
  132. package/dist/utilities/index.d.mts +2 -2
  133. package/dist/utilities/index.mjs +181 -2
  134. package/dist/{v0-CveVV6On.mjs → v0-B_53w7Fu.mjs} +2 -2
  135. package/dist/{v0-BnUwMaOv.d.mts → v0-CDW1Ktk-.d.mts} +1 -1
  136. package/dist/{v0-CZBkpQjr.mjs → v0-D0Exc2bO.mjs} +2 -2
  137. package/dist/{v0-rSxMW8FJ.d.mts → v0-DfFK-p4X.d.mts} +1 -1
  138. package/dist/{v0-DotXXGXU.d.mts → v0-GI9U-rPA.d.mts} +2 -2
  139. package/dist/{v0-CCWHeKJM.mjs → v0-SuxTihEe.mjs} +1 -1
  140. package/dist/{v0-A4GLojAr.mjs → v0-yZ2ZUtVF.mjs} +1 -2
  141. package/dist/{virtual-DFvOoeG6.mjs → virtual-Bbu26O_h.mjs} +1 -2
  142. package/dist/{virtual-C-NsLue0.d.mts → virtual-JIdFLpTQ.d.mts} +2 -2
  143. package/package.json +8 -1
  144. package/dist/adapter-CVoWg0sw.mjs +0 -99
  145. package/dist/useFeatures-YJmONiU7.mjs +0 -124
  146. package/dist/useTheme-C0_i__N6.mjs +0 -162
  147. /package/dist/{adapter-CTsckKAR.mjs → adapter-8UADsA3-.mjs} +0 -0
  148. /package/dist/{adapter-BCtceV3b.mjs → adapter-BuSfpxur.mjs} +0 -0
  149. /package/dist/{adapter-Bc0yPSfo.d.mts → adapter-D5nT3bLw.d.mts} +0 -0
  150. /package/dist/{adapter-bwZo7b5p.mjs → adapter-D8zizQVP.mjs} +0 -0
  151. /package/dist/{adapter-q1sRACUc.mjs → adapter-TiGrumDi.mjs} +0 -0
  152. /package/dist/{adapter-BYzU4Ey5.d.mts → adapter-ryk5H6YZ.d.mts} +0 -0
  153. /package/dist/{index-CROz1VSV.d.mts → index-CX869wwk.d.mts} +0 -0
  154. /package/dist/{index-FtE8MXJ_.d.mts → index-CsuikFeJ.d.mts} +0 -0
  155. /package/dist/{index-DidZKN6S.d.mts → index-Djhiy3nS.d.mts} +0 -0
  156. /package/dist/{index-CyNk9FpR.d.mts → index-DtiaWx5U.d.mts} +0 -0
  157. /package/dist/{index-DXMlYoiQ.d.mts → index-H_hl6-4b.d.mts} +0 -0
  158. /package/dist/{index-BgCkepP_.d.mts → index-u_qSc2xS.d.mts} +0 -0
  159. /package/dist/{memory-DbyZeNjg.d.mts → memory-B7z1RR9r.d.mts} +0 -0
  160. /package/dist/{memory-BJjkQzxs.mjs → memory-CR6zvuaP.mjs} +0 -0
  161. /package/dist/{toArray-C89ZaEuF.mjs → toArray-MY9Kb1Qy.mjs} +0 -0
  162. /package/dist/{v0-UNyykD27.mjs → v0-Ch0yBKEj.mjs} +0 -0
@@ -0,0 +1,221 @@
1
+ import { isArray, isBoolean, isNumber, isObject, isString } from "./utilities/index.mjs";
2
+ import { n as createPluginContext } from "./createPlugin-Oo6t-vBw.mjs";
3
+ import { t as createTokens } from "./createTokens-DoISbwd7.mjs";
4
+ import { t as toArray } from "./toArray-MY9Kb1Qy.mjs";
5
+ import { t as createGroup } from "./createGroup-B_LL7xRr.mjs";
6
+ import { shallowReactive, shallowRef } from "vue";
7
+ //#region src/composables/useFeatures/index.ts
8
+ /**
9
+ * @module useFeatures
10
+ *
11
+ * @see https://0.vuetifyjs.com/composables/plugins/use-features
12
+ *
13
+ * @remarks
14
+ * Feature flag system with boolean and token-based features.
15
+ *
16
+ * Key features:
17
+ * - Boolean features (true/false activation)
18
+ * - Token features with $variation support
19
+ * - Auto-selection of enabled features
20
+ * - Multi-select support for feature combinations
21
+ * - Perfect for A/B testing, progressive rollout, feature toggles
22
+ * - Adapter pattern for external feature flag services (Generic, LaunchDarkly, Flagsmith)
23
+ *
24
+ * Inheritance chain: createRegistry → createSelection → createGroup → createFeatures
25
+ * Integrates with createTokens for token-based features.
26
+ *
27
+ * @example
28
+ * ```ts
29
+ * import { useFeatures } from '@vuetify/v0'
30
+ *
31
+ * const features = useFeatures()
32
+ * features.register({ id: 'new-checkout', value: true })
33
+ * console.log(features.variation('new-checkout'))
34
+ * ```
35
+ */
36
+ function isEnabled(value) {
37
+ if (/* @__PURE__ */ isBoolean(value)) return value;
38
+ if (/* @__PURE__ */ isObject(value) && /* @__PURE__ */ isBoolean(value.$value)) return value.$value;
39
+ }
40
+ const seams = /* @__PURE__ */ new WeakMap();
41
+ function coerce(saved) {
42
+ if (!/* @__PURE__ */ isObject(saved)) return null;
43
+ const map = /* @__PURE__ */ new Map();
44
+ if (/* @__PURE__ */ isArray(saved.enabled)) {
45
+ for (const id of saved.enabled) if (/* @__PURE__ */ isString(id) || /* @__PURE__ */ isNumber(id)) map.set(id, true);
46
+ }
47
+ if (/* @__PURE__ */ isArray(saved.disabled)) {
48
+ for (const id of saved.disabled) if (/* @__PURE__ */ isString(id) || /* @__PURE__ */ isNumber(id)) map.set(id, false);
49
+ }
50
+ return map.size > 0 ? map : null;
51
+ }
52
+ /**
53
+ * Creates a new features instance.
54
+ *
55
+ * @param options The options for the features instance.
56
+ * @returns A new features instance.
57
+ *
58
+ * @see https://0.vuetifyjs.com/composables/plugins/use-features
59
+ *
60
+ * @example
61
+ * ```ts
62
+ * import { createFeatures } from '@vuetify/v0'
63
+ *
64
+ * const features = createFeatures({
65
+ * features: {
66
+ * 'dark-mode': true,
67
+ * 'theme-color': { $variation: 'blue' },
68
+ * },
69
+ * })
70
+ * ```
71
+ */
72
+ function createFeatures(_options = {}) {
73
+ const { features, ...options } = _options;
74
+ const tokens = createTokens(features, { flat: true });
75
+ const registry = createGroup({
76
+ ...options,
77
+ events: true,
78
+ reactive: true
79
+ });
80
+ const touched = shallowReactive(/* @__PURE__ */ new Set());
81
+ const defaults = /* @__PURE__ */ new Map();
82
+ const pending = shallowRef(null);
83
+ for (const [id, { value }] of tokens.entries()) register({
84
+ id,
85
+ value
86
+ });
87
+ function touch(ids) {
88
+ for (const id of /* @__PURE__ */ toArray(ids)) if (registry.has(id)) touched.add(id);
89
+ }
90
+ function select(ids) {
91
+ touch(ids);
92
+ registry.select(ids);
93
+ }
94
+ function unselect(ids) {
95
+ touch(ids);
96
+ registry.unselect(ids);
97
+ }
98
+ function toggle(ids) {
99
+ touch(ids);
100
+ registry.toggle(ids);
101
+ }
102
+ function reset() {
103
+ touched.clear();
104
+ pending.value = null;
105
+ registry.reset();
106
+ for (const [id, enabled] of defaults) if (enabled) registry.select(id);
107
+ }
108
+ function variation(id, fallback = null) {
109
+ const ticket = registry.get(id);
110
+ if (!ticket) return fallback;
111
+ return /* @__PURE__ */ isObject(ticket.value) ? ticket.value.$variation ?? fallback : ticket.value ?? fallback;
112
+ }
113
+ function register(registration = {}) {
114
+ const item = {
115
+ value: false,
116
+ ...registration
117
+ };
118
+ const ticket = registry.register(item);
119
+ if (isEnabled(ticket.value) === true) registry.select(ticket.id);
120
+ defaults.set(ticket.id, registry.selectedIds.has(ticket.id));
121
+ if (pending.value?.has(ticket.id) && !touched.has(ticket.id)) {
122
+ touched.add(ticket.id);
123
+ if (pending.value.get(ticket.id)) registry.select(ticket.id);
124
+ else registry.unselect(ticket.id);
125
+ }
126
+ return ticket;
127
+ }
128
+ function sync(flags) {
129
+ for (const [id, value] of Object.entries(flags)) if (registry.get(id)) {
130
+ const enabled = isEnabled(value);
131
+ registry.upsert(id, { value });
132
+ if (enabled === true) registry.select(id);
133
+ else if (enabled === false) registry.selectedIds.delete(id);
134
+ } else register({
135
+ id,
136
+ value
137
+ });
138
+ }
139
+ function onboard(registrations) {
140
+ return registry.batch(() => registrations.map((registration) => register(registration)));
141
+ }
142
+ function replay(force = false) {
143
+ if (!pending.value) return;
144
+ for (const [id, enabled] of pending.value) {
145
+ if (!registry.has(id)) continue;
146
+ if (!force && touched.has(id)) continue;
147
+ touched.add(id);
148
+ if (enabled) registry.select(id);
149
+ else registry.unselect(id);
150
+ }
151
+ }
152
+ function delta() {
153
+ pending.value;
154
+ const enabled = [];
155
+ const disabled = [];
156
+ for (const id of touched) {
157
+ if (!registry.has(id)) continue;
158
+ const selected = registry.selectedIds.has(id);
159
+ if (selected === defaults.get(id)) continue;
160
+ if (selected) enabled.push(id);
161
+ else disabled.push(id);
162
+ }
163
+ return {
164
+ enabled,
165
+ disabled
166
+ };
167
+ }
168
+ const context = {
169
+ ...registry,
170
+ select,
171
+ unselect,
172
+ toggle,
173
+ reset,
174
+ variation,
175
+ register,
176
+ onboard,
177
+ sync,
178
+ get size() {
179
+ return registry.size;
180
+ }
181
+ };
182
+ seams.set(context, {
183
+ delta,
184
+ restore: (saved) => {
185
+ pending.value = coerce(saved);
186
+ replay();
187
+ },
188
+ replay: () => replay(true)
189
+ });
190
+ return context;
191
+ }
192
+ function createFeaturesFallback() {
193
+ return {
194
+ size: 0,
195
+ variation: (_id, fallback = null) => fallback,
196
+ sync: () => {},
197
+ onboard: () => [],
198
+ register: () => void 0,
199
+ select: () => {},
200
+ unselect: () => {},
201
+ get: () => void 0,
202
+ has: () => false,
203
+ selectedIds: /* @__PURE__ */ new Set(),
204
+ values: () => []
205
+ };
206
+ }
207
+ const [createFeaturesContext, createFeaturesPlugin, useFeatures] = createPluginContext("v0:features", (options) => createFeatures(options), {
208
+ fallback: () => createFeaturesFallback(),
209
+ persist: (context) => seams.get(context)?.delta() ?? null,
210
+ restore: (context, saved) => seams.get(context)?.restore(saved),
211
+ setup: (context, app, { adapter }) => {
212
+ if (!adapter) return;
213
+ for (const a of /* @__PURE__ */ isArray(adapter) ? adapter : [adapter]) {
214
+ context.sync(a.setup((flags) => context.sync(flags)));
215
+ app.onUnmount(() => a.dispose?.());
216
+ }
217
+ seams.get(context)?.replay();
218
+ }
219
+ });
220
+ //#endregion
221
+ export { useFeatures as i, createFeaturesContext as n, createFeaturesPlugin as r, createFeatures as t };
@@ -1,8 +1,8 @@
1
1
  import { isNumber, isString } from "./utilities/index.mjs";
2
- import { o as createPluginContext } from "./useLogger-CbvzXCWb.mjs";
3
- import { t as createSingle } from "./createSingle-Dz-1Iv7u.mjs";
4
- import { r as flatten, t as createTokens } from "./createTokens-C4qcW2Kv.mjs";
5
- import { t as V0LocaleAdapter } from "./v0-CZBkpQjr.mjs";
2
+ import { n as createPluginContext } from "./createPlugin-Oo6t-vBw.mjs";
3
+ import { t as createSingle } from "./createSingle-DHyIQ9Cj.mjs";
4
+ import { r as flatten, t as createTokens } from "./createTokens-DoISbwd7.mjs";
5
+ import { t as V0LocaleAdapter } from "./v0-D0Exc2bO.mjs";
6
6
  //#region src/composables/useLocale/index.ts
7
7
  /**
8
8
  * @module useLocale
@@ -1,161 +1,7 @@
1
- import { s as __LOGGER_ENABLED__, t as IN_BROWSER } from "./globals-CtaXlEOI.mjs";
2
- import { isNullOrUndefined, isUndefined } from "./utilities/index.mjs";
3
- import { i as useContext, t as createTrinity } from "./createTrinity-z-3q9QWR.mjs";
4
- import { t as V0LoggerAdapter } from "./v0-CCWHeKJM.mjs";
5
- import { hasInjectionContext, inject, watch } from "vue";
6
- //#region src/composables/createPlugin/index.ts
7
- /**
8
- * @module createPlugin
9
- *
10
- * @see https://vuejs.org/guide/reusability/plugins.html
11
- * @see https://0.vuetifyjs.com/composables/foundation/create-plugin
12
- *
13
- * @remarks
14
- * Factory for creating Vue plugins with proper context provision.
15
- *
16
- * Wraps the provide function in app.runWithContext() to ensure proper execution context,
17
- * allowing plugins to safely provide dependency injection contexts at the application level.
18
- *
19
- * Also exports `createPluginContext` — a higher-level factory that generates the standard
20
- * context/plugin/consumer triple for plugin composables, eliminating boilerplate.
21
- * Supports `persist()` / `restore()` lifecycle hooks for saving and rehydrating plugin state.
22
- *
23
- * @example
24
- * ```ts
25
- * import { createPlugin } from '@vuetify/v0'
26
- *
27
- * const plugin = createPlugin({
28
- * namespace: 'v0:my-plugin',
29
- * provide: app => app.provide('my-key', { greet: () => 'hello' }),
30
- * })
31
- * // app.use(plugin)
32
- * ```
33
- */
34
- const INSTALLED = Symbol.for("v0:installed-plugins");
35
- function getInstalled(app) {
36
- const ctx = app._context;
37
- return ctx[INSTALLED] ??= /* @__PURE__ */ new Set();
38
- }
39
- /**
40
- * Creates a new Vue plugin.
41
- *
42
- * @param options The plugin options.
43
- * @returns A new Vue plugin.
44
- *
45
- * @see https://0.vuetifyjs.com/composables/foundation/create-plugin
46
- *
47
- * @example
48
- * ```ts
49
- * export const [useContext, provideContext] = createContext<MyContext>('my-plugin')
50
- *
51
- * const context = {}
52
- *
53
- * export const MyPlugin = createPlugin({
54
- * namespace: 'my-plugin',
55
- * provide: (app) => {
56
- * provideContext(context, app)
57
- * },
58
- * setup: (app) => {
59
- * // Optional setup logic
60
- * },
61
- * })
62
- */
63
- function createPlugin(options) {
64
- return { install(app) {
65
- app.runWithContext(() => {
66
- const installed = getInstalled(app);
67
- if (installed.has(options.namespace)) return;
68
- installed.add(options.namespace);
69
- options.provide(app);
70
- options.setup?.(app);
71
- });
72
- } };
73
- }
74
- function deriveKey(namespace) {
75
- return namespace.startsWith("v0:") ? namespace.slice(3) : namespace;
76
- }
77
- function getPersistedStorage() {
78
- return useContext("v0:storage");
79
- }
80
- /**
81
- * Creates the three standard functions for a plugin composable.
82
- *
83
- * @param defaultNamespace The default DI namespace string (e.g. `'v0:logger'`).
84
- * @param factory Function that creates the composable context instance from options.
85
- * @param config Optional setup callback and fallback factory.
86
- * @returns A readonly tuple: `[createXContext, createXPlugin, useX]`.
87
- *
88
- * @example
89
- * ```ts
90
- * // Simple — no setup or fallback
91
- * export const [createStorageContext, createStoragePlugin, useStorage] =
92
- * createPluginContext('v0:storage', options => createStorage(options))
93
- *
94
- * // With fallback — safe outside component instances
95
- * export const [createLoggerContext, createLoggerPlugin, useLogger] =
96
- * createPluginContext('v0:logger', options => createLogger(options), {
97
- * fallback: ns => createFallbackLogger(ns),
98
- * setup: (context) => {
99
- * if (__DEV__ && IN_BROWSER) (window as Window & { __v0Logger__?: typeof context }).__v0Logger__ = context
100
- * },
101
- * })
102
- * ```
103
- */
104
- function createPluginContext(defaultNamespace, factory, config) {
105
- function createXContext(_options = {}) {
106
- const { namespace = defaultNamespace, persist: _persist, ...options } = _options;
107
- return createTrinity(namespace, factory(options));
108
- }
109
- function createXPlugin(_options = {}) {
110
- const { namespace = defaultNamespace, persist: shouldPersist, ...options } = _options;
111
- let context;
112
- return createPlugin({
113
- namespace,
114
- provide: (app) => {
115
- const [, provide, ctx] = createXContext({
116
- ...options,
117
- namespace
118
- });
119
- context = ctx;
120
- provide(context, app);
121
- if (shouldPersist && config?.restore) {
122
- const storage = getPersistedStorage();
123
- const key = deriveKey(namespace);
124
- const saved = storage.get(key);
125
- if (!/* @__PURE__ */ isNullOrUndefined(saved.value)) config.restore(context, saved.value);
126
- }
127
- },
128
- setup: config?.setup || shouldPersist ? (app) => {
129
- const ctx = context;
130
- config?.setup?.(ctx, app, options);
131
- if (shouldPersist && config?.persist) {
132
- const storage = getPersistedStorage();
133
- const key = deriveKey(namespace);
134
- const stored = storage.get(key);
135
- const stop = watch(() => config.persist(ctx), (val) => {
136
- stored.value = val;
137
- });
138
- app.onUnmount(stop);
139
- }
140
- } : void 0
141
- });
142
- }
143
- function useX(namespace = defaultNamespace) {
144
- if (config?.fallback) {
145
- if (!hasInjectionContext()) return config.fallback(namespace);
146
- const provided = inject(namespace, void 0);
147
- if (!/* @__PURE__ */ isUndefined(provided)) return provided;
148
- return config.fallback(namespace);
149
- }
150
- return useContext(namespace);
151
- }
152
- return [
153
- createXContext,
154
- createXPlugin,
155
- useX
156
- ];
157
- }
158
- //#endregion
1
+ import { s as __LOGGER_ENABLED__, t as IN_BROWSER } from "./globals-DaoKtIGF.mjs";
2
+ import { isUndefined } from "./utilities/index.mjs";
3
+ import { n as createPluginContext } from "./createPlugin-Oo6t-vBw.mjs";
4
+ import { t as V0LoggerAdapter } from "./v0-SuxTihEe.mjs";
159
5
  //#region src/composables/useLogger/index.ts
160
6
  /**
161
7
  * @module useLogger
@@ -364,4 +210,4 @@ function useLogger(scope) {
364
210
  return /* @__PURE__ */ isUndefined(scope) || !scope.trim() ? logger : createScopedLogger(logger, scope);
365
211
  }
366
212
  //#endregion
367
- export { createPlugin as a, useLogger as i, createLoggerContext as n, createPluginContext as o, createLoggerPlugin as r, createLogger as t };
213
+ export { useLogger as i, createLoggerContext as n, createLoggerPlugin as r, createLogger as t };
@@ -1,156 +1,9 @@
1
- import { t as IN_BROWSER } from "./globals-CtaXlEOI.mjs";
2
- import { isFunction, isNull, isUndefined, useId as useId$1 } from "./utilities/index.mjs";
1
+ import { UNSAFE_KEYS, isNaN, isNull, isObject, isString, isUndefined, useId as useId$1 } from "./utilities/index.mjs";
3
2
  import { i as useContext, t as createTrinity } from "./createTrinity-z-3q9QWR.mjs";
4
- import { o as createPluginContext } from "./useLogger-CbvzXCWb.mjs";
5
- import { t as createRegistry } from "./createRegistry-B9cOWny2.mjs";
6
- import { onScopeDispose, shallowRef, toValue } from "vue";
7
- //#region src/composables/useTimer/index.ts
8
- /**
9
- * @module useTimer
10
- *
11
- * @see https://0.vuetifyjs.com/composables/system/use-timer
12
- *
13
- * @remarks
14
- * A reactive timer composable with pause/resume support.
15
- *
16
- * Key features:
17
- * - Start/stop/pause/resume controls
18
- * - Reactive remaining time tracking
19
- * - Reactive `duration` via `MaybeRefOrGetter` — read fresh on each `start()`
20
- * - One-shot (default) or repeating mode
21
- * - Automatic cleanup on scope disposal
22
- * - SSR-safe
23
- *
24
- * @example
25
- * ```ts
26
- * import { useTimer } from '@vuetify/v0'
27
- *
28
- * const timer = useTimer(() => console.log('fired'), { duration: 5000 })
29
- * timer.start()
30
- * ```
31
- */
32
- /**
33
- * Creates a reactive timer with pause/resume support.
34
- *
35
- * @param handler Callback invoked when the timer fires.
36
- * @param options Timer configuration.
37
- * @returns Timer controls and reactive state.
38
- *
39
- * @see https://0.vuetifyjs.com/composables/system/use-timer
40
- *
41
- * @example
42
- * ```ts
43
- * const timer = useTimer(() => console.log('fired'), { duration: 5000 })
44
- *
45
- * timer.start()
46
- * timer.pause()
47
- * timer.resume()
48
- * timer.stop()
49
- *
50
- * // Reactive duration — re-read on each start()
51
- * const duration = shallowRef(1000)
52
- * const reactive = useTimer(handler, { duration })
53
- * duration.value = 2000
54
- * reactive.start() // fires after 2000ms
55
- * ```
56
- */
57
- function useTimer(handler, options = {}) {
58
- const { duration = 1e3, repeat = false } = options;
59
- function resolveDuration() {
60
- return toValue(duration);
61
- }
62
- const remaining = shallowRef(resolveDuration());
63
- const isActive = shallowRef(false);
64
- const isPaused = shallowRef(false);
65
- let timeoutId;
66
- let trackingId;
67
- let startedAt = 0;
68
- let budget = remaining.value;
69
- function clearTimer() {
70
- if (!/* @__PURE__ */ isUndefined(timeoutId)) {
71
- globalThis.clearTimeout(timeoutId);
72
- timeoutId = void 0;
73
- }
74
- }
75
- function startTracking() {
76
- stopTracking();
77
- if (!IN_BROWSER) return;
78
- trackingId = globalThis.setInterval(() => {
79
- if (!isActive.value || isPaused.value) return;
80
- const elapsed = Date.now() - startedAt;
81
- remaining.value = Math.max(0, budget - elapsed);
82
- }, 100);
83
- }
84
- function stopTracking() {
85
- if (!/* @__PURE__ */ isUndefined(trackingId)) {
86
- globalThis.clearInterval(trackingId);
87
- trackingId = void 0;
88
- }
89
- }
90
- function fire() {
91
- clearTimer();
92
- stopTracking();
93
- handler();
94
- if (repeat) begin(resolveDuration());
95
- else {
96
- isActive.value = false;
97
- remaining.value = 0;
98
- }
99
- }
100
- function begin(ms) {
101
- clearTimer();
102
- stopTracking();
103
- budget = ms;
104
- startedAt = Date.now();
105
- remaining.value = ms;
106
- isActive.value = true;
107
- isPaused.value = false;
108
- timeoutId = globalThis.setTimeout(fire, ms);
109
- startTracking();
110
- }
111
- function start() {
112
- const ms = resolveDuration();
113
- if (ms < 0) return;
114
- begin(ms);
115
- }
116
- function stop() {
117
- clearTimer();
118
- stopTracking();
119
- isActive.value = false;
120
- isPaused.value = false;
121
- remaining.value = resolveDuration();
122
- }
123
- function pause() {
124
- if (!isActive.value || isPaused.value) return;
125
- const elapsed = Date.now() - startedAt;
126
- budget = Math.max(0, budget - elapsed);
127
- remaining.value = budget;
128
- clearTimer();
129
- stopTracking();
130
- isPaused.value = true;
131
- }
132
- function resume() {
133
- if (!isPaused.value) return;
134
- isPaused.value = false;
135
- startedAt = Date.now();
136
- timeoutId = globalThis.setTimeout(fire, budget);
137
- startTracking();
138
- }
139
- onScopeDispose(() => {
140
- clearTimer();
141
- stopTracking();
142
- }, true);
143
- return {
144
- start,
145
- stop,
146
- pause,
147
- resume,
148
- remaining,
149
- isActive,
150
- isPaused
151
- };
152
- }
153
- //#endregion
3
+ import { n as createPluginContext } from "./createPlugin-Oo6t-vBw.mjs";
4
+ import { t as createRegistry } from "./createRegistry-DVdvep0v.mjs";
5
+ import { t as useTimer } from "./useTimer-CGVXk397.mjs";
6
+ import { onScopeDispose } from "vue";
154
7
  //#region src/composables/createQueue/index.ts
155
8
  /**
156
9
  * @module createQueue
@@ -762,6 +615,49 @@ function createNotifications(_options = {}) {
762
615
  }
763
616
  };
764
617
  }
618
+ function toDate(value) {
619
+ if (!/* @__PURE__ */ isString(value)) return null;
620
+ const date = new Date(value);
621
+ return /* @__PURE__ */ isNaN(date.getTime()) ? null : date;
622
+ }
623
+ function snapshot(context) {
624
+ const out = {};
625
+ let count = 0;
626
+ for (const ticket of context.values()) {
627
+ if (UNSAFE_KEYS.has(String(ticket.id))) continue;
628
+ const entry = {};
629
+ if (!/* @__PURE__ */ isNull(ticket.readAt)) entry.readAt = ticket.readAt.toISOString();
630
+ if (!/* @__PURE__ */ isNull(ticket.seenAt)) entry.seenAt = ticket.seenAt.toISOString();
631
+ if (!/* @__PURE__ */ isNull(ticket.archivedAt)) entry.archivedAt = ticket.archivedAt.toISOString();
632
+ if (!/* @__PURE__ */ isNull(ticket.snoozedUntil) && ticket.snoozedUntil.getTime() > Date.now()) entry.snoozedUntil = ticket.snoozedUntil.toISOString();
633
+ if (Object.keys(entry).length === 0) continue;
634
+ out[ticket.id] = entry;
635
+ count++;
636
+ }
637
+ return count > 0 ? out : null;
638
+ }
639
+ function coerce(saved) {
640
+ if (!/* @__PURE__ */ isObject(saved)) return null;
641
+ const map = /* @__PURE__ */ new Map();
642
+ for (const [id, entry] of Object.entries(saved)) {
643
+ if (!/* @__PURE__ */ isObject(entry)) continue;
644
+ const state = {};
645
+ const readAt = toDate(entry.readAt);
646
+ const seenAt = toDate(entry.seenAt);
647
+ const archivedAt = toDate(entry.archivedAt);
648
+ const snoozedUntil = toDate(entry.snoozedUntil);
649
+ if (!/* @__PURE__ */ isNull(readAt)) state.readAt = readAt;
650
+ if (!/* @__PURE__ */ isNull(seenAt)) state.seenAt = seenAt;
651
+ if (!/* @__PURE__ */ isNull(archivedAt)) state.archivedAt = archivedAt;
652
+ if (!/* @__PURE__ */ isNull(snoozedUntil) && snoozedUntil.getTime() > Date.now()) state.snoozedUntil = snoozedUntil;
653
+ if (Object.keys(state).length > 0) map.set(id, state);
654
+ }
655
+ return map.size > 0 ? map : null;
656
+ }
657
+ function merge(context, map, ticket) {
658
+ const state = map.get(ticket.id) ?? map.get(String(ticket.id));
659
+ if (state) context.upsert(ticket.id, state);
660
+ }
765
661
  function noop() {}
766
662
  const EMPTY = [];
767
663
  function createNotificationsFallback() {
@@ -867,6 +763,13 @@ function createNotificationsFallback() {
867
763
  */
868
764
  const [createNotificationsContext, createNotificationsPlugin, useNotifications] = createPluginContext("v0:notifications", (options) => createNotifications(options), {
869
765
  fallback: () => createNotificationsFallback(),
766
+ persist: (context) => snapshot(context),
767
+ restore: (context, saved) => {
768
+ const map = coerce(saved);
769
+ if (!map) return;
770
+ for (const ticket of context.values()) merge(context, map, ticket);
771
+ context.on("register:ticket", (ticket) => merge(context, map, ticket));
772
+ },
870
773
  setup: (context, app, options) => {
871
774
  app.onUnmount(() => {
872
775
  context.dispose();
@@ -880,8 +783,8 @@ const [createNotificationsContext, createNotificationsPlugin, useNotifications]
880
783
  on: context.on,
881
784
  off: context.off
882
785
  });
883
- if (/* @__PURE__ */ isFunction(adapter.dispose)) app.onUnmount(() => adapter.dispose());
786
+ app.onUnmount(() => adapter.dispose?.());
884
787
  }
885
788
  });
886
789
  //#endregion
887
- export { createQueue as a, useTimer as c, useNotifications as i, createNotificationsContext as n, createQueueContext as o, createNotificationsPlugin as r, useQueue as s, createNotifications as t };
790
+ export { createQueue as a, useNotifications as i, createNotificationsContext as n, createQueueContext as o, createNotificationsPlugin as r, useQueue as s, createNotifications as t };
@@ -1,8 +1,8 @@
1
1
  import { UNSAFE_KEYS } from "./utilities/index.mjs";
2
- import { o as createPluginContext } from "./useLogger-CbvzXCWb.mjs";
3
- import { t as createTokens } from "./createTokens-C4qcW2Kv.mjs";
4
- import { t as toArray } from "./toArray-C89ZaEuF.mjs";
5
- import { t as V0PermissionsAdapter } from "./v0-UNyykD27.mjs";
2
+ import { n as createPluginContext } from "./createPlugin-Oo6t-vBw.mjs";
3
+ import { t as createTokens } from "./createTokens-DoISbwd7.mjs";
4
+ import { t as toArray } from "./toArray-MY9Kb1Qy.mjs";
5
+ import { t as V0PermissionsAdapter } from "./v0-Ch0yBKEj.mjs";
6
6
  //#region src/composables/usePermissions/index.ts
7
7
  /**
8
8
  * @module usePermissions