@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.
- package/README.md +5 -1
- package/dist/{adapter-T7AedXkz.d.mts → adapter-58IvIfAZ.d.mts} +1 -1
- package/dist/{adapter-Drq1v5wV.mjs → adapter-Be9zUc-n.mjs} +6 -3
- package/dist/{adapter-CcHB7rs3.d.mts → adapter-BvWEd9w-.d.mts} +2 -2
- package/dist/{adapter-BZjmDNJF.d.mts → adapter-DlX3FA3A.d.mts} +2 -2
- package/dist/{adapter-CCIeOzqr.mjs → adapter-gQ2SNKZq.mjs} +31 -22
- package/dist/{adapters-D49L7m2R.mjs → adapters-BJ5n7rgh.mjs} +1 -1
- package/dist/adapters-BnKW0BF_.mjs +2 -0
- package/dist/adapters-CBrvizWb.mjs +4 -0
- package/dist/adapters-CMJGA1k7.mjs +2 -0
- package/dist/adapters-Dse4bPxk.mjs +5 -0
- package/dist/browser/index.js +4845 -3272
- package/dist/components/index.d.mts +3 -3
- package/dist/components/index.mjs +2 -2
- package/dist/{components-Dc7sUTsg.mjs → components-CqDewYTU.mjs} +1407 -411
- package/dist/composables/index.d.mts +19 -19
- package/dist/composables/index.mjs +28 -26
- package/dist/{consola-Byg0ybzh.d.mts → consola-BdgyPEfx.d.mts} +1 -1
- package/dist/constants/index.d.mts +2 -2
- package/dist/constants/index.mjs +3 -3
- package/dist/{createDataTable-BbUL9Vva.mjs → createDataTable-rXBqGglI.mjs} +105 -32
- package/dist/{createGroup-C2WCfYPB.mjs → createGroup-BU4olYtB.mjs} +29 -14
- package/dist/{createPagination-Tp4C4He8.mjs → createPagination-CHF7SmmK.mjs} +11 -7
- package/dist/{createTokens-qv02qq4_.mjs → createRegistry-Dl-bSSTr.mjs} +21 -302
- package/dist/{createSelection-AmMX6sjc.mjs → createSelection-Csaa-C8p.mjs} +28 -21
- package/dist/{createSingle-CffpxK__.mjs → createSingle-8xbHAIpY.mjs} +13 -17
- package/dist/createTokens-lNg2M_P_.mjs +302 -0
- package/dist/{createTrinity-vvXk0ARD.mjs → createTrinity-BTCs1pYx.mjs} +34 -31
- package/dist/data-table/adapters/client/index.d.mts +1 -1
- package/dist/data-table/adapters/client/index.mjs +1 -1
- package/dist/data-table/adapters/index.d.mts +4 -4
- package/dist/data-table/adapters/index.mjs +5 -5
- package/dist/data-table/adapters/server/index.d.mts +1 -1
- package/dist/data-table/adapters/server/index.mjs +1 -1
- package/dist/data-table/adapters/virtual/index.d.mts +1 -1
- package/dist/data-table/adapters/virtual/index.mjs +1 -1
- package/dist/data-table/index.d.mts +6 -6
- package/dist/data-table/index.mjs +6 -6
- package/dist/date/index.d.mts +2 -2
- package/dist/date/index.mjs +4 -4
- package/dist/features/adapters/flagsmith/index.d.mts +1 -1
- package/dist/features/adapters/flagsmith/index.mjs +1 -1
- package/dist/features/adapters/launchdarkly/index.d.mts +1 -1
- package/dist/features/adapters/launchdarkly/index.mjs +1 -1
- package/dist/features/adapters/posthog/index.d.mts +1 -1
- package/dist/features/adapters/posthog/index.mjs +1 -1
- package/dist/features/index.d.mts +2 -2
- package/dist/features/index.mjs +1 -1
- package/dist/{globals-CAv9vqkP.mjs → globals-CKdzjeLe.mjs} +1 -1
- package/dist/htmlElements-D4oMQZPJ.mjs +28 -0
- package/dist/{index-M8EpGjjA.d.mts → index-1XdASTjp.d.mts} +1 -1
- package/dist/{index-D26_u_WI.d.mts → index-B7cqgTBL.d.mts} +1599 -468
- package/dist/{index-DoGxDgdN.d.mts → index-BJGcVy7e.d.mts} +57 -6
- package/dist/index-BgCkepP_.d.mts +31 -0
- package/dist/{index-B_XLHftL.d.mts → index-BxKMMWnQ.d.mts} +301 -263
- package/dist/{index-tyzwWFHS.d.mts → index-BzFHTW59.d.mts} +1 -1
- package/dist/{index-CDcl4wPo.d.mts → index-CT5SCLzW.d.mts} +1 -1
- package/dist/{index-BUsrN1vL.d.mts → index-DE3bWw11.d.mts} +2 -2
- package/dist/{index-76fQGkkO.d.mts → index-DTvqw22G.d.mts} +8 -11
- package/dist/{index-F2Fmxnzi.d.mts → index-Dp1HjBxJ.d.mts} +1 -1
- package/dist/{index-B_AlCD7t.d.mts → index-DuddF-NR.d.mts} +2 -9
- package/dist/{index-Dxx0eMLi.d.mts → index-GOpjKzaJ.d.mts} +1 -1
- package/dist/index.d.mts +23 -23
- package/dist/index.mjs +31 -29
- package/dist/json/attributes.json +280 -4
- package/dist/json/importMap.json +60 -0
- package/dist/json/tags.json +136 -2
- package/dist/json/web-types.json +1186 -347
- package/dist/locale/adapters/index.d.mts +2 -2
- package/dist/locale/adapters/index.mjs +2 -2
- package/dist/locale/adapters/v0/index.d.mts +1 -1
- package/dist/locale/adapters/v0/index.mjs +1 -1
- package/dist/locale/adapters/vue-i18n/index.d.mts +1 -1
- package/dist/locale/index.d.mts +3 -3
- package/dist/locale/index.mjs +2 -2
- package/dist/logger/adapters/consola/index.d.mts +1 -1
- package/dist/logger/adapters/index.d.mts +4 -4
- package/dist/logger/adapters/index.mjs +2 -2
- package/dist/logger/adapters/pino/index.d.mts +1 -1
- package/dist/logger/adapters/v0/index.d.mts +1 -1
- package/dist/logger/adapters/v0/index.mjs +1 -1
- package/dist/logger/index.d.mts +5 -5
- package/dist/logger/index.mjs +2 -2
- package/dist/notifications/index.d.mts +2 -2
- package/dist/notifications/index.mjs +3 -54
- package/dist/palettes/ant/generate/index.mjs +1 -0
- package/dist/palettes/ant/index.d.mts +1 -1
- package/dist/palettes/index.d.mts +3 -3
- package/dist/palettes/leonardo/generate/index.mjs +1 -0
- package/dist/palettes/material/generate/index.mjs +1 -0
- package/dist/palettes/material/index.d.mts +1 -1
- package/dist/palettes/md1/index.d.mts +1 -1
- package/dist/palettes/md2/index.d.mts +1 -1
- package/dist/palettes/radix/index.d.mts +1 -1
- package/dist/palettes/tailwind/index.d.mts +1 -1
- package/dist/permissions/adapters/index.d.mts +1 -1
- package/dist/permissions/adapters/index.mjs +2 -2
- package/dist/permissions/adapters/v0/index.d.mts +1 -1
- package/dist/permissions/adapters/v0/index.mjs +1 -1
- package/dist/permissions/index.d.mts +1 -1
- package/dist/permissions/index.mjs +2 -2
- package/dist/{pino-BxddSW2l.d.mts → pino-DNfCEb0p.d.mts} +1 -1
- package/dist/{posthog-B8PEtlFr.mjs → posthog-DZNnPXxS.mjs} +1 -1
- package/dist/rules/index.d.mts +1 -1
- package/dist/rules/index.mjs +1 -1
- package/dist/{server-DNUTnISs.d.mts → server-3ilWFwqe.d.mts} +1 -1
- package/dist/{server-CIftA0pK.mjs → server-y7zLSCSx.mjs} +1 -1
- package/dist/storage/adapters/index.d.mts +2 -2
- package/dist/storage/adapters/index.mjs +1 -1
- package/dist/storage/adapters/memory/index.d.mts +1 -1
- package/dist/storage/adapters/memory/index.mjs +1 -1
- package/dist/storage/index.d.mts +3 -3
- package/dist/storage/index.mjs +2 -2
- package/dist/theme/adapters/index.d.mts +1 -1
- package/dist/theme/adapters/index.mjs +4 -4
- package/dist/theme/adapters/unhead/index.d.mts +1 -1
- package/dist/theme/adapters/unhead/index.mjs +1 -1
- package/dist/theme/adapters/v0/index.d.mts +1 -1
- package/dist/theme/adapters/v0/index.mjs +1 -1
- package/dist/theme/index.d.mts +1 -1
- package/dist/theme/index.mjs +3 -3
- package/dist/{toArray-doLQVI56.mjs → toArray-as9BWxBK.mjs} +10 -0
- package/dist/types/index.d.mts +2 -2
- package/dist/{unhead-BYw3a366.mjs → unhead-DZiD-4Tx.mjs} +2 -2
- package/dist/{useClickOutside-CnCQkh7M.mjs → useClickOutside-CmCUD_Pf.mjs} +577 -1024
- package/dist/{useFeatures-CMpkbU8Q.mjs → useFeatures-ZIvzzuEV.mjs} +16 -6
- package/dist/{useLocale-BYmoHpo6.mjs → useLocale-DTJx3aKR.mjs} +19 -7
- package/dist/{useLogger-BfaFH-Bi.mjs → useLogger-BBTcMN61.mjs} +33 -16
- package/dist/useNotifications-H4knpvNw.mjs +869 -0
- package/dist/{usePermissions-y3Uum3nO.mjs → usePermissions-B_G12Dwd.mjs} +14 -6
- package/dist/{useRules-eqSXpP9V.mjs → useRules--7Qoo60I.mjs} +15 -5
- package/dist/{useTheme-CFH6I91x.mjs → useTheme-Co05TEeD.mjs} +20 -8
- package/dist/utilities/index.d.mts +1 -1
- package/dist/utilities/index.mjs +14 -9
- package/dist/{v0-DXqYgj7J.mjs → v0-BrTEO5sv.mjs} +2 -2
- package/dist/{v0-BAG8p0si.d.mts → v0-CdusXjY_.d.mts} +1 -1
- package/dist/{v0-CFV8A5PF.mjs → v0-D0Mh3EVG.mjs} +1 -1
- package/dist/{v0-BpgPZ1qB.d.mts → v0-D7Fm2C3Y.d.mts} +1 -1
- package/dist/{v0-BqikIgl0.mjs → v0-DeiZuexg.mjs} +1 -1
- package/dist/{v0-DOq_Ia5H.mjs → v0-Dq3zhexO.mjs} +2 -2
- package/dist/{v0-C2UMaHUa.d.mts → v0-DrOub-e1.d.mts} +1 -1
- package/dist/{virtual-D1HwNBLS.mjs → virtual-C0yHf1DC.mjs} +2 -2
- package/dist/{virtual-BaQWQ9ji.d.mts → virtual-D4fckewC.d.mts} +1 -1
- package/package.json +10 -7
- package/SKILL.md +0 -95
- package/dist/adapters-BOVGPozf.mjs +0 -2
- package/dist/adapters-BbNfjyvY.mjs +0 -5
- package/dist/adapters-BhNTUuxE.mjs +0 -2
- package/dist/adapters-RwNU3wNj.mjs +0 -4
- package/dist/htmlElements-DcYtv0hg.mjs +0 -75
- package/dist/index-D6mQAEs2.d.mts +0 -79
- /package/dist/{adapter-DNKjooxI.d.mts → adapter-Dhq68tz0.d.mts} +0 -0
- /package/dist/{flagsmith-DQnnahG5.mjs → flagsmith-Dbh1h8WF.mjs} +0 -0
- /package/dist/{index-DxruGeVY.d.mts → index-C6rdXZ7j.d.mts} +0 -0
- /package/dist/{index-PWQavSPf.d.mts → index-CFhUdAHM.d.mts} +0 -0
- /package/dist/{index-c55Utzva.d.mts → index-CROz1VSV.d.mts} +0 -0
- /package/dist/{launchdarkly-2_48EJ1_.mjs → launchdarkly-BKtW-idu.mjs} +0 -0
- /package/dist/{memory-DUyWthic.d.mts → memory-CeSQE-QV.d.mts} +0 -0
- /package/dist/{memory-XCMtkld1.mjs → memory-oYBvtkgx.mjs} +0 -0
- /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-
|
|
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,
|
|
4
|
-
import { a as createPlugin, i as useLogger, o as createPluginContext } from "./useLogger-
|
|
5
|
-
import {
|
|
6
|
-
import { i as createModel, t as createSelection } from "./createSelection-
|
|
7
|
-
import { t as createSingle } from "./createSingle-
|
|
8
|
-
import
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import "./
|
|
13
|
-
import "./
|
|
14
|
-
import
|
|
15
|
-
import "./
|
|
16
|
-
import "./
|
|
17
|
-
import
|
|
18
|
-
import "./
|
|
19
|
-
import {
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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",
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 (
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 (
|
|
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
|
-
|
|
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 (
|
|
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) && "
|
|
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
|
-
|
|
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 {
|
|
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 };
|