@vuetify/v0 0.0.24-beta.1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/README.md +2 -2
  2. package/dist/adapter-L4Php1_S.d.mts +97 -0
  3. package/dist/browser/index.js +1318 -842
  4. package/dist/components/index.d.mts +4 -4
  5. package/dist/components/index.mjs +6 -6
  6. package/dist/{components-Dd4KKVtk.mjs → components-V4KaMfn-.mjs} +442 -117
  7. package/dist/composables/index.d.mts +5 -4
  8. package/dist/composables/index.mjs +4 -4
  9. package/dist/constants/index.d.mts +1 -1
  10. package/dist/constants/index.mjs +3 -3
  11. package/dist/date/index.d.mts +124 -0
  12. package/dist/date/index.mjs +7514 -0
  13. package/dist/{globals-CiCJWcbb.mjs → globals-CgcVstn0.mjs} +1 -1
  14. package/dist/{index-CAEB2sxS.d.mts → index-CSjKBMhp.d.mts} +738 -349
  15. package/dist/{index-C8YcMooA.d.mts → index-CoO8LW8o.d.mts} +13 -9
  16. package/dist/{index-DYSwiS9k.d.mts → index-DlxrzbvZ.d.mts} +21 -1
  17. package/dist/{index-rcTqb9U3.d.mts → index-DsiFkTD8.d.mts} +662 -306
  18. package/dist/{index-Bby5ljat.d.mts → index-t-t6sAn3.d.mts} +222 -41
  19. package/dist/index.d.mts +8 -7
  20. package/dist/index.mjs +7 -7
  21. package/dist/json/attributes.json +104 -0
  22. package/dist/json/importMap.json +20 -0
  23. package/dist/json/tags.json +46 -0
  24. package/dist/json/web-types.json +309 -9
  25. package/dist/types/index.d.mts +2 -2
  26. package/dist/{useClickOutside-BfEvdnA4.mjs → useClickOutside-Cj8CguMD.mjs} +844 -699
  27. package/dist/utilities/index.d.mts +3 -3
  28. package/dist/utilities/index.mjs +2 -2
  29. package/dist/{utilities-9i1hJnMd.mjs → utilities-B58TiS_S.mjs} +41 -34
  30. package/package.json +21 -3
  31. /package/dist/{constants-3l8TGg5J.mjs → constants-DHKqjdjH.mjs} +0 -0
  32. /package/dist/{htmlElements-CXObxj0V.mjs → htmlElements-DO9n35bD.mjs} +0 -0
  33. /package/dist/{index-DMQJJUrv.d.mts → index-cPmI99rd.d.mts} +0 -0
@@ -1,7 +1,7 @@
1
- import { _ as isUndefined, a as genId, c as isFunction, d as isNullOrUndefined, f as isNumber, g as isSymbol, h as isString, l as isNaN, o as isArray, p as isObject, r as clamp, s as isBoolean, t as instanceExists, u as isNull, v as mergeDeep, y as range } from "./utilities-9i1hJnMd.mjs";
2
- import { a as SUPPORTS_OBSERVER, i as SUPPORTS_MUTATION_OBSERVER, n as SUPPORTS_INTERSECTION_OBSERVER, r as SUPPORTS_MATCH_MEDIA, s as __LOGGER_ENABLED__, t as IN_BROWSER } from "./globals-CiCJWcbb.mjs";
3
- import { computed, effectScope, inject, isRef, onScopeDispose, provide, reactive, readonly, ref, shallowReactive, shallowReadonly, shallowRef, toRef, toValue, unref, watch, watchEffect } from "vue";
4
- import { Temporal } from "@js-temporal/polyfill";
1
+ import { _ as useId$1, a as isFunction, c as isNullOrUndefined, f as isString, g as range, h as mergeDeep, i as isBoolean, l as isNumber, m as isUndefined, o as isNaN, p as isSymbol, r as isArray, s as isNull, t as clamp, u as isObject, v as instanceExists } from "./utilities-B58TiS_S.mjs";
2
+ import { a as SUPPORTS_OBSERVER, i as SUPPORTS_MUTATION_OBSERVER, n as SUPPORTS_INTERSECTION_OBSERVER, r as SUPPORTS_MATCH_MEDIA, s as __LOGGER_ENABLED__, t as IN_BROWSER } from "./globals-CgcVstn0.mjs";
3
+ import { computed, effectScope, inject, isRef, nextTick, onScopeDispose, provide, reactive, readonly, ref, shallowReactive, shallowReadonly, shallowRef, toRef, toValue, unref, watch, watchEffect } from "vue";
4
+ import flagsmith from "flagsmith";
5
5
 
6
6
  //#region src/composables/createContext/index.ts
7
7
  /**
@@ -602,12 +602,13 @@ function useLogger(namespace = "v0:logger") {
602
602
  */
