@vuetify/v0 0.0.13 → 0.0.15

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.
@@ -1,4 +1,4 @@
1
- import { computed, createBlock, createCommentVNode, createPropsRestProxy, defineComponent, getCurrentInstance, getCurrentScope, guardReactiveProps, inject, isRef, mergeModels, mergeProps, normalizeProps, normalizeStyle, onMounted, onScopeDispose, onUnmounted, openBlock, provide, reactive, readonly, ref, renderSlot, resolveDynamicComponent, shallowReactive, shallowReadonly, shallowRef, toRef, toValue, unref, useAttrs, useId, useModel, useTemplateRef, vShow, watch, withCtx, withDirectives } from "vue";
1
+ import { computed, createBlock, createCommentVNode, createPropsRestProxy, createTextVNode, defineComponent, effectScope, getCurrentInstance, guardReactiveProps, inject, isRef, mergeModels, mergeProps, normalizeProps, normalizeStyle, onBeforeUnmount, onMounted, onScopeDispose, onUnmounted, openBlock, provide, reactive, readonly, ref, renderSlot, resolveDynamicComponent, shallowReactive, shallowReadonly, shallowRef, toDisplayString, toRef, toValue, unref, useAttrs, useId, useModel, useTemplateRef, vShow, watch, withCtx, withDirectives } from "vue";
2
2
 
3
3
  //#region src/constants/htmlElements.ts