603
603
  function createRegistry(options) {
604
604
  const logger$1 = useLogger();
605
- const collection = /* @__PURE__ */ new Map();
605
+ const events = options?.events ?? false;
606
+ const reactive$1 = options?.reactive ?? false;
607
+ const collection = reactive$1 ? shallowReactive(/* @__PURE__ */ new Map()) : /* @__PURE__ */ new Map();
606
608
  const catalog = /* @__PURE__ */ new Map();
607
609
  const directory = /* @__PURE__ */ new Map();
608
610
  const cache = /* @__PURE__ */ new Map();
609
611
  const listeners = /* @__PURE__ */ new Map();
610
- const events = options?.events ?? false;
611
612
  let indexDependentCount = 0;
612
613
  let needsReindex = false;
613
614
  let minDirtyIndex = Infinity;
@@ -787,7 +788,7 @@ function createRegistry(options) {
787
788
  }
788
789
  function register(registration = {}) {
789
790
  const size = collection.size;
790
- const id = registration.id ?? /* @__PURE__ */ genId();
791
+ const id = registration.id ?? /* @__PURE__ */ useId$1();
791
792
  if (has(id)) {
792
793
  logger$1.warn(`Ticket "${id}" already exists. Use \`upsert()\` to update or check \`has()\` before registering.`);
793
794
  return get(id);
@@ -797,13 +798,14 @@ function createRegistry(options) {
797
798
  const value = valueIsUndefined ? index : registration.value;
798
799
  const valueIsIndex = valueIsUndefined;
799
800
  if (valueIsIndex) indexDependentCount++;
800
- const ticket = {
801
+ const rawTicket = {
801
802
  ...registration,
802
803
  id,
803
804
  index,
804
805
  value,
805
806
  valueIsIndex
806
807
  };
808
+ const ticket = reactive$1 ? shallowReactive(rawTicket) : rawTicket;
807
809
  collection.set(ticket.id, ticket);
808
810
  directory.set(ticket.index, ticket.id);
809
811
  assign(ticket.value, ticket.id);
@@ -956,8 +958,9 @@ function createRegistryContext(_options = {}) {
956
958
  * Supports disabled items, mandatory selection enforcement, and auto-enrollment.
957
959
  *
958
960
  * @param options The options for the selection instance.
959
- * @template Z The type of the selection ticket.
960
- * @template E The type of the selection context.
961
+ * @template Z The input ticket type - what users provide to register(). Extend SelectionTicketInput to add custom properties.
962
+ * @template E The output ticket type - what users receive from get(). Automatically includes selection methods.
963
+ * @template R The context type. Defaults to SelectionContext<Z, E>.
961
964
  * @returns A new selection instance with selection management methods.
962
965
  *
963
966
  * @remarks
@@ -980,6 +983,7 @@ function createRegistryContext(_options = {}) {
980
983
  * ```ts
981
984
  * import { createSelection } from '@vuetify/v0'
982
985
  *
986
+ * // Basic usage
983
987
  * const selection = createSelection({ mandatory: true })
984
988
  *
985
989
  * selection.onboard([
@@ -994,6 +998,23 @@ function createRegistryContext(_options = {}) {
994
998
  * console.log(selection.selectedIds) // Set { 'item-1', 'item-3' }
995
999
  * console.log(Array.from(selection.selectedValues.value)) // ['Item 1', 'Item 3']
996
1000
  * ```
1001
+ *
1002
+ * @example
1003
+ * ```ts
1004
+ * // With custom ticket type
1005
+ * interface MyTicket extends SelectionTicketInput {
1006
+ * label: string
1007
+ * icon?: string
1008
+ * }
1009
+ *
1010
+ * const tabs = createSelection<MyTicket>()
1011
+ *
1012
+ * tabs.register({ label: 'Home', icon: 'mdi-home' })
1013
+ * tabs.register({ label: 'Settings' })
1014
+ *
1015
+ * const ticket = tabs.get('...')
1016
+ * // ticket has: label, icon, isSelected, select(), unselect(), toggle()
1017
+ * ```
997
1018
  */
998
1019
  function createSelection(_options = {}) {
999
1020
  const { disabled = false, enroll = false, mandatory = false, multiple = false, ...options } = _options;
@@ -1034,7 +1055,7 @@ function createSelection(_options = {}) {
1034
1055
  return selectedIds.has(id);
1035
1056
  }
1036
1057
  function register(registration = {}) {
1037
- const id = registration.id ?? /* @__PURE__ */ genId();
1058
+ const id = registration.id ?? /* @__PURE__ */ useId$1();
1038
1059
  const item = {
1039
1060
  disabled: false,
1040
1061
  select: () => select(id),
@@ -1091,8 +1112,9 @@ function createSelection(_options = {}) {
1091
1112
  * Creates a new selection context.
1092
1113
  *
1093
1114
  * @param options The options for the selection context.
1094
- * @template Z The type of the selection ticket.
1095
- * @template E The type of the selection context.
1115
+ * @template Z The input ticket type - what users provide to register().
1116
+ * @template E The output ticket type - what users receive from get().
1117
+ * @template R The context type. Defaults to SelectionContext<Z, E>.
1096
1118
  * @returns A new selection context.
1097
1119
  *
1098
1120
  * @see https://0.vuetifyjs.com/composables/selection/use-selection
@@ -1114,6 +1136,17 @@ function createSelection(_options = {}) {
1114
1136
  * const checkboxes = useCheckboxes()
1115
1137
  * checkboxes.select('checkbox-1')
1116
1138
  * ```
1139
+ *
1140
+ * @example
1141
+ * ```ts
1142
+ * // With custom ticket type
1143
+ * interface TabTicket extends SelectionTicketInput {
1144
+ * label: string
1145
+ * icon?: string
1146
+ * }
1147
+ *
1148
+ * export const [useTabs, provideTabs, tabs] = createSelectionContext<TabTicket>()
1149
+ * ```
1117
1150
  */
1118
1151
  function createSelectionContext(_options = {}) {
1119
1152
  const { namespace = "v0:selection", ...options } = _options;
@@ -1128,6 +1161,9 @@ function createSelectionContext(_options = {}) {
1128
1161
  * Returns the current selection instance.
1129
1162
  *
1130
1163
  * @param namespace The namespace for the selection context. Defaults to `'v0:selection'`.
1164
+ * @template Z The input ticket type.
1165
+ * @template E The output ticket type.
1166
+ * @template R The context type.
1131
1167
  * @returns The current selection instance.
1132
1168
  *
1133
1169
  * @see https://0.vuetifyjs.com/composables/selection/use-selection
@@ -1388,7 +1424,7 @@ function createGroup(_options = {}) {
1388
1424
  else selection.toggle(id);
1389
1425
  }
1390
1426
  function register(registration = {}) {
1391
- const id = registration.id ?? /* @__PURE__ */ genId();
1427
+ const id = registration.id ?? /* @__PURE__ */ useId$1();
1392
1428
  const item = {
1393
1429
  ...registration,
1394
1430
  id,
@@ -1477,8 +1513,9 @@ function createGroup(_options = {}) {
1477
1513
  * Creates a new group context.
1478
1514
  *
1479
1515
  * @param options The options for the group context.
1480
- * @template Z The type of the group ticket.
1481
- * @template E The type of the group context.
1516
+ * @template Z The input ticket type.
1517
+ * @template E The output ticket type.
1518
+ * @template R The context type.
1482
1519
  * @returns A new group context.
1483
1520
  *
1484
1521
  * @see https://0.vuetifyjs.com/composables/selection/use-group
@@ -1513,6 +1550,9 @@ function createGroupContext(_options = {}) {
1513
1550
  * Returns the current group instance.
1514
1551
  *
1515
1552
  * @param namespace The namespace for the group context. Defaults to `'v0:group'`.
1553
+ * @template Z The input ticket type.
1554
+ * @template E The output ticket type.
1555
+ * @template R The context type.
1516
1556
  * @returns The current group instance.
1517
1557
  *
1518
1558
  * @see https://0.vuetifyjs.com/composables/selection/use-group
@@ -1819,18 +1859,26 @@ function toReactive(objectRef) {
1819
1859
  */
1820
1860
  function createHydration() {
1821
1861
  const isHydrated = shallowRef(false);
1862
+ const isSettled = shallowRef(false);
1822
1863
  function hydrate() {
1823
1864
  isHydrated.value = true;
1824
1865
  }
1866
+ function settle() {
1867
+ isSettled.value = true;
1868
+ }
1825
1869
  return {
1826
1870
  isHydrated: shallowReadonly(isHydrated),
1827
- hydrate
1871
+ isSettled: shallowReadonly(isSettled),
1872
+ hydrate,
1873
+ settle
1828
1874
  };
1829
1875
  }
1830
1876
  function createFallbackHydration() {
1831
1877
  return {
1832
1878
  isHydrated: shallowReadonly(shallowRef(true)),
1833
- hydrate: () => {}
1879
+ isSettled: shallowReadonly(shallowRef(true)),
1880
+ hydrate: () => {},
1881
+ settle: () => {}
1834
1882
  };
1835
1883
  }
1836
1884
  /**
@@ -1894,9 +1942,11 @@ function createHydrationPlugin(_options = {}) {
1894
1942
  provideHydrationContext(context, app);
1895
1943
  },
1896
1944
  setup: (app) => {
1897
- app.mixin({ mounted() {
1945
+ app.mixin({ async mounted() {
1898
1946
  if (!/* @__PURE__ */ isNull(this.$parent)) return;
1899
1947
  context.hydrate();
1948
+ await nextTick();
1949
+ context.settle();
1900
1950
  } });
1901
1951
  }
1902
1952
  });
@@ -1914,13 +1964,16 @@ function createHydrationPlugin(_options = {}) {
1914
1964
  * <script setup lang="ts">
1915
1965
  * import { useHydration } from '@vuetify/v0'
1916
1966
  *
1917
- * const hydration = useHydration()
1967
+ * const { isHydrated, isSettled } = useHydration()
1968
+ *
1969
+ * // Use isSettled to gate animations after state restoration
1970
+ * const transition = computed(() => isSettled.value ? 'fade' : undefined)
1918
1971
  * <\/script>
1919
1972
  *
1920
1973
  * <template>
1921
- * <div>
1922
- * <p>Is hydrated: {{ hydration.isHydrated.value }}</p>
1923
- * </div>
1974
+ * <Transition :name="transition">
1975
+ * <div v-if="show">Animates only after hydration settles</div>
1976
+ * </Transition>
1924
1977
  * </template>
1925
1978
  * ```
1926
1979
  */
@@ -2221,8 +2274,9 @@ function useBreakpoints(namespace = "v0:breakpoints") {
2221
2274
  * Adds computed singular properties: `selectedId`, `selectedItem`, `selectedIndex`, `selectedValue`.
2222
2275
  *
2223
2276
  * @param options The options for the single selection instance.
2224
- * @template Z The type of the single selection ticket.
2225
- * @template E The type of the single selection context.
2277
+ * @template Z The input ticket type - what users provide to register().
2278
+ * @template E The output ticket type - what users receive from get().
2279
+ * @template R The context type.
2226
2280
  * @returns A new single selection instance with single-selection enforcement.
2227
2281
  *
2228
2282
  * @remarks
@@ -2263,6 +2317,18 @@ function useBreakpoints(namespace = "v0:breakpoints") {
2263
2317
  * console.log(tabs.selectedId.value) // 'about'
2264
2318
  * console.log(tabs.selectedIds.size) // 1 (always enforces single selection)
2265
2319
  * ```
2320
+ *
2321
+ * @example
2322
+ * ```ts
2323
+ * // With custom ticket type
2324
+ * interface TabTicket extends SingleTicketInput {
2325
+ * label: string
2326
+ * icon?: string
2327
+ * }
2328
+ *
2329
+ * const tabs = createSingle<TabTicket>()
2330
+ * tabs.register({ label: 'Home', icon: 'mdi-home' })
2331
+ * ```
2266
2332
  */
2267
2333
  function createSingle(_options = {}) {
2268
2334
  const { mandatory = false, multiple = false, ...options } = _options;
@@ -2300,8 +2366,9 @@ function createSingle(_options = {}) {
2300
2366
  * Creates a new single selection context.
2301
2367
  *
2302
2368
  * @param options The options for the single selection context.
2303
- * @template Z The type of the single selection ticket.
2304
- * @template E The type of the single selection context.
2369
+ * @template Z The input ticket type.
2370
+ * @template E The output ticket type.
2371
+ * @template R The context type.
2305
2372
  * @returns A new single selection context.
2306
2373
  *
2307
2374
  * @see https://0.vuetifyjs.com/composables/selection/use-single
@@ -2334,6 +2401,9 @@ function createSingleContext(_options = {}) {
2334
2401
  * Returns the current single selection instance.
2335
2402
  *
2336
2403
  * @param namespace The namespace for the single selection context. Defaults to `'v0:single'`.
2404
+ * @template Z The input ticket type.
2405
+ * @template E The output ticket type.
2406
+ * @template R The context type.
2337
2407
  * @returns The current single selection instance.
2338
2408
  *
2339
2409
  * @see https://0.vuetifyjs.com/composables/selection/use-single
@@ -2803,585 +2873,6 @@ function useLocale(namespace = "v0:locale") {
2803
2873
  }
2804
2874
  }
2805
2875
 
2806
- //#endregion
2807
- //#region src/composables/useDate/adapters/v0.ts
2808
- /**
2809
- * @module Vuetify0DateAdapter
2810
- *
2811
- * @remarks
2812
- * Default DateAdapter for v0, built on the Temporal API.
2813
- * Uses Temporal.PlainDateTime as the primary date type.
2814
- *
2815
- * Implements the full date-io IUtils interface for industry compatibility.
2816
- *
2817
- * Requires native Temporal support or @js-temporal/polyfill.
2818
- *
2819
- * @see https://tc39.es/proposal-temporal/docs/
2820
- * @see https://github.com/dmtrKovalenko/date-io
2821
- */
2822
- /** Single regex for token replacement in formatByString */
2823
- const FORMAT_TOKEN_REGEX = /YYYY|YY|MMMM|MMM|MM|M|dddd|ddd|DD|D|HH|H|hh|h|mm|m|ss|s|A|a/g;
2824
- /** Maximum cache size to prevent memory leaks */
2825
- const MAX_CACHE_SIZE = 50;
2826
- var Vuetify0DateAdapter = class {
2827
- _locale;
2828
- /** Cache for Intl.DateTimeFormat instances, keyed by locale + options */
2829
- formatCache = /* @__PURE__ */ new Map();
2830
- /** Cache for Intl.NumberFormat instances, keyed by locale */
2831
- numberFormatCache = /* @__PURE__ */ new Map();
2832
- constructor(locale = "en-US") {
2833
- this._locale = locale;
2834
- }
2835
- /** Current locale. Setting a new locale clears format caches. */
2836
- get locale() {
2837
- return this._locale;
2838
- }
2839
- set locale(value) {
2840
- if (this._locale !== value) {
2841
- this._locale = value;
2842
- this.formatCache.clear();
2843
- this.numberFormatCache.clear();
2844
- }
2845
- }
2846
- /**
2847
- * Create a date from various input types.
2848
- *
2849
- * @param value - Date value (PlainDateTime, PlainDate, ZonedDateTime, Date, ISO string, timestamp)
2850
- * @returns PlainDateTime or null if invalid
2851
- *
2852
- * @remarks
2853
- * **SSR Safety:** When called without arguments:
2854
- * - Browser: Returns current time via `Temporal.Now.plainDateTimeISO()`
2855
- * - Server: Returns epoch (1970-01-01T00:00:00) for deterministic rendering
2856
- *
2857
- * For SSR apps needing current time, pass `Date.now()` explicitly and handle
2858
- * hydration via `<ClientOnly>` (Nuxt) or `v-if` + `onMounted` pattern.
2859
- */
2860
- date(value) {
2861
- if (/* @__PURE__ */ isNullOrUndefined(value)) return IN_BROWSER ? Temporal.Now.plainDateTimeISO() : Temporal.PlainDateTime.from({
2862
- year: 1970,
2863
- month: 1,
2864
- day: 1,
2865
- hour: 0,
2866
- minute: 0,
2867
- second: 0
2868
- });
2869
- if (value instanceof Temporal.PlainDateTime) return value;
2870
- if (value instanceof Temporal.PlainDate) return value.toPlainDateTime();
2871
- if (value instanceof Temporal.ZonedDateTime) return value.toPlainDateTime();
2872
- if (value instanceof Date) return Temporal.PlainDateTime.from({
2873
- year: value.getFullYear(),
2874
- month: value.getMonth() + 1,
2875
- day: value.getDate(),
2876
- hour: value.getHours(),
2877
- minute: value.getMinutes(),
2878
- second: value.getSeconds(),
2879
- millisecond: value.getMilliseconds()
2880
- });
2881
- if (/* @__PURE__ */ isString(value)) try {
2882
- return Temporal.PlainDateTime.from(value);
2883
- } catch {
2884
- try {
2885
- return this.parseISO(value);
2886
- } catch {
2887
- return null;
2888
- }
2889
- }
2890
- if (/* @__PURE__ */ isNumber(value)) {
2891
- const date = new Date(value);
2892
- return Temporal.PlainDateTime.from({
2893
- year: date.getFullYear(),
2894
- month: date.getMonth() + 1,
2895
- day: date.getDate(),
2896
- hour: date.getHours(),
2897
- minute: date.getMinutes(),
2898
- second: date.getSeconds(),
2899
- millisecond: date.getMilliseconds()
2900
- });
2901
- }
2902
- return null;
2903
- }
2904
- toJsDate(value) {
2905
- return new Date(value.year, value.month - 1, value.day, value.hour, value.minute, value.second, value.millisecond);
2906
- }
2907
- parseISO(dateString) {
2908
- if (/^\d{4}-\d{2}-\d{2}$/.test(dateString)) return Temporal.PlainDate.from(dateString).toPlainDateTime();
2909
- if (dateString.includes("Z") || /[+-]\d{2}:\d{2}$/.test(dateString)) return Temporal.Instant.from(dateString).toZonedDateTimeISO("UTC").toPlainDateTime();
2910
- return Temporal.PlainDateTime.from(dateString);
2911
- }
2912
- toISO(date) {
2913
- return date.toString();
2914
- }
2915
- /**
2916
- * Parses a date string into a PlainDateTime.
2917
- *
2918
- * **Known limitation**: The `format` parameter is currently ignored.
2919
- * Temporal API doesn't provide built-in format parsing, and implementing
2920
- * full format string parsing (e.g., 'MM/DD/YYYY') would require a
2921
- * substantial custom parser. This method delegates to `date()` which
2922
- * handles ISO 8601 strings and common formats.
2923
- *
2924
- * For custom format parsing, consider using a library like date-fns or
2925
- * luxon with a custom adapter.
2926
- *
2927
- * @param value - The date string to parse
2928
- * @param _format - Format hint (currently ignored)
2929
- * @returns Parsed PlainDateTime or null if invalid
2930
- */
2931
- parse(value, _format) {
2932
- try {
2933
- return this.date(value);
2934
- } catch {
2935
- return null;
2936
- }
2937
- }
2938
- isValid(date) {
2939
- if (/* @__PURE__ */ isNullOrUndefined(date)) return false;
2940
- if (date instanceof Temporal.PlainDateTime) return true;
2941
- if (date instanceof Temporal.PlainDate) return true;
2942
- if (date instanceof Temporal.ZonedDateTime) return true;
2943
- if (date instanceof Date) return !Number.isNaN(date.getTime());
2944
- if (/* @__PURE__ */ isString(date)) try {
2945
- Temporal.PlainDateTime.from(date);
2946
- return true;
2947
- } catch {
2948
- try {
2949
- Temporal.PlainDate.from(date);
2950
- return true;
2951
- } catch {
2952
- return false;
2953
- }
2954
- }
2955
- return false;
2956
- }
2957
- isNull(value) {
2958
- return /* @__PURE__ */ isNullOrUndefined(value);
2959
- }
2960
- getCurrentLocaleCode() {
2961
- return this.locale;
2962
- }
2963
- is12HourCycleInCurrentLocale() {
2964
- return new Intl.DateTimeFormat(this.locale, { hour: "numeric" }).resolvedOptions().hour12 ?? false;
2965
- }
2966
- format(date, formatString) {
2967
- const jsDate = this.toJsDate(date);
2968
- const options = {
2969
- fullDate: { dateStyle: "full" },
2970
- fullDateWithWeekday: {
2971
- weekday: "long",
2972
- year: "numeric",
2973
- month: "long",
2974
- day: "numeric"
2975
- },
2976
- normalDate: { dateStyle: "medium" },
2977
- shortDate: { dateStyle: "short" },
2978
- year: { year: "numeric" },
2979
- month: { month: "long" },
2980
- monthShort: { month: "short" },
2981
- monthAndYear: {
2982
- year: "numeric",
2983
- month: "long"
2984
- },
2985
- monthAndDate: {
2986
- month: "long",
2987
- day: "numeric"
2988
- },
2989
- weekday: { weekday: "long" },
2990
- weekdayShort: { weekday: "short" },
2991
- dayOfMonth: { day: "numeric" },
2992
- hours12h: {
2993
- hour: "numeric",
2994
- hour12: true
2995
- },
2996
- hours24h: {
2997
- hour: "numeric",
2998
- hour12: false
2999
- },
3000
- minutes: { minute: "numeric" },
3001
- seconds: { second: "numeric" },
3002
- fullTime: { timeStyle: "medium" },
3003
- fullTime12h: {
3004
- hour: "numeric",
3005
- minute: "numeric",
3006
- second: "numeric",
3007
- hour12: true
3008
- },
3009
- fullTime24h: {
3010
- hour: "numeric",
3011
- minute: "numeric",
3012
- second: "numeric",
3013
- hour12: false
3014
- },
3015
- fullDateTime: {
3016
- dateStyle: "full",
3017
- timeStyle: "short"
3018
- },
3019
- fullDateTime12h: {
3020
- dateStyle: "full",
3021
- hour: "numeric",
3022
- minute: "numeric",
3023
- hour12: true
3024
- },
3025
- fullDateTime24h: {
3026
- dateStyle: "full",
3027
- hour: "numeric",
3028
- minute: "numeric",
3029
- hour12: false
3030
- },
3031
- keyboardDate: {
3032
- year: "numeric",
3033
- month: "2-digit",
3034
- day: "2-digit"
3035
- },
3036
- keyboardDateTime: {
3037
- year: "numeric",
3038
- month: "2-digit",
3039
- day: "2-digit",
3040
- hour: "numeric",
3041
- minute: "numeric"
3042
- },
3043
- keyboardDateTime12h: {
3044
- year: "numeric",
3045
- month: "2-digit",
3046
- day: "2-digit",
3047
- hour: "numeric",
3048
- minute: "numeric",
3049
- hour12: true
3050
- },
3051
- keyboardDateTime24h: {
3052
- year: "numeric",
3053
- month: "2-digit",
3054
- day: "2-digit",
3055
- hour: "numeric",
3056
- minute: "numeric",
3057
- hour12: false
3058
- }
3059
- }[formatString];
3060
- if (options) return this.getFormatter(options).format(jsDate);
3061
- return this.getFormatter({}).format(jsDate);
3062
- }
3063
- formatByString(date, formatString) {
3064
- const jsDate = this.toJsDate(date);
3065
- const getTokenValue = (token) => {
3066
- switch (token) {
3067
- case "YYYY": return String(date.year);
3068
- case "YY": return String(date.year).slice(-2);
3069
- case "MM": return String(date.month).padStart(2, "0");
3070
- case "M": return String(date.month);
3071
- case "DD": return String(date.day).padStart(2, "0");
3072
- case "D": return String(date.day);
3073
- case "HH": return String(date.hour).padStart(2, "0");
3074
- case "H": return String(date.hour);
3075
- case "hh": return String(date.hour % 12 || 12).padStart(2, "0");
3076
- case "h": return String(date.hour % 12 || 12);
3077
- case "mm": return String(date.minute).padStart(2, "0");
3078
- case "m": return String(date.minute);
3079
- case "ss": return String(date.second).padStart(2, "0");
3080
- case "s": return String(date.second);
3081
- case "A": return date.hour < 12 ? "AM" : "PM";
3082
- case "a": return date.hour < 12 ? "am" : "pm";
3083
- case "MMMM": return this.getFormatter({ month: "long" }).format(jsDate);
3084
- case "MMM": return this.getFormatter({ month: "short" }).format(jsDate);
3085
- case "dddd": return this.getFormatter({ weekday: "long" }).format(jsDate);
3086
- case "ddd": return this.getFormatter({ weekday: "short" }).format(jsDate);
3087
- default: return token;
3088
- }
3089
- };
3090
- return formatString.replace(FORMAT_TOKEN_REGEX, (match) => getTokenValue(match));
3091
- }
3092
- getFormatHelperText(format) {
3093
- return {
3094
- keyboardDate: "mm/dd/yyyy",
3095
- keyboardDateTime: "mm/dd/yyyy hh:mm",
3096
- keyboardDateTime12h: "mm/dd/yyyy hh:mm am/pm",
3097
- keyboardDateTime24h: "mm/dd/yyyy hh:mm"
3098
- }[format] ?? format.replace(/YYYY/g, "yyyy").replace(/MM/g, "mm").replace(/DD/g, "dd").replace(/HH/g, "hh").replace(/mm/g, "mm").replace(/ss/g, "ss");
3099
- }
3100
- formatNumber(numberToFormat) {
3101
- return this.getNumberFormatter().format(Number(numberToFormat));
3102
- }
3103
- getMeridiemText(ampm) {
3104
- const date = ampm === "am" ? new Date(2020, 0, 1, 9, 0) : new Date(2020, 0, 1, 15, 0);
3105
- const match = this.getFormatter({
3106
- hour: "numeric",
3107
- hour12: true
3108
- }).format(date).match(/[AP]M|[ap]m|午前|午後|上午|下午/i);
3109
- return match ? match[0] : ampm.toUpperCase();
3110
- }
3111
- startOfDay(date) {
3112
- return date.with({
3113
- hour: 0,
3114
- minute: 0,
3115
- second: 0,
3116
- millisecond: 0,
3117
- microsecond: 0,
3118
- nanosecond: 0
3119
- });
3120
- }
3121
- endOfDay(date) {
3122
- return date.with({
3123
- hour: 23,
3124
- minute: 59,
3125
- second: 59,
3126
- millisecond: 999,
3127
- microsecond: 999,
3128
- nanosecond: 999
3129
- });
3130
- }
3131
- startOfWeek(date, firstDayOfWeek = 0) {
3132
- const diff = (date.dayOfWeek % 7 - firstDayOfWeek + 7) % 7;
3133
- return this.startOfDay(date.subtract({ days: diff }));
3134
- }
3135
- endOfWeek(date, firstDayOfWeek = 0) {
3136
- const start = this.startOfWeek(date, firstDayOfWeek);
3137
- return this.endOfDay(start.add({ days: 6 }));
3138
- }
3139
- startOfMonth(date) {
3140
- return this.startOfDay(date.with({ day: 1 }));
3141
- }
3142
- endOfMonth(date) {
3143
- return this.endOfDay(date.with({ day: date.daysInMonth }));
3144
- }
3145
- startOfYear(date) {
3146
- return this.startOfDay(date.with({
3147
- month: 1,
3148
- day: 1
3149
- }));
3150
- }
3151
- endOfYear(date) {
3152
- return this.endOfDay(date.with({
3153
- month: 12,
3154
- day: 31
3155
- }));
3156
- }
3157
- addSeconds(date, amount) {
3158
- return date.add({ seconds: amount });
3159
- }
3160
- addMinutes(date, amount) {
3161
- return date.add({ minutes: amount });
3162
- }
3163
- addHours(date, amount) {
3164
- return date.add({ hours: amount });
3165
- }
3166
- addDays(date, amount) {
3167
- return date.add({ days: amount });
3168
- }
3169
- addWeeks(date, amount) {
3170
- return date.add({ weeks: amount });
3171
- }
3172
- addMonths(date, amount) {
3173
- return date.add({ months: amount });
3174
- }
3175
- addYears(date, amount) {
3176
- return date.add({ years: amount });
3177
- }
3178
- isAfter(date, comparing) {
3179
- return Temporal.PlainDateTime.compare(date, comparing) > 0;
3180
- }
3181
- isAfterDay(date, comparing) {
3182
- return Temporal.PlainDate.compare(date.toPlainDate(), comparing.toPlainDate()) > 0;
3183
- }
3184
- isAfterMonth(date, comparing) {
3185
- if (date.year !== comparing.year) return date.year > comparing.year;
3186
- return date.month > comparing.month;
3187
- }
3188
- isAfterYear(date, comparing) {
3189
- return date.year > comparing.year;
3190
- }
3191
- isBefore(date, comparing) {
3192
- return Temporal.PlainDateTime.compare(date, comparing) < 0;
3193
- }
3194
- isBeforeDay(date, comparing) {
3195
- return Temporal.PlainDate.compare(date.toPlainDate(), comparing.toPlainDate()) < 0;
3196
- }
3197
- isBeforeMonth(date, comparing) {
3198
- if (date.year !== comparing.year) return date.year < comparing.year;
3199
- return date.month < comparing.month;
3200
- }
3201
- isBeforeYear(date, comparing) {
3202
- return date.year < comparing.year;
3203
- }
3204
- isEqual(date, comparing) {
3205
- return Temporal.PlainDateTime.compare(date, comparing) === 0;
3206
- }
3207
- isSameDay(date, comparing) {
3208
- return Temporal.PlainDate.compare(date.toPlainDate(), comparing.toPlainDate()) === 0;
3209
- }
3210
- isSameMonth(date, comparing) {
3211
- return date.year === comparing.year && date.month === comparing.month;
3212
- }
3213
- isSameYear(date, comparing) {
3214
- return date.year === comparing.year;
3215
- }
3216
- isSameHour(date, comparing) {
3217
- return date.year === comparing.year && date.month === comparing.month && date.day === comparing.day && date.hour === comparing.hour;
3218
- }
3219
- isWithinRange(date, [start, end]) {
3220
- return Temporal.PlainDateTime.compare(date, start) >= 0 && Temporal.PlainDateTime.compare(date, end) <= 0;
3221
- }
3222
- getYear(date) {
3223
- return date.year;
3224
- }
3225
- getMonth(date) {
3226
- return date.month - 1;
3227
- }
3228
- getDate(date) {
3229
- return date.day;
3230
- }
3231
- getHours(date) {
3232
- return date.hour;
3233
- }
3234
- getMinutes(date) {
3235
- return date.minute;
3236
- }
3237
- getSeconds(date) {
3238
- return date.second;
3239
- }
3240
- getDiff(date, comparing, unit) {
3241
- const unitKey = unit ?? "days";
3242
- const comp = /* @__PURE__ */ isString(comparing) ? this.date(comparing) : comparing;
3243
- if (/* @__PURE__ */ isNull(comp)) return 0;
3244
- const duration = date.since(comp, { largestUnit: unitKey });
3245
- switch (unitKey) {
3246
- case "years": return duration.years;
3247
- case "months": return duration.months + duration.years * 12;
3248
- case "weeks": return duration.weeks + Math.floor(duration.days / 7);
3249
- case "days": return duration.days + duration.weeks * 7;
3250
- case "hours": return Math.round(duration.total({ unit: "hours" }));
3251
- case "minutes": return Math.round(duration.total({ unit: "minutes" }));
3252
- case "seconds": return Math.round(duration.total({ unit: "seconds" }));
3253
- default: return duration.days;
3254
- }
3255
- }
3256
- getWeek(date, firstDayOfWeek = 0, minimalDays = 1) {
3257
- const startOfYear = this.startOfYear(date);
3258
- const startOfFirstWeek = this.startOfWeek(startOfYear, firstDayOfWeek);
3259
- let firstWeekStart = startOfFirstWeek;
3260
- if (startOfYear.day - startOfFirstWeek.day < minimalDays) firstWeekStart = startOfFirstWeek.add({ weeks: 1 });
3261
- const startOfCurrentWeek = this.startOfWeek(date, firstDayOfWeek);
3262
- const diff = this.getDiff(startOfCurrentWeek, firstWeekStart, "weeks");
3263
- return Math.max(1, diff + 1);
3264
- }
3265
- getDaysInMonth(date) {
3266
- return date.daysInMonth;
3267
- }
3268
- setYear(date, year) {
3269
- return date.with({ year });
3270
- }
3271
- setMonth(date, month) {
3272
- return date.with({ month: month + 1 });
3273
- }
3274
- setDate(date, day) {
3275
- return date.with({ day });
3276
- }
3277
- setHours(date, hours) {
3278
- return date.with({ hour: hours });
3279
- }
3280
- setMinutes(date, minutes) {
3281
- return date.with({ minute: minutes });
3282
- }
3283
- setSeconds(date, seconds) {
3284
- return date.with({ second: seconds });
3285
- }
3286
- getWeekdays(firstDayOfWeek = 0, format = "short") {
3287
- const weekdays = [];
3288
- const refDate = Temporal.PlainDate.from("2015-01-04");
3289
- const formatter = this.getFormatter({ weekday: format });
3290
- for (let i = 0; i < 7; i++) {
3291
- const day = refDate.add({ days: (i + firstDayOfWeek) % 7 });
3292
- const jsDate = new Date(day.year, day.month - 1, day.day);
3293
- weekdays.push(formatter.format(jsDate));
3294
- }
3295
- return weekdays;
3296
- }
3297
- getWeekArray(date, firstDayOfWeek = 0) {
3298
- const weeks = [];
3299
- const monthStart = this.startOfMonth(date);
3300
- const monthEnd = this.endOfMonth(date);
3301
- let current = this.startOfWeek(monthStart, firstDayOfWeek);
3302
- const end = this.endOfWeek(monthEnd);
3303
- while (Temporal.PlainDateTime.compare(current, end) <= 0) {
3304
- const week = [];
3305
- for (let i = 0; i < 7; i++) {
3306
- week.push(current);
3307
- current = current.add({ days: 1 });
3308
- }
3309
- weeks.push(week);
3310
- }
3311
- return weeks;
3312
- }
3313
- getMonthArray(date) {
3314
- const year = date.year;
3315
- const months = [];
3316
- for (let month = 1; month <= 12; month++) months.push(Temporal.PlainDateTime.from({
3317
- year,
3318
- month,
3319
- day: 1
3320
- }));
3321
- return months;
3322
- }
3323
- getYearRange(start, end) {
3324
- const years = [];
3325
- let current = start.year;
3326
- while (current <= end.year) {
3327
- years.push(Temporal.PlainDateTime.from({
3328
- year: current,
3329
- month: 1,
3330
- day: 1
3331
- }));
3332
- current++;
3333
- }
3334
- return years;
3335
- }
3336
- getNextMonth(date) {
3337
- return this.startOfMonth(date.add({ months: 1 }));
3338
- }
3339
- getPreviousMonth(date) {
3340
- return this.startOfMonth(date.subtract({ months: 1 }));
3341
- }
3342
- mergeDateAndTime(date, time) {
3343
- return date.with({
3344
- hour: time.hour,
3345
- minute: time.minute,
3346
- second: time.second,
3347
- millisecond: time.millisecond
3348
- });
3349
- }
3350
- /**
3351
- * Gets a cached Intl.DateTimeFormat instance or creates one if not cached.
3352
- * Cache is limited to MAX_CACHE_SIZE entries to prevent memory leaks.
3353
- */
3354
- getFormatter(options) {
3355
- const key = `${this.locale}:${JSON.stringify(options)}`;
3356
- let formatter = this.formatCache.get(key);
3357
- if (!formatter) {
3358
- if (this.formatCache.size >= MAX_CACHE_SIZE) {
3359
- const firstKey = this.formatCache.keys().next().value;
3360
- if (firstKey) this.formatCache.delete(firstKey);
3361
- }
3362
- formatter = new Intl.DateTimeFormat(this.locale, options);
3363
- this.formatCache.set(key, formatter);
3364
- }
3365
- return formatter;
3366
- }
3367
- /**
3368
- * Gets a cached Intl.NumberFormat instance or creates one if not cached.
3369
- * Cache is limited to MAX_CACHE_SIZE entries to prevent memory leaks.
3370
- */
3371
- getNumberFormatter() {
3372
- let formatter = this.numberFormatCache.get(this.locale);
3373
- if (!formatter) {
3374
- if (this.numberFormatCache.size >= MAX_CACHE_SIZE) {
3375
- const firstKey = this.numberFormatCache.keys().next().value;
3376
- if (firstKey) this.numberFormatCache.delete(firstKey);
3377
- }
3378
- formatter = new Intl.NumberFormat(this.locale);
3379
- this.numberFormatCache.set(this.locale, formatter);
3380
- }
3381
- return formatter;
3382
- }
3383
- };
3384
-
3385
2876
  //#endregion
3386
2877
  //#region src/composables/useDate/index.ts
3387
2878
  /**
@@ -3392,16 +2883,16 @@ var Vuetify0DateAdapter = class {
3392
2883
  *
3393
2884
  * Key features:
3394
2885
  * - Adapter pattern for date library abstraction
3395
- * - Temporal API as default adapter (modern, immutable dates)
3396
2886
  * - Locale-aware formatting via Intl.DateTimeFormat
3397
2887
  * - Integration with useLocale for automatic locale sync
3398
2888
  *
3399
- * @example
2889
+ * @example Using the built-in Temporal adapter
3400
2890
  * ```ts
2891
+ * import { Vuetify0DateAdapter } from '@vuetify/v0/date'
3401
2892
  * import { createDatePlugin } from '@vuetify/v0'
3402
2893
  *
3403
2894
  * const app = createApp(App)
3404
- * app.use(createDatePlugin())
2895
+ * app.use(createDatePlugin({ adapter: new Vuetify0DateAdapter() }))
3405
2896
  *
3406
2897
  * // In a component:
3407
2898
  * const { adapter } = useDate()
@@ -3417,7 +2908,7 @@ var Vuetify0DateAdapter = class {
3417
2908
  * // ... implementation
3418
2909
  * }
3419
2910
  *
3420
- * const context = createDate({ adapter: new DateFnsAdapter() })
2911
+ * app.use(createDatePlugin({ adapter: new DateFnsAdapter() }))
3421
2912
  * ```
3422
2913
  */
3423
2914
  /**
@@ -3440,7 +2931,8 @@ const defaultLocales = {
3440
2931
  /**
3441
2932
  * Creates a new date context.
3442
2933
  *
3443
- * @param options Optional adapter and locale configuration.
2934
+ * @param options Adapter and locale configuration.
2935
+ * @template Z The date type used by the adapter.
3444
2936
  * @template E The date context type.
3445
2937
  * @returns A date context.
3446
2938
  *
@@ -3448,18 +2940,20 @@ const defaultLocales = {
3448
2940
  *
3449
2941
  * @example
3450
2942
  * ```ts
3451
- * const { adapter } = createDate()
3452
- * const today = adapter.date() // Temporal.PlainDateTime
2943
+ * import { Vuetify0DateAdapter } from '@vuetify/v0/date'
3453
2944
  *
3454
- * // With locale options
3455
- * const { adapter: deAdapter } = createDate({ locale: 'de-DE' })
2945
+ * const { adapter } = createDate({ adapter: new Vuetify0DateAdapter() })
2946
+ * const today = adapter.date()
3456
2947
  *
3457
- * // With custom adapter
3458
- * const { adapter } = createDate({ adapter: new DateFnsAdapter() })
2948
+ * // With locale options
2949
+ * const { adapter } = createDate({
2950
+ * adapter: new Vuetify0DateAdapter(),
2951
+ * locale: 'de-DE',
2952
+ * })
3459
2953
  * ```
3460
2954
  */
3461
- function createDate(options = {}) {
3462
- const { locales = defaultLocales, adapter = new Vuetify0DateAdapter(), locale: initialLocale } = options;
2955
+ function createDate(options) {
2956
+ const { locales = defaultLocales, adapter, locale: initialLocale } = options;
3463
2957
  let selectedId;
3464
2958
  try {
3465
2959
  if (instanceExists()) selectedId = useLocale().selectedId;
@@ -3487,22 +2981,10 @@ function createDate(options = {}) {
3487
2981
  };
3488
2982
  }
3489
2983
  /**
3490
- * Creates a fallback date context for when useDate is called outside of a Vue component.
3491
- *
3492
- * @returns A fallback date context with Vuetify0DateAdapter.
3493
- * @internal
3494
- */
3495
- function createDateFallback() {
3496
- const adapter = new Vuetify0DateAdapter();
3497
- return {
3498
- adapter,
3499
- locale: computed(() => adapter.locale ?? "en-US")
3500
- };
3501
- }
3502
- /**
3503
2984
  * Creates a new date context trinity.
3504
2985
  *
3505
- * @param options Optional adapter, locale, and namespace configuration.
2986
+ * @param options Adapter, locale, and namespace configuration.
2987
+ * @template Z The date type used by the adapter.
3506
2988
  * @template E The date context type.
3507
2989
  * @returns A trinity [useContext, provideContext, defaultContext].
3508
2990
  *
@@ -3510,18 +2992,15 @@ function createDateFallback() {
3510
2992
  *
3511
2993
  * @example
3512
2994
  * ```ts
3513
- * const [useAppDate, provideAppDate] = createDateContext({
3514
- * namespace: 'app:date',
3515
- * })
2995
+ * import { Vuetify0DateAdapter } from '@vuetify/v0/date'
3516
2996
  *
3517
- * // With custom adapter
3518
2997
  * const [useAppDate, provideAppDate] = createDateContext({
3519
- * adapter: new DateFnsAdapter(),
2998
+ * adapter: new Vuetify0DateAdapter(),
3520
2999
  * namespace: 'app:date',
3521
3000
  * })
3522
3001
  * ```
3523
3002
  */
3524
- function createDateContext(options = {}) {
3003
+ function createDateContext(options) {
3525
3004
  const { namespace = "v0:date", ...dateOptions } = options;
3526
3005
  const [useDateContext, _provideDateContext] = createContext(namespace);
3527
3006
  const context = createDate(dateOptions);
@@ -3533,7 +3012,8 @@ function createDateContext(options = {}) {
3533
3012
  /**
3534
3013
  * Creates a new date plugin.
3535
3014
  *
3536
- * @param options Optional adapter, locale, and namespace configuration.
3015
+ * @param options Adapter, locale, and namespace configuration.
3016
+ * @template Z The date type used by the adapter.
3537
3017
  * @template E The date context type.
3538
3018
  * @returns A Vue plugin.
3539
3019
  *
@@ -3541,17 +3021,19 @@ function createDateContext(options = {}) {
3541
3021
  *
3542
3022
  * @example
3543
3023
  * ```ts
3544
- * const app = createApp(App)
3545
- * app.use(createDatePlugin())
3024
+ * import { Vuetify0DateAdapter } from '@vuetify/v0/date'
3546
3025
  *
3547
- * // With options
3548
- * app.use(createDatePlugin({ locale: 'de-DE' }))
3026
+ * const app = createApp(App)
3027
+ * app.use(createDatePlugin({ adapter: new Vuetify0DateAdapter() }))
3549
3028
  *
3550
- * // With custom adapter
3551
- * app.use(createDatePlugin({ adapter: new DateFnsAdapter() }))
3029
+ * // With locale options
3030
+ * app.use(createDatePlugin({
3031
+ * adapter: new Vuetify0DateAdapter(),
3032
+ * locale: 'de-DE',
3033
+ * }))
3552
3034
  * ```
3553
3035
  */
3554
- function createDatePlugin(options = {}) {
3036
+ function createDatePlugin(options) {
3555
3037
  const { namespace = "v0:date", ...dateOptions } = options;
3556
3038
  const [, provideDateContext, context] = createDateContext({
3557
3039
  namespace,
@@ -3567,16 +3049,26 @@ function createDatePlugin(options = {}) {
3567
3049
  /**
3568
3050
  * Returns the current date context.
3569
3051
  *
3570
- * When called inside a component with a provided date context (via plugin or provider),
3571
- * returns that context. Otherwise, returns a fallback context with Vuetify0DateAdapter.
3052
+ * Requires `createDatePlugin` to be installed with an adapter.
3572
3053
  *
3573
3054
  * @param namespace The namespace to look up (defaults to 'v0:date').
3055
+ * @template Z The date type used by the adapter.
3574
3056
  * @template E The date context type.
3575
3057
  * @returns The current date context.
3058
+ * @throws If called outside a component or without a date plugin installed.
3576
3059
  *
3577
3060
  * @see https://0.vuetifyjs.com/composables/plugins/use-date
3578
3061
  *
3579
3062
  * @example
3063
+ * ```ts
3064
+ * // main.ts
3065
+ * import { Vuetify0DateAdapter } from '@vuetify/v0/date'
3066
+ * import { createDatePlugin } from '@vuetify/v0'
3067
+ *
3068
+ * app.use(createDatePlugin({ adapter: new Vuetify0DateAdapter() }))
3069
+ * ```
3070
+ *
3071
+ * @example
3580
3072
  * ```vue
3581
3073
  * <script setup lang="ts">
3582
3074
  * import { useDate } from '@vuetify/v0'
@@ -3587,15 +3079,126 @@ function createDatePlugin(options = {}) {
3587
3079
  * ```
3588
3080
  */
3589
3081
  function useDate(namespace = "v0:date") {
3590
- const fallback = createDateFallback();
3591
- if (!instanceExists()) return fallback;
3592
- try {
3593
- return useContext(namespace, fallback);
3594
- } catch {
3595
- return fallback;
3596
- }
3082
+ if (!instanceExists()) throw new Error("[v0] useDate() must be called inside a Vue component with createDatePlugin installed.\n\nExample:\n import { Vuetify0DateAdapter } from '@vuetify/v0/date'\n import { createDatePlugin } from '@vuetify/v0'\n\n app.use(createDatePlugin({ adapter: new Vuetify0DateAdapter() }))");
3083
+ return useContext(namespace);
3597
3084
  }
3598
3085
 
3086
+ //#endregion
3087
+ //#region src/composables/useFeatures/adapters/generic/index.ts
3088
+ var FeaturesAdapter = class {};
3089
+
3090
+ //#endregion
3091
+ //#region src/composables/useFeatures/adapters/flagsmith/index.ts
3092
+ /**
3093
+ * @module FlagsmithFeatureAdapter
3094
+ *
3095
+ * @remarks
3096
+ * Flagsmith adapter for feature flags.
3097
+ */
3098
+ var FlagsmithFeatureAdapter = class {
3099
+ client;
3100
+ options;
3101
+ constructor(client = flagsmith, options) {
3102
+ this.client = client;
3103
+ this.options = options;
3104
+ }
3105
+ setup(onUpdate) {
3106
+ const updateFlags = () => {
3107
+ const flags = this.client.getAllFlags();
3108
+ const adapterFlags = {};
3109
+ if (flags) for (const [key, flag] of Object.entries(flags)) {
3110
+ const isEnabled = flag.enabled;
3111
+ const variation = flag.value;
3112
+ adapterFlags[key] = variation !== null && variation !== void 0 ? {
3113
+ $value: isEnabled,
3114
+ $variation: variation
3115
+ } : isEnabled;
3116
+ }
3117
+ return adapterFlags;
3118
+ };
3119
+ this.client.init({
3120
+ ...this.options,
3121
+ onChange: (oldFlags, params, loadingState) => {
3122
+ onUpdate(updateFlags());
3123
+ this.options.onChange?.(oldFlags, params, loadingState);
3124
+ }
3125
+ });
3126
+ this.disposeFn = () => this.client.stopListening();
3127
+ return updateFlags();
3128
+ }
3129
+ dispose() {
3130
+ this.disposeFn();
3131
+ }
3132
+ disposeFn = () => {};
3133
+ };
3134
+
3135
+ //#endregion
3136
+ //#region src/composables/useFeatures/adapters/launchdarkly/index.ts
3137
+ var LaunchDarklyFeatureAdapter = class {
3138
+ constructor(client) {
3139
+ this.client = client;
3140
+ }
3141
+ setup(onUpdate) {
3142
+ const updateFlags = () => {
3143
+ const allFlags = this.client.allFlags();
3144
+ const flags = {};
3145
+ for (const [key, value] of Object.entries(allFlags)) flags[key] = typeof value === "boolean" ? value : {
3146
+ $value: true,
3147
+ $variation: value
3148
+ };
3149
+ onUpdate(flags);
3150
+ return flags;
3151
+ };
3152
+ this.client.on("change", updateFlags);
3153
+ this.disposeFn = () => this.client.off("change", updateFlags);
3154
+ return updateFlags();
3155
+ }
3156
+ dispose() {
3157
+ this.disposeFn();
3158
+ }
3159
+ disposeFn = () => {};
3160
+ };
3161
+
3162
+ //#endregion
3163
+ //#region src/composables/useFeatures/adapters/posthog/index.ts
3164
+ var PostHogFeatureAdapter = class {
3165
+ constructor(client) {
3166
+ this.client = client;
3167
+ }
3168
+ setup(onUpdate) {
3169
+ const updateFlags = () => {
3170
+ const flags = {};
3171
+ const activeFlags = this.client.featureFlags.getFlags();
3172
+ if (activeFlags) {
3173
+ for (const key of activeFlags) {
3174
+ const isEnabled = this.client.isFeatureEnabled(key) ?? false;
3175
+ const payload = this.client.getFeatureFlagPayload(key);
3176
+ if (payload !== void 0 && payload !== null) flags[key] = {
3177
+ $value: isEnabled,
3178
+ $variation: payload
3179
+ };
3180
+ else {
3181
+ const variant = this.client.getFeatureFlag(key);
3182
+ flags[key] = variant !== true && variant !== false && variant !== void 0 && variant !== null ? {
3183
+ $value: true,
3184
+ $variation: variant
3185
+ } : isEnabled;
3186
+ }
3187
+ }
3188
+ onUpdate(flags);
3189
+ return flags;
3190
+ }
3191
+ return {};
3192
+ };
3193
+ this.disposeFn = this.client.onFeatureFlags(updateFlags);
3194
+ return updateFlags();
3195
+ }
3196
+ dispose() {
3197
+ this.disposeFn();
3198
+ }
3199
+ disposeFn = () => {};
3200
+ };
3201
+
3599
3202
  //#endregion
3600
3203
  //#region src/composables/useFeatures/index.ts
3601
3204
  /**
@@ -3612,6 +3215,7 @@ function useDate(namespace = "v0:date") {
3612
3215
  * - Auto-selection of enabled features
3613
3216
  * - Multi-select support for feature combinations
3614
3217
  * - Perfect for A/B testing, progressive rollout, feature toggles
3218
+ * - Adapter pattern for external feature flag services
3615
3219
  *
3616
3220
  * Inheritance chain: useRegistry → createSelection → createGroup → createFeatures
3617
3221
  * Integrates with useTokens for token-based features.
@@ -3642,7 +3246,10 @@ function useDate(namespace = "v0:date") {
3642
3246
  function createFeatures(_options = {}) {
3643
3247
  const { features, ...options } = _options;
3644
3248
  const tokens = createTokens(features, { flat: true });
3645
- const registry = createGroup(options);
3249
+ const registry = createGroup({
3250
+ ...options,
3251
+ reactive: true
3252
+ });
3646
3253
  for (const [id, { value }] of tokens.entries()) register({
3647
3254
  id,
3648
3255
  value
@@ -3661,10 +3268,22 @@ function createFeatures(_options = {}) {
3661
3268
  if (/* @__PURE__ */ isBoolean(ticket.value) && ticket.value === true || /* @__PURE__ */ isObject(ticket.value) && /* @__PURE__ */ isBoolean(ticket.value.$value) && ticket.value.$value === true) registry.select(ticket.id);
3662
3269
  return ticket;
3663
3270
  }
3271
+ function sync(flags) {
3272
+ for (const [id, value] of Object.entries(flags)) if (registry.get(id)) {
3273
+ const shouldSelect = /* @__PURE__ */ isBoolean(value) ? value === true : /* @__PURE__ */ isObject(value) && /* @__PURE__ */ isBoolean(value.$value) && value.$value === true;
3274
+ registry.upsert(id, { value });
3275
+ if (shouldSelect) registry.select(id);
3276
+ else registry.unselect(id);
3277
+ } else register({
3278
+ id,
3279
+ value
3280
+ });
3281
+ }
3664
3282
  return {
3665
3283
  ...registry,
3666
3284
  variation,
3667
3285
  register,
3286
+ sync,
3668
3287
  get size() {
3669
3288
  return registry.size;
3670
3289
  }
@@ -3733,7 +3352,7 @@ function createFeaturesContext(_options = {}) {
3733
3352
  * ```
3734
3353
  */
3735
3354
  function createFeaturesPlugin(_options = {}) {
3736
- const { namespace = "v0:features", ...options } = _options;
3355
+ const { namespace = "v0:features", adapter, ...options } = _options;
3737
3356
  const [, provideFeaturesContext, context] = createFeaturesContext({
3738
3357
  ...options,
3739
3358
  namespace
@@ -3742,6 +3361,17 @@ function createFeaturesPlugin(_options = {}) {
3742
3361
  namespace,
3743
3362
  provide: (app) => {
3744
3363
  provideFeaturesContext(context, app);
3364
+ },
3365
+ setup: (app) => {
3366
+ if (!adapter) return;
3367
+ const adapters = /* @__PURE__ */ isArray(adapter) ? adapter : [adapter];
3368
+ for (const adapter$1 of adapters) {
3369
+ const initialFlags = adapter$1.setup((flags) => {
3370
+ context.sync(flags);
3371
+ });
3372
+ context.sync(initialFlags);
3373
+ if (/* @__PURE__ */ isFunction(adapter$1.dispose)) app.onUnmount(() => adapter$1.dispose());
3374
+ }
3745
3375
  }
3746
3376
  });
3747
3377
  }
@@ -4593,7 +4223,7 @@ function matchesKeyGroup(e, group, platformIsMac) {
4593
4223
  */
4594
4224
  function useIntersectionObserver(target, callback, options = {}) {
4595
4225
  const { isHydrated } = useHydration();
4596
- const targetRef = isRef(target) ? target : shallowRef(target);
4226
+ const targetRef = toRef(target);
4597
4227
  const observer = shallowRef();
4598
4228
  const isPaused = shallowRef(false);
4599
4229
  const isIntersecting = shallowRef(false);
@@ -4632,17 +4262,17 @@ function useIntersectionObserver(target, callback, options = {}) {
4632
4262
  }]);
4633
4263
  }
4634
4264
  watch(() => targetRef.value, (el, oldEl) => {
4635
- if (oldEl) cleanup();
4265
+ if (oldEl || observer.value) cleanup();
4636
4266
  if (isHydrated.value && el) setup();
4637
4267
  }, { immediate: true });
4638
- if (!isHydrated.value) {
4639
- const stopHydrationWatch = watch(() => isHydrated.value, (hydrated) => {
4640
- if (hydrated && targetRef.value && !observer.value) {
4641
- setup();
4642
- stopHydrationWatch();
4643
- }
4644
- });
4645
- }
4268
+ let stopHydrationWatch;
4269
+ if (!isHydrated.value) stopHydrationWatch = watch(() => isHydrated.value, (hydrated) => {
4270
+ if (hydrated && targetRef.value && !observer.value) {
4271
+ setup();
4272
+ stopHydrationWatch?.();
4273
+ stopHydrationWatch = void 0;
4274
+ }
4275
+ });
4646
4276
  function cleanup() {
4647
4277
  if (observer.value) {
4648
4278
  observer.value.disconnect();
@@ -4659,6 +4289,8 @@ function useIntersectionObserver(target, callback, options = {}) {
4659
4289
  setup();
4660
4290
  }
4661
4291
  function stop() {
4292
+ stopHydrationWatch?.();
4293
+ stopHydrationWatch = void 0;
4662
4294
  cleanup();
4663
4295
  observer.value = null;
4664
4296
  }
@@ -4994,6 +4626,7 @@ function usePrefersContrast() {
4994
4626
  */
4995
4627
  function useMutationObserver(target, callback, options = {}) {
4996
4628
  const { isHydrated } = useHydration();
4629
+ const targetRef = toRef(target);
4997
4630
  const observer = shallowRef();
4998
4631
  const isPaused = shallowRef(false);
4999
4632
  const isActive = toRef(() => !!observer.value);
@@ -5008,7 +4641,7 @@ function useMutationObserver(target, callback, options = {}) {
5008
4641
  };
5009
4642
  function setup() {
5010
4643
  if (/* @__PURE__ */ isNull(observer.value)) return;
5011
- if (!isHydrated.value || !SUPPORTS_MUTATION_OBSERVER || !target.value || isPaused.value) return;
4644
+ if (!isHydrated.value || !SUPPORTS_MUTATION_OBSERVER || !targetRef.value || isPaused.value) return;
5012
4645
  observer.value = new MutationObserver((mutations) => {
5013
4646
  callback(mutations.map((mutation) => ({
5014
4647
  type: mutation.type,
@@ -5023,7 +4656,7 @@ function useMutationObserver(target, callback, options = {}) {
5023
4656
  })));
5024
4657
  if (options.once) stop();
5025
4658
  });
5026
- observer.value.observe(target.value, observerOptions);
4659
+ observer.value.observe(targetRef.value, observerOptions);
5027
4660
  if (options.immediate) {
5028
4661
  const emptyNodeList = {
5029
4662
  length: 0,
@@ -5033,7 +4666,7 @@ function useMutationObserver(target, callback, options = {}) {
5033
4666
  };
5034
4667
  callback([{
5035
4668
  type: "childList",
5036
- target: target.value,
4669
+ target: targetRef.value,
5037
4670
  addedNodes: emptyNodeList,
5038
4671
  removedNodes: emptyNodeList,
5039
4672
  previousSibling: null,
@@ -5045,18 +4678,18 @@ function useMutationObserver(target, callback, options = {}) {
5045
4678
  if (options.once) stop();
5046
4679
  }
5047
4680
  }
5048
- watch(() => target.value, (el, oldEl) => {
5049
- if (oldEl) cleanup();
4681
+ watch(() => targetRef.value, (el, oldEl) => {
4682
+ if (oldEl || observer.value) cleanup();
5050
4683
  if (isHydrated.value && el) setup();
5051
4684
  }, { immediate: true });
5052
- if (!isHydrated.value) {
5053
- const stopHydrationWatch = watch(() => isHydrated.value, (hydrated) => {
5054
- if (hydrated && target.value && !observer.value) {
5055
- setup();
5056
- stopHydrationWatch();
5057
- }
5058
- });
5059
- }
4685
+ let stopHydrationWatch;
4686
+ if (!isHydrated.value) stopHydrationWatch = watch(() => isHydrated.value, (hydrated) => {
4687
+ if (hydrated && targetRef.value && !observer.value) {
4688
+ setup();
4689
+ stopHydrationWatch?.();
4690
+ stopHydrationWatch = void 0;
4691
+ }
4692
+ });
5060
4693
  function cleanup() {
5061
4694
  if (observer.value) {
5062
4695
  observer.value.disconnect();
@@ -5072,6 +4705,8 @@ function useMutationObserver(target, callback, options = {}) {
5072
4705
  setup();
5073
4706
  }
5074
4707
  function stop() {
4708
+ stopHydrationWatch?.();
4709
+ stopHydrationWatch = void 0;
5075
4710
  cleanup();
5076
4711
  observer.value = null;
5077
4712
  }
@@ -5085,6 +4720,509 @@ function useMutationObserver(target, callback, options = {}) {
5085
4720
  };
5086
4721
  }
5087
4722
 
4723
+ //#endregion
4724
+ //#region src/composables/createNested/strategies.ts
4725
+ /**
4726
+ * Multiple open strategy: allows multiple nodes to be open simultaneously.
4727
+ *
4728
+ * @remarks
4729
+ * Perfect for tree views, file explorers, and nested menus where users expect
4730
+ * to keep multiple sections expanded at once.
4731
+ *
4732
+ * @example
4733
+ * ```ts
4734
+ * const tree = createNested({ openStrategy: multipleOpenStrategy })
4735
+ * tree.open('node-1')
4736
+ * tree.open('node-2')
4737
+ * // Both nodes are now open
4738
+ * ```
4739
+ */
4740
+ const multipleOpenStrategy = {
4741
+ onOpen: void 0,
4742
+ onClose: void 0
4743
+ };
4744
+ /**
4745
+ * Single open strategy: only one node can be open at a time (accordion behavior).
4746
+ *
4747
+ * @remarks
4748
+ * Perfect for accordions, single-select navigation, and contexts where only
4749
+ * one section should be visible at a time.
4750
+ *
4751
+ * @example
4752
+ * ```ts
4753
+ * const tree = createNested({ openStrategy: singleOpenStrategy })
4754
+ * tree.open('node-1') // node-1 opens
4755
+ * tree.open('node-2') // node-1 closes, node-2 opens
4756
+ * ```
4757
+ */
4758
+ const singleOpenStrategy = {
4759
+ onOpen: (id, context) => {
4760
+ for (const openedId of context.openedIds) if (openedId !== id) context.openedIds.delete(openedId);
4761
+ },
4762
+ onClose: void 0
4763
+ };
4764
+
4765
+ //#endregion
4766
+ //#region src/composables/createNested/index.ts
4767
+ /**
4768
+ * @module createNested
4769
+ *
4770
+ * @remarks
4771
+ * Hierarchical tree management composable extending createGroup with:
4772
+ * - Parent-child relationship tracking (children/parents Maps)
4773
+ * - Open/close state management
4774
+ * - Tree traversal utilities (getPath, getDescendants, etc.)
4775
+ * - Pluggable open strategies
4776
+ *
4777
+ * Inheritance chain: createSelection → createGroup → createNested
4778
+ */
4779
+ /**
4780
+ * Resolves open mode to an OpenStrategy.
4781
+ */
4782
+ function resolveOpenStrategy(open = "multiple") {
4783
+ return open === "single" ? singleOpenStrategy : multipleOpenStrategy;
4784
+ }
4785
+ /**
4786
+ * Creates a new nested tree instance with hierarchical management.
4787
+ *
4788
+ * Extends `createGroup` to support parent-child relationships, tree traversal,
4789
+ * and open/close state management. Perfect for tree views, nested navigation,
4790
+ * and hierarchical data structures.
4791
+ *
4792
+ * @param options The options for the nested instance.
4793
+ * @template Z The type of the nested ticket.
4794
+ * @template E The type of the nested context.
4795
+ * @returns A new nested instance with tree management capabilities.
4796
+ *
4797
+ * @remarks
4798
+ * **Key Differences from `createGroup`:**
4799
+ * - `register()` accepts `parentId` for establishing parent-child relationships
4800
+ * - `unregister()` accepts optional `cascade` parameter for cascading deletions
4801
+ * - Adds tree traversal methods: `getPath()`, `getAncestors()`, `getDescendants()`
4802
+ * - Adds computed properties: `roots`, `leaves`, `isLeaf()`, `getDepth()`
4803
+ * - Adds open state management: `open()`, `close()`, `flip()`, `opened()`
4804
+ *
4805
+ * @see https://0.vuetifyjs.com/composables/selection/use-nested
4806
+ *
4807
+ * @example
4808
+ * ```ts
4809
+ * import { createNested } from '@vuetify/v0'
4810
+ *
4811
+ * const tree = createNested()
4812
+ *
4813
+ * const root = tree.register({ id: 'root', value: 'Root' })
4814
+ * const child1 = tree.register({ id: 'child-1', value: 'Child 1', parentId: 'root' })
4815
+ * const child2 = tree.register({ id: 'child-2', value: 'Child 2', parentId: 'root' })
4816
+ *
4817
+ * console.log(tree.getPath('child-1')) // ['root', 'child-1']
4818
+ * console.log(tree.getDescendants('root')) // ['child-1', 'child-2']
4819
+ * console.log(tree.isLeaf('child-2')) // true
4820
+ *
4821
+ * tree.open('root')
4822
+ * console.log(tree.opened('root')) // true
4823
+ * ```
4824
+ */
4825
+ function createNested(_options = {}) {
4826
+ const { open: openMode = "multiple", openAll = false, reveal: revealOnOpen = false, selection: selectionMode = "cascade", openStrategy, ...options } = _options;
4827
+ const resolvedOpenStrategy = openStrategy ?? resolveOpenStrategy(openMode);
4828
+ const group = createGroup(options);
4829
+ const logger$1 = useLogger();
4830
+ const children = shallowReactive(/* @__PURE__ */ new Map());
4831
+ const parents = shallowReactive(/* @__PURE__ */ new Map());
4832
+ const openedIds = shallowReactive(/* @__PURE__ */ new Set());
4833
+ const openedItems = computed(() => {
4834
+ return new Set(Array.from(openedIds).map((id) => group.get(id)).filter((item) => !/* @__PURE__ */ isUndefined(item)));
4835
+ });
4836
+ const roots = computed(() => {
4837
+ return group.values().filter((item) => /* @__PURE__ */ isUndefined(parents.get(item.id)));
4838
+ });
4839
+ const leaves = computed(() => {
4840
+ return group.values().filter((item) => {
4841
+ const childList = children.get(item.id);
4842
+ return /* @__PURE__ */ isUndefined(childList) || childList.length === 0;
4843
+ });
4844
+ });
4845
+ function opened(id) {
4846
+ return openedIds.has(id);
4847
+ }
4848
+ function open(ids) {
4849
+ for (const id of toArray(ids)) {
4850
+ if (!group.has(id)) continue;
4851
+ if (revealOnOpen) {
4852
+ let parentId = parents.get(id);
4853
+ while (!/* @__PURE__ */ isUndefined(parentId)) {
4854
+ openedIds.add(parentId);
4855
+ parentId = parents.get(parentId);
4856
+ }
4857
+ }
4858
+ openedIds.add(id);
4859
+ resolvedOpenStrategy.onOpen?.(id, context);
4860
+ }
4861
+ }
4862
+ function close(ids) {
4863
+ for (const id of toArray(ids)) {
4864
+ if (!group.has(id)) continue;
4865
+ openedIds.delete(id);
4866
+ resolvedOpenStrategy.onClose?.(id, context);
4867
+ }
4868
+ }
4869
+ function flip(ids) {
4870
+ for (const id of toArray(ids)) {
4871
+ if (!group.has(id)) continue;
4872
+ if (opened(id)) close(id);
4873
+ else open(id);
4874
+ }
4875
+ }
4876
+ /**
4877
+ * Open node(s) and their immediate non-leaf children.
4878
+ * Useful for expanding a section with its immediate subcategories.
4879
+ */
4880
+ function unfold(ids) {
4881
+ for (const id of toArray(ids)) {
4882
+ if (!group.has(id)) continue;
4883
+ open(id);
4884
+ const childIds = children.get(id) ?? [];
4885
+ for (const childId of childIds) if (!isLeaf(childId)) open(childId);
4886
+ }
4887
+ }
4888
+ /**
4889
+ * Reveal a node by opening all its ancestors.
4890
+ * Makes the node visible in a collapsed tree without opening the node itself.
4891
+ */
4892
+ function reveal(ids) {
4893
+ for (const id of toArray(ids)) {
4894
+ if (!group.has(id)) continue;
4895
+ const ancestorIds = getAncestors(id);
4896
+ if (ancestorIds.length > 0) open(ancestorIds);
4897
+ }
4898
+ }
4899
+ /**
4900
+ * Fully expand a node and all its non-leaf descendants.
4901
+ * Opens the entire subtree rooted at the given node.
4902
+ */
4903
+ function expand(ids) {
4904
+ for (const id of toArray(ids)) {
4905
+ if (!group.has(id)) continue;
4906
+ if (!isLeaf(id)) open(id);
4907
+ for (const descendantId of getDescendants(id)) if (!isLeaf(descendantId)) open(descendantId);
4908
+ }
4909
+ }
4910
+ function expandAll() {
4911
+ for (const id of group.keys()) if (!isLeaf(id)) openedIds.add(id);
4912
+ }
4913
+ function collapseAll() {
4914
+ openedIds.clear();
4915
+ }
4916
+ function getPath(id) {
4917
+ const path = [];
4918
+ let currentId = id;
4919
+ while (!/* @__PURE__ */ isUndefined(currentId)) {
4920
+ path.unshift(currentId);
4921
+ currentId = parents.get(currentId);
4922
+ }
4923
+ return path;
4924
+ }
4925
+ function getAncestors(id) {
4926
+ return getPath(id).slice(0, -1);
4927
+ }
4928
+ function getDescendants(id) {
4929
+ const descendants = [];
4930
+ const queue = [...children.get(id) ?? []];
4931
+ let index = 0;
4932
+ while (index < queue.length) {
4933
+ const currentId = queue[index++];
4934
+ descendants.push(currentId);
4935
+ queue.push(...children.get(currentId) ?? []);
4936
+ }
4937
+ return descendants;
4938
+ }
4939
+ function isLeaf(id) {
4940
+ const childList = children.get(id);
4941
+ return /* @__PURE__ */ isUndefined(childList) || childList.length === 0;
4942
+ }
4943
+ function getDepth(id) {
4944
+ return getAncestors(id).length;
4945
+ }
4946
+ /**
4947
+ * Check if `ancestorId` is an ancestor of `descendantId`.
4948
+ * Returns false if either ID doesn't exist in the tree.
4949
+ */
4950
+ function isAncestorOf(ancestorId, descendantId) {
4951
+ if (!group.has(ancestorId) || !group.has(descendantId)) return false;
4952
+ if (ancestorId === descendantId) return false;
4953
+ let currentId = parents.get(descendantId);
4954
+ while (!/* @__PURE__ */ isUndefined(currentId)) {
4955
+ if (currentId === ancestorId) return true;
4956
+ currentId = parents.get(currentId);
4957
+ }
4958
+ return false;
4959
+ }
4960
+ /**
4961
+ * Check if `id` has `ancestorId` as an ancestor.
4962
+ * Semantic alias for isAncestorOf(ancestorId, id).
4963
+ */
4964
+ function hasAncestor(id, ancestorId) {
4965
+ return isAncestorOf(ancestorId, id);
4966
+ }
4967
+ /**
4968
+ * Get siblings of a node (including self).
4969
+ * For root nodes, returns all root IDs.
4970
+ */
4971
+ function siblings(id) {
4972
+ if (!group.has(id)) return [];
4973
+ const parentId = parents.get(id);
4974
+ if (/* @__PURE__ */ isUndefined(parentId)) return group.values().filter((item) => /* @__PURE__ */ isUndefined(parents.get(item.id))).map((item) => item.id);
4975
+ return children.get(parentId) ?? [];
4976
+ }
4977
+ /**
4978
+ * Get 1-indexed position among siblings (for aria-posinset).
4979
+ * Returns 0 if node not found.
4980
+ */
4981
+ function position(id) {
4982
+ const index = siblings(id).indexOf(id);
4983
+ return index === -1 ? 0 : index + 1;
4984
+ }
4985
+ function updateAncestors(id) {
4986
+ const ancestorIds = getAncestors(id).toReversed();
4987
+ for (const aid of ancestorIds) {
4988
+ const childIds = children.get(aid) ?? [];
4989
+ if (childIds.length === 0) continue;
4990
+ const allSelected = childIds.every((cid) => group.selected(cid));
4991
+ const someSelected = childIds.some((cid) => group.selected(cid) || group.mixed(cid));
4992
+ if (allSelected) {
4993
+ group.unmix(aid);
4994
+ group.select(aid);
4995
+ } else if (someSelected) {
4996
+ group.unselect(aid);
4997
+ group.mix(aid);
4998
+ } else {
4999
+ group.unmix(aid);
5000
+ group.unselect(aid);
5001
+ }
5002
+ }
5003
+ }
5004
+ function getLeafDescendants(id) {
5005
+ return getDescendants(id).filter((did) => isLeaf(did));
5006
+ }
5007
+ function select(ids) {
5008
+ for (const id of toArray(ids)) {
5009
+ if (!group.has(id)) continue;
5010
+ if (selectionMode === "independent") group.select(id);
5011
+ else if (selectionMode === "leaf") if (isLeaf(id)) group.select(id);
5012
+ else for (const lid of getLeafDescendants(id)) group.select(lid);
5013
+ else {
5014
+ group.unmix(id);
5015
+ group.select(id);
5016
+ for (const did of getDescendants(id)) {
5017
+ group.unmix(did);
5018
+ group.select(did);
5019
+ }
5020
+ updateAncestors(id);
5021
+ }
5022
+ }
5023
+ }
5024
+ function unselect(ids) {
5025
+ for (const id of toArray(ids)) {
5026
+ if (!group.has(id)) continue;
5027
+ if (selectionMode === "independent") group.unselect(id);
5028
+ else if (selectionMode === "leaf") if (isLeaf(id)) group.unselect(id);
5029
+ else for (const lid of getLeafDescendants(id)) group.unselect(lid);
5030
+ else {
5031
+ group.unmix(id);
5032
+ group.unselect(id);
5033
+ for (const did of getDescendants(id)) {
5034
+ group.unmix(did);
5035
+ group.unselect(did);
5036
+ }
5037
+ updateAncestors(id);
5038
+ }
5039
+ }
5040
+ }
5041
+ function toggle(ids) {
5042
+ for (const id of toArray(ids)) if (selectionMode === "independent") group.toggle(id);
5043
+ else if (selectionMode === "leaf") if (isLeaf(id)) group.toggle(id);
5044
+ else {
5045
+ const leafIds = getLeafDescendants(id);
5046
+ if (leafIds.every((lid) => group.selected(lid))) for (const lid of leafIds) group.unselect(lid);
5047
+ else for (const lid of leafIds) group.select(lid);
5048
+ }
5049
+ else if (group.selected(id) || group.mixed(id)) unselect(id);
5050
+ else select(id);
5051
+ }
5052
+ /**
5053
+ * Converts the tree to a flat array with parentId references.
5054
+ * Useful for serialization or sending to APIs/AI systems.
5055
+ */
5056
+ function toFlat() {
5057
+ return group.values().map((item) => ({
5058
+ id: item.id,
5059
+ parentId: parents.get(item.id),
5060
+ value: item.value
5061
+ }));
5062
+ }
5063
+ function register(registration = {}) {
5064
+ const id = registration.id ?? /* @__PURE__ */ useId$1();
5065
+ const parentId = registration.parentId;
5066
+ const nested = registration.children;
5067
+ if (!/* @__PURE__ */ isUndefined(parentId) && !group.has(parentId)) logger$1.warn(`Parent with id "${parentId}" does not exist. Registering "${id}" without parent.`);
5068
+ if (!/* @__PURE__ */ isUndefined(parentId) && group.has(parentId)) {
5069
+ parents.set(id, parentId);
5070
+ const list = children.get(parentId);
5071
+ if (list) list.push(id);
5072
+ else children.set(parentId, [id]);
5073
+ if (openAll) openedIds.add(parentId);
5074
+ } else parents.set(id, void 0);
5075
+ const { children: _, ...rest } = registration;
5076
+ const item = {
5077
+ ...rest,
5078
+ id,
5079
+ parentId: parents.get(id),
5080
+ isOpen: toRef(() => opened(id)),
5081
+ isLeaf: toRef(() => isLeaf(id)),
5082
+ depth: toRef(() => getDepth(id)),
5083
+ open: () => open(id),
5084
+ close: () => close(id),
5085
+ flip: () => flip(id),
5086
+ reveal: () => reveal(id),
5087
+ getPath: () => getPath(id),
5088
+ getAncestors: () => getAncestors(id),
5089
+ getDescendants: () => getDescendants(id),
5090
+ isAncestorOf: (descendantId) => isAncestorOf(id, descendantId),
5091
+ hasAncestor: (ancestorId) => hasAncestor(id, ancestorId),
5092
+ siblings: () => siblings(id),
5093
+ position: () => position(id)
5094
+ };
5095
+ const ticket = group.register(item);
5096
+ if (nested?.length) for (const child of nested) register({
5097
+ ...child,
5098
+ parentId: id
5099
+ });
5100
+ return ticket;
5101
+ }
5102
+ function unregister(id, cascade = false) {
5103
+ if (!group.has(id)) return;
5104
+ const parentId = parents.get(id);
5105
+ if (!/* @__PURE__ */ isUndefined(parentId)) {
5106
+ const siblings$1 = children.get(parentId);
5107
+ if (siblings$1) {
5108
+ const filtered = siblings$1.filter((sid) => sid !== id);
5109
+ if (filtered.length === 0) children.delete(parentId);
5110
+ else children.set(parentId, filtered);
5111
+ }
5112
+ }
5113
+ const list = children.get(id);
5114
+ if (list?.length) if (cascade) for (const did of getDescendants(id)) {
5115
+ parents.delete(did);
5116
+ children.delete(did);
5117
+ openedIds.delete(did);
5118
+ group.unregister(did);
5119
+ }
5120
+ else {
5121
+ for (const did of getDescendants(id)) openedIds.delete(did);
5122
+ for (const cid of list) parents.set(cid, void 0);
5123
+ }
5124
+ parents.delete(id);
5125
+ children.delete(id);
5126
+ openedIds.delete(id);
5127
+ group.unregister(id);
5128
+ }
5129
+ function offboard(ids, cascade = false) {
5130
+ for (const id of ids) unregister(id, cascade);
5131
+ }
5132
+ function onboard(registrations) {
5133
+ return registrations.map((registration) => register(registration));
5134
+ }
5135
+ function clear() {
5136
+ children.clear();
5137
+ parents.clear();
5138
+ openedIds.clear();
5139
+ group.reset();
5140
+ }
5141
+ function reset() {
5142
+ clear();
5143
+ }
5144
+ const context = {
5145
+ ...group,
5146
+ children,
5147
+ parents,
5148
+ openedIds,
5149
+ openedItems,
5150
+ roots,
5151
+ leaves,
5152
+ getPath,
5153
+ getAncestors,
5154
+ getDescendants,
5155
+ isLeaf,
5156
+ getDepth,
5157
+ isAncestorOf,
5158
+ hasAncestor,
5159
+ siblings,
5160
+ position,
5161
+ open,
5162
+ close,
5163
+ flip,
5164
+ opened,
5165
+ unfold,
5166
+ reveal,
5167
+ expand,
5168
+ expandAll,
5169
+ collapseAll,
5170
+ toFlat,
5171
+ openStrategy: resolvedOpenStrategy,
5172
+ select,
5173
+ unselect,
5174
+ toggle,
5175
+ register,
5176
+ unregister,
5177
+ offboard,
5178
+ onboard,
5179
+ clear,
5180
+ reset,
5181
+ get size() {
5182
+ return group.size;
5183
+ }
5184
+ };
5185
+ return context;
5186
+ }
5187
+ /**
5188
+ * Creates a new nested context with provide/inject pattern.
5189
+ *
5190
+ * @param options The options for the nested context.
5191
+ * @returns A trinity tuple [useNested, provideNested, defaultNested]
5192
+ *
5193
+ * @see https://0.vuetifyjs.com/composables/selection/use-nested
5194
+ *
5195
+ * @example
5196
+ * ```ts
5197
+ * import { createNestedContext } from '@vuetify/v0'
5198
+ *
5199
+ * export const [useTree, provideTree, tree] = createNestedContext()
5200
+ *
5201
+ * // In parent: provideTree()
5202
+ * // In child: const tree = useTree()
5203
+ * ```
5204
+ */
5205
+ function createNestedContext(_options = {}) {
5206
+ const { namespace = "v0:nested", ...options } = _options;
5207
+ const [useNestedContext, _provideNestedContext] = createContext(namespace);
5208
+ const context = createNested(options);
5209
+ function provideNestedContext(_context = context, app) {
5210
+ return _provideNestedContext(_context, app);
5211
+ }
5212
+ return createTrinity(useNestedContext, provideNestedContext, context);
5213
+ }
5214
+ /**
5215
+ * Returns the current nested instance from context.
5216
+ *
5217
+ * @param namespace The namespace for the nested context. Defaults to `'v0:nested'`.
5218
+ * @returns The current nested instance.
5219
+ *
5220
+ * @see https://0.vuetifyjs.com/composables/selection/use-nested
5221
+ */
5222
+ function useNested(namespace = "v0:nested") {
5223
+ return useContext(namespace);
5224
+ }
5225
+
5088
5226
  //#endregion
5089
5227
  //#region src/composables/useResizeObserver/index.ts
5090
5228
  /**
@@ -5146,12 +5284,13 @@ function useMutationObserver(target, callback, options = {}) {
5146
5284
  */
5147
5285
  function useResizeObserver(target, callback, options = {}) {
5148
5286
  const { isHydrated } = useHydration();
5287
+ const targetRef = toRef(target);
5149
5288
  const observer = shallowRef();
5150
5289
  const isPaused = shallowRef(false);
5151
5290
  const isActive = toRef(() => !!observer.value);
5152
5291
  function setup() {
5153
5292
  if (/* @__PURE__ */ isNull(observer.value)) return;
5154
- if (!isHydrated.value || !SUPPORTS_OBSERVER || !target.value || isPaused.value) return;
5293
+ if (!isHydrated.value || !SUPPORTS_OBSERVER || !targetRef.value || isPaused.value) return;
5155
5294
  observer.value = new ResizeObserver((entries) => {
5156
5295
  callback(entries.map((entry) => ({
5157
5296
  contentRect: {
@@ -5164,9 +5303,9 @@ function useResizeObserver(target, callback, options = {}) {
5164
5303
  })));
5165
5304
  if (options.once) stop();
5166
5305
  });
5167
- observer.value.observe(target.value, { box: options.box || "content-box" });
5306
+ observer.value.observe(targetRef.value, { box: options.box || "content-box" });
5168
5307
  if (options.immediate) {
5169
- const rect = target.value.getBoundingClientRect();
5308
+ const rect = targetRef.value.getBoundingClientRect();
5170
5309
  callback([{
5171
5310
  contentRect: {
5172
5311
  width: rect.width,
@@ -5174,22 +5313,22 @@ function useResizeObserver(target, callback, options = {}) {
5174
5313
  top: rect.top,
5175
5314
  left: rect.left
5176
5315
  },
5177
- target: target.value
5316
+ target: targetRef.value
5178
5317
  }]);
5179
5318
  }
5180
5319
  }
5181
- watch(() => target.value, (el, oldEl) => {
5182
- if (oldEl) cleanup();
5320
+ watch(() => targetRef.value, (el, oldEl) => {
5321
+ if (oldEl || observer.value) cleanup();
5183
5322
  if (isHydrated.value && el) setup();
5184
5323
  }, { immediate: true });
5185
- if (!isHydrated.value) {
5186
- const stopHydrationWatch = watch(() => isHydrated.value, (hydrated) => {
5187
- if (hydrated && target.value && !observer.value) {
5188
- setup();
5189
- stopHydrationWatch();
5190
- }
5191
- });
5192
- }
5324
+ let stopHydrationWatch;
5325
+ if (!isHydrated.value) stopHydrationWatch = watch(() => isHydrated.value, (hydrated) => {
5326
+ if (hydrated && targetRef.value && !observer.value) {
5327
+ setup();
5328
+ stopHydrationWatch?.();
5329
+ stopHydrationWatch = void 0;
5330
+ }
5331
+ });
5193
5332
  function cleanup() {
5194
5333
  if (observer.value) {
5195
5334
  observer.value.disconnect();
@@ -5205,6 +5344,8 @@ function useResizeObserver(target, callback, options = {}) {
5205
5344
  setup();
5206
5345
  }
5207
5346
  function stop() {
5347
+ stopHydrationWatch?.();
5348
+ stopHydrationWatch = void 0;
5208
5349
  cleanup();
5209
5350
  observer.value = null;
5210
5351
  }
@@ -5941,7 +6082,7 @@ function createQueue(_options = {}) {
5941
6082
  }
5942
6083
  }
5943
6084
  function register(registration = {}) {
5944
- const id = registration.id ?? /* @__PURE__ */ genId();
6085
+ const id = registration.id ?? /* @__PURE__ */ useId$1();
5945
6086
  const timeout = Object.prototype.hasOwnProperty.call(registration, "timeout") ? registration.timeout : _timeout;
5946
6087
  const ticket = {
5947
6088
  ...registration,
@@ -6198,8 +6339,9 @@ function createStep(_options = {}) {
6198
6339
  * Creates a new step context.
6199
6340
  *
6200
6341
  * @param options The options for the step context.
6201
- * @template Z The type of the step ticket.
6202
- * @template E The type of the step context.
6342
+ * @template Z The input ticket type.
6343
+ * @template E The output ticket type.
6344
+ * @template R The context type.
6203
6345
  * @returns A new step context.
6204
6346
  *
6205
6347
  * @see https://0.vuetifyjs.com/composables/selection/use-step
@@ -6232,6 +6374,9 @@ function createStepContext(_options = {}) {
6232
6374
  * Returns the current step instance.
6233
6375
  *
6234
6376
  * @param namespace The namespace for the step context. Defaults to `'v0:step'`.
6377
+ * @template Z The input ticket type.
6378
+ * @template E The output ticket type.
6379
+ * @template R The context type.
6235
6380
  * @returns The current step instance.
6236
6381
  *
6237
6382
  * @see https://0.vuetifyjs.com/composables/selection/use-step
@@ -7653,4 +7798,4 @@ function useClickOutside(target, handler, options = {}) {
7653
7798
  }
7654
7799
 
7655
7800
  //#endregion
7656
- export { useFilter as $, createContext as $t, PermissionAdapter as A, createHydrationPlugin as At, useMediaQuery as B, createSelectionContext as Bt, createQueue as C, createBreakpoints as Ct, createPermissionsContext as D, createFallbackHydration as Dt, createPermissions as E, useBreakpoints as Et, createOverflowContext as F, createGroupContext as Ft, useElementIntersection as G, createLoggerContext as Gt, usePrefersDark as H, createRegistry as Ht, useOverflow as I, useGroup as It, createForm as J, Vuetify0LoggerAdapter as Jt, useIntersectionObserver as K, createLoggerPlugin as Kt, useElementSize as L, toArray as Lt, createPaginationContext as M, toReactive as Mt, usePagination as N, useProxyModel as Nt, createPermissionsPlugin as O, createHydration as Ot, createOverflow as P, createGroup as Pt, createFilterContext as Q, createTrinity as Qt, useResizeObserver as R, useProxyRegistry as Rt, useStep as S, useSingle as St, useQueue as T, createBreakpointsPlugin as Tt, usePrefersReducedMotion as U, createRegistryContext as Ut, usePrefersContrast as V, useSelection as Vt, useLazy as W, createLogger as Wt, useForm as X, ConsolaLoggerAdapter as Xt, createFormContext as Y, PinoLoggerAdapter as Yt, createFilter as Z, createPlugin as Zt, createStoragePlugin as _, createTokens as _t, useVirtual as a, createDate as at, createStep as b, createSingle as bt, createTimelineContext as c, createDatePlugin as ct, createThemeContext as d, createLocale as dt, provideContext as en, useFilterContext as et, createThemePlugin as f, createLocaleContext as ft, createStorageContext as g, Vuetify0LocaleAdapter as gt, createStorage as h, useLocale as ht, useWindowEventListener as i, useFeatures as it, createPagination as j, useHydration as jt, usePermissions as k, createHydrationContext as kt, useTimeline as l, useDate as lt, Vuetify0ThemeAdapter as m, createLocalePlugin as mt, useDocumentEventListener as n, createFeaturesContext as nt, useToggleScope as o, createDateContext as ot, useTheme as p, createLocaleFallback as pt, useHotkey as q, useLogger as qt, useEventListener as r, createFeaturesPlugin as rt, createTimeline as s, createDateFallback as st, useClickOutside as t, useContext as tn, createFeatures as tt, createTheme as u, Vuetify0DateAdapter as ut, useStorage as v, createTokensContext as vt, createQueueContext as w, createBreakpointsContext as wt, createStepContext as x, createSingleContext as xt, MemoryAdapter as y, useTokens as yt, useMutationObserver as z, createSelection as zt };
7801
+ export { createForm as $, createLoggerPlugin as $t, PermissionAdapter as A, createBreakpoints as At, createNestedContext as B, useProxyModel as Bt, createQueue as C, Vuetify0LocaleAdapter as Ct, createPermissionsContext as D, createSingle as Dt, createPermissions as E, useTokens as Et, createOverflowContext as F, createHydration as Ft, useMediaQuery as G, useProxyRegistry as Gt, multipleOpenStrategy as H, createGroupContext as Ht, useOverflow as I, createHydrationContext as It, usePrefersReducedMotion as J, useSelection as Jt, usePrefersContrast as K, createSelection as Kt, useElementSize as L, createHydrationPlugin as Lt, createPaginationContext as M, createBreakpointsPlugin as Mt, usePagination as N, useBreakpoints as Nt, createPermissionsPlugin as O, createSingleContext as Ot, createOverflow as P, createFallbackHydration as Pt, useHotkey as Q, createLoggerContext as Qt, useResizeObserver as R, useHydration as Rt, useStep as S, useLocale as St, useQueue as T, createTokensContext as Tt, singleOpenStrategy as U, useGroup as Ut, useNested as V, createGroup as Vt, useMutationObserver as W, toArray as Wt, useElementIntersection as X, createRegistryContext as Xt, useLazy as Y, createRegistry as Yt, useIntersectionObserver as Z, createLogger as Zt, createStoragePlugin as _, useDate as _t, useVirtual as a, createTrinity as an, useFilterContext as at, createStep as b, createLocaleFallback as bt, createTimelineContext as c, useContext as cn, createFeaturesPlugin as ct, createThemeContext as d, LaunchDarklyFeatureAdapter as dt, useLogger as en, createFormContext as et, createThemePlugin as f, FlagsmithFeatureAdapter as ft, createStorageContext as g, createDatePlugin as gt, createStorage as h, createDateContext as ht, useWindowEventListener as i, createPlugin as in, useFilter as it, createPagination as j, createBreakpointsContext as jt, usePermissions as k, useSingle as kt, useTimeline as l, useFeatures as lt, Vuetify0ThemeAdapter as m, createDate as mt, useDocumentEventListener as n, PinoLoggerAdapter as nn, createFilter as nt, useToggleScope as o, createContext as on, createFeatures as ot, useTheme as p, FeaturesAdapter as pt, usePrefersDark as q, createSelectionContext as qt, useEventListener as r, ConsolaLoggerAdapter as rn, createFilterContext as rt, createTimeline as s, provideContext as sn, createFeaturesContext as st, useClickOutside as t, Vuetify0LoggerAdapter as tn, useForm as tt, createTheme as u, PostHogFeatureAdapter as ut, useStorage as v, createLocale as vt, createQueueContext as w, createTokens as wt, createStepContext as x, createLocalePlugin as xt, MemoryAdapter as y, createLocaleContext as yt, createNested as z, toReactive as zt };