4
4
  const selfClosingTags = [
@@ -119,6 +119,10 @@ function isPrimitive(item) {
119
119
  return typeof item === "string" || typeof item === "number" || typeof item === "boolean";
120
120
  }
121
121
  /* @__NO_SIDE_EFFECTS__ */
122
+ function isNaN(item) {
123
+ return /* @__PURE__ */ isNumber(item) && Number.isNaN(item);
124
+ }
125
+ /* @__NO_SIDE_EFFECTS__ */
122
126
  function mergeDeep(target, ...sources) {
123
127
  if (sources.length === 0) return target;
124
128
  const source = sources.shift();
@@ -137,10 +141,78 @@ function mergeDeep(target, ...sources) {
137
141
  function genId() {
138
142
  return Math.random().toString(36).slice(2, 9);
139
143
  }
144
+ /**
145
+ * Clamps a value between a minimum and maximum
146
+ *
147
+ * @param value The value to clamp
148
+ * @param min The minimum value (default: 0)
149
+ * @param max The maximum value (default: 1)
150
+ * @returns The clamped value
151
+ *
152
+ * @example
153
+ * ```ts
154
+ * clamp(5, 0, 10) // 5
155
+ * clamp(-5, 0, 10) // 0
156
+ * clamp(15, 0, 10) // 10
157
+ * ```
158
+ */
159
+ /* @__NO_SIDE_EFFECTS__ */
160
+ function clamp(value, min = 0, max = 1) {
161
+ return Math.max(min, Math.min(max, value));
162
+ }
163
+ /**
164
+ * Creates an array of sequential numbers
165
+ *
166
+ * @param length The length of the array to create
167
+ * @param start The starting index (default: 0)
168
+ * @returns An array of sequential numbers
169
+ *
170
+ * @example
171
+ * ```ts
172
+ * range(3) // [0, 1, 2]
173
+ * range(3, 1) // [1, 2, 3]
174
+ * range(5, 10) // [10, 11, 12, 13, 14]
175
+ * range(0) // []
176
+ * ```
177
+ */
178
+ /* @__NO_SIDE_EFFECTS__ */
179
+ function range(length, start = 0) {
180
+ return Array.from({ length }, (_, index) => start + index);
181
+ }
182
+ /**
183
+ * Debounces a function call by the specified delay
184
+ *
185
+ * @param fn The function to debounce
186
+ * @param delay The delay in milliseconds
187
+ * @returns A debounced function with clear and immediate methods
188
+ *
189
+ * @example
190
+ * ```ts
191
+ * const debouncedFn = debounce(() => console.log('called'), 500)
192
+ * debouncedFn() // Will call after 500ms
193
+ * debouncedFn.clear() // Cancel pending call
194
+ * debouncedFn.immediate() // Call immediately
195
+ * ```
196
+ */
197
+ function debounce(fn, delay) {
198
+ let timeoutId;
199
+ function debounced(...args) {
200
+ if (!/* @__PURE__ */ isUndefined(timeoutId)) clearTimeout(timeoutId);
201
+ timeoutId = setTimeout(() => fn(...args), delay);
202
+ }
203
+ debounced.clear = () => {
204
+ if (!/* @__PURE__ */ isUndefined(timeoutId)) clearTimeout(timeoutId);
205
+ };
206
+ debounced.immediate = (...args) => {
207
+ debounced.clear();
208
+ fn(...args);
209
+ };
210
+ return debounced;
211
+ }
140
212
 
141
213
  //#endregion
142
214
  //#region src/components/Atom/Atom.vue
143
- const _sfc_main$18 = /* @__PURE__ */ defineComponent({
215
+ const _sfc_main$25 = /* @__PURE__ */ defineComponent({
144
216
  name: "Atom",
145
217
  __name: "Atom",
146
218
  props: {
@@ -171,7 +243,7 @@ const _sfc_main$18 = /* @__PURE__ */ defineComponent({
171
243
  };
172
244
  }
173
245
  });
174
- var Atom_default = _sfc_main$18;
246
+ var Atom_default = _sfc_main$25;
175
247
 
176
248
  //#endregion
177
249
  //#region src/composables/createContext/index.ts
@@ -210,7 +282,7 @@ var Atom_default = _sfc_main$18;
210
282
  */
211
283
  function useContext(key, defaultValue) {
212
284
  const context = inject(key, defaultValue);
213
- if (context === void 0) throw new Error(`Context "${String(key)}" not found. Ensure it's provided by an ancestor.`);
285
+ if (/* @__PURE__ */ isUndefined(context)) throw new Error(`Context "${String(key)}" not found. Ensure it's provided by an ancestor.`);
214
286
  return context;
215
287
  }
216
288
  /**
@@ -528,6 +600,95 @@ function toReactive(objectRef) {
528
600
  }));
529
601
  }
530
602
 
603
+ //#endregion
604
+ //#region src/composables/useEventListener/index.ts
605
+ /**
606
+ * @module useEventListener
607
+ *
608
+ * @remarks
609
+ * Event listener composable with automatic cleanup on scope disposal.
610
+ *
611
+ * Key features:
612
+ * - Supports Window, Document, and HTMLElement targets
613
+ * - Reactive targets, events, and listeners
614
+ * - Event options support (capture, passive, once)
615
+ * - Automatic removeEventListener on unmount
616
+ * - Multiple overloads for type safety
617
+ *
618
+ * Perfect for safely managing event listeners in Vue components.
619
+ */
620
+ /**
621
+ * Attaches an event listener to a target.
622
+ *
623
+ * @param target The target to attach the event listener to.
624
+ * @param event The event to listen for.
625
+ * @param listener The event listener.
626
+ * @param options The event listener options.
627
+ * @returns A function to remove the event listener.
628
+ *
629
+ * @see https://0.vuetifyjs.com/composables/system/use-event-listener
630
+ */
631
+ function useEventListener(target, event, listener, options) {
632
+ const cleanups = [];
633
+ function cleanup() {
634
+ for (const fn of cleanups) fn();
635
+ cleanups.length = 0;
636
+ }
637
+ function register(el, event$1, listener$1, options$1) {
638
+ el.addEventListener(event$1, listener$1, options$1);
639
+ return () => el.removeEventListener(event$1, listener$1, options$1);
640
+ }
641
+ const stopWatcher = watch(() => [
642
+ toValue(target),
643
+ toValue(event),
644
+ unref(listener),
645
+ toValue(options)
646
+ ], ([el, events, listeners, opts]) => {
647
+ cleanup();
648
+ if (!el) return;
649
+ const eventList = toArray(events);
650
+ const listenerList = toArray(listeners);
651
+ for (const event$1 of eventList) for (const listenerFn of listenerList) cleanups.push(register(el, event$1, listenerFn, opts));
652
+ }, {
653
+ immediate: true,
654
+ flush: "post"
655
+ });
656
+ function stop() {
657
+ stopWatcher();
658
+ cleanup();
659
+ }
660
+ onScopeDispose(stop, true);
661
+ return stop;
662
+ }
663
+ /**
664
+ * Attaches an event listener to the window.
665
+ *
666
+ * @param event The event to listen for.
667
+ * @param listener The event listener.
668
+ * @param options The event listener options.
669
+ * @template E The event type.
670
+ * @returns A function to remove the event listener.
671
+ *
672
+ * @see https://0.vuetifyjs.com/composables/system/use-event-listener
673
+ */
674
+ function useWindowEventListener(event, listener, options) {
675
+ return useEventListener(window, event, listener, options);
676
+ }
677
+ /**
678
+ * Attaches an event listener to the document.
679
+ *
680
+ * @param event The event to listen for.
681
+ * @param listener The event listener.
682
+ * @param options The event listener options.
683
+ * @template E The event type.
684
+ * @returns A function to remove the event listener.
685
+ *
686
+ * @see https://0.vuetifyjs.com/composables/system/use-event-listener
687
+ */
688
+ function useDocumentEventListener(event, listener, options) {
689
+ return useEventListener(document, event, listener, options);
690
+ }
691
+
531
692
  //#endregion
532
693
  //#region src/composables/useHydration/index.ts
533
694
  /**
@@ -574,6 +735,12 @@ function createHydration() {
574
735
  hydrate
575
736
  };
576
737
  }
738
+ function createFallbackHydration() {
739
+ return {
740
+ isHydrated: shallowReadonly(shallowRef(true)),
741
+ hydrate: () => {}
742
+ };
743
+ }
577
744
  /**
578
745
  * Creates a new hydration context trinity.
579
746
  *
@@ -666,7 +833,13 @@ function createHydrationPlugin(_options = {}) {
666
833
  * ```
667
834
  */
668
835
  function useHydration(namespace = "v0:hydration") {
669
- return useContext(namespace);
836
+ const fallback = createFallbackHydration();
837
+ if (!getCurrentInstance()) return fallback;
838
+ try {
839
+ return useContext(namespace, fallback);
840
+ } catch {
841
+ return fallback;
842
+ }
670
843
  }
671
844
 
672
845
  //#endregion
@@ -677,7 +850,7 @@ const SUPPORTS_MATCH_MEDIA = IN_BROWSER && "matchMedia" in window && typeof wind
677
850
  const SUPPORTS_OBSERVER = IN_BROWSER && "ResizeObserver" in window;
678
851
  const SUPPORTS_INTERSECTION_OBSERVER = IN_BROWSER && "IntersectionObserver" in window;
679
852
  const SUPPORTS_MUTATION_OBSERVER = IN_BROWSER && "MutationObserver" in window;
680
- const version = "0.0.13";
853
+ const version = "0.0.15";
681
854
  const __LOGGER_ENABLED__ = false;
682
855
 
683
856
  //#endregion
@@ -908,9 +1081,9 @@ function createBreakpointsPlugin(_options = {}) {
908
1081
  const unwatch = watch(hydration.isHydrated, (hydrated) => {
909
1082
  if (hydrated) listener();
910
1083
  }, { immediate: true });
911
- window.addEventListener("resize", listener, { passive: true });
1084
+ const cleanup = useWindowEventListener("resize", listener, { passive: true });
912
1085
  onScopeDispose(() => {
913
- window.removeEventListener("resize", listener);
1086
+ cleanup();
914
1087
  unwatch();
915
1088
  }, true);
916
1089
  } });
@@ -945,95 +1118,6 @@ function useBreakpoints(namespace = "v0:breakpoints") {
945
1118
  return useContext(namespace);
946
1119
  }
947
1120
 
948
- //#endregion
949
- //#region src/composables/useEventListener/index.ts
950
- /**
951
- * @module useEventListener
952
- *
953
- * @remarks
954
- * Event listener composable with automatic cleanup on scope disposal.
955
- *
956
- * Key features:
957
- * - Supports Window, Document, and HTMLElement targets
958
- * - Reactive targets, events, and listeners
959
- * - Event options support (capture, passive, once)
960
- * - Automatic removeEventListener on unmount
961
- * - Multiple overloads for type safety
962
- *
963
- * Perfect for safely managing event listeners in Vue components.
964
- */
965
- /**
966
- * Attaches an event listener to a target.
967
- *
968
- * @param target The target to attach the event listener to.
969
- * @param event The event to listen for.
970
- * @param listener The event listener.
971
- * @param options The event listener options.
972
- * @returns A function to remove the event listener.
973
- *
974
- * @see https://0.vuetifyjs.com/composables/system/use-event-listener
975
- */
976
- function useEventListener(target, event, listener, options) {
977
- const cleanups = [];
978
- function cleanup() {
979
- for (const fn of cleanups) fn();
980
- cleanups.length = 0;
981
- }
982
- function register(el, event$1, listener$1, options$1) {
983
- el.addEventListener(event$1, listener$1, options$1);
984
- return () => el.removeEventListener(event$1, listener$1, options$1);
985
- }
986
- const stopWatcher = watch(() => [
987
- toValue(target),
988
- toValue(event),
989
- unref(listener),
990
- toValue(options)
991
- ], ([el, events, listeners, opts]) => {
992
- cleanup();
993
- if (!el) return;
994
- const eventList = toArray(events);
995
- const listenerList = toArray(listeners);
996
- for (const event$1 of eventList) for (const listenerFn of listenerList) cleanups.push(register(el, event$1, listenerFn, opts));
997
- }, {
998
- immediate: true,
999
- flush: "post"
1000
- });
1001
- function stop() {
1002
- stopWatcher();
1003
- cleanup();
1004
- }
1005
- onScopeDispose(stop, true);
1006
- return stop;
1007
- }
1008
- /**
1009
- * Attaches an event listener to the window.
1010
- *
1011
- * @param event The event to listen for.
1012
- * @param listener The event listener.
1013
- * @param options The event listener options.
1014
- * @template E The event type.
1015
- * @returns A function to remove the event listener.
1016
- *
1017
- * @see https://0.vuetifyjs.com/composables/system/use-event-listener
1018
- */
1019
- function useWindowEventListener(event, listener, options) {
1020
- return useEventListener(window, event, listener, options);
1021
- }
1022
- /**
1023
- * Attaches an event listener to the document.
1024
- *
1025
- * @param event The event to listen for.
1026
- * @param listener The event listener.
1027
- * @param options The event listener options.
1028
- * @template E The event type.
1029
- * @returns A function to remove the event listener.
1030
- *
1031
- * @see https://0.vuetifyjs.com/composables/system/use-event-listener
1032
- */
1033
- function useDocumentEventListener(event, listener, options) {
1034
- return useEventListener(document, event, listener, options);
1035
- }
1036
-
1037
1121
  //#endregion
1038
1122
  //#region src/composables/useLogger/adapters/consola.ts
1039
1123
  var ConsolaLoggerAdapter = class {
@@ -1454,6 +1538,9 @@ function useRegistry(options) {
1454
1538
  const cache = /* @__PURE__ */ new Map();
1455
1539
  const listeners = /* @__PURE__ */ new Map();
1456
1540
  const events = options?.events ?? false;
1541
+ let indexDependentCount = 0;
1542
+ let needsReindex = false;
1543
+ let minDirtyIndex = Infinity;
1457
1544
  function emit(event, data = void 0) {
1458
1545
  if (!events) return;
1459
1546
  const cbs = listeners.get(event);
@@ -1488,13 +1575,15 @@ function useRegistry(options) {
1488
1575
  let value = existing.value;
1489
1576
  let valueIsIndex = existing.valueIsIndex;
1490
1577
  if (hasValue) {
1491
- if (patch.value === void 0) {
1578
+ if (/* @__PURE__ */ isUndefined(patch.value)) {
1492
1579
  value = existing.index;
1493
1580
  valueIsIndex = true;
1494
1581
  } else {
1495
1582
  value = patch.value;
1496
1583
  valueIsIndex = false;
1497
1584
  }
1585
+ if (valueIsIndex !== existing.valueIsIndex) if (valueIsIndex) indexDependentCount++;
1586
+ else indexDependentCount--;
1498
1587
  if (!Object.is(value, existing.value)) {
1499
1588
  unassign(existing.value, id);
1500
1589
  assign(value, id);
@@ -1514,9 +1603,11 @@ function useRegistry(options) {
1514
1603
  return updated;
1515
1604
  }
1516
1605
  function browse(value) {
1606
+ if (indexDependentCount > 0 && needsReindex) reindex();
1517
1607
  return catalog.get(value);
1518
1608
  }
1519
1609
  function lookup(index) {
1610
+ if (needsReindex) reindex();
1520
1611
  return directory.get(index);
1521
1612
  }
1522
1613
  function has(id) {
@@ -1566,25 +1657,39 @@ function useRegistry(options) {
1566
1657
  if (catalog.size > 0) catalog.clear();
1567
1658
  if (directory.size > 0) directory.clear();
1568
1659
  invalidate();
1660
+ indexDependentCount = 0;
1661
+ needsReindex = false;
1662
+ minDirtyIndex = Infinity;
1569
1663
  emit("clear:registry");
1570
1664
  }
1571
1665
  function invalidate() {
1572
1666
  if (cache.size > 0) cache.clear();
1573
1667
  }
1574
1668
  function reindex() {
1575
- if (catalog.size > 0) catalog.clear();
1576
- if (directory.size > 0) directory.clear();
1669
+ const startIndex = minDirtyIndex === Infinity ? 0 : minDirtyIndex;
1670
+ if (startIndex === 0) {
1671
+ if (catalog.size > 0) catalog.clear();
1672
+ if (directory.size > 0) directory.clear();
1673
+ }
1577
1674
  invalidate();
1578
1675
  let index = 0;
1579
- for (const ticket of values()) {
1580
- if (ticket.index !== index) {
1581
- ticket.index = index;
1582
- if (ticket.valueIsIndex) ticket.value = index;
1676
+ for (const ticket of collection.values()) {
1677
+ if (index < startIndex) {
1678
+ index++;
1679
+ continue;
1583
1680
  }
1681
+ if (startIndex > 0) directory.delete(ticket.index);
1682
+ if (ticket.valueIsIndex) {
1683
+ if (startIndex > 0) unassign(ticket.value, ticket.id);
1684
+ ticket.value = index;
1685
+ assign(ticket.value, ticket.id);
1686
+ } else if (startIndex === 0) assign(ticket.value, ticket.id);
1687
+ ticket.index = index;
1584
1688
  directory.set(index, ticket.id);
1585
- assign(ticket.value, ticket.id);
1586
1689
  index++;
1587
1690
  }
1691
+ needsReindex = false;
1692
+ minDirtyIndex = Infinity;
1588
1693
  emit("reindex:registry");
1589
1694
  }
1590
1695
  function register(registration = {}) {
@@ -1598,6 +1703,7 @@ function useRegistry(options) {
1598
1703
  const index = registration.index ?? size;
1599
1704
  const value = valueIsUndefined ? index : registration.value;
1600
1705
  const valueIsIndex = valueIsUndefined;
1706
+ if (valueIsIndex) indexDependentCount++;
1601
1707
  const ticket = {
1602
1708
  ...registration,
1603
1709
  id,
@@ -1615,15 +1721,40 @@ function useRegistry(options) {
1615
1721
  function unregister(id) {
1616
1722
  const ticket = collection.get(id);
1617
1723
  if (!ticket) return;
1724
+ if (ticket.valueIsIndex) indexDependentCount--;
1618
1725
  collection.delete(ticket.id);
1619
1726
  directory.delete(ticket.index);
1620
1727
  unassign(ticket.value, ticket.id);
1621
1728
  invalidate();
1622
1729
  emit("unregister:ticket", ticket);
1623
- reindex();
1730
+ if (indexDependentCount > 0 && ticket.index < collection.size) {
1731
+ minDirtyIndex = Math.min(minDirtyIndex, ticket.index);
1732
+ reindex();
1733
+ } else {
1734
+ minDirtyIndex = Math.min(minDirtyIndex, ticket.index);
1735
+ needsReindex = true;
1736
+ }
1737
+ }
1738
+ function offboard(ids) {
1739
+ const removed = [];
1740
+ for (const id of ids) {
1741
+ const ticket = collection.get(id);
1742
+ if (!ticket) continue;
1743
+ if (ticket.valueIsIndex) indexDependentCount--;
1744
+ minDirtyIndex = Math.min(minDirtyIndex, ticket.index);
1745
+ collection.delete(ticket.id);
1746
+ directory.delete(ticket.index);
1747
+ unassign(ticket.value, ticket.id);
1748
+ removed.push(ticket);
1749
+ }
1750
+ if (removed.length === 0) return;
1751
+ invalidate();
1752
+ if (events) for (const ticket of removed) emit("unregister:ticket", ticket);
1753
+ needsReindex = true;
1624
1754
  }
1625
1755
  function seek(direction = "first", from, predicate) {
1626
1756
  if (collection.size === 0) return void 0;
1757
+ if (needsReindex) reindex();
1627
1758
  const tickets = values();
1628
1759
  const index = /* @__PURE__ */ isUndefined(from) ? void 0 : Math.max(0, Math.min(from, tickets.length - 1));
1629
1760
  if (direction === "last") {
@@ -1660,8 +1791,9 @@ function useRegistry(options) {
1660
1791
  reindex,
1661
1792
  seek,
1662
1793
  onboard(registrations) {
1663
- return registrations.map((registration) => this.register(registration));
1794
+ return registrations.map((registration) => register(registration));
1664
1795
  },
1796
+ offboard,
1665
1797
  get size() {
1666
1798
  return collection.size;
1667
1799
  }
@@ -1682,7 +1814,11 @@ function useRegistry(options) {
1682
1814
  * ```ts
1683
1815
  * import { createRegistryContext } from '@vuetify/v0'
1684
1816
  *
1685
- * export const [useItems, provideItems, items] = createRegistryContext('items')
1817
+ * // With default namespace 'v0:registry'
1818
+ * export const [useItems, provideItems, items] = createRegistryContext()
1819
+ *
1820
+ * // Or with custom namespace
1821
+ * export const [useItems, provideItems, items] = createRegistryContext({ namespace: 'my-items' })
1686
1822
  *
1687
1823
  * // In a parent component:
1688
1824
  * provideItems()
@@ -1692,8 +1828,8 @@ function useRegistry(options) {
1692
1828
  * items.register({ id: 'item-1', value: 'Value 1' })
1693
1829
  * ```
1694
1830
  */
1695
- function createRegistryContext(_options) {
1696
- const { namespace,...options } = _options;
1831
+ function createRegistryContext(_options = {}) {
1832
+ const { namespace = "v0:registry",...options } = _options;
1697
1833
  const [useRegistryContext, _provideRegistryContext] = createContext(namespace);
1698
1834
  const context = useRegistry(options);
1699
1835
  function provideRegistryContext(_context = context, app) {
@@ -1804,12 +1940,12 @@ function createSelection(_options = {}) {
1804
1940
  const id = registration.id ?? /* @__PURE__ */ genId();
1805
1941
  const item = {
1806
1942
  disabled: false,
1807
- ...registration,
1808
- id,
1809
- isSelected: toRef(() => selected(id)),
1810
1943
  select: () => select(id),
1811
1944
  unselect: () => unselect(id),
1812
- toggle: () => toggle(id)
1945
+ toggle: () => toggle(id),
1946
+ isSelected: toRef(() => selected(id)),
1947
+ ...registration,
1948
+ id
1813
1949
  };
1814
1950
  const ticket = registry.register(item);
1815
1951
  if (enroll && !toValue(item.disabled)) selectedIds.add(ticket.id);
@@ -1820,6 +1956,13 @@ function createSelection(_options = {}) {
1820
1956
  selectedIds.delete(id);
1821
1957
  registry.unregister(id);
1822
1958
  }
1959
+ function offboard(ids) {
1960
+ for (const id of ids) selectedIds.delete(id);
1961
+ registry.offboard(ids);
1962
+ }
1963
+ function onboard(registrations) {
1964
+ return registrations.map((registration) => register(registration));
1965
+ }
1823
1966
  function reset() {
1824
1967
  registry.clear();
1825
1968
  selectedIds.clear();
@@ -1833,6 +1976,8 @@ function createSelection(_options = {}) {
1833
1976
  selectedValues,
1834
1977
  register,
1835
1978
  unregister,
1979
+ onboard,
1980
+ offboard,
1836
1981
  reset,
1837
1982
  mandate,
1838
1983
  seek,
@@ -1848,7 +1993,6 @@ function createSelection(_options = {}) {
1848
1993
  /**
1849
1994
  * Creates a new selection context.
1850
1995
  *
1851
- * @param namespace The namespace for the selection context.
1852
1996
  * @param options The options for the selection context.
1853
1997
  * @template Z The type of the selection ticket.
1854
1998
  * @template E The type of the selection context.
@@ -1860,7 +2004,11 @@ function createSelection(_options = {}) {
1860
2004
  * ```ts
1861
2005
  * import { createSelectionContext } from '@vuetify/v0'
1862
2006
  *
1863
- * export const [useCheckboxes, provideCheckboxes, checkboxes] = createSelectionContext('checkboxes')
2007
+ * // With default namespace 'v0:selection'
2008
+ * export const [useCheckboxes, provideCheckboxes, checkboxes] = createSelectionContext()
2009
+ *
2010
+ * // Or with custom namespace
2011
+ * export const [useCheckboxes, provideCheckboxes, checkboxes] = createSelectionContext({ namespace: 'checkboxes' })
1864
2012
  *
1865
2013
  * // In a parent component:
1866
2014
  * provideCheckboxes()
@@ -1870,8 +2018,8 @@ function createSelection(_options = {}) {
1870
2018
  * checkboxes.select('checkbox-1')
1871
2019
  * ```
1872
2020
  */
1873
- function createSelectionContext(_options) {
1874
- const { namespace,...options } = _options;
2021
+ function createSelectionContext(_options = {}) {
2022
+ const { namespace = "v0:selection",...options } = _options;
1875
2023
  const [useSelectionContext, _provideSelectionContext] = createContext(namespace);
1876
2024
  const context = createSelection(options);
1877
2025
  function provideSelectionContext(_context = context, app) {
@@ -1907,31 +2055,102 @@ function useSelection(namespace = "v0:selection") {
1907
2055
  }
1908
2056
 
1909
2057
  //#endregion
1910
- //#region src/composables/useGroup/index.ts
2058
+ //#region src/composables/useProxyRegistry/index.ts
1911
2059
  /**
1912
- * @module useGroup
2060
+ * @module useProxyRegistry
1913
2061
  *
1914
2062
  * @remarks
1915
- * Multi-selection composable that extends useSelection with batch operation support.
2063
+ * Proxy composable for reactive registry keys, values, entries, and size.
1916
2064
  *
1917
2065
  * Key features:
1918
- * - Batch operations (select/unselect/toggle accept ID | ID[])
1919
- * - selectedIndexes computed Set for position-based tracking
1920
- * - Perfect for checkboxes, multi-select dropdowns, filter panels
2066
+ * - Reactive proxy for registry data
2067
+ * - Deep or shallow reactivity options
2068
+ * - Event-based updates
2069
+ * - Automatic cleanup on scope disposal
2070
+ * - Transforms Map-based registry into reactive refs
1921
2071
  *
1922
- * Inheritance chain: useRegistry useSelection useGroup
1923
- * Extended by: useFeatures
2072
+ * Perfect for exposing registry data as reactive computed properties.
1924
2073
  */
1925
2074
  /**
1926
- * Creates a new group instance with batch selection operations.
2075
+ * Creates a proxy registry that provides reactive objects for registry data.
2076
+ *
2077
+ * @param registry The registry instance to proxy.
2078
+ * @param options The options for the proxy registry.
2079
+ * @template Z The type of the registry ticket.
2080
+ * @returns A proxy registry with reactive objects.
2081
+ *
2082
+ * @see https://0.vuetifyjs.com/composables/registration/use-proxy-registry
2083
+ *
2084
+ * @example
2085
+ * ```ts
2086
+ * import { useRegistry, useProxyRegistry } from '@vuetify/v0'
2087
+ *
2088
+ * const registry = useRegistry({ events: true })
2089
+ * const proxy = useProxyRegistry(registry)
2090
+ *
2091
+ * registry.register({ value: 'Item 1' })
2092
+ * console.log(proxy.size) // 1
2093
+ * ```
2094
+ */
2095
+ function useProxyRegistry(registry, options) {
2096
+ const state = (options?.deep ? reactive : shallowReactive)({
2097
+ keys: registry.keys(),
2098
+ values: registry.values(),
2099
+ entries: registry.entries(),
2100
+ size: registry.size
2101
+ });
2102
+ function update() {
2103
+ state.keys = registry.keys();
2104
+ state.values = registry.values();
2105
+ state.entries = registry.entries();
2106
+ state.size = registry.size;
2107
+ }
2108
+ registry.on("register:ticket", update);
2109
+ registry.on("unregister:ticket", update);
2110
+ registry.on("update:ticket", update);
2111
+ registry.on("clear:registry", update);
2112
+ onScopeDispose(() => {
2113
+ registry.off("register:ticket", update);
2114
+ registry.off("unregister:ticket", update);
2115
+ registry.off("update:ticket", update);
2116
+ registry.off("clear:registry", update);
2117
+ }, true);
2118
+ return state;
2119
+ }
2120
+
2121
+ //#endregion
2122
+ //#region src/composables/useGroup/index.ts
2123
+ /**
2124
+ * @module useGroup
2125
+ *
2126
+ * @remarks
2127
+ * Multi-selection composable that extends useSelection with batch operations and tri-state support.
2128
+ *
2129
+ * Key features:
2130
+ * - Batch operations (select/unselect/toggle accept ID | ID[])
2131
+ * - Tri-state support via mixed/indeterminate state (mix/unmix)
2132
+ * - selectedIndexes computed Set for position-based tracking
2133
+ * - Perfect for checkbox trees, multi-select dropdowns, filter panels
2134
+ *
2135
+ * Tri-state behavior:
2136
+ * - Items can be selected, mixed (indeterminate), or unselected
2137
+ * - select() clears mixed state, mix() clears selected state (mutually exclusive)
2138
+ * - toggle() on a mixed item selects it (resolves positively)
2139
+ *
2140
+ * Inheritance chain: useRegistry → useSelection → useGroup
2141
+ * Extended by: useFeatures
2142
+ */
2143
+ /**
2144
+ * Creates a new group instance with batch selection and tri-state support.
1927
2145
  *
1928
2146
  * Extends `createSelection` to support selecting, unselecting, and toggling multiple items
1929
- * at once by passing an array of IDs. Adds `selectedIndexes` computed property.
2147
+ * at once by passing an array of IDs. Adds tri-state (mixed/indeterminate) support for
2148
+ * checkbox trees and similar use cases.
1930
2149
  *
1931
2150
  * @param options The options for the group instance.
1932
2151
  * @template Z The type of the group ticket.
1933
2152
  * @template E The type of the group context.
1934
- * @returns A new group instance with batch selection support.
2153
+ * @returns A new group instance with batch selection and tri-state support.
1935
2154
  *
1936
2155
  * @remarks
1937
2156
  * **Key Differences from `createSelection`:**
@@ -1939,13 +2158,22 @@ function useSelection(namespace = "v0:selection") {
1939
2158
  * - `unselect()` accepts `ID | ID[]` for batch operations
1940
2159
  * - `toggle()` accepts `ID | ID[]` for batch operations
1941
2160
  * - Adds `selectedIndexes` computed Set for getting selected item indexes
1942
- * - Perfect for checkboxes, multi-select dropdowns, and bulk operations
2161
+ * - Adds tri-state support via `mix()`, `unmix()`, `mixed()`, `mixedIds`, `mixedItems`
2162
+ * - Perfect for checkbox trees, multi-select dropdowns, and bulk operations
2163
+ *
2164
+ * **Tri-State Support:**
2165
+ * - Items can be in one of three states: selected, mixed (indeterminate), or unselected
2166
+ * - `mix(id)` sets item to mixed state (clears selected if set)
2167
+ * - `unmix(id)` clears mixed state
2168
+ * - `select(id)` clears mixed state before selecting
2169
+ * - `toggle(id)` on a mixed item selects it (resolves the indeterminate state positively)
2170
+ * - Mixed state works on disabled items (it's a computed state, not user action)
1943
2171
  *
1944
2172
  * **Batch Operations:**
1945
2173
  * - Single ID: `group.select('item-1')`
1946
2174
  * - Array of IDs: `group.select(['item-1', 'item-2', 'item-3'])`
1947
2175
  * - Uses `toArray()` utility internally to normalize input
1948
- * - Disabled items are automatically skipped in batch operations
2176
+ * - Disabled items are automatically skipped in select operations
1949
2177
  * - Non-existent IDs are silently ignored
1950
2178
  *
1951
2179
  * **Inheritance Chain:**
@@ -1974,45 +2202,148 @@ function useSelection(namespace = "v0:selection") {
1974
2202
  * console.log(checkboxes.selectedIds) // Set { 'option-a', 'option-c' }
1975
2203
  * console.log(Array.from(checkboxes.selectedIndexes.value)) // [0, 2]
1976
2204
  *
1977
- * // Toggle operations
1978
- * checkboxes.toggle(['option-a', 'option-b'])
1979
- * console.log(checkboxes.selectedIds) // Set { 'option-b', 'option-c' }
2205
+ * // Set item to mixed/indeterminate state
2206
+ * checkboxes.mix('option-a')
2207
+ * console.log(checkboxes.mixedIds) // Set { 'option-a' }
2208
+ * console.log(checkboxes.selectedIds) // Set { 'option-c' } (option-a removed)
2209
+ *
2210
+ * // Toggle a mixed item selects it
2211
+ * checkboxes.toggle('option-a')
2212
+ * console.log(checkboxes.selectedIds) // Set { 'option-a', 'option-c' }
2213
+ * console.log(checkboxes.mixedIds) // Set {} (cleared)
1980
2214
  * ```
1981
2215
  */
1982
2216
  function createGroup(_options = {}) {
1983
2217
  const { mandatory = false, multiple = true,...options } = _options;
1984
- const registry = createSelection({
2218
+ const selection = createSelection({
1985
2219
  ...options,
1986
2220
  mandatory,
1987
- multiple
2221
+ multiple,
2222
+ events: true
1988
2223
  });
2224
+ const proxy = useProxyRegistry(selection);
2225
+ const mixedIds = shallowReactive(/* @__PURE__ */ new Set());
1989
2226
  const selectedIndexes = computed(() => {
1990
- return new Set(Array.from(registry.selectedItems.value).map((item) => item?.index));
2227
+ return new Set(Array.from(selection.selectedItems.value).map((item) => item?.index));
2228
+ });
2229
+ const mixedItems = computed(() => {
2230
+ return new Set(Array.from(mixedIds).map((id) => selection.get(id)));
1991
2231
  });
2232
+ function mixed(id) {
2233
+ return mixedIds.has(id);
2234
+ }
2235
+ function mix(ids) {
2236
+ for (const id of toArray(ids)) {
2237
+ if (!selection.has(id)) continue;
2238
+ selection.selectedIds.delete(id);
2239
+ mixedIds.add(id);
2240
+ }
2241
+ }
2242
+ function unmix(ids) {
2243
+ for (const id of toArray(ids)) mixedIds.delete(id);
2244
+ }
1992
2245
  function select(ids) {
1993
- for (const id of toArray(ids)) registry.select(id);
2246
+ for (const id of toArray(ids)) {
2247
+ mixedIds.delete(id);
2248
+ selection.select(id);
2249
+ }
1994
2250
  }
1995
2251
  function unselect(ids) {
1996
- for (const id of toArray(ids)) registry.unselect(id);
2252
+ for (const id of toArray(ids)) selection.unselect(id);
1997
2253
  }
1998
2254
  function toggle(ids) {
1999
- for (const id of toArray(ids)) registry.toggle(id);
2255
+ for (const id of toArray(ids)) if (mixed(id)) select(id);
2256
+ else selection.toggle(id);
2257
+ }
2258
+ function register(registration = {}) {
2259
+ const id = registration.id ?? /* @__PURE__ */ genId();
2260
+ const item = {
2261
+ ...registration,
2262
+ id,
2263
+ isMixed: toRef(() => mixed(id)),
2264
+ select: () => select(id),
2265
+ unselect: () => unselect(id),
2266
+ toggle: () => toggle(id),
2267
+ mix: () => mix(id),
2268
+ unmix: () => unmix(id)
2269
+ };
2270
+ const ticket = selection.register(item);
2271
+ if (toValue(registration.indeterminate)) mix(id);
2272
+ return ticket;
2273
+ }
2274
+ function unregister(id) {
2275
+ mixedIds.delete(id);
2276
+ selection.unregister(id);
2277
+ }
2278
+ function offboard(ids) {
2279
+ for (const id of ids) mixedIds.delete(id);
2280
+ selection.offboard(ids);
2281
+ }
2282
+ function onboard(registrations) {
2283
+ return registrations.map((registration) => register(registration));
2284
+ }
2285
+ function reset() {
2286
+ mixedIds.clear();
2287
+ selection.reset();
2288
+ }
2289
+ const selectableItems = computed(() => {
2290
+ return proxy.values.filter((item) => !toValue(item.disabled));
2291
+ });
2292
+ const isAllSelected = computed(() => {
2293
+ const items = selectableItems.value;
2294
+ if (items.length === 0) return false;
2295
+ return items.every((item) => selection.selectedIds.has(item.id));
2296
+ });
2297
+ const isMixed = toRef(() => {
2298
+ return mixedIds.size > 0 || !isNoneSelected.value && !isAllSelected.value;
2299
+ });
2300
+ const isNoneSelected = toRef(() => selection.selectedIds.size === 0);
2301
+ function selectAll() {
2302
+ for (const item of selectableItems.value) {
2303
+ mixedIds.delete(item.id);
2304
+ selection.select(item.id);
2305
+ }
2306
+ }
2307
+ function unselectAll() {
2308
+ const first = selection.selectedIds.values().next().value;
2309
+ selection.selectedIds.clear();
2310
+ if (!mandatory || !first) return;
2311
+ selection.select(first);
2312
+ }
2313
+ function toggleAll() {
2314
+ if (isAllSelected.value) unselectAll();
2315
+ else selectAll();
2000
2316
  }
2001
2317
  return {
2002
- ...registry,
2318
+ ...selection,
2319
+ mixed,
2320
+ mix,
2321
+ unmix,
2003
2322
  select,
2004
2323
  unselect,
2005
2324
  toggle,
2325
+ register,
2326
+ unregister,
2327
+ offboard,
2328
+ onboard,
2329
+ reset,
2330
+ selectAll,
2331
+ unselectAll,
2332
+ toggleAll,
2333
+ mixedIds,
2334
+ mixedItems,
2006
2335
  selectedIndexes,
2336
+ isNoneSelected,
2337
+ isAllSelected,
2338
+ isMixed,
2007
2339
  get size() {
2008
- return registry.size;
2340
+ return selection.size;
2009
2341
  }
2010
2342
  };
2011
2343
  }
2012
2344
  /**
2013
2345
  * Creates a new group context.
2014
2346
  *
2015
- * @param namespace The namespace for the group context.
2016
2347
  * @param options The options for the group context.
2017
2348
  * @template Z The type of the group ticket.
2018
2349
  * @template E The type of the group context.
@@ -2024,7 +2355,11 @@ function createGroup(_options = {}) {
2024
2355
  * ```ts
2025
2356
  * import { createGroupContext } from '@vuetify/v0'
2026
2357
  *
2027
- * export const [useMyGroup, provideMyGroup, myGroup] = createGroupContext('my-group')
2358
+ * // With default namespace 'v0:group'
2359
+ * export const [useMyGroup, provideMyGroup, myGroup] = createGroupContext()
2360
+ *
2361
+ * // Or with custom namespace
2362
+ * export const [useMyGroup, provideMyGroup, myGroup] = createGroupContext({ namespace: 'my-group' })
2028
2363
  *
2029
2364
  * // In a parent component:
2030
2365
  * provideMyGroup()
@@ -2033,8 +2368,8 @@ function createGroup(_options = {}) {
2033
2368
  * const group = useMyGroup()
2034
2369
  * ```
2035
2370
  */
2036
- function createGroupContext(_options) {
2037
- const { namespace,...options } = _options;
2371
+ function createGroupContext(_options = {}) {
2372
+ const { namespace = "v0:group",...options } = _options;
2038
2373
  const [useGroupContext, _provideGroupContext] = createContext(namespace);
2039
2374
  const context = createGroup(options);
2040
2375
  function provideGroupContext(_context = context, app) {
@@ -2065,7 +2400,7 @@ function createGroupContext(_options) {
2065
2400
  * </template>
2066
2401
  * ```
2067
2402
  */
2068
- function useGroup(namespace) {
2403
+ function useGroup(namespace = "v0:group") {
2069
2404
  return useContext(namespace);
2070
2405
  }
2071
2406
 
@@ -2129,9 +2464,10 @@ function createTokens(tokens = {}, options = {}) {
2129
2464
  function resolve(token, visited = /* @__PURE__ */ new Set()) {
2130
2465
  const cacheKey = /* @__PURE__ */ isString(token) ? token : JSON.stringify(token);
2131
2466
  const cached = cache.get(cacheKey);
2132
- if (cached !== void 0) return cached;
2467
+ if (!/* @__PURE__ */ isUndefined(cached)) return cached;
2133
2468
  const reference = isTokenAlias(token) ? token.$value : token;
2134
- const clean = /* @__PURE__ */ isString(reference) && isAlias(reference) ? reference.slice(1, -1) : String(reference);
2469
+ const isAliasReference = /* @__PURE__ */ isString(reference) && isAlias(reference);
2470
+ const clean = isAliasReference ? reference.slice(1, -1) : String(reference);
2135
2471
  if (visited.has(clean)) {
2136
2472
  logger.warn(`Circular alias detected for "${clean}"`);
2137
2473
  cache.set(cacheKey, void 0);
@@ -2146,15 +2482,15 @@ function createTokens(tokens = {}, options = {}) {
2146
2482
  const prefix = parts.slice(0, i).join(".");
2147
2483
  const suffix = parts.slice(i);
2148
2484
  const candidate = registry.get(prefix);
2149
- if (candidate?.value !== void 0) {
2485
+ if (!/* @__PURE__ */ isUndefined(candidate?.value)) {
2150
2486
  found = candidate;
2151
2487
  segments = suffix;
2152
2488
  break;
2153
2489
  }
2154
2490
  }
2155
2491
  }
2156
- if (found?.value === void 0) {
2157
- logger.warn(`Alias not found for "${String(reference)}"`);
2492
+ if (/* @__PURE__ */ isUndefined(found?.value)) {
2493
+ if (isAliasReference) logger.warn(`Alias not found for "${String(reference)}"`);
2158
2494
  cache.set(cacheKey, void 0);
2159
2495
  return;
2160
2496
  }
@@ -2170,7 +2506,7 @@ function createTokens(tokens = {}, options = {}) {
2170
2506
  current = current[segment];
2171
2507
  if (isTokenAlias(current)) current = current.$value;
2172
2508
  }
2173
- if (current === void 0) {
2509
+ if (/* @__PURE__ */ isUndefined(current)) {
2174
2510
  logger.warn(`Path not found inside "${clean}": ${segments.join(".")}`);
2175
2511
  cache.set(cacheKey, void 0);
2176
2512
  return;
@@ -2221,7 +2557,7 @@ function createTokens(tokens = {}, options = {}) {
2221
2557
  * ```
2222
2558
  */
2223
2559
  function createTokensContext(_options) {
2224
- const { namespace, tokens = {},...options } = _options;
2560
+ const { namespace = "v0:tokens", tokens = {},...options } = _options;
2225
2561
  const [useTokensContext, _provideTokensContext] = createContext(namespace);
2226
2562
  const context = createTokens(tokens, options);
2227
2563
  function provideTokensContext(_context = context, app) {
@@ -2541,7 +2877,7 @@ function defaultFilter(query, item, keys, mode = "some") {
2541
2877
  * @template Z The type of the items.
2542
2878
  * @returns The filtered items.
2543
2879
  *
2544
- * @see https://0.vuetifyjs.com/composables/selection/use-filter
2880
+ * @see https://0.vuetifyjs.com/composables/utilities/use-filter
2545
2881
  *
2546
2882
  * @example
2547
2883
  * ```ts
@@ -2641,7 +2977,7 @@ function createForm(options) {
2641
2977
  if (ticket.isValid.value === false) return false;
2642
2978
  if (ticket.isValid.value === null) return null;
2643
2979
  }
2644
- return hasFields || null;
2980
+ return hasFields ? true : null;
2645
2981
  });
2646
2982
  function reset() {
2647
2983
  for (const ticket of registry.values()) ticket.reset();
@@ -2731,7 +3067,6 @@ function createForm(options) {
2731
3067
  /**
2732
3068
  * Creates a new form context.
2733
3069
  *
2734
- * @param namespace The namespace for the form context.
2735
3070
  * @param options The options for the form context.
2736
3071
  * @template Z The type of the form ticket.
2737
3072
  * @template E The type of the form context.
@@ -2743,7 +3078,12 @@ function createForm(options) {
2743
3078
  * ```ts
2744
3079
  * import { createFormContext } from '@vuetify/v0'
2745
3080
  *
2746
- * export const [useMyForm, provideMyForm, myForm] = createFormContext('my-form', {
3081
+ * // With default namespace 'v0:form'
3082
+ * export const [useMyForm, provideMyForm, myForm] = createFormContext({ validateOn: 'change' })
3083
+ *
3084
+ * // Or with custom namespace
3085
+ * export const [useMyForm, provideMyForm, myForm] = createFormContext({
3086
+ * namespace: 'my-form',
2747
3087
  * validateOn: 'change',
2748
3088
  * })
2749
3089
  *
@@ -2755,8 +3095,8 @@ function createForm(options) {
2755
3095
  * form.register({ id: 'field', value: ref(''), rules: [...] })
2756
3096
  * ```
2757
3097
  */
2758
- function createFormContext(_options) {
2759
- const { namespace,...options } = _options;
3098
+ function createFormContext(_options = {}) {
3099
+ const { namespace = "v0:form",...options } = _options;
2760
3100
  const [useFormContext, _provideFormContext] = createContext(namespace);
2761
3101
  const context = createForm(options);
2762
3102
  function provideFormContext(_context = context, app) {
@@ -2853,6 +3193,7 @@ function useIntersectionObserver(target, callback, options = {}) {
2853
3193
  const observer = shallowRef();
2854
3194
  const isPaused = shallowRef(false);
2855
3195
  const isIntersecting = shallowRef(false);
3196
+ const isActive = toRef(() => !!observer.value);
2856
3197
  function setup() {
2857
3198
  if (!isHydrated.value || !SUPPORTS_INTERSECTION_OBSERVER || !target.value || isPaused.value) return;
2858
3199
  observer.value = new IntersectionObserver((entries) => {
@@ -2906,10 +3247,11 @@ function useIntersectionObserver(target, callback, options = {}) {
2906
3247
  function stop() {
2907
3248
  cleanup();
2908
3249
  }
2909
- onUnmounted(stop);
3250
+ onScopeDispose(stop, true);
2910
3251
  return {
2911
- isIntersecting: readonly(isIntersecting),
2912
- isPaused: readonly(isPaused),
3252
+ isActive: shallowReadonly(isActive),
3253
+ isIntersecting: shallowReadonly(isIntersecting),
3254
+ isPaused: shallowReadonly(isPaused),
2913
3255
  pause,
2914
3256
  resume,
2915
3257
  stop
@@ -2946,7 +3288,7 @@ function useIntersectionObserver(target, callback, options = {}) {
2946
3288
  function useElementIntersection(target, options = {}) {
2947
3289
  const isIntersecting = shallowRef(false);
2948
3290
  const intersectionRatio = shallowRef(0);
2949
- const { pause: _pause, resume, stop, isPaused } = useIntersectionObserver(target, (entries) => {
3291
+ const { pause: _pause, resume, stop, isActive, isPaused } = useIntersectionObserver(target, (entries) => {
2950
3292
  const entry = entries.at(-1);
2951
3293
  if (entry) {
2952
3294
  isIntersecting.value = entry.isIntersecting;
@@ -2962,8 +3304,9 @@ function useElementIntersection(target, options = {}) {
2962
3304
  _pause();
2963
3305
  }
2964
3306
  return {
2965
- isIntersecting: readonly(isIntersecting),
2966
- intersectionRatio: readonly(intersectionRatio),
3307
+ isIntersecting: shallowReadonly(isIntersecting),
3308
+ intersectionRatio: shallowReadonly(intersectionRatio),
3309
+ isActive,
2967
3310
  isPaused,
2968
3311
  pause,
2969
3312
  resume,
@@ -2983,7 +3326,7 @@ function useElementIntersection(target, options = {}) {
2983
3326
  * - Key-specific event handling
2984
3327
  * - preventDefault and stopPropagation options
2985
3328
  * - Automatic cleanup on scope disposal
2986
- * - Auto-starts when in component scope
3329
+ * - Built on useEventListener for consistent event handling
2987
3330
  *
2988
3331
  * Simplified wrapper around useEventListener for keyboard interactions.
2989
3332
  */
@@ -2999,36 +3342,44 @@ function useElementIntersection(target, options = {}) {
2999
3342
  * ```ts
3000
3343
  * import { useKeydown } from '@vuetify/v0'
3001
3344
  *
3002
- * const { startListening, stopListening } = useKeydown([
3345
+ * const { isActive, start, stop } = useKeydown([
3003
3346
  * { key: 'Enter', handler: () => console.log('Enter pressed') },
3004
3347
  * { key: 'Escape', handler: () => console.log('Escape pressed'), preventDefault: true },
3005
3348
  * ])
3006
3349
  *
3007
- * startListening()
3008
- * stopListening()
3350
+ * // Listener is automatically active when called in component setup
3351
+ * // Manually control if needed:
3352
+ * stop()
3353
+ * start()
3009
3354
  * ```
3010
3355
  */
3011
3356
  function useKeydown(handlers) {
3012
- const keyHandlers = Array.isArray(handlers) ? handlers : [handlers];
3357
+ let cleanup = null;
3358
+ const isActive = toRef(() => !!cleanup);
3013
3359
  function onKeydown(event) {
3014
- const handler = keyHandlers.find((h) => h.key === event.key);
3360
+ const handlerList = toValue(handlers);
3361
+ const handler = (Array.isArray(handlerList) ? handlerList : [handlerList]).find((h) => h.key === event.key);
3015
3362
  if (handler) {
3016
3363
  if (handler.preventDefault) event.preventDefault();
3017
3364
  if (handler.stopPropagation) event.stopPropagation();
3018
3365
  handler.handler(event);
3019
3366
  }
3020
3367
  }
3021
- function startListening() {
3022
- document.addEventListener("keydown", onKeydown);
3368
+ function start() {
3369
+ if (cleanup) return;
3370
+ cleanup = useDocumentEventListener("keydown", onKeydown);
3023
3371
  }
3024
- function stopListening() {
3025
- document.removeEventListener("keydown", onKeydown);
3372
+ function stop() {
3373
+ if (!cleanup) return;
3374
+ cleanup();
3375
+ cleanup = null;
3026
3376
  }
3027
- if (getCurrentScope()) onMounted(startListening);
3028
- onScopeDispose(stopListening, true);
3377
+ cleanup = useDocumentEventListener("keydown", onKeydown);
3378
+ onScopeDispose(stop);
3029
3379
  return {
3030
- startListening,
3031
- stopListening
3380
+ isActive,
3381
+ start,
3382
+ stop
3032
3383
  };
3033
3384
  }
3034
3385
 
@@ -3132,7 +3483,6 @@ function createSingle(_options = {}) {
3132
3483
  /**
3133
3484
  * Creates a new single selection context.
3134
3485
  *
3135
- * @param namespace The namespace for the single selection context.
3136
3486
  * @param options The options for the single selection context.
3137
3487
  * @template Z The type of the single selection ticket.
3138
3488
  * @template E The type of the single selection context.
@@ -3144,18 +3494,19 @@ function createSingle(_options = {}) {
3144
3494
  * ```ts
3145
3495
  * import { createSingleContext } from '@vuetify/v0'
3146
3496
  *
3147
- * export const [useTabs, provideTabs, tabs] = createSingleContext('tabs', { mandatory: true })
3497
+ * // With default namespace 'v0:single'
3498
+ * export const [useSingle, provideSingle, context] = createSingleContext()
3148
3499
  *
3149
3500
  * // In a parent component:
3150
- * provideTabs()
3501
+ * provideSingle()
3151
3502
  *
3152
3503
  * // In a child component:
3153
- * const tabs = useTabs()
3154
- * tabs.select('tab-1')
3504
+ * const single = useSingle()
3505
+ * single.select('tab-1')
3155
3506
  * ```
3156
3507
  */
3157
- function createSingleContext(_options) {
3158
- const { namespace,...options } = _options;
3508
+ function createSingleContext(_options = {}) {
3509
+ const { namespace = "v0:single",...options } = _options;
3159
3510
  const [useSingleContext, _provideSingleContext] = createContext(namespace);
3160
3511
  const context = createSingle(options);
3161
3512
  function provideSingleContext(_context = context, app) {
@@ -3197,7 +3548,7 @@ function useSingle(namespace = "v0:single") {
3197
3548
  *
3198
3549
  * This adapter provides translation and number formatting
3199
3550
  * capabilities using the Intl API and supports both
3200
- * numbered and named variables in translation strings.
3551
+ * numbered ({0}, {1}) and named ({name}) variables in translation strings.
3201
3552
  */
3202
3553
  var Vuetify0LocaleAdapter = class {
3203
3554
  t(message, ...params) {
@@ -3205,13 +3556,13 @@ var Vuetify0LocaleAdapter = class {
3205
3556
  if (params.length > 0 && /* @__PURE__ */ isObject(params[0])) {
3206
3557
  const variables = params[0];
3207
3558
  resolvedMessage = resolvedMessage.replace(/{([a-zA-Z][a-zA-Z0-9_]*)}/g, (match, name) => {
3208
- return variables[name] === void 0 ? match : String(variables[name]);
3559
+ return /* @__PURE__ */ isUndefined(variables[name]) ? match : String(variables[name]);
3209
3560
  });
3210
3561
  params = params.slice(1);
3211
3562
  }
3212
3563
  resolvedMessage = resolvedMessage.replace(/\{(\d+)\}/g, (match, index) => {
3213
3564
  const idx = Number.parseInt(index, 10);
3214
- if (params[idx] !== void 0) return String(params[idx]);
3565
+ if (!/* @__PURE__ */ isUndefined(params[idx])) return String(params[idx]);
3215
3566
  return match;
3216
3567
  });
3217
3568
  return resolvedMessage;
@@ -3252,21 +3603,20 @@ var Vuetify0LocaleAdapter = class {
3252
3603
  */
3253
3604
  function createLocale(_options = {}) {
3254
3605
  const { adapter = new Vuetify0LocaleAdapter(), messages = {},...options } = _options;
3255
- const tokens = createTokens(messages, { flat: true });
3606
+ const tokens = createTokens(messages);
3256
3607
  const registry = createSingle(options);
3257
3608
  for (const id in messages) {
3258
- registry.register({
3259
- id,
3260
- value: messages[id]
3261
- });
3609
+ registry.register({ id });
3262
3610
  if (id === options.default && !registry.selectedId.value) registry.select(id);
3263
3611
  }
3264
- function t(key, ...params) {
3612
+ function t(key, params, fallback) {
3265
3613
  const locale = registry.selectedId.value;
3266
- if (!locale) return key;
3267
- const message = (registry.get(locale)?.value)?.[key];
3268
- const template = /* @__PURE__ */ isString(message) ? resolve(locale, message) : key;
3269
- return adapter.t(template, ...params);
3614
+ const args = toArray(params);
3615
+ if (!locale) return adapter.t(fallback ?? key, ...args);
3616
+ const path = `${locale}.${key}`;
3617
+ const message = tokens.get(path)?.value;
3618
+ const template = /* @__PURE__ */ isString(message) ? resolve(locale, message) : fallback ?? key;
3619
+ return adapter.t(template, ...args);
3270
3620
  }
3271
3621
  function n(value, ...params) {
3272
3622
  return adapter.n(value, registry.selectedId.value, ...params);
@@ -3274,17 +3624,10 @@ function createLocale(_options = {}) {
3274
3624
  function resolve(locale, str) {
3275
3625
  return str.replace(/{([a-zA-Z0-9.-_]+)}/g, (match, key) => {
3276
3626
  const [prefix, ...rest] = key.split(".");
3277
- const path = rest.join(".");
3278
- const prefixTicket = registry.get(prefix);
3279
- const target = prefixTicket ? prefix : locale;
3280
- const name = prefixTicket ? path : key;
3281
- const resolved = (registry.get(target)?.value)?.[name];
3627
+ const target = registry.has(prefix) ? prefix : locale;
3628
+ const path = `${target}.${registry.has(prefix) ? rest.join(".") : key}`;
3629
+ const resolved = tokens.get(path)?.value;
3282
3630
  if (/* @__PURE__ */ isString(resolved)) return resolve(target, resolved);
3283
- const alias = `{${key}}`;
3284
- if (tokens.isAlias(alias)) {
3285
- const result = tokens.resolve(alias);
3286
- return /* @__PURE__ */ isString(result) ? result : match;
3287
- }
3288
3631
  return match;
3289
3632
  });
3290
3633
  }
@@ -3297,6 +3640,13 @@ function createLocale(_options = {}) {
3297
3640
  }
3298
3641
  };
3299
3642
  }
3643
+ function createLocaleFallback() {
3644
+ return {
3645
+ size: 0,
3646
+ t: (key, _params, fallback) => fallback ?? key,
3647
+ n: String
3648
+ };
3649
+ }
3300
3650
  /**
3301
3651
  * Creates a new locale context.
3302
3652
  *
@@ -3371,7 +3721,13 @@ function createLocalePlugin(_options = {}) {
3371
3721
  * @see https://0.vuetifyjs.com/composables/plugins/use-locale
3372
3722
  */
3373
3723
  function useLocale(namespace = "v0:locale") {
3374
- return useContext(namespace);
3724
+ const fallback = createLocaleFallback();
3725
+ if (!getCurrentInstance()) return fallback;
3726
+ try {
3727
+ return useContext(namespace, fallback);
3728
+ } catch {
3729
+ return fallback;
3730
+ }
3375
3731
  }
3376
3732
 
3377
3733
  //#endregion
@@ -3439,6 +3795,7 @@ function useMutationObserver(target, callback, options = {}) {
3439
3795
  const { isHydrated } = useHydration();
3440
3796
  const observer = shallowRef();
3441
3797
  const isPaused = shallowRef(false);
3798
+ const isActive = computed(() => !!observer.value);
3442
3799
  const observerOptions = {
3443
3800
  childList: options.childList ?? true,
3444
3801
  attributes: options.attributes ?? false,
@@ -3505,9 +3862,10 @@ function useMutationObserver(target, callback, options = {}) {
3505
3862
  function stop() {
3506
3863
  cleanup();
3507
3864
  }
3508
- onUnmounted(stop);
3865
+ onScopeDispose(stop, true);
3509
3866
  return {
3510
- isPaused: readonly(isPaused),
3867
+ isActive: shallowReadonly(isActive),
3868
+ isPaused: shallowReadonly(isPaused),
3511
3869
  pause,
3512
3870
  resume,
3513
3871
  stop
@@ -3515,360 +3873,881 @@ function useMutationObserver(target, callback, options = {}) {
3515
3873
  }
3516
3874
 
3517
3875
  //#endregion
3518
- //#region src/composables/usePermissions/adapters/adapter.ts
3519
- var PermissionAdapter = class {};
3520
-
3521
- //#endregion
3522
- //#region src/composables/usePermissions/adapters/v0.ts
3523
- var Vuetify0PermissionAdapter = class extends PermissionAdapter {
3524
- constructor() {
3525
- super();
3526
- }
3527
- can(role, action, subject, context, permissions) {
3528
- const access = `${role}.${action}.${subject}`;
3529
- const ticket = permissions.get(access);
3530
- if (!ticket || !ticket.value) return false;
3531
- return /* @__PURE__ */ isFunction(ticket.value) ? ticket.value(context) : ticket.value;
3532
- }
3533
- };
3534
-
3535
- //#endregion
3536
- //#region src/composables/usePermissions/index.ts
3876
+ //#region src/composables/useResizeObserver/index.ts
3537
3877
  /**
3538
- * @module usePermissions
3539
- *
3540
- * @see https://0.vuetifyjs.com/composables/plugins/use-permissions
3878
+ * @module useResizeObserver
3541
3879
  *
3542
3880
  * @remarks
3543
- * Permission management composable with support for RBAC and ABAC patterns.
3881
+ * ResizeObserver composable with lifecycle management.
3544
3882
  *
3545
3883
  * Key features:
3546
- * - Role-Based Access Control (RBAC) support
3547
- * - Attribute-Based Access Control (ABAC) with context
3548
- * - Functional permission conditions
3549
- * - Token-based permission storage
3550
- * - Adapter pattern for custom permission systems
3884
+ * - ResizeObserver API wrapper
3885
+ * - Pause/resume/stop functionality
3886
+ * - Automatic cleanup on unmount
3887
+ * - SSR-safe (checks SUPPORTS_OBSERVER)
3888
+ * - Hydration-aware
3889
+ * - Box model options (content-box/border-box)
3551
3890
  *
3552
- * Built on useTokens for flexible permission configuration.
3891
+ * Perfect for responsive components and size-based rendering.
3553
3892
  */
3554
3893
  /**
3555
- * Creates a new permissions instance.
3894
+ * A composable that uses the Resize Observer API to detect when an element's
3895
+ * size changes.
3556
3896
  *
3557
- * @param options The options for the permissions instance.
3558
- * @template Z The type of the permission ticket.
3559
- * @template E The type of the permission context.
3560
- * @returns A new permissions instance.
3897
+ * @param target The element to observe.
3898
+ * @param callback The callback to execute when the element's size changes.
3899
+ * @param options The options for the Resize Observer.
3900
+ * @returns An object with methods to control the observer.
3561
3901
  *
3562
- * @see https://0.vuetifyjs.com/composables/plugins/use-permissions
3902
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver
3903
+ * @see https://0.vuetifyjs.com/composables/system/use-resize-observer
3563
3904
  *
3564
3905
  * @example
3565
3906
  * ```ts
3566
- * import { createPermissions } from '@vuetify/v0'
3907
+ * import { ref } from 'vue'
3908
+ * import { useResizeObserver } from '@vuetify/v0'
3567
3909
  *
3568
- * const [usePermissions, providePermissions] = createPermissions({
3569
- * namespace: 'v0:permissions',
3570
- * permissions: {
3571
- * admin: [['read', 'users']],
3572
- * editor: [['edit', 'posts']],
3910
+ * const el = ref<HTMLElement>()
3911
+ * const width = ref(0)
3912
+ * const height = ref(0)
3913
+ *
3914
+ * const { pause, resume, isPaused } = useResizeObserver(
3915
+ * el,
3916
+ * (entries) => {
3917
+ * const entry = entries[0]
3918
+ * if (entry) {
3919
+ * width.value = entry.contentRect.width
3920
+ * height.value = entry.contentRect.height
3921
+ * console.log('Size changed:', width.value, 'x', height.value)
3922
+ * }
3573
3923
  * },
3574
- * })
3924
+ * { immediate: true }
3925
+ * )
3926
+ *
3927
+ * // Pause observation
3928
+ * pause()
3929
+ *
3930
+ * // Resume observation
3931
+ * resume()
3575
3932
  * ```
3576
3933
  */
3577
- function createPermissions(_options = {}) {
3578
- const { adapter = new Vuetify0PermissionAdapter(), permissions = {},...options } = _options;
3579
- const record = {};
3580
- for (const role in permissions) {
3581
- if (!record[role]) record[role] = {};
3582
- for (const [actions, subjects, condition = true] of permissions[role]) for (const action of toArray(actions)) for (const subject of toArray(subjects)) {
3583
- if (!record[role][action]) record[role][action] = {};
3584
- record[role][action][subject] = condition;
3934
+ function useResizeObserver(target, callback, options = {}) {
3935
+ const { isHydrated } = useHydration();
3936
+ const observer = shallowRef();
3937
+ const isPaused = shallowRef(false);
3938
+ const isActive = toRef(() => !!observer.value);
3939
+ function setup() {
3940
+ if (!isHydrated.value || !SUPPORTS_OBSERVER || !target.value || isPaused.value) return;
3941
+ observer.value = new ResizeObserver((entries) => {
3942
+ callback(entries.map((entry) => ({
3943
+ contentRect: {
3944
+ width: entry.contentRect.width,
3945
+ height: entry.contentRect.height,
3946
+ top: entry.contentRect.top,
3947
+ left: entry.contentRect.left
3948
+ },
3949
+ target: entry.target
3950
+ })));
3951
+ });
3952
+ observer.value.observe(target.value, { box: options.box || "content-box" });
3953
+ if (options.immediate) {
3954
+ const rect = target.value.getBoundingClientRect();
3955
+ callback([{
3956
+ contentRect: {
3957
+ width: rect.width,
3958
+ height: rect.height,
3959
+ top: rect.top,
3960
+ left: rect.left
3961
+ },
3962
+ target: target.value
3963
+ }]);
3585
3964
  }
3586
3965
  }
3587
- const tokens = createTokens(record, options);
3588
- function can(id, action, subject, context = {}) {
3589
- return adapter.can(id, action, subject, context, tokens);
3966
+ watch([isHydrated, target], () => {
3967
+ cleanup();
3968
+ setup();
3969
+ }, { immediate: true });
3970
+ function cleanup() {
3971
+ if (observer.value) {
3972
+ observer.value.disconnect();
3973
+ observer.value = void 0;
3974
+ }
3590
3975
  }
3976
+ function pause() {
3977
+ isPaused.value = true;
3978
+ observer.value?.disconnect();
3979
+ }
3980
+ function resume() {
3981
+ isPaused.value = false;
3982
+ setup();
3983
+ }
3984
+ function stop() {
3985
+ cleanup();
3986
+ }
3987
+ onScopeDispose(stop, true);
3591
3988
  return {
3592
- ...tokens,
3593
- can
3989
+ isActive: shallowReadonly(isActive),
3990
+ isPaused: shallowReadonly(isPaused),
3991
+ pause,
3992
+ resume,
3993
+ stop
3594
3994
  };
3595
3995
  }
3596
3996
  /**
3597
- * Creates a new permissions context.
3997
+ * A convenience composable that uses the Resize Observer API to track an
3998
+ * element's size.
3598
3999
  *
3599
- * @param options The options for the permissions context.
3600
- * @template Z The type of the permission ticket.
3601
- * @template E The type of the permission context.
3602
- * @returns A new permissions context.
4000
+ * @param target The element to observe.
4001
+ * @returns An object with the element's width and height.
3603
4002
  *
3604
- * @see https://0.vuetifyjs.com/composables/plugins/use-permissions
4003
+ * @see https://0.vuetifyjs.com/composables/system/use-resize-observer#use-element-size
3605
4004
  *
3606
4005
  * @example
3607
4006
  * ```ts
3608
- * import { createPermissionsContext } from '@vuetify/v0'
4007
+ * import { ref, watchEffect } from 'vue'
4008
+ * import { useElementSize } from '@vuetify/v0'
3609
4009
  *
3610
- * export const [usePermissions, providePermissions, context] = createPermissionsContext({
3611
- * namespace: 'app:permissions',
3612
- * permissions: {
3613
- * admin: [['read', 'users'], ['edit', 'users']],
3614
- * editor: [['edit', 'posts']],
3615
- * },
4010
+ * const box = ref<HTMLElement>()
4011
+ * const { width, height } = useElementSize(box)
4012
+ *
4013
+ * // Width and height are reactive refs
4014
+ * watchEffect(() => {
4015
+ * console.log('Box size:', width.value, 'x', height.value)
3616
4016
  * })
3617
4017
  * ```
3618
4018
  */
3619
- function createPermissionsContext(_options = {}) {
3620
- const { namespace = "v0:permissions",...options } = _options;
3621
- const [usePermissionsContext, _providePermissionsContext] = createContext(namespace);
3622
- const context = createPermissions(options);
3623
- function providePermissionsContext(_context = context, app) {
3624
- return _providePermissionsContext(_context, app);
4019
+ function useElementSize(target) {
4020
+ const width = shallowRef(0);
4021
+ const height = shallowRef(0);
4022
+ const { pause: _pause, resume, stop, isActive, isPaused } = useResizeObserver(target, (entries) => {
4023
+ const entry = entries[0];
4024
+ if (entry) {
4025
+ width.value = entry.contentRect.width;
4026
+ height.value = entry.contentRect.height;
4027
+ }
4028
+ }, { immediate: true });
4029
+ function pause() {
4030
+ width.value = 0;
4031
+ height.value = 0;
4032
+ _pause();
3625
4033
  }
3626
- return createTrinity(usePermissionsContext, providePermissionsContext, context);
4034
+ return {
4035
+ width,
4036
+ height,
4037
+ isActive,
4038
+ isPaused,
4039
+ pause,
4040
+ resume,
4041
+ stop
4042
+ };
3627
4043
  }
4044
+
4045
+ //#endregion
4046
+ //#region src/composables/useOverflow/index.ts
3628
4047
  /**
3629
- * Creates a new permissions plugin.
3630
- *
3631
- * @param options The options for the permissions plugin.
3632
- * @template Z The type of the permission ticket.
3633
- * @template E The type of the permission context.
3634
- * @returns A new permissions plugin.
4048
+ * @module useOverflow
3635
4049
  *
3636
- * @see https://0.vuetifyjs.com/composables/plugins/use-permissions
4050
+ * @remarks
4051
+ * Composable for computing how many items fit in a container based on available width.
4052
+ * Enables responsive truncation logic for Pagination, Breadcrumbs, and similar components.
3637
4053
  *
3638
- * @example
3639
- * ```ts
3640
- * import { createApp } from 'vue'
3641
- * import { createPermissionsPlugin } from '@vuetify/v0'
3642
- * import App from './App.vue'
4054
+ * Key features:
4055
+ * - Container width tracking via ResizeObserver
4056
+ * - Two modes: variable-width (per-item) or uniform-width (sample-based)
4057
+ * - Computes capacity (how many items fit)
4058
+ * - SSR-safe with Infinity fallback
4059
+ * - Supports reserved space for nav buttons, ellipsis, etc.
4060
+ *
4061
+ * Use variable mode (default) for items with different widths like Breadcrumbs.
4062
+ * Use uniform mode (itemWidth option) for same-width items like Pagination buttons.
4063
+ */
4064
+ /**
4065
+ * Creates a new overflow context for computing how many items fit in a container.
3643
4066
  *
3644
- * const app = createApp(App)
4067
+ * @param options Configuration options
4068
+ * @returns Overflow context with container ref, capacity, and measurement functions
3645
4069
  *
3646
- * app.use(
3647
- * createPermissionsPlugin({
3648
- * permissions: {
3649
- * admin: [['read', 'users']],
3650
- * editor: [['edit', 'posts']],
3651
- * },
4070
+ * @example Variable-width mode (Breadcrumbs)
4071
+ * ```vue
4072
+ * <script lang="ts" setup>
4073
+ * import { useTemplateRef } from 'vue'
4074
+ * import { createOverflow } from '@vuetify/v0'
4075
+ *
4076
+ * const containerRef = useTemplateRef('container')
4077
+ * const overflow = createOverflow({
4078
+ * container: containerRef,
4079
+ * gap: 8,
4080
+ * reserved: 40,
3652
4081
  * })
3653
- * )
4082
+ * <\/script>
3654
4083
  *
3655
- * app.mount('#app')
4084
+ * <template>
4085
+ * <div ref="container">
4086
+ * <span
4087
+ * v-for="(item, i) in items.slice(0, overflow.capacity.value)"
4088
+ * :key="i"
4089
+ * :ref="el => overflow.measure(i, el)"
4090
+ * >
4091
+ * {{ item }}
4092
+ * </span>
4093
+ * <span v-if="overflow.isOverflowing.value">...</span>
4094
+ * </div>
4095
+ * </template>
4096
+ * ```
4097
+ *
4098
+ * @example Uniform-width mode (Pagination)
4099
+ * ```ts
4100
+ * const overflow = createOverflow({
4101
+ * container: () => atom.value?.element,
4102
+ * itemWidth: buttonWidth,
4103
+ * reserved: () => buttonWidth.value * 4,
4104
+ * })
3656
4105
  * ```
3657
4106
  */
3658
- function createPermissionsPlugin(_options = {}) {
3659
- const { namespace = "v0:permissions",...options } = _options;
3660
- const [, providePermissionContext, context] = createPermissionsContext({
3661
- ...options,
3662
- namespace
3663
- });
3664
- return createPlugin({
3665
- namespace,
3666
- provide: (app) => {
3667
- providePermissionContext(context, app);
4107
+ function createOverflow(options = {}) {
4108
+ const { container: _container, gap = 0, reserved = 0, itemWidth, reverse } = options;
4109
+ const container = /* @__PURE__ */ isUndefined(_container) ? shallowRef() : toRef(_container);
4110
+ const widths = shallowRef(/* @__PURE__ */ new Map());
4111
+ const { width } = useElementSize(container);
4112
+ function measure(index, el) {
4113
+ if (!el) {
4114
+ if (widths.value.has(index)) {
4115
+ const next = new Map(widths.value);
4116
+ next.delete(index);
4117
+ widths.value = next;
4118
+ }
4119
+ return;
4120
+ }
4121
+ const style = getComputedStyle(el);
4122
+ const marginX = Number.parseFloat(style.marginLeft) + Number.parseFloat(style.marginRight);
4123
+ const w = el.offsetWidth + marginX;
4124
+ if (widths.value.get(index) !== w) widths.value = new Map(widths.value).set(index, w);
4125
+ }
4126
+ function reset() {
4127
+ widths.value = /* @__PURE__ */ new Map();
4128
+ }
4129
+ const total = computed(() => {
4130
+ const g = toValue(gap);
4131
+ let sum = 0;
4132
+ let count = 0;
4133
+ for (const w of widths.value.values()) {
4134
+ sum += w + (count > 0 ? g : 0);
4135
+ count++;
3668
4136
  }
4137
+ return sum;
3669
4138
  });
4139
+ return {
4140
+ container,
4141
+ width,
4142
+ capacity: computed(() => {
4143
+ const available = width.value - toValue(reserved);
4144
+ if (width.value === 0) return Infinity;
4145
+ if (available <= 0) return 0;
4146
+ const g = toValue(gap);
4147
+ const uniformWidth = toValue(itemWidth);
4148
+ if (uniformWidth && uniformWidth > 0) {
4149
+ const first = uniformWidth;
4150
+ const subsequent = uniformWidth + g;
4151
+ if (available < first) return 0;
4152
+ return Math.max(1, Math.floor((available - first) / subsequent) + 1);
4153
+ }
4154
+ const entries = [...widths.value.entries()].toSorted((a, b) => a[0] - b[0]);
4155
+ if (toValue(reverse)) entries.reverse();
4156
+ let sum = 0;
4157
+ let count = 0;
4158
+ for (const [, w] of entries) {
4159
+ const next = sum + w + (count > 0 ? g : 0);
4160
+ if (next > available) break;
4161
+ sum = next;
4162
+ count++;
4163
+ }
4164
+ return count;
4165
+ }),
4166
+ total,
4167
+ isOverflowing: toRef(() => {
4168
+ return total.value > width.value - toValue(reserved);
4169
+ }),
4170
+ measure,
4171
+ reset
4172
+ };
3670
4173
  }
3671
4174
  /**
3672
- * Returns the current permissions instance.
4175
+ * Creates an overflow context with dependency injection support.
3673
4176
  *
3674
- * @template Z The type of the permission ticket.
3675
- * @returns The current permissions instance.
4177
+ * @param options Configuration options including namespace
4178
+ * @returns Trinity tuple: [useContext, provideContext, defaultContext]
3676
4179
  *
3677
- * @see https://0.vuetifyjs.com/composables/plugins/use-permissions
4180
+ * @example
4181
+ * ```ts
4182
+ * // Create injectable context
4183
+ * const [useOverflow, provideOverflow, overflow] = createOverflowContext({
4184
+ * namespace: 'my-overflow',
4185
+ * gap: 8,
4186
+ * reserved: 160,
4187
+ * })
4188
+ *
4189
+ * // In parent component
4190
+ * provideOverflow()
4191
+ *
4192
+ * // In child component
4193
+ * const overflow = useOverflow()
4194
+ * ```
4195
+ */
4196
+ function createOverflowContext(_options = {}) {
4197
+ const { namespace = "v0:overflow",...options } = _options;
4198
+ const [useOverflowContext, _provideOverflowContext] = createContext(namespace);
4199
+ const context = createOverflow(options);
4200
+ function provideOverflowContext(_context = context, app) {
4201
+ return _provideOverflowContext(_context, app);
4202
+ }
4203
+ return createTrinity(useOverflowContext, provideOverflowContext, context);
4204
+ }
4205
+ /**
4206
+ * Returns the current overflow context from dependency injection.
4207
+ *
4208
+ * @param namespace The namespace for the overflow context. Defaults to `v0:overflow`.
4209
+ * @returns The current overflow context.
3678
4210
  *
3679
4211
  * @example
3680
4212
  * ```vue
3681
- * <script setup lang="ts">
3682
- * import { usePermissions } from '@vuetify/v0'
4213
+ * <script lang="ts" setup>
4214
+ * import { useOverflow } from '@vuetify/v0'
3683
4215
  *
3684
- * const { can } = usePermissions()
4216
+ * // Inject overflow context provided by parent
4217
+ * const overflow = useOverflow()
3685
4218
  * <\/script>
3686
4219
  *
3687
4220
  * <template>
3688
4221
  * <div>
3689
- * <p v-if="can('admin', 'read', 'users')">Admin access</p>
4222
+ * <p>Capacity: {{ overflow.capacity.value }}</p>
3690
4223
  * </div>
3691
4224
  * </template>
3692
4225
  * ```
3693
4226
  */
3694
- function usePermissions(namespace = "v0:permissions") {
4227
+ function useOverflow(namespace = "v0:overflow") {
3695
4228
  return useContext(namespace);
3696
4229
  }
3697
4230
 
3698
4231
  //#endregion
3699
- //#region src/composables/useProxyModel/index.ts
4232
+ //#region src/composables/usePagination/index.ts
3700
4233
  /**
3701
- * @module useProxyModel
4234
+ * @module usePagination
3702
4235
  *
3703
4236
  * @remarks
3704
- * Proxy composable for bidirectional sync between selection registry and v-model.
4237
+ * Lightweight pagination composable for navigating through pages.
3705
4238
  *
3706
4239
  * Key features:
3707
- * - Bidirectional synchronization
3708
- * - Array and single-value modes
3709
- * - Automatic cleanup on scope disposal
3710
- * - Perfect for form controls with selection backing
3711
- *
3712
- * Bridges the gap between selection composables and Vue's v-model.
4240
+ * - No registry overhead - just a bounded integer
4241
+ * - Direct ref support for v-model compatibility
4242
+ * - Navigation methods: next, prev, first, last
4243
+ * - Computed visible items with ellipsis
4244
+ * - Trinity pattern for dependency injection
4245
+ *
4246
+ * Unlike registry-based composables, pagination tracks a single number
4247
+ * within a range, making it efficient for large page counts.
3713
4248
  */
3714
4249
  /**
3715
- * Syncs a ref with a selection registry bidirectionally.
3716
- *
3717
- * @param registry The selection registry to bind to.
3718
- * @param model The ref to sync.
3719
- * @param options The options for the proxy model.
3720
- * @template Z The type of the selection ticket.
3721
- * @returns A function to stop the sync.
4250
+ * Creates a pagination instance.
3722
4251
  *
3723
- * @see https://0.vuetifyjs.com/composables/forms/use-proxy-model
4252
+ * @param options The options for the pagination instance.
4253
+ * @returns A pagination context with navigation methods.
3724
4254
  *
3725
4255
  * @example
3726
4256
  * ```ts
3727
- * import { createSelection, useProxyModel } from '@vuetify/v0'
4257
+ * import { createPagination } from '@vuetify/v0'
3728
4258
  *
3729
- * const model = ref()
3730
- * const registry = createSelection({ events: true })
3731
- * registry.onboard([
3732
- * { id: 'item-1', value: 'Item 1' },
3733
- * { id: 'item-2', value: 'Item 2' },
3734
- * ])
4259
+ * // Basic usage
4260
+ * const pagination = createPagination({ size: 100 })
4261
+ * pagination.next()
4262
+ * pagination.items.value // [{ type: 'page', value: 1 }, { type: 'page', value: 2 }, ...]
3735
4263
  *
3736
- * const stop = useProxyModel(registry, model)
4264
+ * // With v-model (pass a ref)
4265
+ * const page = ref(1)
4266
+ * const pagination = createPagination({ page, size: 100 })
4267
+ * // Mutating pagination.page or the passed ref syncs both
3737
4268
  * ```
3738
4269
  */
3739
- function useProxyModel(registry, model, options) {
3740
- const multiple = options?.multiple ?? false;
3741
- const _transformIn = options?.transformIn;
3742
- const _transformOut = options?.transformOut;
3743
- function transformIn(val) {
3744
- const value = toValue(val);
3745
- return toArray(/* @__PURE__ */ isFunction(_transformIn) ? _transformIn(value) : value);
4270
+ function createPagination(_options = {}) {
4271
+ const { page: _page = 1, itemsPerPage: _itemsPerPage = 10, size: _size = 0, visible: _visible = 7, ellipsis = "..." } = _options;
4272
+ const page = isRef(_page) ? _page : shallowRef(_page);
4273
+ const pages = computed(() => {
4274
+ const size = toValue(_size);
4275
+ const perPage = toValue(_itemsPerPage);
4276
+ if (size <= 0 || /* @__PURE__ */ isNaN(size)) return 0;
4277
+ return Math.ceil(size / perPage);
4278
+ });
4279
+ function first() {
4280
+ page.value = 1;
3746
4281
  }
3747
- function transformOut(val) {
3748
- if (/* @__PURE__ */ isFunction(_transformOut)) return _transformOut(val);
3749
- return multiple ? val : val[0];
4282
+ function last() {
4283
+ page.value = pages.value;
3750
4284
  }
3751
- const modelAsArray = transformIn(model);
3752
- const pending = new Set(modelAsArray);
3753
- for (const value of modelAsArray) {
3754
- const ids = registry.browse(value);
3755
- if (/* @__PURE__ */ isArray(ids)) {
3756
- for (const id of ids) registry.select(id);
3757
- pending.delete(value);
3758
- } else if (ids) {
3759
- registry.select(ids);
3760
- pending.delete(value);
3761
- }
4285
+ function next() {
4286
+ if (page.value < pages.value) page.value++;
3762
4287
  }
3763
- const registryWatch = watch(registry.selectedValues, (val) => {
3764
- modelWatch.pause();
3765
- model.value = transformOut(Array.from(toValue(val)));
3766
- modelWatch.resume();
3767
- }, { flush: "sync" });
3768
- const modelWatch = watch(model, (val) => {
3769
- registryWatch.pause();
3770
- const currentIds = new Set(toValue(registry.selectedIds));
3771
- const targetIds = /* @__PURE__ */ new Set();
3772
- for (const value of transformIn(val)) {
3773
- const ids = registry.browse(value);
3774
- if (/* @__PURE__ */ isArray(ids)) for (const single of ids) targetIds.add(single);
3775
- else if (ids) targetIds.add(ids);
3776
- }
3777
- if (multiple) {
3778
- for (const id of currentIds.difference(targetIds)) registry.selectedIds.delete(id);
3779
- for (const id of targetIds.difference(currentIds)) registry.selectedIds.add(id);
3780
- } else {
3781
- const next = targetIds.values().next().value;
3782
- const last = currentIds.values().next().value;
3783
- if (last !== void 0) registry.unselect(last);
3784
- if (next !== void 0) registry.select(next);
3785
- }
3786
- registryWatch.resume();
3787
- }, {
3788
- flush: "sync",
3789
- deep: multiple
3790
- });
3791
- function onRegister(ticket) {
3792
- if (!pending.has(ticket.value) || ticket.disabled) return;
3793
- registryWatch.pause();
3794
- modelWatch.pause();
3795
- registry.select(ticket.id);
3796
- pending.delete(ticket.value);
3797
- modelWatch.resume();
3798
- registryWatch.resume();
4288
+ function prev() {
4289
+ if (page.value > 1) page.value--;
4290
+ }
4291
+ function select(value) {
4292
+ if (value < 1) page.value = 1;
4293
+ else if (value > pages.value) page.value = pages.value;
4294
+ else page.value = value;
4295
+ }
4296
+ const isFirst = computed(() => page.value <= 1);
4297
+ const isLast = computed(() => page.value >= pages.value);
4298
+ const pageStart = computed(() => (page.value - 1) * toValue(_itemsPerPage));
4299
+ const pageStop = computed(() => Math.min(pageStart.value + toValue(_itemsPerPage), toValue(_size)));
4300
+ function toPage(value) {
4301
+ return {
4302
+ type: "page",
4303
+ value
4304
+ };
3799
4305
  }
3800
- registry.on("register:ticket", onRegister);
3801
- function stop() {
3802
- registryWatch();
3803
- modelWatch();
3804
- registry.off("register:ticket", onRegister);
4306
+ function toEllipsis() {
4307
+ return ellipsis === false ? false : {
4308
+ type: "ellipsis",
4309
+ value: ellipsis
4310
+ };
3805
4311
  }
3806
- onScopeDispose(stop, true);
3807
- return stop;
3808
- }
3809
-
3810
- //#endregion
3811
- //#region src/composables/useProxyRegistry/index.ts
3812
- /**
3813
- * @module useProxyRegistry
3814
- *
3815
- * @remarks
3816
- * Proxy composable for reactive registry keys, values, entries, and size.
3817
- *
3818
- * Key features:
3819
- * - Reactive proxy for registry data
3820
- * - Deep or shallow reactivity options
3821
- * - Event-based updates
3822
- * - Automatic cleanup on scope disposal
3823
- * - Transforms Map-based registry into reactive refs
4312
+ function filter(array) {
4313
+ return array.filter(Boolean);
4314
+ }
4315
+ return {
4316
+ page,
4317
+ ellipsis,
4318
+ items: computed(() => {
4319
+ const pageCount = pages.value;
4320
+ const visible = toValue(_visible);
4321
+ const current = page.value;
4322
+ if (pageCount <= 0 || /* @__PURE__ */ isNaN(pageCount) || pageCount > Number.MAX_SAFE_INTEGER) return [];
4323
+ if (visible <= 0) return [];
4324
+ if (visible <= 2) return [toPage(current)];
4325
+ if (pageCount <= visible) return (/* @__PURE__ */ range(pageCount, 1)).map(toPage);
4326
+ if (visible === 3) {
4327
+ const mid = current <= 1 ? 2 : current >= pageCount ? pageCount - 1 : current;
4328
+ return [
4329
+ toPage(1),
4330
+ toPage(mid),
4331
+ toPage(pageCount)
4332
+ ];
4333
+ }
4334
+ const boundary = visible - 2;
4335
+ const middle = visible - 4;
4336
+ if (middle <= 0) {
4337
+ if (current <= boundary) return filter([
4338
+ ...(/* @__PURE__ */ range(boundary, 1)).map(toPage),
4339
+ toEllipsis(),
4340
+ toPage(pageCount)
4341
+ ]);
4342
+ if (current > pageCount - boundary) return filter([
4343
+ toPage(1),
4344
+ toEllipsis(),
4345
+ ...(/* @__PURE__ */ range(boundary, pageCount - boundary + 1)).map(toPage)
4346
+ ]);
4347
+ return current <= Math.ceil(pageCount / 2) ? filter([
4348
+ toPage(1),
4349
+ toPage(current),
4350
+ toEllipsis(),
4351
+ toPage(pageCount)
4352
+ ]) : filter([
4353
+ toPage(1),
4354
+ toEllipsis(),
4355
+ toPage(current),
4356
+ toPage(pageCount)
4357
+ ]);
4358
+ }
4359
+ const leftThreshold = boundary - 1;
4360
+ const rightThreshold = pageCount - boundary + 2;
4361
+ if (current <= leftThreshold) return filter([
4362
+ ...(/* @__PURE__ */ range(boundary, 1)).map(toPage),
4363
+ toEllipsis(),
4364
+ toPage(pageCount)
4365
+ ]);
4366
+ else if (current >= rightThreshold) return filter([
4367
+ toPage(1),
4368
+ toEllipsis(),
4369
+ ...(/* @__PURE__ */ range(boundary, pageCount - boundary + 1)).map(toPage)
4370
+ ]);
4371
+ else {
4372
+ const start = current - Math.floor(middle / 2);
4373
+ return filter([
4374
+ toPage(1),
4375
+ toEllipsis(),
4376
+ ...(/* @__PURE__ */ range(middle, start)).map(toPage),
4377
+ toEllipsis(),
4378
+ toPage(pageCount)
4379
+ ]);
4380
+ }
4381
+ }),
4382
+ pageStart,
4383
+ pageStop,
4384
+ isFirst,
4385
+ isLast,
4386
+ first,
4387
+ last,
4388
+ next,
4389
+ prev,
4390
+ select,
4391
+ get itemsPerPage() {
4392
+ return toValue(_itemsPerPage);
4393
+ },
4394
+ get size() {
4395
+ return toValue(_size);
4396
+ },
4397
+ get pages() {
4398
+ return pages.value;
4399
+ }
4400
+ };
4401
+ }
4402
+ /**
4403
+ * Creates a pagination context for dependency injection.
3824
4404
  *
3825
- * Perfect for exposing registry data as reactive computed properties.
4405
+ * @param options The options including namespace.
4406
+ * @returns A trinity: [usePagination, providePagination, defaultContext]
4407
+ *
4408
+ * @example
4409
+ * ```ts
4410
+ * // With default namespace 'v0:pagination'
4411
+ * const [usePagination, providePaginationContext] = createPaginationContext({ size: 50 })
4412
+ *
4413
+ * // Or with custom namespace
4414
+ * const [usePagination, providePaginationContext] = createPaginationContext({
4415
+ * namespace: 'my-pagination',
4416
+ * size: 50,
4417
+ * })
4418
+ *
4419
+ * // Parent component
4420
+ * providePaginationContext()
4421
+ *
4422
+ * // Child component
4423
+ * const pagination = usePagination()
4424
+ * pagination.next()
4425
+ * ```
3826
4426
  */
4427
+ function createPaginationContext(_options = {}) {
4428
+ const { namespace = "v0:pagination",...options } = _options;
4429
+ const [usePaginationContext, _providePaginationContext] = createContext(namespace);
4430
+ const context = createPagination(options);
4431
+ function providePaginationContext(_context = context, app) {
4432
+ return _providePaginationContext(_context, app);
4433
+ }
4434
+ return createTrinity(usePaginationContext, providePaginationContext, context);
4435
+ }
3827
4436
  /**
3828
- * Creates a proxy registry that provides reactive objects for registry data.
4437
+ * Returns the current pagination instance from context.
3829
4438
  *
3830
- * @param registry The registry instance to proxy.
3831
- * @param options The options for the proxy registry.
3832
- * @template Z The type of the registry ticket.
3833
- * @returns A proxy registry with reactive objects.
4439
+ * @param namespace The namespace. @default 'v0:pagination'
4440
+ * @returns The pagination context.
3834
4441
  *
3835
- * @see https://0.vuetifyjs.com/composables/registration/use-proxy-registry
4442
+ * @example
4443
+ * ```vue
4444
+ * <script setup>
4445
+ * import { usePagination } from '@vuetify/v0'
4446
+ *
4447
+ * const pagination = usePagination()
4448
+ * <\/script>
4449
+ *
4450
+ * <template>
4451
+ * <button @click="pagination.prev()" :disabled="pagination.isFirst.value">Prev</button>
4452
+ * <button @click="pagination.next()" :disabled="pagination.isLast.value">Next</button>
4453
+ * </template>
4454
+ * ```
4455
+ */
4456
+ function usePagination(namespace = "v0:pagination") {
4457
+ return useContext(namespace);
4458
+ }
4459
+
4460
+ //#endregion
4461
+ //#region src/composables/usePermissions/adapters/adapter.ts
4462
+ var PermissionAdapter = class {};
4463
+
4464
+ //#endregion
4465
+ //#region src/composables/usePermissions/adapters/v0.ts
4466
+ var Vuetify0PermissionAdapter = class extends PermissionAdapter {
4467
+ constructor() {
4468
+ super();
4469
+ }
4470
+ can(role, action, subject, context, permissions) {
4471
+ const access = `${role}.${action}.${subject}`;
4472
+ const ticket = permissions.get(access);
4473
+ if (!ticket || !ticket.value) return false;
4474
+ return /* @__PURE__ */ isFunction(ticket.value) ? ticket.value(context) : ticket.value;
4475
+ }
4476
+ };
4477
+
4478
+ //#endregion
4479
+ //#region src/composables/usePermissions/index.ts
4480
+ /**
4481
+ * @module usePermissions
4482
+ *
4483
+ * @see https://0.vuetifyjs.com/composables/plugins/use-permissions
4484
+ *
4485
+ * @remarks
4486
+ * Permission management composable with support for RBAC and ABAC patterns.
4487
+ *
4488
+ * Key features:
4489
+ * - Role-Based Access Control (RBAC) support
4490
+ * - Attribute-Based Access Control (ABAC) with context
4491
+ * - Functional permission conditions
4492
+ * - Token-based permission storage
4493
+ * - Adapter pattern for custom permission systems
4494
+ *
4495
+ * Built on useTokens for flexible permission configuration.
4496
+ */
4497
+ /**
4498
+ * Creates a new permissions instance.
4499
+ *
4500
+ * @param options The options for the permissions instance.
4501
+ * @template Z The type of the permission ticket.
4502
+ * @template E The type of the permission context.
4503
+ * @returns A new permissions instance.
4504
+ *
4505
+ * @see https://0.vuetifyjs.com/composables/plugins/use-permissions
3836
4506
  *
3837
4507
  * @example
3838
4508
  * ```ts
3839
- * import { useRegistry, useProxyRegistry } from '@vuetify/v0'
4509
+ * import { createPermissions } from '@vuetify/v0'
3840
4510
  *
3841
- * const registry = useRegistry({ events: true })
3842
- * const proxy = useProxyRegistry(registry)
4511
+ * const [usePermissions, providePermissions] = createPermissions({
4512
+ * namespace: 'v0:permissions',
4513
+ * permissions: {
4514
+ * admin: [['read', 'users']],
4515
+ * editor: [['edit', 'posts']],
4516
+ * },
4517
+ * })
4518
+ * ```
4519
+ */
4520
+ function createPermissions(_options = {}) {
4521
+ const { adapter = new Vuetify0PermissionAdapter(), permissions = {},...options } = _options;
4522
+ const record = {};
4523
+ for (const role in permissions) {
4524
+ if (!record[role]) record[role] = {};
4525
+ for (const [actions, subjects, condition = true] of permissions[role]) for (const action of toArray(actions)) for (const subject of toArray(subjects)) {
4526
+ if (!record[role][action]) record[role][action] = {};
4527
+ record[role][action][subject] = condition;
4528
+ }
4529
+ }
4530
+ const tokens = createTokens(record, options);
4531
+ function can(id, action, subject, context = {}) {
4532
+ return adapter.can(id, action, subject, context, tokens);
4533
+ }
4534
+ return {
4535
+ ...tokens,
4536
+ can
4537
+ };
4538
+ }
4539
+ /**
4540
+ * Creates a new permissions context.
3843
4541
  *
3844
- * registry.register({ value: 'Item 1' })
3845
- * console.log(proxy.size) // 1
4542
+ * @param options The options for the permissions context.
4543
+ * @template Z The type of the permission ticket.
4544
+ * @template E The type of the permission context.
4545
+ * @returns A new permissions context.
4546
+ *
4547
+ * @see https://0.vuetifyjs.com/composables/plugins/use-permissions
4548
+ *
4549
+ * @example
4550
+ * ```ts
4551
+ * import { createPermissionsContext } from '@vuetify/v0'
4552
+ *
4553
+ * export const [usePermissions, providePermissions, context] = createPermissionsContext({
4554
+ * namespace: 'app:permissions',
4555
+ * permissions: {
4556
+ * admin: [['read', 'users'], ['edit', 'users']],
4557
+ * editor: [['edit', 'posts']],
4558
+ * },
4559
+ * })
3846
4560
  * ```
3847
4561
  */
3848
- function useProxyRegistry(registry, options) {
3849
- const state = (options?.deep ? reactive : shallowReactive)({
3850
- keys: registry.keys(),
3851
- values: registry.values(),
3852
- entries: registry.entries(),
3853
- size: registry.size
4562
+ function createPermissionsContext(_options = {}) {
4563
+ const { namespace = "v0:permissions",...options } = _options;
4564
+ const [usePermissionsContext, _providePermissionsContext] = createContext(namespace);
4565
+ const context = createPermissions(options);
4566
+ function providePermissionsContext(_context = context, app) {
4567
+ return _providePermissionsContext(_context, app);
4568
+ }
4569
+ return createTrinity(usePermissionsContext, providePermissionsContext, context);
4570
+ }
4571
+ /**
4572
+ * Creates a new permissions plugin.
4573
+ *
4574
+ * @param options The options for the permissions plugin.
4575
+ * @template Z The type of the permission ticket.
4576
+ * @template E The type of the permission context.
4577
+ * @returns A new permissions plugin.
4578
+ *
4579
+ * @see https://0.vuetifyjs.com/composables/plugins/use-permissions
4580
+ *
4581
+ * @example
4582
+ * ```ts
4583
+ * import { createApp } from 'vue'
4584
+ * import { createPermissionsPlugin } from '@vuetify/v0'
4585
+ * import App from './App.vue'
4586
+ *
4587
+ * const app = createApp(App)
4588
+ *
4589
+ * app.use(
4590
+ * createPermissionsPlugin({
4591
+ * permissions: {
4592
+ * admin: [['read', 'users']],
4593
+ * editor: [['edit', 'posts']],
4594
+ * },
4595
+ * })
4596
+ * )
4597
+ *
4598
+ * app.mount('#app')
4599
+ * ```
4600
+ */
4601
+ function createPermissionsPlugin(_options = {}) {
4602
+ const { namespace = "v0:permissions",...options } = _options;
4603
+ const [, providePermissionContext, context] = createPermissionsContext({
4604
+ ...options,
4605
+ namespace
4606
+ });
4607
+ return createPlugin({
4608
+ namespace,
4609
+ provide: (app) => {
4610
+ providePermissionContext(context, app);
4611
+ }
4612
+ });
4613
+ }
4614
+ /**
4615
+ * Returns the current permissions instance.
4616
+ *
4617
+ * @template Z The type of the permission ticket.
4618
+ * @returns The current permissions instance.
4619
+ *
4620
+ * @see https://0.vuetifyjs.com/composables/plugins/use-permissions
4621
+ *
4622
+ * @example
4623
+ * ```vue
4624
+ * <script setup lang="ts">
4625
+ * import { usePermissions } from '@vuetify/v0'
4626
+ *
4627
+ * const { can } = usePermissions()
4628
+ * <\/script>
4629
+ *
4630
+ * <template>
4631
+ * <div>
4632
+ * <p v-if="can('admin', 'read', 'users')">Admin access</p>
4633
+ * </div>
4634
+ * </template>
4635
+ * ```
4636
+ */
4637
+ function usePermissions(namespace = "v0:permissions") {
4638
+ return useContext(namespace);
4639
+ }
4640
+
4641
+ //#endregion
4642
+ //#region src/composables/useProxyModel/index.ts
4643
+ /**
4644
+ * @module useProxyModel
4645
+ *
4646
+ * @remarks
4647
+ * Proxy composable for bidirectional sync between selection registry and v-model.
4648
+ *
4649
+ * Key features:
4650
+ * - Bidirectional synchronization
4651
+ * - Array and single-value modes
4652
+ * - Automatic cleanup on scope disposal
4653
+ * - Perfect for form controls with selection backing
4654
+ *
4655
+ * Bridges the gap between selection composables and Vue's v-model.
4656
+ */
4657
+ /**
4658
+ * Syncs a ref with a selection registry bidirectionally.
4659
+ *
4660
+ * @param registry The selection registry to bind to.
4661
+ * @param model The ref to sync.
4662
+ * @param options The options for the proxy model.
4663
+ * @template Z The type of the selection ticket.
4664
+ * @returns A function to stop the sync.
4665
+ *
4666
+ * @see https://0.vuetifyjs.com/composables/forms/use-proxy-model
4667
+ *
4668
+ * @example
4669
+ * ```ts
4670
+ * import { createSelection, useProxyModel } from '@vuetify/v0'
4671
+ *
4672
+ * const model = ref()
4673
+ * const registry = createSelection({ events: true })
4674
+ * registry.onboard([
4675
+ * { id: 'item-1', value: 'Item 1' },
4676
+ * { id: 'item-2', value: 'Item 2' },
4677
+ * ])
4678
+ *
4679
+ * const stop = useProxyModel(registry, model)
4680
+ * ```
4681
+ */
4682
+ function useProxyModel(registry, model, options) {
4683
+ const multiple = options?.multiple ?? false;
4684
+ const _transformIn = options?.transformIn;
4685
+ const _transformOut = options?.transformOut;
4686
+ function transformIn(val) {
4687
+ const value = toValue(val);
4688
+ return toArray(/* @__PURE__ */ isFunction(_transformIn) ? _transformIn(value) : value);
4689
+ }
4690
+ function transformOut(val) {
4691
+ if (/* @__PURE__ */ isFunction(_transformOut)) return _transformOut(val);
4692
+ return multiple ? val : val[0];
4693
+ }
4694
+ const modelAsArray = transformIn(model);
4695
+ const pending = new Set(modelAsArray);
4696
+ for (const value of modelAsArray) {
4697
+ const ids = registry.browse(value);
4698
+ if (/* @__PURE__ */ isArray(ids)) {
4699
+ for (const id of ids) registry.select(id);
4700
+ pending.delete(value);
4701
+ } else if (ids) {
4702
+ registry.select(ids);
4703
+ pending.delete(value);
4704
+ }
4705
+ }
4706
+ const registryWatch = watch(registry.selectedValues, (val) => {
4707
+ modelWatch.pause();
4708
+ model.value = transformOut(Array.from(toValue(val)));
4709
+ modelWatch.resume();
4710
+ }, { flush: "sync" });
4711
+ const modelWatch = watch(model, (val) => {
4712
+ registryWatch.pause();
4713
+ const currentIds = new Set(toValue(registry.selectedIds));
4714
+ const targetIds = /* @__PURE__ */ new Set();
4715
+ for (const value of transformIn(val)) {
4716
+ const ids = registry.browse(value);
4717
+ if (/* @__PURE__ */ isArray(ids)) for (const single of ids) targetIds.add(single);
4718
+ else if (ids) targetIds.add(ids);
4719
+ }
4720
+ if (multiple) {
4721
+ for (const id of currentIds.difference(targetIds)) registry.selectedIds.delete(id);
4722
+ for (const id of targetIds.difference(currentIds)) registry.selectedIds.add(id);
4723
+ } else {
4724
+ const next = targetIds.values().next().value;
4725
+ const last = currentIds.values().next().value;
4726
+ if (!/* @__PURE__ */ isUndefined(last)) registry.unselect(last);
4727
+ if (!/* @__PURE__ */ isUndefined(next)) registry.select(next);
4728
+ }
4729
+ registryWatch.resume();
4730
+ }, {
4731
+ flush: "sync",
4732
+ deep: multiple
3854
4733
  });
3855
- function update() {
3856
- state.keys = registry.keys();
3857
- state.values = registry.values();
3858
- state.entries = registry.entries();
3859
- state.size = registry.size;
4734
+ function onRegister(ticket) {
4735
+ if (!pending.has(ticket.value) || ticket.disabled) return;
4736
+ registryWatch.pause();
4737
+ modelWatch.pause();
4738
+ registry.select(ticket.id);
4739
+ pending.delete(ticket.value);
4740
+ modelWatch.resume();
4741
+ registryWatch.resume();
3860
4742
  }
3861
- registry.on("register:ticket", update);
3862
- registry.on("unregister:ticket", update);
3863
- registry.on("update:ticket", update);
3864
- registry.on("clear:registry", update);
3865
- onScopeDispose(() => {
3866
- registry.off("register:ticket", update);
3867
- registry.off("unregister:ticket", update);
3868
- registry.off("update:ticket", update);
3869
- registry.off("clear:registry", update);
3870
- }, true);
3871
- return state;
4743
+ registry.on("register:ticket", onRegister);
4744
+ function stop() {
4745
+ registryWatch();
4746
+ modelWatch();
4747
+ registry.off("register:ticket", onRegister);
4748
+ }
4749
+ onScopeDispose(stop, true);
4750
+ return stop;
3872
4751
  }
3873
4752
 
3874
4753
  //#endregion
@@ -3922,300 +4801,144 @@ function useProxyRegistry(registry, options) {
3922
4801
  function createQueue(_options = {}) {
3923
4802
  const { timeout: _timeout = 3e3,...options } = _options;
3924
4803
  const registry = useRegistry({
3925
- ...options,
3926
- events: true
3927
- });
3928
- const timeouts = /* @__PURE__ */ new Map();
3929
- function startTimeout(ticket) {
3930
- if (ticket.timeout === void 0 || ticket.timeout === -1 || ticket.isPaused) return;
3931
- const timeout = setTimeout(() => {
3932
- timeouts.delete(ticket.id);
3933
- registry.unregister(ticket.id);
3934
- resume();
3935
- }, ticket.timeout);
3936
- timeouts.set(ticket.id, timeout);
3937
- }
3938
- function clearTimeout(id) {
3939
- const timeout = timeouts.get(id);
3940
- if (timeout) {
3941
- globalThis.clearTimeout(timeout);
3942
- timeouts.delete(id);
3943
- }
3944
- }
3945
- function register(registration = {}) {
3946
- const id = registration.id ?? /* @__PURE__ */ genId();
3947
- const timeout = Object.prototype.hasOwnProperty.call(registration, "timeout") ? registration.timeout : _timeout;
3948
- const ticket = {
3949
- ...registration,
3950
- id,
3951
- timeout,
3952
- isPaused: registry.size > 0,
3953
- dismiss: () => unregister(id)
3954
- };
3955
- const registered = registry.register(ticket);
3956
- startTimeout(registered);
3957
- return registered;
3958
- }
3959
- function unregister(id) {
3960
- const ticket = id === void 0 ? registry.seek("first") : registry.get(id);
3961
- if (!ticket) return void 0;
3962
- const wasFirst = ticket.index === 0;
3963
- clearTimeout(ticket.id);
3964
- registry.unregister(ticket.id);
3965
- if (wasFirst) resume();
3966
- return ticket;
3967
- }
3968
- function pause() {
3969
- const ticket = registry.seek("first");
3970
- if (!ticket || ticket.isPaused) return void 0;
3971
- clearTimeout(ticket.id);
3972
- registry.upsert(ticket.id, { isPaused: true });
3973
- return ticket;
3974
- }
3975
- function resume() {
3976
- const ticket = registry.seek("first");
3977
- if (!ticket || ticket.index !== 0 || !ticket.isPaused) return void 0;
3978
- registry.upsert(ticket.id, { isPaused: false });
3979
- startTimeout(ticket);
3980
- return ticket;
3981
- }
3982
- function clear() {
3983
- for (const id of timeouts.keys()) clearTimeout(id);
3984
- registry.clear();
3985
- }
3986
- function dispose() {
3987
- clear();
3988
- registry.dispose();
3989
- }
3990
- onScopeDispose(dispose, true);
3991
- return {
3992
- ...registry,
3993
- register,
3994
- unregister,
3995
- pause,
3996
- resume,
3997
- clear,
3998
- dispose,
3999
- get size() {
4000
- return registry.size;
4001
- }
4002
- };
4003
- }
4004
- /**
4005
- * Creates a new queue context.
4006
- *
4007
- * @param namespace The namespace for the queue context.
4008
- * @param options The options for the queue context.
4009
- * @template Z The type of the queue ticket.
4010
- * @template E The type of the queue context.
4011
- * @returns A new queue context.
4012
- *
4013
- * @see https://0.vuetifyjs.com/composables/registration/use-queue
4014
- *
4015
- * @example
4016
- * ```ts
4017
- * import { createQueueContext } from '@vuetify/v0'
4018
- *
4019
- * export const [useQueue, provideQueue] = createQueueContext('v0:queue', {
4020
- * timeout: 5000,
4021
- * })
4022
- * ```
4023
- */
4024
- function createQueueContext(_options) {
4025
- const { namespace,...options } = _options;
4026
- const [useQueueContext, _provideQueueContext] = createContext(namespace);
4027
- const context = createQueue(options);
4028
- function provideQueueContext(_context = context, app) {
4029
- return _provideQueueContext(_context, app);
4030
- }
4031
- return createTrinity(useQueueContext, provideQueueContext, context);
4032
- }
4033
- /**
4034
- * Returns the current queue instance.
4035
- *
4036
- * @param namespace The namespace for the queue context. Defaults to `'v0:queue'`.
4037
- * @returns The current queue instance.
4038
- *
4039
- * @see https://0.vuetifyjs.com/composables/registration/use-queue
4040
- *
4041
- * @example
4042
- * ```vue
4043
- * <script setup lang="ts">
4044
- * import { useQueue } from '@vuetify/v0'
4045
- *
4046
- * const queue = useQueue()
4047
- * <\/script>
4048
- * ```
4049
- */
4050
- function useQueue(namespace = "v0:queue") {
4051
- return useContext(namespace);
4052
- }
4053
-
4054
- //#endregion
4055
- //#region src/composables/useResizeObserver/index.ts
4056
- /**
4057
- * @module useResizeObserver
4058
- *
4059
- * @remarks
4060
- * ResizeObserver composable with lifecycle management.
4061
- *
4062
- * Key features:
4063
- * - ResizeObserver API wrapper
4064
- * - Pause/resume/stop functionality
4065
- * - Automatic cleanup on unmount
4066
- * - SSR-safe (checks SUPPORTS_OBSERVER)
4067
- * - Hydration-aware
4068
- * - Box model options (content-box/border-box)
4069
- *
4070
- * Perfect for responsive components and size-based rendering.
4071
- */
4072
- /**
4073
- * A composable that uses the Resize Observer API to detect when an element's
4074
- * size changes.
4075
- *
4076
- * @param target The element to observe.
4077
- * @param callback The callback to execute when the element's size changes.
4078
- * @param options The options for the Resize Observer.
4079
- * @returns An object with methods to control the observer.
4080
- *
4081
- * @see https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver
4082
- * @see https://0.vuetifyjs.com/composables/system/use-resize-observer
4083
- *
4084
- * @example
4085
- * ```ts
4086
- * import { ref } from 'vue'
4087
- * import { useResizeObserver } from '@vuetify/v0'
4088
- *
4089
- * const el = ref<HTMLElement>()
4090
- * const width = ref(0)
4091
- * const height = ref(0)
4092
- *
4093
- * const { pause, resume, isPaused } = useResizeObserver(
4094
- * el,
4095
- * (entries) => {
4096
- * const entry = entries[0]
4097
- * if (entry) {
4098
- * width.value = entry.contentRect.width
4099
- * height.value = entry.contentRect.height
4100
- * console.log('Size changed:', width.value, 'x', height.value)
4101
- * }
4102
- * },
4103
- * { immediate: true }
4104
- * )
4105
- *
4106
- * // Pause observation
4107
- * pause()
4108
- *
4109
- * // Resume observation
4110
- * resume()
4111
- * ```
4112
- */
4113
- function useResizeObserver(target, callback, options = {}) {
4114
- const { isHydrated } = useHydration();
4115
- const observer = shallowRef();
4116
- const isPaused = shallowRef(false);
4117
- function setup() {
4118
- if (!isHydrated.value || !SUPPORTS_OBSERVER || !target.value || isPaused.value) return;
4119
- observer.value = new ResizeObserver((entries) => {
4120
- callback(entries.map((entry) => ({
4121
- contentRect: {
4122
- width: entry.contentRect.width,
4123
- height: entry.contentRect.height,
4124
- top: entry.contentRect.top,
4125
- left: entry.contentRect.left
4126
- },
4127
- target: entry.target
4128
- })));
4129
- });
4130
- observer.value.observe(target.value, { box: options.box || "content-box" });
4131
- if (options.immediate) {
4132
- const rect = target.value.getBoundingClientRect();
4133
- callback([{
4134
- contentRect: {
4135
- width: rect.width,
4136
- height: rect.height,
4137
- top: rect.top,
4138
- left: rect.left
4139
- },
4140
- target: target.value
4141
- }]);
4804
+ ...options,
4805
+ events: true
4806
+ });
4807
+ const timeouts = /* @__PURE__ */ new Map();
4808
+ function startTimeout(ticket) {
4809
+ if (/* @__PURE__ */ isUndefined(ticket.timeout) || ticket.timeout < 0 || ticket.isPaused) return;
4810
+ const timeout = setTimeout(() => {
4811
+ timeouts.delete(ticket.id);
4812
+ registry.unregister(ticket.id);
4813
+ resume();
4814
+ }, ticket.timeout);
4815
+ timeouts.set(ticket.id, timeout);
4816
+ }
4817
+ function clearTimeout$1(id) {
4818
+ const timeout = timeouts.get(id);
4819
+ if (timeout) {
4820
+ globalThis.clearTimeout(timeout);
4821
+ timeouts.delete(id);
4142
4822
  }
4143
4823
  }
4144
- watch([isHydrated, target], () => {
4145
- cleanup();
4146
- setup();
4147
- }, { immediate: true });
4148
- function cleanup() {
4149
- if (observer.value) {
4150
- observer.value.disconnect();
4151
- observer.value = void 0;
4824
+ function register(registration = {}) {
4825
+ const id = registration.id ?? /* @__PURE__ */ genId();
4826
+ const timeout = Object.prototype.hasOwnProperty.call(registration, "timeout") ? registration.timeout : _timeout;
4827
+ const ticket = {
4828
+ ...registration,
4829
+ id,
4830
+ timeout,
4831
+ isPaused: registry.size > 0,
4832
+ dismiss: () => unregister(id)
4833
+ };
4834
+ const registered = registry.register(ticket);
4835
+ startTimeout(registered);
4836
+ return registered;
4837
+ }
4838
+ function unregister(id) {
4839
+ const ticket = /* @__PURE__ */ isUndefined(id) ? registry.seek("first") : registry.get(id);
4840
+ if (!ticket) return void 0;
4841
+ const wasFirst = ticket.index === 0;
4842
+ clearTimeout$1(ticket.id);
4843
+ registry.unregister(ticket.id);
4844
+ if (wasFirst) resume();
4845
+ return ticket;
4846
+ }
4847
+ function offboard(ids) {
4848
+ let hadFirst = false;
4849
+ for (const id of ids) {
4850
+ const ticket = registry.get(id);
4851
+ if (!ticket) continue;
4852
+ if (ticket.index === 0) hadFirst = true;
4853
+ clearTimeout$1(ticket.id);
4152
4854
  }
4855
+ registry.offboard(ids);
4856
+ if (hadFirst) resume();
4153
4857
  }
4154
4858
  function pause() {
4155
- isPaused.value = true;
4156
- observer.value?.disconnect();
4859
+ const ticket = registry.seek("first");
4860
+ if (!ticket || ticket.isPaused) return void 0;
4861
+ clearTimeout$1(ticket.id);
4862
+ return registry.upsert(ticket.id, { isPaused: true });
4157
4863
  }
4158
4864
  function resume() {
4159
- isPaused.value = false;
4160
- setup();
4865
+ const ticket = registry.seek("first");
4866
+ if (!ticket || ticket.index !== 0 || !ticket.isPaused) return void 0;
4867
+ const updated = registry.upsert(ticket.id, { isPaused: false });
4868
+ startTimeout(updated);
4869
+ return updated;
4161
4870
  }
4162
- function stop() {
4163
- cleanup();
4871
+ function clear() {
4872
+ for (const id of timeouts.keys()) clearTimeout$1(id);
4873
+ registry.clear();
4874
+ }
4875
+ function dispose() {
4876
+ clear();
4877
+ registry.dispose();
4164
4878
  }
4165
- onUnmounted(stop);
4879
+ onScopeDispose(dispose, true);
4166
4880
  return {
4167
- isPaused: readonly(isPaused),
4881
+ ...registry,
4882
+ register,
4883
+ unregister,
4884
+ offboard,
4168
4885
  pause,
4169
4886
  resume,
4170
- stop
4887
+ clear,
4888
+ dispose,
4889
+ get size() {
4890
+ return registry.size;
4891
+ }
4171
4892
  };
4172
4893
  }
4173
4894
  /**
4174
- * A convenience composable that uses the Resize Observer API to track an
4175
- * element's size.
4895
+ * Creates a new queue context.
4176
4896
  *
4177
- * @param target The element to observe.
4178
- * @returns An object with the element's width and height.
4897
+ * @param namespace The namespace for the queue context.
4898
+ * @param options The options for the queue context.
4899
+ * @template Z The type of the queue ticket.
4900
+ * @template E The type of the queue context.
4901
+ * @returns A new queue context.
4179
4902
  *
4180
- * @see https://0.vuetifyjs.com/composables/system/use-resize-observer#use-element-size
4903
+ * @see https://0.vuetifyjs.com/composables/registration/use-queue
4181
4904
  *
4182
4905
  * @example
4183
4906
  * ```ts
4184
- * import { ref, watchEffect } from 'vue'
4185
- * import { useElementSize } from '@vuetify/v0'
4186
- *
4187
- * const box = ref<HTMLElement>()
4188
- * const { width, height } = useElementSize(box)
4907
+ * import { createQueueContext } from '@vuetify/v0'
4189
4908
  *
4190
- * // Width and height are reactive refs
4191
- * watchEffect(() => {
4192
- * console.log('Box size:', width.value, 'x', height.value)
4909
+ * export const [useQueue, provideQueue] = createQueueContext('v0:queue', {
4910
+ * timeout: 5000,
4193
4911
  * })
4194
4912
  * ```
4195
4913
  */
4196
- function useElementSize(target) {
4197
- const width = shallowRef(0);
4198
- const height = shallowRef(0);
4199
- const { pause: _pause, resume, stop, isPaused } = useResizeObserver(target, (entries) => {
4200
- const entry = entries[0];
4201
- if (entry) {
4202
- width.value = entry.contentRect.width;
4203
- height.value = entry.contentRect.height;
4204
- }
4205
- }, { immediate: true });
4206
- function pause() {
4207
- width.value = 0;
4208
- height.value = 0;
4209
- _pause();
4914
+ function createQueueContext(_options) {
4915
+ const { namespace,...options } = _options;
4916
+ const [useQueueContext, _provideQueueContext] = createContext(namespace);
4917
+ const context = createQueue(options);
4918
+ function provideQueueContext(_context = context, app) {
4919
+ return _provideQueueContext(_context, app);
4210
4920
  }
4211
- return {
4212
- width,
4213
- height,
4214
- isPaused,
4215
- pause,
4216
- resume,
4217
- stop
4218
- };
4921
+ return createTrinity(useQueueContext, provideQueueContext, context);
4922
+ }
4923
+ /**
4924
+ * Returns the current queue instance.
4925
+ *
4926
+ * @param namespace The namespace for the queue context. Defaults to `'v0:queue'`.
4927
+ * @returns The current queue instance.
4928
+ *
4929
+ * @see https://0.vuetifyjs.com/composables/registration/use-queue
4930
+ *
4931
+ * @example
4932
+ * ```vue
4933
+ * <script setup lang="ts">
4934
+ * import { useQueue } from '@vuetify/v0'
4935
+ *
4936
+ * const queue = useQueue()
4937
+ * <\/script>
4938
+ * ```
4939
+ */
4940
+ function useQueue(namespace = "v0:queue") {
4941
+ return useContext(namespace);
4219
4942
  }
4220
4943
 
4221
4944
  //#endregion
@@ -4331,13 +5054,13 @@ function createStep(_options = {}) {
4331
5054
  let index = circular ? wrapped(length, currentIndex + count) : currentIndex + count;
4332
5055
  if (!circular && (index < 0 || index >= length)) return;
4333
5056
  let id = registry.lookup(index);
4334
- while (id !== void 0 && toValue(registry.get(id)?.disabled) && hops < length) {
5057
+ while (!/* @__PURE__ */ isUndefined(id) && toValue(registry.get(id)?.disabled) && hops < length) {
4335
5058
  index = circular ? wrapped(length, index + direction) : index + direction;
4336
5059
  if (!circular && (index < 0 || index >= length)) return;
4337
5060
  id = registry.lookup(index);
4338
5061
  hops++;
4339
5062
  }
4340
- if (id === void 0 || hops === length) return;
5063
+ if (/* @__PURE__ */ isUndefined(id) || hops === length) return;
4341
5064
  registry.selectedIds.clear();
4342
5065
  registry.select(id);
4343
5066
  }
@@ -4356,7 +5079,6 @@ function createStep(_options = {}) {
4356
5079
  /**
4357
5080
  * Creates a new step context.
4358
5081
  *
4359
- * @param namespace The namespace for the step context.
4360
5082
  * @param options The options for the step context.
4361
5083
  * @template Z The type of the step ticket.
4362
5084
  * @template E The type of the step context.
@@ -4368,18 +5090,19 @@ function createStep(_options = {}) {
4368
5090
  * ```ts
4369
5091
  * import { createStepContext } from '@vuetify/v0'
4370
5092
  *
4371
- * export const [useWizard, provideWizard, wizard] = createStepContext('wizard')
5093
+ * // With default namespace 'v0:step'
5094
+ * export const [useStep, provideStep, context] = createStepContext()
4372
5095
  *
4373
5096
  * // In a parent component:
4374
- * provideWizard()
5097
+ * provideStep()
4375
5098
  *
4376
5099
  * // In a child component:
4377
- * const wizard = useWizard()
4378
- * wizard.next() // Progress to next step
5100
+ * const context = useStep()
5101
+ * context.next() // Progress to next step
4379
5102
  * ```
4380
5103
  */
4381
- function createStepContext(_options) {
4382
- const { namespace,...options } = _options;
5104
+ function createStepContext(_options = {}) {
5105
+ const { namespace = "v0:step",...options } = _options;
4383
5106
  const [useStepContext, _provideStepContext] = createContext(namespace);
4384
5107
  const context = createStep(options);
4385
5108
  function provideStepContext(_context = context, app) {
@@ -4458,7 +5181,6 @@ var MemoryAdapter = class {
4458
5181
  *
4459
5182
  * Uses adapter pattern to abstract storage implementation details.
4460
5183
  */
4461
- const [useStorageContext, provideStorageContext] = createContext("v0:storage");
4462
5184
  /**
4463
5185
  * Creates a new storage instance.
4464
5186
  *
@@ -4506,7 +5228,7 @@ function createStorage(options = {}) {
4506
5228
  }
4507
5229
  const valueRef = ref(initialValue);
4508
5230
  const stop = watch(valueRef, (newValue) => {
4509
- if (newValue === void 0 || newValue === null) adapter?.removeItem(prefixedKey);
5231
+ if (/* @__PURE__ */ isNullOrUndefined(newValue)) adapter?.removeItem(prefixedKey);
4510
5232
  else adapter?.setItem(prefixedKey, serializer.write(newValue));
4511
5233
  }, { deep: true });
4512
5234
  watchers.set(prefixedKey, stop);
@@ -4546,12 +5268,12 @@ function createStorage(options = {}) {
4546
5268
  }
4547
5269
  function createStorageContext(_options = {}) {
4548
5270
  const { namespace = "v0:storage",...options } = _options;
4549
- const [useStorageContext$1, _provideStorageContext] = createContext(namespace);
5271
+ const [useStorageContext, _provideStorageContext] = createContext(namespace);
4550
5272
  const context = createStorage(options);
4551
- function provideStorageContext$1(_context = context, app) {
5273
+ function provideStorageContext(_context = context, app) {
4552
5274
  return _provideStorageContext(_context, app);
4553
5275
  }
4554
- return createTrinity(useStorageContext$1, provideStorageContext$1, context);
5276
+ return createTrinity(useStorageContext, provideStorageContext, context);
4555
5277
  }
4556
5278
  /**
4557
5279
  * Creates a new storage plugin.
@@ -4576,14 +5298,14 @@ function createStorageContext(_options = {}) {
4576
5298
  */
4577
5299
  function createStoragePlugin(_options = {}) {
4578
5300
  const { namespace = "v0:storage",...options } = _options;
4579
- const [, provideStorageContext$1, context] = createStorageContext({
5301
+ const [, provideStorageContext, context] = createStorageContext({
4580
5302
  ...options,
4581
5303
  namespace
4582
5304
  });
4583
5305
  return createPlugin({
4584
5306
  namespace,
4585
5307
  provide: (app) => {
4586
- provideStorageContext$1(context, app);
5308
+ provideStorageContext(context, app);
4587
5309
  }
4588
5310
  });
4589
5311
  }
@@ -4631,7 +5353,7 @@ var ThemeAdapter = class {
4631
5353
  const vars = Object.entries(themeColors).map(([key, val]) => ` --${this.prefix}-${key}: ${val};`).join("\n");
4632
5354
  css += `[data-theme="${theme}"] {\n${vars}\n}\n`;
4633
5355
  }
4634
- if (isDark !== void 0) css += `:root {\n color-scheme: ${isDark ? "dark" : "light"};\n}\n`;
5356
+ if (!/* @__PURE__ */ isUndefined(isDark)) css += `:root {\n color-scheme: ${isDark ? "dark" : "light"};\n}\n`;
4635
5357
  return css;
4636
5358
  }
4637
5359
  };
@@ -5023,13 +5745,12 @@ function createTimeline(_options = {}) {
5023
5745
  };
5024
5746
  }
5025
5747
  /**
5026
- * Creates a new timeline plugin.
5748
+ * Creates a new timeline context.
5027
5749
  *
5028
- * @param namespace The namespace for the timeline plugin.
5029
- * @param options The options for the timeline plugin.
5750
+ * @param options The options for the timeline context.
5030
5751
  * @template Z The type of the timeline ticket.
5031
5752
  * @template E The type of the timeline context.
5032
- * @returns A new timeline plugin.
5753
+ * @returns A new timeline context.
5033
5754
  *
5034
5755
  * @see https://0.vuetifyjs.com/composables/registration/use-timeline
5035
5756
  *
@@ -5037,7 +5758,9 @@ function createTimeline(_options = {}) {
5037
5758
  * ```ts
5038
5759
  * import { createTimelineContext } from '@vuetify/v0'
5039
5760
  *
5040
- * export const [useTimeline, provideTimeline, context] = createTimelineContext('v0:timeline', { size: 5 })
5761
+ * // With default namespace 'v0:timeline'
5762
+ * export const [useTimeline, provideTimeline, context] = createTimelineContext({ size: 5 })
5763
+ *
5041
5764
  * context.register({ id: 'example' })
5042
5765
  *
5043
5766
  * // In a parent component
@@ -5049,39 +5772,409 @@ function createTimeline(_options = {}) {
5049
5772
  * console.log(timeline.values()) // [{ id: 'example' }]
5050
5773
  * ```
5051
5774
  */
5052
- function createTimelineContext(_options) {
5053
- const { namespace,...options } = _options;
5775
+ function createTimelineContext(_options = {}) {
5776
+ const { namespace = "v0:timeline",...options } = _options;
5054
5777
  const [useTimelineContext, _provideTimelineContext] = createContext(namespace);
5055
5778
  const context = createTimeline(options);
5056
5779
  function provideTimelineContext(_context = context, app) {
5057
5780
  return _provideTimelineContext(_context, app);
5058
5781
  }
5059
- return createTrinity(useTimelineContext, provideTimelineContext, context);
5060
- }
5061
- /**
5062
- * Returns the current timeline instance.
5063
- *
5064
- * @param namespace The namespace for the timeline context. Defaults to `'v0:timeline'`.
5065
- * @returns The current timeline instance.
5066
- *
5067
- * @see https://0.vuetifyjs.com/composables/registration/use-timeline
5068
- *
5069
- * @example
5070
- * ```vue
5071
- * <script setup lang="ts">
5072
- * import { useTimeline } from '@vuetify/v0'
5073
- *
5074
- * const timeline = useTimeline()
5075
- * <\/script>
5076
- * ```
5077
- */
5078
- function useTimeline(namespace = "v0:timeline") {
5079
- return useContext(namespace);
5782
+ return createTrinity(useTimelineContext, provideTimelineContext, context);
5783
+ }
5784
+ /**
5785
+ * Returns the current timeline instance.
5786
+ *
5787
+ * @param namespace The namespace for the timeline context. Defaults to `'v0:timeline'`.
5788
+ * @returns The current timeline instance.
5789
+ *
5790
+ * @see https://0.vuetifyjs.com/composables/registration/use-timeline
5791
+ *
5792
+ * @example
5793
+ * ```vue
5794
+ * <script setup lang="ts">
5795
+ * import { useTimeline } from '@vuetify/v0'
5796
+ *
5797
+ * const timeline = useTimeline()
5798
+ * <\/script>
5799
+ * ```
5800
+ */
5801
+ function useTimeline(namespace = "v0:timeline") {
5802
+ return useContext(namespace);
5803
+ }
5804
+
5805
+ //#endregion
5806
+ //#region src/composables/useToggleScope/index.ts
5807
+ /**
5808
+ * @module useToggleScope
5809
+ *
5810
+ * @remarks
5811
+ * Conditionally manages an effect scope based on a reactive boolean condition.
5812
+ * When the source becomes true, creates and runs an effect scope. When false, stops the scope.
5813
+ * All reactive effects created within the scoped function are automatically cleaned up on deactivation.
5814
+ *
5815
+ * Key features:
5816
+ * - Uses Vue's effectScope for efficient reactive effect lifecycle management
5817
+ * - Automatic cleanup when condition becomes false
5818
+ * - Supports optional reset callback for scope restart capability
5819
+ * - Handles rapid toggling and parent scope disposal safely
5820
+ * - SSR-safe (effectScope is part of Vue core)
5821
+ *
5822
+ * Perfect for conditional side effects, feature flags, and performance optimization
5823
+ * by only running reactive effects when needed.
5824
+ */
5825
+ /**
5826
+ * Conditionally manages an effect scope based on a reactive boolean source.
5827
+ *
5828
+ * @param source A reactive boolean value or getter that controls the scope lifecycle
5829
+ * @param fn The function to run within the effect scope. Can optionally receive controls for manual scope management.
5830
+ * @returns Controls object with isActive state and start/stop/reset methods
5831
+ *
5832
+ * @see https://vuejs.org/api/reactivity-advanced.html#effectscope
5833
+ * @see https://0.vuetifyjs.com/composables/system/use-toggle-scope
5834
+ *
5835
+ * @example
5836
+ * ```ts
5837
+ * import { ref } from 'vue'
5838
+ * import { useToggleScope } from '@vuetify/v0'
5839
+ *
5840
+ * const isEnabled = ref(false)
5841
+ *
5842
+ * const { isActive } = useToggleScope(isEnabled, () => {
5843
+ * // This code runs when isEnabled becomes true
5844
+ * const unwatch = watch(someRef, () => {
5845
+ * console.log('Watching...')
5846
+ * })
5847
+ *
5848
+ * // Cleanup happens automatically when isEnabled becomes false
5849
+ * })
5850
+ *
5851
+ * // Toggle the scope on/off
5852
+ * isEnabled.value = true // Starts the scope
5853
+ * console.log(isActive.value) // true
5854
+ * isEnabled.value = false // Stops and cleans up
5855
+ * console.log(isActive.value) // false
5856
+ * ```
5857
+ *
5858
+ * @example
5859
+ * With manual controls:
5860
+ * ```ts
5861
+ * const isEnabled = ref(true)
5862
+ *
5863
+ * useToggleScope(isEnabled, (controls) => {
5864
+ * // Access controls inside the scope
5865
+ * console.log('Active:', controls.isActive.value)
5866
+ *
5867
+ * // Manually reset the scope if needed
5868
+ * someEvent.on('reset', () => controls.reset())
5869
+ * })
5870
+ * ```
5871
+ */
5872
+ function useToggleScope(source, fn) {
5873
+ const scope = shallowRef();
5874
+ const isActive = toRef(() => !!scope.value);
5875
+ function start() {
5876
+ if (scope.value) return;
5877
+ scope.value = effectScope();
5878
+ scope.value.run(() => fn.length > 0 ? fn(controls) : fn());
5879
+ }
5880
+ function stop() {
5881
+ scope.value?.stop();
5882
+ scope.value = void 0;
5883
+ }
5884
+ function reset() {
5885
+ stop();
5886
+ start();
5887
+ }
5888
+ const controls = {
5889
+ isActive: shallowReadonly(isActive),
5890
+ start,
5891
+ stop,
5892
+ reset
5893
+ };
5894
+ watch(source, (active) => {
5895
+ if (active && !scope.value) start();
5896
+ else if (!active) stop();
5897
+ }, { immediate: true });
5898
+ onScopeDispose(() => {
5899
+ stop();
5900
+ });
5901
+ return controls;
5902
+ }
5903
+
5904
+ //#endregion
5905
+ //#region src/composables/useVirtual/index.ts
5906
+ /**
5907
+ * @module useVirtual
5908
+ *
5909
+ * @remarks
5910
+ * Virtual scrolling composable for efficiently rendering large lists.
5911
+ *
5912
+ * Key features:
5913
+ * - Renders only visible items (viewport + overscan)
5914
+ * - Dynamic or fixed item heights
5915
+ * - SSR-safe (checks IN_BROWSER)
5916
+ * - Bidirectional scrolling (forward/reverse for chat apps)
5917
+ * - Scroll anchoring (maintains position across data changes)
5918
+ * - Edge detection for infinite scroll
5919
+ * - iOS momentum and elastic scrolling
5920
+ * - Configurable overscan (extra items rendered for smooth scrolling)
5921
+ *
5922
+ * Perfect for large data sets, chat apps, and infinite scroll implementations.
5923
+ */
5924
+ /**
5925
+ * Virtual scrolling composable for efficiently rendering large lists
5926
+ *
5927
+ * @param items Reactive array of items to virtualize
5928
+ * @param options Configuration options
5929
+ * @returns Virtual scrolling context
5930
+ *
5931
+ * @see https://0.vuetifyjs.com/composables/utilities/use-virtual
5932
+ *
5933
+ * @example
5934
+ * ```vue
5935
+ * <script setup lang="ts">
5936
+ * import { useVirtual } from '@vuetify/v0'
5937
+ *
5938
+ * const items = ref(Array.from({ length: 10000 }, (_, i) => ({ id: i, name: `Item ${i}` })))
5939
+ * <\/script>
5940
+ *
5941
+ * <template>
5942
+ * <div
5943
+ * ref="element"
5944
+ * style="height: 600px; overflow-y: auto;"
5945
+ * @scroll="scroll"
5946
+ * >
5947
+ * <div :style="{ height: `${offset}px` }" />
5948
+ *
5949
+ * <div v-for="item in items" :key="item.index">
5950
+ * {{ item.raw.name }}
5951
+ * </div>
5952
+ *
5953
+ * <div :style="{ height: `${size}px` }" />
5954
+ * </div>
5955
+ * </template>
5956
+ * ```
5957
+ */
5958
+ function useVirtual(items, _options = {}) {
5959
+ const { itemHeight: _itemHeight, height, overscan = 5, direction = "forward", anchor = "auto", anchorSmooth = true, onStartReached, onEndReached, startThreshold = 0, endThreshold = 0, momentum: momentumOption, elastic: elasticOption } = _options;
5960
+ const element = ref();
5961
+ const itemHeight = shallowRef(Number.parseFloat(String(_itemHeight || 0)));
5962
+ const heights = shallowRef([]);
5963
+ const offsets = shallowRef([]);
5964
+ const first = shallowRef(0);
5965
+ const last = shallowRef(0);
5966
+ const offset = shallowRef(0);
5967
+ const size = shallowRef(0);
5968
+ const viewportHeight = shallowRef(0);
5969
+ const state = shallowRef("ok");
5970
+ const isIOS = IN_BROWSER && /iPad|iPhone|iPod/.test(navigator.userAgent);
5971
+ const momentum = momentumOption ?? isIOS;
5972
+ const elastic = elasticOption ?? isIOS;
5973
+ let raf = -1;
5974
+ let rebuildRaf = -1;
5975
+ let edgeRaf = -1;
5976
+ const cachedViewport = Number.parseInt(String(height)) || 0;
5977
+ let anchorIndex = -1;
5978
+ let anchorOffset = 0;
5979
+ const computedItems = computed(() => items.value.slice(first.value, last.value).map((item, i) => ({
5980
+ raw: item,
5981
+ index: i + first.value
5982
+ })));
5983
+ watch(element, (el) => {
5984
+ if (!IN_BROWSER || !el?.style) return;
5985
+ if (momentum) el.style.webkitOverflowScrolling = "touch";
5986
+ if (!elastic) el.style.overscrollBehavior = "none";
5987
+ });
5988
+ useResizeObserver(element, (entries) => {
5989
+ if (!entries[0]) return;
5990
+ viewportHeight.value = entries[0].contentRect.height;
5991
+ update();
5992
+ });
5993
+ watch(items, (newItems) => {
5994
+ captureAnchor();
5995
+ const length = newItems.length;
5996
+ const newHeights = heights.value.length === length ? heights.value : Array.from({ length }, () => null);
5997
+ if (heights.value !== newHeights) heights.value = newHeights;
5998
+ rebuild();
5999
+ }, { immediate: true });
6000
+ watch(element, () => {
6001
+ if (!element.value) return;
6002
+ if (direction === "reverse" && items.value.length > 0) {
6003
+ const lastIndex = items.value.length - 1;
6004
+ const totalHeight = (offsets.value[lastIndex] || 0) + (heights.value[lastIndex] || itemHeight.value);
6005
+ element.value.scrollTop = totalHeight;
6006
+ }
6007
+ update();
6008
+ });
6009
+ function captureAnchor() {
6010
+ if (!element.value || anchor === "auto") return;
6011
+ if (anchor === "start") {
6012
+ anchorIndex = 0;
6013
+ anchorOffset = 0;
6014
+ } else if (anchor === "end") {
6015
+ anchorIndex = items.value.length - 1;
6016
+ anchorOffset = 0;
6017
+ } else if (/* @__PURE__ */ isFunction(anchor)) {
6018
+ const result = anchor(items.value);
6019
+ if (/* @__PURE__ */ isNumber(result)) {
6020
+ anchorIndex = result;
6021
+ anchorOffset = element.value.scrollTop - (offsets.value[result] || 0);
6022
+ }
6023
+ } else {
6024
+ anchorIndex = first.value;
6025
+ anchorOffset = element.value.scrollTop - (offsets.value[first.value] || 0);
6026
+ }
6027
+ }
6028
+ function restoreAnchor() {
6029
+ if (!element.value || anchorIndex < 0) return;
6030
+ const newScrollTop = (offsets.value[anchorIndex] || 0) + anchorOffset;
6031
+ if (anchorSmooth && direction === "forward") element.value.scrollTo({
6032
+ top: newScrollTop,
6033
+ behavior: "smooth"
6034
+ });
6035
+ else element.value.scrollTop = newScrollTop;
6036
+ anchorIndex = -1;
6037
+ anchorOffset = 0;
6038
+ }
6039
+ function rebuild() {
6040
+ const length = items.value.length;
6041
+ const newOffsets = offsets.value.length === length ? offsets.value : Array.from({ length });
6042
+ let offset$1 = 0;
6043
+ for (let i = 0; i < length; i++) {
6044
+ newOffsets[i] = offset$1;
6045
+ offset$1 += heights.value[i] || itemHeight.value;
6046
+ }
6047
+ if (offsets.value !== newOffsets) offsets.value = newOffsets;
6048
+ update();
6049
+ restoreAnchor();
6050
+ }
6051
+ function findIndex(scrollTop) {
6052
+ const arr = offsets.value;
6053
+ if (arr.length === 0) return 0;
6054
+ let low = 0;
6055
+ let high = arr.length - 1;
6056
+ while (low <= high) {
6057
+ const mid = low + high >> 1;
6058
+ if (arr[mid] <= scrollTop) low = mid + 1;
6059
+ else high = mid - 1;
6060
+ }
6061
+ return Math.max(0, high);
6062
+ }
6063
+ function update() {
6064
+ if (!element.value) return;
6065
+ const viewport = viewportHeight.value || cachedViewport;
6066
+ if (!viewport || !itemHeight.value) return;
6067
+ const scrollTop = element.value.scrollTop || 0;
6068
+ const length = items.value.length;
6069
+ const visibleStart = findIndex(scrollTop);
6070
+ const visibleEnd = findIndex(scrollTop + viewport) + 1;
6071
+ const start = /* @__PURE__ */ clamp(visibleStart - overscan, 0, length);
6072
+ const end = /* @__PURE__ */ clamp(visibleEnd + overscan, start, length);
6073
+ first.value = start;
6074
+ last.value = end;
6075
+ offset.value = offsets.value[start] || 0;
6076
+ const lastIndex = length - 1;
6077
+ const totalHeight = (offsets.value[lastIndex] || 0) + (heights.value[lastIndex] || itemHeight.value);
6078
+ size.value = totalHeight - (offsets.value[end] || totalHeight);
6079
+ }
6080
+ function checkEdges() {
6081
+ if (!element.value) return;
6082
+ const scrollTop = element.value.scrollTop;
6083
+ const scrollHeight = element.value.scrollHeight;
6084
+ const clientHeight = element.value.clientHeight;
6085
+ const distanceFromStart = scrollTop;
6086
+ const distanceFromEnd = scrollHeight - (scrollTop + clientHeight);
6087
+ if (IN_BROWSER) {
6088
+ cancelAnimationFrame(edgeRaf);
6089
+ edgeRaf = requestAnimationFrame(() => {
6090
+ if (onStartReached && distanceFromStart <= startThreshold) onStartReached(distanceFromStart);
6091
+ if (onEndReached && distanceFromEnd <= endThreshold) onEndReached(distanceFromEnd);
6092
+ });
6093
+ } else {
6094
+ if (onStartReached && distanceFromStart <= startThreshold) onStartReached(distanceFromStart);
6095
+ if (onEndReached && distanceFromEnd <= endThreshold) onEndReached(distanceFromEnd);
6096
+ }
6097
+ }
6098
+ function resize(index, height$1) {
6099
+ if (heights.value[index] === height$1) return;
6100
+ heights.value[index] = height$1;
6101
+ if (!itemHeight.value) itemHeight.value = height$1;
6102
+ if (IN_BROWSER) {
6103
+ cancelAnimationFrame(rebuildRaf);
6104
+ rebuildRaf = requestAnimationFrame(rebuild);
6105
+ } else rebuild();
6106
+ }
6107
+ function scroll() {
6108
+ if (IN_BROWSER) {
6109
+ cancelAnimationFrame(raf);
6110
+ raf = requestAnimationFrame(update);
6111
+ checkEdges();
6112
+ } else update();
6113
+ }
6114
+ function scrollTo(index, scrollOptions) {
6115
+ if (!element.value) return;
6116
+ const targetOffset = offsets.value[index] || 0;
6117
+ const behavior = scrollOptions?.behavior ?? "auto";
6118
+ const block = scrollOptions?.block ?? "start";
6119
+ const extraOffset = scrollOptions?.offset ?? 0;
6120
+ let scrollTop = targetOffset + extraOffset;
6121
+ switch (block) {
6122
+ case "center": {
6123
+ const viewport = viewportHeight.value || cachedViewport;
6124
+ const itemH = heights.value[index] || itemHeight.value;
6125
+ scrollTop = targetOffset - viewport / 2 + itemH / 2 + extraOffset;
6126
+ break;
6127
+ }
6128
+ case "end": {
6129
+ const viewport = viewportHeight.value || cachedViewport;
6130
+ const itemH = heights.value[index] || itemHeight.value;
6131
+ scrollTop = targetOffset - viewport + itemH + extraOffset;
6132
+ break;
6133
+ }
6134
+ case "nearest": {
6135
+ const viewport = viewportHeight.value || cachedViewport;
6136
+ const currentScroll = element.value.scrollTop;
6137
+ const itemH = heights.value[index] || itemHeight.value;
6138
+ if (targetOffset < currentScroll) scrollTop = targetOffset + extraOffset;
6139
+ else if (targetOffset + itemH > currentScroll + viewport) scrollTop = targetOffset - viewport + itemH + extraOffset;
6140
+ else return;
6141
+ break;
6142
+ }
6143
+ }
6144
+ if (behavior === "smooth") element.value.scrollTo({
6145
+ top: scrollTop,
6146
+ behavior: "smooth"
6147
+ });
6148
+ else element.value.scrollTop = scrollTop;
6149
+ update();
6150
+ }
6151
+ function reset() {
6152
+ state.value = "ok";
6153
+ anchorIndex = -1;
6154
+ anchorOffset = 0;
6155
+ if (element.value && direction === "reverse" && items.value.length > 0) {
6156
+ const lastIndex = items.value.length - 1;
6157
+ const totalHeight = (offsets.value[lastIndex] || 0) + (heights.value[lastIndex] || itemHeight.value);
6158
+ element.value.scrollTop = totalHeight;
6159
+ }
6160
+ }
6161
+ return {
6162
+ element,
6163
+ items: computedItems,
6164
+ offset: readonly(offset),
6165
+ size: readonly(size),
6166
+ state,
6167
+ scrollTo,
6168
+ scroll,
6169
+ scrollend: scroll,
6170
+ resize,
6171
+ reset
6172
+ };
5080
6173
  }
5081
6174
 
5082
6175
  //#endregion
5083
6176
  //#region src/components/Avatar/AvatarFallback.vue
5084
- const _sfc_main$17 = /* @__PURE__ */ defineComponent({
6177
+ const _sfc_main$24 = /* @__PURE__ */ defineComponent({
5085
6178
  name: "AvatarFallback",
5086
6179
  __name: "AvatarFallback",
5087
6180
  props: {
@@ -5107,11 +6200,11 @@ const _sfc_main$17 = /* @__PURE__ */ defineComponent({
5107
6200
  };
5108
6201
  }
5109
6202
  });
5110
- var AvatarFallback_default = _sfc_main$17;
6203
+ var AvatarFallback_default = _sfc_main$24;
5111
6204
 
5112
6205
  //#endregion
5113
6206
  //#region src/components/Avatar/AvatarImage.vue
5114
- const _sfc_main$16 = /* @__PURE__ */ defineComponent({
6207
+ const _sfc_main$23 = /* @__PURE__ */ defineComponent({
5115
6208
  name: "AvatarImage",
5116
6209
  inheritAttrs: false,
5117
6210
  __name: "AvatarImage",
@@ -5168,11 +6261,11 @@ const _sfc_main$16 = /* @__PURE__ */ defineComponent({
5168
6261
  };
5169
6262
  }
5170
6263
  });
5171
- var AvatarImage_default = _sfc_main$16;
6264
+ var AvatarImage_default = _sfc_main$23;
5172
6265
 
5173
6266
  //#endregion
5174
6267
  //#region src/components/Avatar/AvatarRoot.vue
5175
- const _sfc_main$15 = /* @__PURE__ */ defineComponent({
6268
+ const _sfc_main$22 = /* @__PURE__ */ defineComponent({
5176
6269
  name: "AvatarRoot",
5177
6270
  __name: "AvatarRoot",
5178
6271
  props: {
@@ -5198,7 +6291,7 @@ const _sfc_main$15 = /* @__PURE__ */ defineComponent({
5198
6291
  };
5199
6292
  }
5200
6293
  });
5201
- var AvatarRoot_default = _sfc_main$15;
6294
+ var AvatarRoot_default = _sfc_main$22;
5202
6295
 
5203
6296
  //#endregion
5204
6297
  //#region src/components/Avatar/index.ts
@@ -5210,7 +6303,7 @@ const Avatar = {
5210
6303
 
5211
6304
  //#endregion
5212
6305
  //#region src/components/ExpansionPanel/ExpansionPanelActivator.vue
5213
- const _sfc_main$14 = /* @__PURE__ */ defineComponent({
6306
+ const _sfc_main$21 = /* @__PURE__ */ defineComponent({
5214
6307
  name: "ExpansionPanelActivator",
5215
6308
  __name: "ExpansionPanelActivator",
5216
6309
  props: {
@@ -5226,7 +6319,7 @@ const _sfc_main$14 = /* @__PURE__ */ defineComponent({
5226
6319
  context.ticket.toggle();
5227
6320
  }
5228
6321
  }
5229
- const bindableProps = computed(() => ({
6322
+ const slotProps = toRef(() => ({
5230
6323
  "id": context.headerId.value,
5231
6324
  "role": "button",
5232
6325
  "tabindex": context.isDisabled.value ? -1 : 0,
@@ -5238,20 +6331,24 @@ const _sfc_main$14 = /* @__PURE__ */ defineComponent({
5238
6331
  "onClick": context.ticket.toggle,
5239
6332
  onKeydown
5240
6333
  }));
6334
+ const isExpanded = toRef(() => context.ticket.isSelected.value);
6335
+ const isDisabled = toRef(() => context.isDisabled.value);
5241
6336
  return (_ctx, _cache) => {
5242
6337
  return openBlock(), createBlock(unref(Atom_default), {
5243
- id: bindableProps.value.id,
5244
- "aria-controls": bindableProps.value["aria-controls"],
5245
- "aria-disabled": bindableProps.value["aria-disabled"],
5246
- "aria-expanded": bindableProps.value["aria-expanded"],
6338
+ id: slotProps.value.id,
6339
+ "aria-controls": slotProps.value["aria-controls"],
6340
+ "aria-disabled": slotProps.value["aria-disabled"],
6341
+ "aria-expanded": slotProps.value["aria-expanded"],
5247
6342
  as: __props.as,
6343
+ "data-disabled": isDisabled.value ? "" : void 0,
6344
+ "data-expanded": isExpanded.value ? "" : void 0,
5248
6345
  renderless: __props.renderless,
5249
- role: bindableProps.value.role,
5250
- tabindex: bindableProps.value.tabindex,
6346
+ role: slotProps.value.role,
6347
+ tabindex: slotProps.value.tabindex,
5251
6348
  onClick: unref(context).ticket.toggle,
5252
6349
  onKeydown
5253
6350
  }, {
5254
- default: withCtx(() => [renderSlot(_ctx.$slots, "default", normalizeProps(guardReactiveProps(bindableProps.value)))]),
6351
+ default: withCtx(() => [renderSlot(_ctx.$slots, "default", normalizeProps(guardReactiveProps(slotProps.value)))]),
5255
6352
  _: 3
5256
6353
  }, 8, [
5257
6354
  "id",
@@ -5259,6 +6356,8 @@ const _sfc_main$14 = /* @__PURE__ */ defineComponent({
5259
6356
  "aria-disabled",
5260
6357
  "aria-expanded",
5261
6358
  "as",
6359
+ "data-disabled",
6360
+ "data-expanded",
5262
6361
  "renderless",
5263
6362
  "role",
5264
6363
  "tabindex",
@@ -5267,51 +6366,54 @@ const _sfc_main$14 = /* @__PURE__ */ defineComponent({
5267
6366
  };
5268
6367
  }
5269
6368
  });
5270
- var ExpansionPanelActivator_default = _sfc_main$14;
6369
+ var ExpansionPanelActivator_default = _sfc_main$21;
5271
6370
 
5272
6371
  //#endregion
5273
6372
  //#region src/components/ExpansionPanel/ExpansionPanelContent.vue
5274
- const _sfc_main$13 = /* @__PURE__ */ defineComponent({
6373
+ const _sfc_main$20 = /* @__PURE__ */ defineComponent({
5275
6374
  name: "ExpansionPanelContent",
5276
6375
  __name: "ExpansionPanelContent",
5277
6376
  props: {
5278
6377
  itemNamespace: { default: "v0:expansion-panel-item" },
5279
- as: {},
6378
+ as: { default: "div" },
5280
6379
  renderless: { type: Boolean }
5281
6380
  },
5282
6381
  setup(__props) {
5283
6382
  const context = useContext(__props.itemNamespace);
5284
- const bindableProps = computed(() => ({
6383
+ const slotProps = toRef(() => ({
5285
6384
  "id": context.contentId.value,
5286
6385
  "role": "region",
5287
6386
  "aria-labelledby": context.headerId.value,
5288
6387
  "isSelected": context.ticket.isSelected.value
5289
6388
  }));
6389
+ const isExpanded = toRef(() => context.ticket.isSelected.value);
5290
6390
  return (_ctx, _cache) => {
5291
6391
  return openBlock(), createBlock(unref(Atom_default), {
5292
- id: bindableProps.value.id,
5293
- "aria-labelledby": bindableProps.value["aria-labelledby"],
6392
+ id: slotProps.value.id,
6393
+ "aria-labelledby": slotProps.value["aria-labelledby"],
5294
6394
  as: __props.as,
6395
+ "data-expanded": isExpanded.value ? "" : void 0,
5295
6396
  renderless: __props.renderless,
5296
- role: bindableProps.value.role
6397
+ role: slotProps.value.role
5297
6398
  }, {
5298
- default: withCtx(() => [renderSlot(_ctx.$slots, "default", normalizeProps(guardReactiveProps(bindableProps.value)))]),
6399
+ default: withCtx(() => [renderSlot(_ctx.$slots, "default", normalizeProps(guardReactiveProps(slotProps.value)))]),
5299
6400
  _: 3
5300
6401
  }, 8, [
5301
6402
  "id",
5302
6403
  "aria-labelledby",
5303
6404
  "as",
6405
+ "data-expanded",
5304
6406
  "renderless",
5305
6407
  "role"
5306
6408
  ]);
5307
6409
  };
5308
6410
  }
5309
6411
  });
5310
- var ExpansionPanelContent_default = _sfc_main$13;
6412
+ var ExpansionPanelContent_default = _sfc_main$20;
5311
6413
 
5312
6414
  //#endregion
5313
6415
  //#region src/components/ExpansionPanel/ExpansionPanelItem.vue
5314
- const _sfc_main$12 = /* @__PURE__ */ defineComponent({
6416
+ const _sfc_main$19 = /* @__PURE__ */ defineComponent({
5315
6417
  name: "ExpansionPanelItem",
5316
6418
  __name: "ExpansionPanelItem",
5317
6419
  props: {
@@ -5354,11 +6456,11 @@ const _sfc_main$12 = /* @__PURE__ */ defineComponent({
5354
6456
  };
5355
6457
  }
5356
6458
  });
5357
- var ExpansionPanelItem_default = _sfc_main$12;
6459
+ var ExpansionPanelItem_default = _sfc_main$19;
5358
6460
 
5359
6461
  //#endregion
5360
6462
  //#region src/components/ExpansionPanel/ExpansionPanelRoot.vue
5361
- const _sfc_main$11 = /* @__PURE__ */ defineComponent({
6463
+ const _sfc_main$18 = /* @__PURE__ */ defineComponent({
5362
6464
  name: "ExpansionPanelRoot",
5363
6465
  __name: "ExpansionPanelRoot",
5364
6466
  props: /* @__PURE__ */ mergeModels({
@@ -5432,7 +6534,7 @@ const _sfc_main$11 = /* @__PURE__ */ defineComponent({
5432
6534
  };
5433
6535
  }
5434
6536
  });
5435
- var ExpansionPanelRoot_default = _sfc_main$11;
6537
+ var ExpansionPanelRoot_default = _sfc_main$18;
5436
6538
 
5437
6539
  //#endregion
5438
6540
  //#region src/components/ExpansionPanel/index.ts
@@ -5445,13 +6547,14 @@ const ExpansionPanel = {
5445
6547
 
5446
6548
  //#endregion
5447
6549
  //#region src/components/Group/GroupItem.vue
5448
- const _sfc_main$10 = /* @__PURE__ */ defineComponent({
6550
+ const _sfc_main$17 = /* @__PURE__ */ defineComponent({
5449
6551
  name: "GroupItem",
5450
6552
  __name: "GroupItem",
5451
6553
  props: {
5452
6554
  label: {},
5453
6555
  id: {},
5454
6556
  disabled: {},
6557
+ indeterminate: { default: false },
5455
6558
  value: {},
5456
6559
  namespace: { default: "v0:group" }
5457
6560
  },
@@ -5460,9 +6563,10 @@ const _sfc_main$10 = /* @__PURE__ */ defineComponent({
5460
6563
  const ticket = group.register({
5461
6564
  id: __props.id,
5462
6565
  value: __props.value,
5463
- disabled: __props.disabled
6566
+ disabled: __props.disabled,
6567
+ indeterminate: __props.indeterminate
5464
6568
  });
5465
- const isDisabled = toRef(() => ticket.disabled || group.disabled);
6569
+ const isDisabled = toRef(() => toValue(ticket.disabled) || toValue(group.disabled));
5466
6570
  onUnmounted(() => {
5467
6571
  group.unregister(ticket.id);
5468
6572
  });
@@ -5472,21 +6576,24 @@ const _sfc_main$10 = /* @__PURE__ */ defineComponent({
5472
6576
  ariaDisabled: toValue(isDisabled.value),
5473
6577
  ariaSelected: toValue(unref(ticket).isSelected),
5474
6578
  disabled: toValue(isDisabled.value),
6579
+ isMixed: toValue(unref(ticket).isMixed),
5475
6580
  isSelected: toValue(unref(ticket).isSelected),
5476
6581
  label: __props.label,
6582
+ mix: unref(ticket).mix,
5477
6583
  select: unref(ticket).select,
5478
6584
  toggle: unref(ticket).toggle,
6585
+ unmix: unref(ticket).unmix,
5479
6586
  unselect: unref(ticket).unselect,
5480
6587
  value: __props.value
5481
6588
  });
5482
6589
  };
5483
6590
  }
5484
6591
  });
5485
- var GroupItem_default = _sfc_main$10;
6592
+ var GroupItem_default = _sfc_main$17;
5486
6593
 
5487
6594
  //#endregion
5488
6595
  //#region src/components/Group/GroupRoot.vue
5489
- const _sfc_main$9 = /* @__PURE__ */ defineComponent({
6596
+ const _sfc_main$16 = /* @__PURE__ */ defineComponent({
5490
6597
  name: "GroupRoot",
5491
6598
  __name: "GroupRoot",
5492
6599
  props: /* @__PURE__ */ mergeModels({
@@ -5523,14 +6630,20 @@ const _sfc_main$9 = /* @__PURE__ */ defineComponent({
5523
6630
  return renderSlot(_ctx.$slots, "default", {
5524
6631
  ariaMultiselectable: true,
5525
6632
  disabled: toValue(unref(context).disabled),
6633
+ isAllSelected: unref(context).isAllSelected.value,
6634
+ isMixed: unref(context).isMixed.value,
6635
+ isNoneSelected: unref(context).isNoneSelected.value,
5526
6636
  select: unref(context).select,
6637
+ selectAll: unref(context).selectAll,
5527
6638
  toggle: unref(context).toggle,
5528
- unselect: unref(context).unselect
6639
+ toggleAll: unref(context).toggleAll,
6640
+ unselect: unref(context).unselect,
6641
+ unselectAll: unref(context).unselectAll
5529
6642
  });
5530
6643
  };
5531
6644
  }
5532
6645
  });
5533
- var GroupRoot_default = _sfc_main$9;
6646
+ var GroupRoot_default = _sfc_main$16;
5534
6647
 
5535
6648
  //#endregion
5536
6649
  //#region src/components/Group/index.ts
@@ -5539,6 +6652,512 @@ const Group = {
5539
6652
  Item: GroupItem_default
5540
6653
  };
5541
6654
 
6655
+ //#endregion
6656
+ //#region src/components/Pagination/PaginationRoot.vue
6657
+ function usePaginationControls(namespace) {
6658
+ return useContext(`${namespace}:controls`);
6659
+ }
6660
+ function usePaginationItems(namespace) {
6661
+ return useContext(`${namespace}:items`);
6662
+ }
6663
+ const _sfc_main$15 = /* @__PURE__ */ defineComponent({
6664
+ name: "PaginationRoot",
6665
+ __name: "PaginationRoot",
6666
+ props: /* @__PURE__ */ mergeModels({
6667
+ namespace: { default: "v0:pagination" },
6668
+ size: { default: 1 },
6669
+ totalVisible: {},
6670
+ itemsPerPage: { default: 10 },
6671
+ ellipsis: {
6672
+ type: [String, Boolean],
6673
+ default: "..."
6674
+ },
6675
+ as: { default: "nav" },
6676
+ renderless: { type: Boolean }
6677
+ }, {
6678
+ "modelValue": { default: 1 },
6679
+ "modelModifiers": {}
6680
+ }),
6681
+ emits: /* @__PURE__ */ mergeModels(["update:model-value"], ["update:modelValue"]),
6682
+ setup(__props) {
6683
+ const page = useModel(__props, "modelValue");
6684
+ const itemWidth = shallowRef(0);
6685
+ const itemGap = shallowRef(0);
6686
+ const atom = useTemplateRef("atom");
6687
+ const locale = useLocale();
6688
+ const [, provideControlContext, controls] = createRegistryContext({ namespace: `${__props.namespace}:controls` });
6689
+ const [, provideItemContext, items] = createRegistryContext({ namespace: `${__props.namespace}:items` });
6690
+ const overflow = createOverflow({
6691
+ container: () => atom.value?.element,
6692
+ itemWidth,
6693
+ gap: itemGap
6694
+ });
6695
+ watch([() => items.size, () => overflow.width.value], () => {
6696
+ const el = items.seek("first")?.value;
6697
+ const root = overflow.container.value;
6698
+ if (!el || !root) return;
6699
+ const rootStyle = getComputedStyle(root);
6700
+ const style = getComputedStyle(el);
6701
+ const marginX = Number.parseFloat(style.marginLeft) + Number.parseFloat(style.marginRight);
6702
+ const gapX = Number.parseFloat(rootStyle.gap) || 0;
6703
+ itemWidth.value = el.offsetWidth + marginX;
6704
+ itemGap.value = gapX;
6705
+ }, { flush: "post" });
6706
+ const visible = computed(() => {
6707
+ const totalCap = overflow.capacity.value;
6708
+ if (totalCap === Infinity) return __props.totalVisible ?? Infinity;
6709
+ const pageCap = Math.max(0, totalCap - controls.size);
6710
+ const noVisible = /* @__PURE__ */ isNullOrUndefined(__props.totalVisible);
6711
+ if (pageCap > 0) return noVisible ? pageCap : Math.min(__props.totalVisible, pageCap);
6712
+ return noVisible ? 1 : __props.totalVisible;
6713
+ });
6714
+ const [, providePaginationContext, pagination] = createPaginationContext({
6715
+ namespace: __props.namespace,
6716
+ page,
6717
+ visible,
6718
+ ellipsis: __props.ellipsis,
6719
+ size: () => __props.size,
6720
+ itemsPerPage: () => __props.itemsPerPage
6721
+ });
6722
+ const slotProps = toRef(() => ({
6723
+ ariaLabel: locale.t("Pagination.label", void 0, "Pagination"),
6724
+ page: pagination.page.value,
6725
+ size: pagination.size,
6726
+ pages: pagination.pages,
6727
+ itemsPerPage: pagination.itemsPerPage,
6728
+ items: pagination.items.value,
6729
+ pageStart: pagination.pageStart.value,
6730
+ pageStop: pagination.pageStop.value,
6731
+ isFirst: pagination.isFirst.value,
6732
+ isLast: pagination.isLast.value,
6733
+ first: pagination.first,
6734
+ last: pagination.last,
6735
+ next: pagination.next,
6736
+ prev: pagination.prev,
6737
+ select: pagination.select
6738
+ }));
6739
+ providePaginationContext();
6740
+ provideControlContext();
6741
+ provideItemContext();
6742
+ return (_ctx, _cache) => {
6743
+ return openBlock(), createBlock(unref(Atom_default), {
6744
+ ref_key: "atom",
6745
+ ref: atom,
6746
+ "aria-label": slotProps.value.ariaLabel,
6747
+ as: __props.as,
6748
+ renderless: __props.renderless
6749
+ }, {
6750
+ default: withCtx(() => [renderSlot(_ctx.$slots, "default", normalizeProps(guardReactiveProps(slotProps.value)))]),
6751
+ _: 3
6752
+ }, 8, [
6753
+ "aria-label",
6754
+ "as",
6755
+ "renderless"
6756
+ ]);
6757
+ };
6758
+ }
6759
+ });
6760
+ var PaginationRoot_default = _sfc_main$15;
6761
+
6762
+ //#endregion
6763
+ //#region src/components/Pagination/PaginationEllipsis.vue
6764
+ const _sfc_main$14 = /* @__PURE__ */ defineComponent({
6765
+ name: "PaginationEllipsis",
6766
+ __name: "PaginationEllipsis",
6767
+ props: {
6768
+ namespace: { default: "v0:pagination" },
6769
+ ellipsis: {},
6770
+ id: { default: () => /* @__PURE__ */ genId() },
6771
+ as: { default: "span" },
6772
+ renderless: { type: Boolean }
6773
+ },
6774
+ setup(__props) {
6775
+ const pagination = usePagination(__props.namespace);
6776
+ const items = usePaginationItems(__props.namespace);
6777
+ const atom = useTemplateRef("atom");
6778
+ watch(() => atom.value?.element, (el) => {
6779
+ if (!el) return;
6780
+ items.register({
6781
+ id: __props.id,
6782
+ value: el
6783
+ });
6784
+ }, { immediate: true });
6785
+ onBeforeUnmount(() => items.unregister(__props.id));
6786
+ const resolvedEllipsis = toRef(() => __props.ellipsis ?? pagination.ellipsis);
6787
+ const slotProps = toRef(() => ({
6788
+ ariaHidden: "true",
6789
+ ellipsis: resolvedEllipsis.value
6790
+ }));
6791
+ return (_ctx, _cache) => {
6792
+ return openBlock(), createBlock(unref(Atom_default), {
6793
+ ref_key: "atom",
6794
+ ref: atom,
6795
+ "aria-hidden": slotProps.value.ariaHidden,
6796
+ as: __props.as,
6797
+ renderless: __props.renderless
6798
+ }, {
6799
+ default: withCtx(() => [renderSlot(_ctx.$slots, "default", normalizeProps(guardReactiveProps(slotProps.value)), () => [createTextVNode(toDisplayString(resolvedEllipsis.value), 1)])]),
6800
+ _: 3
6801
+ }, 8, [
6802
+ "aria-hidden",
6803
+ "as",
6804
+ "renderless"
6805
+ ]);
6806
+ };
6807
+ }
6808
+ });
6809
+ var PaginationEllipsis_default = _sfc_main$14;
6810
+
6811
+ //#endregion
6812
+ //#region src/components/Pagination/PaginationFirst.vue
6813
+ const _sfc_main$13 = /* @__PURE__ */ defineComponent({
6814
+ name: "PaginationFirst",
6815
+ __name: "PaginationFirst",
6816
+ props: {
6817
+ namespace: { default: "v0:pagination" },
6818
+ disabled: { type: Boolean },
6819
+ id: { default: () => /* @__PURE__ */ genId() },
6820
+ as: { default: "button" },
6821
+ renderless: { type: Boolean }
6822
+ },
6823
+ setup(__props) {
6824
+ const locale = useLocale();
6825
+ const pagination = usePagination(__props.namespace);
6826
+ const controls = usePaginationControls(__props.namespace);
6827
+ const atom = useTemplateRef("atom");
6828
+ watch(() => atom.value?.element, (el) => {
6829
+ if (!el) return;
6830
+ controls.register({
6831
+ id: __props.id,
6832
+ value: el
6833
+ });
6834
+ }, { immediate: true });
6835
+ onBeforeUnmount(() => controls.unregister(__props.id));
6836
+ const isDisabled = toRef(() => __props.disabled || pagination.isFirst.value);
6837
+ function onClick() {
6838
+ if (isDisabled.value) return;
6839
+ pagination.first();
6840
+ }
6841
+ const slotProps = toRef(() => ({
6842
+ ariaLabel: locale.t("Pagination.first", void 0, "Go to first page"),
6843
+ disabled: isDisabled.value,
6844
+ onClick
6845
+ }));
6846
+ return (_ctx, _cache) => {
6847
+ return openBlock(), createBlock(unref(Atom_default), {
6848
+ ref_key: "atom",
6849
+ ref: atom,
6850
+ "aria-disabled": slotProps.value.disabled,
6851
+ "aria-label": slotProps.value.ariaLabel,
6852
+ as: __props.as,
6853
+ "data-disabled": slotProps.value.disabled || void 0,
6854
+ disabled: __props.as === "button" ? slotProps.value.disabled : void 0,
6855
+ renderless: __props.renderless,
6856
+ type: __props.as === "button" ? "button" : void 0,
6857
+ onClick: slotProps.value.onClick
6858
+ }, {
6859
+ default: withCtx(() => [renderSlot(_ctx.$slots, "default", normalizeProps(guardReactiveProps(slotProps.value)))]),
6860
+ _: 3
6861
+ }, 8, [
6862
+ "aria-disabled",
6863
+ "aria-label",
6864
+ "as",
6865
+ "data-disabled",
6866
+ "disabled",
6867
+ "renderless",
6868
+ "type",
6869
+ "onClick"
6870
+ ]);
6871
+ };
6872
+ }
6873
+ });
6874
+ var PaginationFirst_default = _sfc_main$13;
6875
+
6876
+ //#endregion
6877
+ //#region src/components/Pagination/PaginationItem.vue
6878
+ const _sfc_main$12 = /* @__PURE__ */ defineComponent({
6879
+ name: "PaginationItem",
6880
+ __name: "PaginationItem",
6881
+ props: {
6882
+ namespace: { default: "v0:pagination" },
6883
+ value: {},
6884
+ disabled: {
6885
+ type: Boolean,
6886
+ default: false
6887
+ },
6888
+ id: { default: () => /* @__PURE__ */ genId() },
6889
+ as: { default: "button" },
6890
+ renderless: { type: Boolean }
6891
+ },
6892
+ setup(__props) {
6893
+ const locale = useLocale();
6894
+ const pagination = usePagination(__props.namespace);
6895
+ const items = usePaginationItems(__props.namespace);
6896
+ const atom = useTemplateRef("atom");
6897
+ watch(() => atom.value?.element, (el) => {
6898
+ if (!el) return;
6899
+ items.register({
6900
+ id: __props.id,
6901
+ value: el
6902
+ });
6903
+ }, { immediate: true });
6904
+ onBeforeUnmount(() => items.unregister(__props.id));
6905
+ const isSelected = toRef(() => pagination.page.value === __props.value);
6906
+ const ariaLabel = toRef(() => {
6907
+ return isSelected.value ? locale.t("Pagination.currentPage", { page: __props.value }, `Page ${__props.value}, current page`) : locale.t("Pagination.goToPage", { page: __props.value }, `Go to page ${__props.value}`);
6908
+ });
6909
+ const slotProps = toRef(() => ({
6910
+ ariaLabel: ariaLabel.value,
6911
+ ariaCurrent: isSelected.value ? "page" : void 0,
6912
+ page: __props.value,
6913
+ isSelected: isSelected.value,
6914
+ dataSelected: isSelected.value,
6915
+ disabled: __props.disabled,
6916
+ select
6917
+ }));
6918
+ function select() {
6919
+ if (__props.disabled) return;
6920
+ pagination.select(__props.value);
6921
+ }
6922
+ return (_ctx, _cache) => {
6923
+ return openBlock(), createBlock(unref(Atom_default), {
6924
+ ref_key: "atom",
6925
+ ref: atom,
6926
+ "aria-current": slotProps.value.ariaCurrent,
6927
+ "aria-label": slotProps.value.ariaLabel,
6928
+ as: __props.as,
6929
+ "data-disabled": slotProps.value.disabled || void 0,
6930
+ "data-selected": slotProps.value.dataSelected || void 0,
6931
+ disabled: __props.as === "button" ? slotProps.value.disabled : void 0,
6932
+ renderless: __props.renderless,
6933
+ type: __props.as === "button" ? "button" : void 0,
6934
+ onClick: slotProps.value.select
6935
+ }, {
6936
+ default: withCtx(() => [renderSlot(_ctx.$slots, "default", normalizeProps(guardReactiveProps(slotProps.value)))]),
6937
+ _: 3
6938
+ }, 8, [
6939
+ "aria-current",
6940
+ "aria-label",
6941
+ "as",
6942
+ "data-disabled",
6943
+ "data-selected",
6944
+ "disabled",
6945
+ "renderless",
6946
+ "type",
6947
+ "onClick"
6948
+ ]);
6949
+ };
6950
+ }
6951
+ });
6952
+ var PaginationItem_default = _sfc_main$12;
6953
+
6954
+ //#endregion
6955
+ //#region src/components/Pagination/PaginationLast.vue
6956
+ const _sfc_main$11 = /* @__PURE__ */ defineComponent({
6957
+ name: "PaginationLast",
6958
+ __name: "PaginationLast",
6959
+ props: {
6960
+ namespace: { default: "v0:pagination" },
6961
+ disabled: { type: Boolean },
6962
+ id: { default: () => /* @__PURE__ */ genId() },
6963
+ as: { default: "button" },
6964
+ renderless: { type: Boolean }
6965
+ },
6966
+ setup(__props) {
6967
+ const locale = useLocale();
6968
+ const pagination = usePagination(__props.namespace);
6969
+ const controls = usePaginationControls(__props.namespace);
6970
+ const atom = useTemplateRef("atom");
6971
+ watch(() => atom.value?.element, (el) => {
6972
+ if (!el) return;
6973
+ controls.register({
6974
+ id: __props.id,
6975
+ value: el
6976
+ });
6977
+ }, { immediate: true });
6978
+ onBeforeUnmount(() => controls.unregister(__props.id));
6979
+ const isDisabled = toRef(() => __props.disabled || pagination.isLast.value);
6980
+ function onClick() {
6981
+ if (isDisabled.value) return;
6982
+ pagination.last();
6983
+ }
6984
+ const slotProps = toRef(() => ({
6985
+ ariaLabel: locale.t("Pagination.last", void 0, "Go to last page"),
6986
+ disabled: isDisabled.value,
6987
+ onClick
6988
+ }));
6989
+ return (_ctx, _cache) => {
6990
+ return openBlock(), createBlock(unref(Atom_default), {
6991
+ ref_key: "atom",
6992
+ ref: atom,
6993
+ "aria-disabled": slotProps.value.disabled,
6994
+ "aria-label": slotProps.value.ariaLabel,
6995
+ as: __props.as,
6996
+ "data-disabled": slotProps.value.disabled || void 0,
6997
+ disabled: __props.as === "button" ? slotProps.value.disabled : void 0,
6998
+ renderless: __props.renderless,
6999
+ type: __props.as === "button" ? "button" : void 0,
7000
+ onClick: slotProps.value.onClick
7001
+ }, {
7002
+ default: withCtx(() => [renderSlot(_ctx.$slots, "default", normalizeProps(guardReactiveProps(slotProps.value)))]),
7003
+ _: 3
7004
+ }, 8, [
7005
+ "aria-disabled",
7006
+ "aria-label",
7007
+ "as",
7008
+ "data-disabled",
7009
+ "disabled",
7010
+ "renderless",
7011
+ "type",
7012
+ "onClick"
7013
+ ]);
7014
+ };
7015
+ }
7016
+ });
7017
+ var PaginationLast_default = _sfc_main$11;
7018
+
7019
+ //#endregion
7020
+ //#region src/components/Pagination/PaginationNext.vue
7021
+ const _sfc_main$10 = /* @__PURE__ */ defineComponent({
7022
+ name: "PaginationNext",
7023
+ __name: "PaginationNext",
7024
+ props: {
7025
+ namespace: { default: "v0:pagination" },
7026
+ disabled: { type: Boolean },
7027
+ id: { default: () => /* @__PURE__ */ genId() },
7028
+ as: { default: "button" },
7029
+ renderless: { type: Boolean }
7030
+ },
7031
+ setup(__props) {
7032
+ const locale = useLocale();
7033
+ const pagination = usePagination(__props.namespace);
7034
+ const controls = usePaginationControls(__props.namespace);
7035
+ const atom = useTemplateRef("atom");
7036
+ watch(() => atom.value?.element, (el) => {
7037
+ if (!el) return;
7038
+ controls.register({
7039
+ id: __props.id,
7040
+ value: el
7041
+ });
7042
+ }, { immediate: true });
7043
+ onBeforeUnmount(() => controls.unregister(__props.id));
7044
+ const isDisabled = toRef(() => __props.disabled || pagination.isLast.value);
7045
+ function onClick() {
7046
+ if (isDisabled.value) return;
7047
+ pagination.next();
7048
+ }
7049
+ const slotProps = toRef(() => ({
7050
+ ariaLabel: locale.t("Pagination.next", void 0, "Go to next page"),
7051
+ disabled: isDisabled.value,
7052
+ onClick
7053
+ }));
7054
+ return (_ctx, _cache) => {
7055
+ return openBlock(), createBlock(unref(Atom_default), {
7056
+ ref_key: "atom",
7057
+ ref: atom,
7058
+ "aria-disabled": slotProps.value.disabled,
7059
+ "aria-label": slotProps.value.ariaLabel,
7060
+ as: __props.as,
7061
+ "data-disabled": slotProps.value.disabled || void 0,
7062
+ disabled: __props.as === "button" ? slotProps.value.disabled : void 0,
7063
+ renderless: __props.renderless,
7064
+ type: __props.as === "button" ? "button" : void 0,
7065
+ onClick: slotProps.value.onClick
7066
+ }, {
7067
+ default: withCtx(() => [renderSlot(_ctx.$slots, "default", normalizeProps(guardReactiveProps(slotProps.value)))]),
7068
+ _: 3
7069
+ }, 8, [
7070
+ "aria-disabled",
7071
+ "aria-label",
7072
+ "as",
7073
+ "data-disabled",
7074
+ "disabled",
7075
+ "renderless",
7076
+ "type",
7077
+ "onClick"
7078
+ ]);
7079
+ };
7080
+ }
7081
+ });
7082
+ var PaginationNext_default = _sfc_main$10;
7083
+
7084
+ //#endregion
7085
+ //#region src/components/Pagination/PaginationPrev.vue
7086
+ const _sfc_main$9 = /* @__PURE__ */ defineComponent({
7087
+ name: "PaginationPrev",
7088
+ __name: "PaginationPrev",
7089
+ props: {
7090
+ namespace: { default: "v0:pagination" },
7091
+ disabled: { type: Boolean },
7092
+ id: { default: () => /* @__PURE__ */ genId() },
7093
+ as: { default: "button" },
7094
+ renderless: { type: Boolean }
7095
+ },
7096
+ setup(__props) {
7097
+ const locale = useLocale();
7098
+ const pagination = usePagination(__props.namespace);
7099
+ const controls = usePaginationControls(__props.namespace);
7100
+ const atom = useTemplateRef("atom");
7101
+ watch(() => atom.value?.element, (el) => {
7102
+ if (!el) return;
7103
+ controls.register({
7104
+ id: __props.id,
7105
+ value: el
7106
+ });
7107
+ }, { immediate: true });
7108
+ onBeforeUnmount(() => controls.unregister(__props.id));
7109
+ const isDisabled = toRef(() => __props.disabled || pagination.isFirst.value);
7110
+ function onClick() {
7111
+ if (isDisabled.value) return;
7112
+ pagination.prev();
7113
+ }
7114
+ const slotProps = toRef(() => ({
7115
+ ariaLabel: locale.t("Pagination.prev", void 0, "Go to previous page"),
7116
+ disabled: isDisabled.value,
7117
+ onClick
7118
+ }));
7119
+ return (_ctx, _cache) => {
7120
+ return openBlock(), createBlock(unref(Atom_default), {
7121
+ ref_key: "atom",
7122
+ ref: atom,
7123
+ "aria-disabled": slotProps.value.disabled,
7124
+ "aria-label": slotProps.value.ariaLabel,
7125
+ as: __props.as,
7126
+ "data-disabled": slotProps.value.disabled || void 0,
7127
+ disabled: __props.as === "button" ? slotProps.value.disabled : void 0,
7128
+ renderless: __props.renderless,
7129
+ type: __props.as === "button" ? "button" : void 0,
7130
+ onClick: slotProps.value.onClick
7131
+ }, {
7132
+ default: withCtx(() => [renderSlot(_ctx.$slots, "default", normalizeProps(guardReactiveProps(slotProps.value)))]),
7133
+ _: 3
7134
+ }, 8, [
7135
+ "aria-disabled",
7136
+ "aria-label",
7137
+ "as",
7138
+ "data-disabled",
7139
+ "disabled",
7140
+ "renderless",
7141
+ "type",
7142
+ "onClick"
7143
+ ]);
7144
+ };
7145
+ }
7146
+ });
7147
+ var PaginationPrev_default = _sfc_main$9;
7148
+
7149
+ //#endregion
7150
+ //#region src/components/Pagination/index.ts
7151
+ const Pagination = {
7152
+ Root: PaginationRoot_default,
7153
+ Item: PaginationItem_default,
7154
+ First: PaginationFirst_default,
7155
+ Prev: PaginationPrev_default,
7156
+ Ellipsis: PaginationEllipsis_default,
7157
+ Next: PaginationNext_default,
7158
+ Last: PaginationLast_default
7159
+ };
7160
+
5542
7161
  //#endregion
5543
7162
  //#region src/components/Popover/PopoverRoot.vue
5544
7163
  const [usePopoverContext, providePopoverContext] = createContext("Popover");
@@ -5705,7 +7324,7 @@ const _sfc_main$5 = /* @__PURE__ */ defineComponent({
5705
7324
  value: __props.value,
5706
7325
  disabled: __props.disabled
5707
7326
  });
5708
- const isDisabled = toRef(() => ticket.disabled || selection.disabled);
7327
+ const isDisabled = toRef(() => toValue(ticket.disabled) || toValue(selection.disabled));
5709
7328
  onUnmounted(() => {
5710
7329
  selection.unregister(ticket.id);
5711
7330
  });
@@ -5807,7 +7426,7 @@ const _sfc_main$3 = /* @__PURE__ */ defineComponent({
5807
7426
  value: __props.value,
5808
7427
  disabled: __props.disabled
5809
7428
  });
5810
- const isDisabled = toRef(() => ticket.disabled || single.disabled);
7429
+ const isDisabled = toRef(() => toValue(ticket.disabled) || toValue(single.disabled));
5811
7430
  onUnmounted(() => {
5812
7431
  single.unregister(ticket.id);
5813
7432
  });
@@ -5903,7 +7522,7 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
5903
7522
  value: __props.value,
5904
7523
  disabled: __props.disabled
5905
7524
  });
5906
- const isDisabled = toRef(() => ticket.disabled || step.disabled);
7525
+ const isDisabled = toRef(() => toValue(ticket.disabled) || toValue(step.disabled));
5907
7526
  onUnmounted(() => {
5908
7527
  step.unregister(ticket.id);
5909
7528
  });
@@ -5986,4 +7605,4 @@ const Step = {
5986
7605
  };
5987
7606
 
5988
7607
  //#endregion
5989
- export { Atom_default as Atom, Avatar, COMMON_ELEMENTS, ConsolaLoggerAdapter, ExpansionPanel, Group, IN_BROWSER, MemoryAdapter, PermissionAdapter, PinoLoggerAdapter, Popover, SELF_CLOSING_TAGS, SUPPORTS_INTERSECTION_OBSERVER, SUPPORTS_MATCH_MEDIA, SUPPORTS_MUTATION_OBSERVER, SUPPORTS_OBSERVER, SUPPORTS_TOUCH, Selection, Single, Step, Vuetify0LocaleAdapter, Vuetify0LoggerAdapter, Vuetify0ThemeAdapter, __LOGGER_ENABLED__, createBreakpoints, createBreakpointsContext, createBreakpointsPlugin, createContext, createFeatures, createFeaturesContext, createFeaturesPlugin, createForm, createFormContext, createGroup, createGroupContext, createHydration, createHydrationContext, createHydrationPlugin, createLocale, createLocaleContext, createLocalePlugin, createLogger, createLoggerContext, createLoggerPlugin, createPermissions, createPermissionsContext, createPermissionsPlugin, createPlugin, createQueue, createQueueContext, createRegistryContext, createSelection, createSelectionContext, createSingle, createSingleContext, createStep, createStepContext, createStorage, createStorageContext, createStoragePlugin, createTheme, createThemeContext, createThemePlugin, createTimeline, createTimelineContext, createTokens, createTokensContext, createTrinity, genId, isArray, isBoolean, isFunction, isNull, isNullOrUndefined, isNumber, isObject, isPrimitive, isSelfClosingTag, isString, isUndefined, mergeDeep, provideContext, providePopoverContext, provideStorageContext, toArray, toReactive, useBreakpoints, useContext, useDocumentEventListener, useElementIntersection, useElementSize, useEventListener, useFeatures, useFilter, useForm, useGroup, useHydration, useIntersectionObserver, useKeydown, useLocale, useLogger, useMutationObserver, usePermissions, usePopoverContext, useProxyModel, useProxyRegistry, useQueue, useRegistry, useResizeObserver, useSelection, useSingle, useStep, useStorage, useStorageContext, useTheme, useTimeline, useTokens, useWindowEventListener, version };
7608
+ export { Atom_default as Atom, Avatar, COMMON_ELEMENTS, ConsolaLoggerAdapter, ExpansionPanel, Group, IN_BROWSER, MemoryAdapter, Pagination, PermissionAdapter, PinoLoggerAdapter, Popover, SELF_CLOSING_TAGS, SUPPORTS_INTERSECTION_OBSERVER, SUPPORTS_MATCH_MEDIA, SUPPORTS_MUTATION_OBSERVER, SUPPORTS_OBSERVER, SUPPORTS_TOUCH, Selection, Single, Step, Vuetify0LocaleAdapter, Vuetify0LoggerAdapter, Vuetify0ThemeAdapter, __LOGGER_ENABLED__, clamp, createBreakpoints, createBreakpointsContext, createBreakpointsPlugin, createContext, createFallbackHydration, createFeatures, createFeaturesContext, createFeaturesPlugin, createForm, createFormContext, createGroup, createGroupContext, createHydration, createHydrationContext, createHydrationPlugin, createLocale, createLocaleContext, createLocaleFallback, createLocalePlugin, createLogger, createLoggerContext, createLoggerPlugin, createOverflow, createOverflowContext, createPagination, createPaginationContext, createPermissions, createPermissionsContext, createPermissionsPlugin, createPlugin, createQueue, createQueueContext, createRegistryContext, createSelection, createSelectionContext, createSingle, createSingleContext, createStep, createStepContext, createStorage, createStorageContext, createStoragePlugin, createTheme, createThemeContext, createThemePlugin, createTimeline, createTimelineContext, createTokens, createTokensContext, createTrinity, debounce, genId, isArray, isBoolean, isFunction, isNaN, isNull, isNullOrUndefined, isNumber, isObject, isPrimitive, isSelfClosingTag, isString, isUndefined, mergeDeep, provideContext, providePopoverContext, range, toArray, toReactive, useBreakpoints, useContext, useDocumentEventListener, useElementIntersection, useElementSize, useEventListener, useFeatures, useFilter, useForm, useGroup, useHydration, useIntersectionObserver, useKeydown, useLocale, useLogger, useMutationObserver, useOverflow, usePagination, usePaginationControls, usePaginationItems, usePermissions, usePopoverContext, useProxyModel, useProxyRegistry, useQueue, useRegistry, useResizeObserver, useSelection, useSingle, useStep, useStorage, useTheme, useTimeline, useToggleScope, useTokens, useVirtual, useWindowEventListener, version };