@vuetify/v0 0.0.16 → 0.0.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +125 -47
- package/dist/browser/index.js +1801 -1604
- package/dist/components/index.d.mts +4 -4
- package/dist/components/index.mjs +6 -6
- package/dist/{components-Dk00OFL2.mjs → components-D590hSY0.mjs} +151 -54
- package/dist/composables/index.d.mts +4 -4
- package/dist/composables/index.mjs +5 -5
- package/dist/{composables-YOUVfUsn.mjs → composables-FE6B8JUW.mjs} +370 -303
- package/dist/constants/index.d.mts +1 -1
- package/dist/constants/index.mjs +3 -3
- package/dist/{globals-Rnihe4SF.mjs → globals-exvZ8fiO.mjs} +1 -1
- package/dist/index-4jSy8KIt.d.mts +73 -0
- package/dist/{index-BzW68rBC.d.mts → index-BYyEPh1S.d.mts} +227 -17
- package/dist/index-CjzlIAtF.d.mts +296 -0
- package/dist/{index-BeJMYhId.d.mts → index-DahjxaTj.d.mts} +899 -136
- package/dist/{index-BulceeMA.d.mts → index-Gr6XPRWt.d.mts} +50 -18
- package/dist/index.d.mts +7 -7
- package/dist/index.mjs +8 -8
- package/dist/types/index.d.mts +1 -1
- package/dist/{useStep-Bqhi_DDs.mjs → useStep-Dw7XloDM.mjs} +1067 -1258
- package/dist/utilities/index.d.mts +2 -2
- package/dist/utilities/index.mjs +1 -1
- package/dist/utilities-BrFKLHFS.mjs +363 -0
- package/package.json +3 -3
- package/dist/index-BXN7M6o_.d.mts +0 -71
- package/dist/index-Bd3J4RNS.d.mts +0 -11
- package/dist/utilities-DQWf_4V_.mjs +0 -139
- /package/dist/{constants-BWV0uYsM.mjs → constants-DypzAkYp.mjs} +0 -0
- /package/dist/{htmlElements-BYo-fMlZ.mjs → htmlElements-CXObxj0V.mjs} +0 -0
- /package/dist/{index-B6lIRI3i.d.mts → index-B9mKi4pr.d.mts} +0 -0
|
@@ -1,25 +1,9 @@
|
|
|
1
|
-
import { _ as range, d as isObject, h as isUndefined,
|
|
2
|
-
import { a as SUPPORTS_OBSERVER, s as __LOGGER_ENABLED__, t as IN_BROWSER } from "./globals-
|
|
3
|
-
import { computed, getCurrentInstance, inject, isRef, onScopeDispose, provide, reactive, shallowReactive, shallowReadonly, shallowRef, toRef, toValue, watch } from "vue";
|
|
1
|
+
import { _ as range, d as isObject, h as isUndefined, l as isNullOrUndefined, m as isSymbol, o as isFunction, p as isString, r as genId, s as isNaN } from "./utilities-BrFKLHFS.mjs";
|
|
2
|
+
import { a as SUPPORTS_OBSERVER, s as __LOGGER_ENABLED__, t as IN_BROWSER } from "./globals-exvZ8fiO.mjs";
|
|
3
|
+
import { computed, getCurrentInstance, inject, isRef, onScopeDispose, provide, reactive, shallowReactive, shallowReadonly, shallowRef, toRef, toValue, watch, watchEffect } from "vue";
|
|
4
4
|
|
|
5
5
|
//#region src/composables/createContext/index.ts
|
|
6
6
|
/**
|
|
7
|
-
* @module createContext
|
|
8
|
-
*
|
|
9
|
-
* @see https://0.vuetifyjs.com/composables/foundation/create-context
|
|
10
|
-
*
|
|
11
|
-
* @remarks
|
|
12
|
-
* Factory for creating type-safe Vue dependency injection contexts.
|
|
13
|
-
*
|
|
14
|
-
* Provides a wrapper around Vue's provide/inject that throws errors when context is not found,
|
|
15
|
-
* eliminating silent failures and improving developer experience. Supports both app-level and
|
|
16
|
-
* component-level provision.
|
|
17
|
-
*
|
|
18
|
-
* Supports two modes:
|
|
19
|
-
* - **Static key**: `createContext('my-key')` - key is fixed at creation time
|
|
20
|
-
* - **Dynamic key**: `createContext()` or `createContext({ suffix: 'item' })` - key provided at runtime
|
|
21
|
-
*/
|
|
22
|
-
/**
|
|
23
7
|
* Injects a context provided by an ancestor component.
|
|
24
8
|
*
|
|
25
9
|
* @param key The key of the context to inject.
|
|
@@ -441,12 +425,12 @@ function createFallbackLogger(namespace = "v0:logger") {
|
|
|
441
425
|
return `[${namespace} ${type}] ${message}`;
|
|
442
426
|
}
|
|
443
427
|
return {
|
|
444
|
-
debug: (message, ...args) => console.
|
|
445
|
-
info: (message, ...args) => console.
|
|
446
|
-
warn: (message, ...args) => console.
|
|
447
|
-
error: (message, ...args) => console.
|
|
448
|
-
trace: (message, ...args) => console.
|
|
449
|
-
fatal: (message, ...args) => console.
|
|
428
|
+
debug: (message, ...args) => console.debug(format(message, "debug"), ...args),
|
|
429
|
+
info: (message, ...args) => console.info(format(message, "info"), ...args),
|
|
430
|
+
warn: (message, ...args) => console.warn(format(message, "warn"), ...args),
|
|
431
|
+
error: (message, ...args) => console.error(format(message, "error"), ...args),
|
|
432
|
+
trace: (message, ...args) => console.trace(format(message, "trace"), ...args),
|
|
433
|
+
fatal: (message, ...args) => console.error(format(message, "fatal"), ...args),
|
|
450
434
|
level: () => {},
|
|
451
435
|
current: () => "info",
|
|
452
436
|
enabled: () => true,
|
|
@@ -474,7 +458,7 @@ function createFallbackLogger(namespace = "v0:logger") {
|
|
|
474
458
|
* ```
|
|
475
459
|
*/
|
|
476
460
|
function createLoggerContext(_options = {}) {
|
|
477
|
-
const { namespace = "v0:logger"
|
|
461
|
+
const { namespace = "v0:logger", ...options } = _options;
|
|
478
462
|
const [useLoggerContext, _provideLoggerContext] = createContext(namespace);
|
|
479
463
|
const context = createLogger(options);
|
|
480
464
|
function provideLoggerContext(_context = context, app) {
|
|
@@ -509,7 +493,7 @@ function createLoggerContext(_options = {}) {
|
|
|
509
493
|
* ```
|
|
510
494
|
*/
|
|
511
495
|
function createLoggerPlugin(_options = {}) {
|
|
512
|
-
const { namespace = "v0:logger"
|
|
496
|
+
const { namespace = "v0:logger", ...options } = _options;
|
|
513
497
|
const [, provideLoggerContext, context] = createLoggerContext({
|
|
514
498
|
...options,
|
|
515
499
|
namespace
|
|
@@ -558,21 +542,6 @@ function useLogger(namespace = "v0:logger") {
|
|
|
558
542
|
//#endregion
|
|
559
543
|
//#region src/composables/useRegistry/index.ts
|
|
560
544
|
/**
|
|
561
|
-
* @module useRegistry
|
|
562
|
-
*
|
|
563
|
-
* @remarks
|
|
564
|
-
* A foundational composable for managing collections of items (tickets) with:
|
|
565
|
-
* - Unique ID-based access
|
|
566
|
-
* - Index-based ordering
|
|
567
|
-
* - Value-based reverse lookup
|
|
568
|
-
* - Automatic reindexing
|
|
569
|
-
* - Optional event emission
|
|
570
|
-
* - Performance-optimized caching
|
|
571
|
-
*
|
|
572
|
-
* The registry serves as the base for many other composables in the system,
|
|
573
|
-
* including useSelection, useForm, useTimeline, and more.
|
|
574
|
-
*/
|
|
575
|
-
/**
|
|
576
545
|
* Creates a new registry instance.
|
|
577
546
|
*
|
|
578
547
|
* @param options The options for the registry instance.
|
|
@@ -606,6 +575,8 @@ function useRegistry(options) {
|
|
|
606
575
|
let indexDependentCount = 0;
|
|
607
576
|
let needsReindex = false;
|
|
608
577
|
let minDirtyIndex = Infinity;
|
|
578
|
+
let batching = false;
|
|
579
|
+
let pendingEmits = [];
|
|
609
580
|
function emit(event, data = void 0) {
|
|
610
581
|
if (!events) return;
|
|
611
582
|
const cbs = listeners.get(event);
|
|
@@ -614,17 +585,21 @@ function useRegistry(options) {
|
|
|
614
585
|
}
|
|
615
586
|
function on(event, cb) {
|
|
616
587
|
if (!events) {
|
|
617
|
-
logger.warn(`
|
|
588
|
+
logger.warn(`Events are disabled. Initialize with \`useRegistry({ events: true })\` to enable.`);
|
|
618
589
|
return;
|
|
619
590
|
}
|
|
620
591
|
if (!listeners.has(event)) listeners.set(event, /* @__PURE__ */ new Set());
|
|
621
592
|
listeners.get(event).add(cb);
|
|
622
593
|
}
|
|
623
594
|
function off(event, cb) {
|
|
595
|
+
if (!events) {
|
|
596
|
+
logger.warn(`Events are disabled. Initialize with \`useRegistry({ events: true })\` to enable.`);
|
|
597
|
+
return;
|
|
598
|
+
}
|
|
624
599
|
listeners.get(event)?.delete(cb);
|
|
625
600
|
}
|
|
626
601
|
function dispose() {
|
|
627
|
-
|
|
602
|
+
listeners.clear();
|
|
628
603
|
clear();
|
|
629
604
|
}
|
|
630
605
|
function get(id) {
|
|
@@ -681,24 +656,19 @@ function useRegistry(options) {
|
|
|
681
656
|
function assign(value, id) {
|
|
682
657
|
const bucket = catalog.get(value);
|
|
683
658
|
if (bucket) {
|
|
684
|
-
if (
|
|
685
|
-
|
|
686
|
-
} else if (bucket !== id) catalog.set(value, [bucket, id]);
|
|
687
|
-
} else catalog.set(value, id);
|
|
659
|
+
if (!bucket.includes(id)) bucket.push(id);
|
|
660
|
+
} else catalog.set(value, [id]);
|
|
688
661
|
}
|
|
689
662
|
function unassign(value, id) {
|
|
690
663
|
const bucket = catalog.get(value);
|
|
691
664
|
if (!bucket) return;
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
else if (next.length === 1) catalog.set(value, next[0]);
|
|
696
|
-
else catalog.set(value, next);
|
|
697
|
-
} else if (bucket === id) catalog.delete(value);
|
|
665
|
+
const next = bucket.filter((v) => v !== id);
|
|
666
|
+
if (next.length === 0) catalog.delete(value);
|
|
667
|
+
else catalog.set(value, next);
|
|
698
668
|
}
|
|
699
669
|
function keys() {
|
|
700
670
|
const cached = cache.get("keys");
|
|
701
|
-
if (
|
|
671
|
+
if (!/* @__PURE__ */ isUndefined(cached)) return cached;
|
|
702
672
|
const keys$1 = Array.from(collection.keys());
|
|
703
673
|
cache.set("keys", keys$1);
|
|
704
674
|
return keys$1;
|
|
@@ -718,9 +688,9 @@ function useRegistry(options) {
|
|
|
718
688
|
return entries$1;
|
|
719
689
|
}
|
|
720
690
|
function clear() {
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
691
|
+
collection.clear();
|
|
692
|
+
catalog.clear();
|
|
693
|
+
directory.clear();
|
|
724
694
|
invalidate();
|
|
725
695
|
indexDependentCount = 0;
|
|
726
696
|
needsReindex = false;
|
|
@@ -728,13 +698,35 @@ function useRegistry(options) {
|
|
|
728
698
|
emit("clear:registry");
|
|
729
699
|
}
|
|
730
700
|
function invalidate() {
|
|
731
|
-
if (
|
|
701
|
+
if (batching) return;
|
|
702
|
+
cache.clear();
|
|
703
|
+
}
|
|
704
|
+
function queueEmit(event, data) {
|
|
705
|
+
if (batching) pendingEmits.push({
|
|
706
|
+
event,
|
|
707
|
+
data
|
|
708
|
+
});
|
|
709
|
+
else emit(event, data);
|
|
710
|
+
}
|
|
711
|
+
function batch(fn) {
|
|
712
|
+
if (batching) return fn();
|
|
713
|
+
batching = true;
|
|
714
|
+
pendingEmits = [];
|
|
715
|
+
try {
|
|
716
|
+
const result = fn();
|
|
717
|
+
cache.clear();
|
|
718
|
+
for (const { event, data } of pendingEmits) emit(event, data);
|
|
719
|
+
return result;
|
|
720
|
+
} finally {
|
|
721
|
+
batching = false;
|
|
722
|
+
pendingEmits = [];
|
|
723
|
+
}
|
|
732
724
|
}
|
|
733
725
|
function reindex() {
|
|
734
726
|
const startIndex = minDirtyIndex === Infinity ? 0 : minDirtyIndex;
|
|
735
727
|
if (startIndex === 0) {
|
|
736
|
-
|
|
737
|
-
|
|
728
|
+
catalog.clear();
|
|
729
|
+
directory.clear();
|
|
738
730
|
}
|
|
739
731
|
invalidate();
|
|
740
732
|
let index = 0;
|
|
@@ -761,7 +753,7 @@ function useRegistry(options) {
|
|
|
761
753
|
const size = collection.size;
|
|
762
754
|
const id = registration.id ?? /* @__PURE__ */ genId();
|
|
763
755
|
if (has(id)) {
|
|
764
|
-
logger.warn(`Ticket
|
|
756
|
+
logger.warn(`Ticket "${id}" already exists. Use \`upsert()\` to update or check \`has()\` before registering.`);
|
|
765
757
|
return get(id);
|
|
766
758
|
}
|
|
767
759
|
const valueIsUndefined = /* @__PURE__ */ isUndefined(registration.value);
|
|
@@ -780,7 +772,7 @@ function useRegistry(options) {
|
|
|
780
772
|
directory.set(ticket.index, ticket.id);
|
|
781
773
|
assign(ticket.value, ticket.id);
|
|
782
774
|
invalidate();
|
|
783
|
-
|
|
775
|
+
queueEmit("register:ticket", ticket);
|
|
784
776
|
return ticket;
|
|
785
777
|
}
|
|
786
778
|
function unregister(id) {
|
|
@@ -790,15 +782,12 @@ function useRegistry(options) {
|
|
|
790
782
|
collection.delete(ticket.id);
|
|
791
783
|
directory.delete(ticket.index);
|
|
792
784
|
unassign(ticket.value, ticket.id);
|
|
793
|
-
|
|
785
|
+
const willReindex = indexDependentCount > 0 && ticket.index < collection.size;
|
|
786
|
+
if (!willReindex) invalidate();
|
|
794
787
|
emit("unregister:ticket", ticket);
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
} else {
|
|
799
|
-
minDirtyIndex = Math.min(minDirtyIndex, ticket.index);
|
|
800
|
-
needsReindex = true;
|
|
801
|
-
}
|
|
788
|
+
minDirtyIndex = Math.min(minDirtyIndex, ticket.index);
|
|
789
|
+
if (willReindex) reindex();
|
|
790
|
+
else needsReindex = true;
|
|
802
791
|
}
|
|
803
792
|
function offboard(ids) {
|
|
804
793
|
const removed = [];
|
|
@@ -814,12 +803,16 @@ function useRegistry(options) {
|
|
|
814
803
|
}
|
|
815
804
|
if (removed.length === 0) return;
|
|
816
805
|
invalidate();
|
|
817
|
-
|
|
806
|
+
for (const ticket of removed) queueEmit("unregister:ticket", ticket);
|
|
818
807
|
needsReindex = true;
|
|
819
808
|
}
|
|
820
809
|
function seek(direction = "first", from, predicate) {
|
|
821
810
|
if (collection.size === 0) return void 0;
|
|
822
811
|
if (needsReindex) reindex();
|
|
812
|
+
if (!predicate && /* @__PURE__ */ isUndefined(from)) {
|
|
813
|
+
const tickets$1 = values();
|
|
814
|
+
return direction === "first" ? tickets$1[0] : tickets$1.at(-1);
|
|
815
|
+
}
|
|
823
816
|
const tickets = values();
|
|
824
817
|
const index = /* @__PURE__ */ isUndefined(from) ? void 0 : Math.max(0, Math.min(from, tickets.length - 1));
|
|
825
818
|
if (direction === "last") {
|
|
@@ -855,8 +848,9 @@ function useRegistry(options) {
|
|
|
855
848
|
unregister,
|
|
856
849
|
reindex,
|
|
857
850
|
seek,
|
|
851
|
+
batch,
|
|
858
852
|
onboard(registrations) {
|
|
859
|
-
return registrations.map((registration) => register(registration));
|
|
853
|
+
return batch(() => registrations.map((registration) => register(registration)));
|
|
860
854
|
},
|
|
861
855
|
offboard,
|
|
862
856
|
get size() {
|
|
@@ -867,8 +861,7 @@ function useRegistry(options) {
|
|
|
867
861
|
/**
|
|
868
862
|
* Creates a new registry context.
|
|
869
863
|
*
|
|
870
|
-
* @param
|
|
871
|
-
* @param options The options for the registry context.
|
|
864
|
+
* @param options The options for the registry context, including `namespace` (defaults to `'v0:registry'`) and `events`.
|
|
872
865
|
* @template Z The type of registry ticket that extends RegistryTicket. Use this to add custom properties to tickets.
|
|
873
866
|
* @template E The type of registry context that extends RegistryContext<Z>. Use this when extending the registry with additional methods.
|
|
874
867
|
* @returns A new registry context.
|
|
@@ -894,7 +887,7 @@ function useRegistry(options) {
|
|
|
894
887
|
* ```
|
|
895
888
|
*/
|
|
896
889
|
function createRegistryContext(_options = {}) {
|
|
897
|
-
const { namespace = "v0:registry"
|
|
890
|
+
const { namespace = "v0:registry", ...options } = _options;
|
|
898
891
|
const [useRegistryContext, _provideRegistryContext] = createContext(namespace);
|
|
899
892
|
const context = useRegistry(options);
|
|
900
893
|
function provideRegistryContext(_context = context, app) {
|
|
@@ -906,21 +899,6 @@ function createRegistryContext(_options = {}) {
|
|
|
906
899
|
//#endregion
|
|
907
900
|
//#region src/composables/useSelection/index.ts
|
|
908
901
|
/**
|
|
909
|
-
* @module useSelection
|
|
910
|
-
*
|
|
911
|
-
* @remarks
|
|
912
|
-
* Base composable for managing selected items in a collection with Set-based tracking.
|
|
913
|
-
*
|
|
914
|
-
* Key features:
|
|
915
|
-
* - Set-based selectedIds for O(1) selection checks
|
|
916
|
-
* - Mandatory selection mode (prevents deselecting last item)
|
|
917
|
-
* - Auto-enrollment option (selects non-disabled items on register)
|
|
918
|
-
* - Disabled item filtering
|
|
919
|
-
* - Computed selectedItems and selectedValues Sets
|
|
920
|
-
*
|
|
921
|
-
* Extends useRegistry and serves as the base for useSingle, useGroup, useStep, and useFeatures.
|
|
922
|
-
*/
|
|
923
|
-
/**
|
|
924
902
|
* Creates a new selection instance for managing multiple selected items.
|
|
925
903
|
*
|
|
926
904
|
* Extends `useRegistry` with selection tracking via a reactive `Set` of selected IDs.
|
|
@@ -967,14 +945,14 @@ function createRegistryContext(_options = {}) {
|
|
|
967
945
|
* ```
|
|
968
946
|
*/
|
|
969
947
|
function createSelection(_options = {}) {
|
|
970
|
-
const { disabled = false, enroll = false, mandatory = false, multiple = false
|
|
948
|
+
const { disabled = false, enroll = false, mandatory = false, multiple = false, ...options } = _options;
|
|
971
949
|
const registry = useRegistry(options);
|
|
972
950
|
const selectedIds = shallowReactive(/* @__PURE__ */ new Set());
|
|
973
951
|
const selectedItems = computed(() => {
|
|
974
|
-
return new Set(Array.from(selectedIds).map((id) => registry.get(id)));
|
|
952
|
+
return new Set(Array.from(selectedIds).map((id) => registry.get(id)).filter((item) => !/* @__PURE__ */ isUndefined(item)));
|
|
975
953
|
});
|
|
976
954
|
const selectedValues = computed(() => {
|
|
977
|
-
return new Set(Array.from(selectedItems.value).map((item) => item
|
|
955
|
+
return new Set(Array.from(selectedItems.value).map((item) => item.value));
|
|
978
956
|
});
|
|
979
957
|
function seek(direction = "first", from) {
|
|
980
958
|
return registry.seek(direction, from, (ticket) => !toValue(ticket.disabled));
|
|
@@ -985,16 +963,19 @@ function createSelection(_options = {}) {
|
|
|
985
963
|
if (ticket) select(ticket.id);
|
|
986
964
|
}
|
|
987
965
|
function select(id) {
|
|
966
|
+
if (toValue(disabled)) return;
|
|
988
967
|
const item = registry.get(id);
|
|
989
968
|
if (!item || toValue(item.disabled)) return;
|
|
990
969
|
if (!multiple) selectedIds.clear();
|
|
991
970
|
selectedIds.add(id);
|
|
992
971
|
}
|
|
993
972
|
function unselect(id) {
|
|
973
|
+
if (toValue(disabled)) return;
|
|
994
974
|
if (mandatory && selectedIds.size === 1) return;
|
|
995
975
|
selectedIds.delete(id);
|
|
996
976
|
}
|
|
997
977
|
function toggle(id) {
|
|
978
|
+
if (toValue(disabled)) return;
|
|
998
979
|
if (selected(id)) unselect(id);
|
|
999
980
|
else select(id);
|
|
1000
981
|
}
|
|
@@ -1013,7 +994,7 @@ function createSelection(_options = {}) {
|
|
|
1013
994
|
id
|
|
1014
995
|
};
|
|
1015
996
|
const ticket = registry.register(item);
|
|
1016
|
-
if (enroll && !toValue(item.disabled)) selectedIds.add(ticket.id);
|
|
997
|
+
if (enroll && !toValue(disabled) && !toValue(item.disabled)) selectedIds.add(ticket.id);
|
|
1017
998
|
if (mandatory === "force") mandate();
|
|
1018
999
|
return ticket;
|
|
1019
1000
|
}
|
|
@@ -1084,7 +1065,7 @@ function createSelection(_options = {}) {
|
|
|
1084
1065
|
* ```
|
|
1085
1066
|
*/
|
|
1086
1067
|
function createSelectionContext(_options = {}) {
|
|
1087
|
-
const { namespace = "v0:selection"
|
|
1068
|
+
const { namespace = "v0:selection", ...options } = _options;
|
|
1088
1069
|
const [useSelectionContext, _provideSelectionContext] = createContext(namespace);
|
|
1089
1070
|
const context = createSelection(options);
|
|
1090
1071
|
function provideSelectionContext(_context = context, app) {
|
|
@@ -1157,20 +1138,6 @@ function toArray(value) {
|
|
|
1157
1138
|
//#endregion
|
|
1158
1139
|
//#region src/composables/useProxyModel/index.ts
|
|
1159
1140
|
/**
|
|
1160
|
-
* @module useProxyModel
|
|
1161
|
-
*
|
|
1162
|
-
* @remarks
|
|
1163
|
-
* Proxy composable for bidirectional sync between selection registry and v-model.
|
|
1164
|
-
*
|
|
1165
|
-
* Key features:
|
|
1166
|
-
* - Bidirectional synchronization
|
|
1167
|
-
* - Array and single-value modes
|
|
1168
|
-
* - Automatic cleanup on scope disposal
|
|
1169
|
-
* - Perfect for form controls with selection backing
|
|
1170
|
-
*
|
|
1171
|
-
* Bridges the gap between selection composables and Vue's v-model.
|
|
1172
|
-
*/
|
|
1173
|
-
/**
|
|
1174
1141
|
* Syncs a ref with a selection registry bidirectionally.
|
|
1175
1142
|
*
|
|
1176
1143
|
* @param registry The selection registry to bind to.
|
|
@@ -1211,12 +1178,9 @@ function useProxyModel(registry, model, options) {
|
|
|
1211
1178
|
const pending = new Set(modelAsArray);
|
|
1212
1179
|
for (const value of modelAsArray) {
|
|
1213
1180
|
const ids = registry.browse(value);
|
|
1214
|
-
if (
|
|
1181
|
+
if (ids) {
|
|
1215
1182
|
for (const id of ids) registry.select(id);
|
|
1216
1183
|
pending.delete(value);
|
|
1217
|
-
} else if (ids) {
|
|
1218
|
-
registry.select(ids);
|
|
1219
|
-
pending.delete(value);
|
|
1220
1184
|
}
|
|
1221
1185
|
}
|
|
1222
1186
|
const registryWatch = watch(registry.selectedValues, (val) => {
|
|
@@ -1230,8 +1194,7 @@ function useProxyModel(registry, model, options) {
|
|
|
1230
1194
|
const targetIds = /* @__PURE__ */ new Set();
|
|
1231
1195
|
for (const value of transformIn(val)) {
|
|
1232
1196
|
const ids = registry.browse(value);
|
|
1233
|
-
if (
|
|
1234
|
-
else if (ids) targetIds.add(ids);
|
|
1197
|
+
if (ids) for (const id of ids) targetIds.add(id);
|
|
1235
1198
|
}
|
|
1236
1199
|
if (multiple) {
|
|
1237
1200
|
for (const id of currentIds.difference(targetIds)) registry.selectedIds.delete(id);
|
|
@@ -1247,7 +1210,8 @@ function useProxyModel(registry, model, options) {
|
|
|
1247
1210
|
flush: "sync",
|
|
1248
1211
|
deep: multiple
|
|
1249
1212
|
});
|
|
1250
|
-
function onRegister(
|
|
1213
|
+
function onRegister(data) {
|
|
1214
|
+
const ticket = data;
|
|
1251
1215
|
if (!pending.has(ticket.value) || ticket.disabled) return;
|
|
1252
1216
|
registryWatch.pause();
|
|
1253
1217
|
modelWatch.pause();
|
|
@@ -1269,21 +1233,6 @@ function useProxyModel(registry, model, options) {
|
|
|
1269
1233
|
//#endregion
|
|
1270
1234
|
//#region src/composables/useProxyRegistry/index.ts
|
|
1271
1235
|
/**
|
|
1272
|
-
* @module useProxyRegistry
|
|
1273
|
-
*
|
|
1274
|
-
* @remarks
|
|
1275
|
-
* Proxy composable for reactive registry keys, values, entries, and size.
|
|
1276
|
-
*
|
|
1277
|
-
* Key features:
|
|
1278
|
-
* - Reactive proxy for registry data
|
|
1279
|
-
* - Deep or shallow reactivity options
|
|
1280
|
-
* - Event-based updates
|
|
1281
|
-
* - Automatic cleanup on scope disposal
|
|
1282
|
-
* - Transforms Map-based registry into reactive refs
|
|
1283
|
-
*
|
|
1284
|
-
* Perfect for exposing registry data as reactive computed properties.
|
|
1285
|
-
*/
|
|
1286
|
-
/**
|
|
1287
1236
|
* Creates a proxy registry that provides reactive objects for registry data.
|
|
1288
1237
|
*
|
|
1289
1238
|
* @param registry The registry instance to proxy.
|
|
@@ -1333,26 +1282,6 @@ function useProxyRegistry(registry, options) {
|
|
|
1333
1282
|
//#endregion
|
|
1334
1283
|
//#region src/composables/useGroup/index.ts
|
|
1335
1284
|
/**
|
|
1336
|
-
* @module useGroup
|
|
1337
|
-
*
|
|
1338
|
-
* @remarks
|
|
1339
|
-
* Multi-selection composable that extends useSelection with batch operations and tri-state support.
|
|
1340
|
-
*
|
|
1341
|
-
* Key features:
|
|
1342
|
-
* - Batch operations (select/unselect/toggle accept ID | ID[])
|
|
1343
|
-
* - Tri-state support via mixed/indeterminate state (mix/unmix)
|
|
1344
|
-
* - selectedIndexes computed Set for position-based tracking
|
|
1345
|
-
* - Perfect for checkbox trees, multi-select dropdowns, filter panels
|
|
1346
|
-
*
|
|
1347
|
-
* Tri-state behavior:
|
|
1348
|
-
* - Items can be selected, mixed (indeterminate), or unselected
|
|
1349
|
-
* - select() clears mixed state, mix() clears selected state (mutually exclusive)
|
|
1350
|
-
* - toggle() on a mixed item selects it (resolves positively)
|
|
1351
|
-
*
|
|
1352
|
-
* Inheritance chain: useRegistry → useSelection → useGroup
|
|
1353
|
-
* Extended by: useFeatures
|
|
1354
|
-
*/
|
|
1355
|
-
/**
|
|
1356
1285
|
* Creates a new group instance with batch selection and tri-state support.
|
|
1357
1286
|
*
|
|
1358
1287
|
* Extends `createSelection` to support selecting, unselecting, and toggling multiple items
|
|
@@ -1426,7 +1355,7 @@ function useProxyRegistry(registry, options) {
|
|
|
1426
1355
|
* ```
|
|
1427
1356
|
*/
|
|
1428
1357
|
function createGroup(_options = {}) {
|
|
1429
|
-
const { mandatory = false, multiple = true
|
|
1358
|
+
const { mandatory = false, multiple = true, ...options } = _options;
|
|
1430
1359
|
const selection = createSelection({
|
|
1431
1360
|
...options,
|
|
1432
1361
|
mandatory,
|
|
@@ -1436,10 +1365,10 @@ function createGroup(_options = {}) {
|
|
|
1436
1365
|
const proxy = useProxyRegistry(selection);
|
|
1437
1366
|
const mixedIds = shallowReactive(/* @__PURE__ */ new Set());
|
|
1438
1367
|
const selectedIndexes = computed(() => {
|
|
1439
|
-
return new Set(Array.from(selection.selectedItems.value).map((item) => item?.index));
|
|
1368
|
+
return new Set(Array.from(selection.selectedItems.value).map((item) => item?.index).filter((index) => !/* @__PURE__ */ isUndefined(index)));
|
|
1440
1369
|
});
|
|
1441
1370
|
const mixedItems = computed(() => {
|
|
1442
|
-
return new Set(Array.from(mixedIds).map((id) => selection.get(id)));
|
|
1371
|
+
return new Set(Array.from(mixedIds).map((id) => selection.get(id)).filter((item) => !/* @__PURE__ */ isUndefined(item)));
|
|
1443
1372
|
});
|
|
1444
1373
|
function mixed(id) {
|
|
1445
1374
|
return mixedIds.has(id);
|
|
@@ -1506,10 +1435,10 @@ function createGroup(_options = {}) {
|
|
|
1506
1435
|
if (items.length === 0) return false;
|
|
1507
1436
|
return items.every((item) => selection.selectedIds.has(item.id));
|
|
1508
1437
|
});
|
|
1509
|
-
const
|
|
1438
|
+
const isNoneSelected = computed(() => selection.selectedIds.size === 0);
|
|
1439
|
+
const isMixed = computed(() => {
|
|
1510
1440
|
return mixedIds.size > 0 || !isNoneSelected.value && !isAllSelected.value;
|
|
1511
1441
|
});
|
|
1512
|
-
const isNoneSelected = toRef(() => selection.selectedIds.size === 0);
|
|
1513
1442
|
function selectAll() {
|
|
1514
1443
|
for (const item of selectableItems.value) {
|
|
1515
1444
|
mixedIds.delete(item.id);
|
|
@@ -1581,7 +1510,7 @@ function createGroup(_options = {}) {
|
|
|
1581
1510
|
* ```
|
|
1582
1511
|
*/
|
|
1583
1512
|
function createGroupContext(_options = {}) {
|
|
1584
|
-
const { namespace = "v0:group"
|
|
1513
|
+
const { namespace = "v0:group", ...options } = _options;
|
|
1585
1514
|
const [useGroupContext, _provideGroupContext] = createContext(namespace);
|
|
1586
1515
|
const context = createGroup(options);
|
|
1587
1516
|
function provideGroupContext(_context = context, app) {
|
|
@@ -1617,1364 +1546,1244 @@ function useGroup(namespace = "v0:group") {
|
|
|
1617
1546
|
}
|
|
1618
1547
|
|
|
1619
1548
|
//#endregion
|
|
1620
|
-
//#region src/composables/
|
|
1549
|
+
//#region src/composables/useLocale/adapters/v0.ts
|
|
1621
1550
|
/**
|
|
1622
|
-
*
|
|
1551
|
+
* Vuetify0.x locale adapter implementation
|
|
1623
1552
|
*
|
|
1624
|
-
*
|
|
1553
|
+
* This adapter provides translation and number formatting
|
|
1554
|
+
* capabilities using the Intl API and supports both
|
|
1555
|
+
* numbered ({0}, {1}) and named ({name}) variables in translation strings.
|
|
1556
|
+
*/
|
|
1557
|
+
var Vuetify0LocaleAdapter = class {
|
|
1558
|
+
t(message, ...params) {
|
|
1559
|
+
let resolvedMessage = message;
|
|
1560
|
+
if (params.length > 0 && /* @__PURE__ */ isObject(params[0])) {
|
|
1561
|
+
const variables = params[0];
|
|
1562
|
+
resolvedMessage = resolvedMessage.replace(/{([a-zA-Z][a-zA-Z0-9_]*)}/g, (match, name) => {
|
|
1563
|
+
return /* @__PURE__ */ isUndefined(variables[name]) ? match : String(variables[name]);
|
|
1564
|
+
});
|
|
1565
|
+
params = params.slice(1);
|
|
1566
|
+
}
|
|
1567
|
+
resolvedMessage = resolvedMessage.replace(/\{(\d+)\}/g, (match, index) => {
|
|
1568
|
+
const idx = Number.parseInt(index, 10);
|
|
1569
|
+
if (!/* @__PURE__ */ isUndefined(params[idx])) return String(params[idx]);
|
|
1570
|
+
return match;
|
|
1571
|
+
});
|
|
1572
|
+
return resolvedMessage;
|
|
1573
|
+
}
|
|
1574
|
+
n(value, locale, ...params) {
|
|
1575
|
+
if (!IN_BROWSER || !locale) return value.toString();
|
|
1576
|
+
const options = params[0];
|
|
1577
|
+
return new Intl.NumberFormat(String(locale), options).format(value);
|
|
1578
|
+
}
|
|
1579
|
+
};
|
|
1580
|
+
|
|
1581
|
+
//#endregion
|
|
1582
|
+
//#region src/composables/useSingle/index.ts
|
|
1583
|
+
/**
|
|
1584
|
+
* Creates a new single selection instance that enforces only one selected item at a time.
|
|
1625
1585
|
*
|
|
1626
|
-
*
|
|
1627
|
-
*
|
|
1586
|
+
* Extends `createSelection` by automatically clearing previous selections when a new item is selected.
|
|
1587
|
+
* Adds computed singular properties: `selectedId`, `selectedItem`, `selectedIndex`, `selectedValue`.
|
|
1628
1588
|
*
|
|
1629
|
-
*
|
|
1630
|
-
*
|
|
1631
|
-
*
|
|
1632
|
-
*
|
|
1633
|
-
* - Plugin installation support
|
|
1634
|
-
* - Perfect for hydration-safe rendering
|
|
1589
|
+
* @param options The options for the single selection instance.
|
|
1590
|
+
* @template Z The type of the single selection ticket.
|
|
1591
|
+
* @template E The type of the single selection context.
|
|
1592
|
+
* @returns A new single selection instance with single-selection enforcement.
|
|
1635
1593
|
*
|
|
1636
|
-
*
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
*
|
|
1594
|
+
* @remarks
|
|
1595
|
+
* **Key Differences from `createSelection`:**
|
|
1596
|
+
* - Automatically clears `selectedIds` before selecting a new item (enforces single selection)
|
|
1597
|
+
* - Provides singular computed properties instead of plural sets
|
|
1598
|
+
* - Perfect for tabs, radio buttons, theme selectors, and other single-choice UI components
|
|
1640
1599
|
*
|
|
1641
|
-
*
|
|
1600
|
+
* **Computed Properties:**
|
|
1601
|
+
* - `selectedId`: The ID of the selected item (undefined if none selected)
|
|
1602
|
+
* - `selectedItem`: The selected ticket object (undefined if none selected)
|
|
1603
|
+
* - `selectedIndex`: The index of the selected item (-1 if none selected)
|
|
1604
|
+
* - `selectedValue`: The value of the selected item (undefined if none selected)
|
|
1642
1605
|
*
|
|
1643
|
-
*
|
|
1606
|
+
* **Inheritance Chain:**
|
|
1607
|
+
* `useRegistry` → `createSelection` → `createSingle` → `createStep`
|
|
1608
|
+
*
|
|
1609
|
+
* @see https://0.vuetifyjs.com/composables/selection/use-single
|
|
1644
1610
|
*
|
|
1645
1611
|
* @example
|
|
1646
1612
|
* ```ts
|
|
1647
|
-
* import {
|
|
1613
|
+
* import { createSingle } from '@vuetify/v0'
|
|
1648
1614
|
*
|
|
1649
|
-
* const
|
|
1650
|
-
* console.log(hydration.isHydrated.value) // false
|
|
1651
|
-
* hydration.hydrate()
|
|
1652
|
-
* console.log(hydration.isHydrated.value) // true
|
|
1653
|
-
* ```
|
|
1654
|
-
*/
|
|
1655
|
-
function createHydration() {
|
|
1656
|
-
const isHydrated = shallowRef(false);
|
|
1657
|
-
function hydrate() {
|
|
1658
|
-
isHydrated.value = true;
|
|
1659
|
-
}
|
|
1660
|
-
return {
|
|
1661
|
-
isHydrated: shallowReadonly(isHydrated),
|
|
1662
|
-
hydrate
|
|
1663
|
-
};
|
|
1664
|
-
}
|
|
1665
|
-
function createFallbackHydration() {
|
|
1666
|
-
return {
|
|
1667
|
-
isHydrated: shallowReadonly(shallowRef(true)),
|
|
1668
|
-
hydrate: () => {}
|
|
1669
|
-
};
|
|
1670
|
-
}
|
|
1671
|
-
/**
|
|
1672
|
-
* Creates a new hydration context trinity.
|
|
1615
|
+
* const tabs = createSingle({ mandatory: true })
|
|
1673
1616
|
*
|
|
1674
|
-
*
|
|
1675
|
-
*
|
|
1676
|
-
*
|
|
1617
|
+
* tabs.onboard([
|
|
1618
|
+
* { id: 'home', value: 'Home' },
|
|
1619
|
+
* { id: 'about', value: 'About' },
|
|
1620
|
+
* { id: 'contact', value: 'Contact' },
|
|
1621
|
+
* ])
|
|
1677
1622
|
*
|
|
1678
|
-
*
|
|
1623
|
+
* tabs.first() // Select first tab
|
|
1679
1624
|
*
|
|
1680
|
-
*
|
|
1681
|
-
*
|
|
1682
|
-
* import { createHydrationContext } from '@vuetify/v0'
|
|
1625
|
+
* console.log(tabs.selectedId.value) // 'home'
|
|
1626
|
+
* console.log(tabs.selectedIndex.value) // 0
|
|
1683
1627
|
*
|
|
1684
|
-
*
|
|
1685
|
-
*
|
|
1686
|
-
*
|
|
1628
|
+
* tabs.select('about') // Switch to about tab
|
|
1629
|
+
* console.log(tabs.selectedId.value) // 'about'
|
|
1630
|
+
* console.log(tabs.selectedIds.size) // 1 (always enforces single selection)
|
|
1687
1631
|
* ```
|
|
1688
1632
|
*/
|
|
1689
|
-
function
|
|
1690
|
-
const {
|
|
1691
|
-
const
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1633
|
+
function createSingle(_options = {}) {
|
|
1634
|
+
const { mandatory = false, multiple = false, ...options } = _options;
|
|
1635
|
+
const registry = createSelection({
|
|
1636
|
+
...options,
|
|
1637
|
+
mandatory,
|
|
1638
|
+
multiple
|
|
1639
|
+
});
|
|
1640
|
+
const selectedId = computed(() => registry.selectedIds.values().next().value);
|
|
1641
|
+
const selectedItem = computed(() => registry.selectedItems.value.values().next().value);
|
|
1642
|
+
const selectedIndex = computed(() => selectedItem.value?.index ?? -1);
|
|
1643
|
+
const selectedValue = computed(() => selectedItem.value?.value);
|
|
1644
|
+
function unselect(id) {
|
|
1645
|
+
if (mandatory && registry.selectedIds.size === 1) return;
|
|
1646
|
+
registry.selectedIds.delete(id);
|
|
1695
1647
|
}
|
|
1696
|
-
|
|
1648
|
+
function toggle(id) {
|
|
1649
|
+
if (registry.selectedIds.has(id)) unselect(id);
|
|
1650
|
+
else registry.select(id);
|
|
1651
|
+
}
|
|
1652
|
+
return {
|
|
1653
|
+
...registry,
|
|
1654
|
+
selectedId,
|
|
1655
|
+
selectedItem,
|
|
1656
|
+
selectedIndex,
|
|
1657
|
+
selectedValue,
|
|
1658
|
+
unselect,
|
|
1659
|
+
toggle,
|
|
1660
|
+
get size() {
|
|
1661
|
+
return registry.size;
|
|
1662
|
+
}
|
|
1663
|
+
};
|
|
1697
1664
|
}
|
|
1698
1665
|
/**
|
|
1699
|
-
* Creates a new
|
|
1666
|
+
* Creates a new single selection context.
|
|
1700
1667
|
*
|
|
1701
|
-
* @param options The options for the
|
|
1702
|
-
* @template
|
|
1703
|
-
* @
|
|
1668
|
+
* @param options The options for the single selection context.
|
|
1669
|
+
* @template Z The type of the single selection ticket.
|
|
1670
|
+
* @template E The type of the single selection context.
|
|
1671
|
+
* @returns A new single selection context.
|
|
1704
1672
|
*
|
|
1705
|
-
* @see https://0.vuetifyjs.com/composables/
|
|
1673
|
+
* @see https://0.vuetifyjs.com/composables/selection/use-single
|
|
1706
1674
|
*
|
|
1707
1675
|
* @example
|
|
1708
1676
|
* ```ts
|
|
1709
|
-
* import {
|
|
1710
|
-
* import { createHydrationPlugin } from '@vuetify/v0'
|
|
1711
|
-
* import App from './App.vue'
|
|
1677
|
+
* import { createSingleContext } from '@vuetify/v0'
|
|
1712
1678
|
*
|
|
1713
|
-
*
|
|
1679
|
+
* // With default namespace 'v0:single'
|
|
1680
|
+
* export const [useSingle, provideSingle, context] = createSingleContext()
|
|
1714
1681
|
*
|
|
1715
|
-
*
|
|
1682
|
+
* // In a parent component:
|
|
1683
|
+
* provideSingle()
|
|
1716
1684
|
*
|
|
1717
|
-
*
|
|
1685
|
+
* // In a child component:
|
|
1686
|
+
* const single = useSingle()
|
|
1687
|
+
* single.select('tab-1')
|
|
1718
1688
|
* ```
|
|
1719
1689
|
*/
|
|
1720
|
-
function
|
|
1721
|
-
const { namespace = "v0:
|
|
1722
|
-
const [,
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
provide: (app) => {
|
|
1729
|
-
provideHydrationContext(context, app);
|
|
1730
|
-
},
|
|
1731
|
-
setup: (app) => {
|
|
1732
|
-
app.mixin({ mounted() {
|
|
1733
|
-
if (this.$parent !== null) return;
|
|
1734
|
-
context.hydrate();
|
|
1735
|
-
} });
|
|
1736
|
-
}
|
|
1737
|
-
});
|
|
1690
|
+
function createSingleContext(_options = {}) {
|
|
1691
|
+
const { namespace = "v0:single", ...options } = _options;
|
|
1692
|
+
const [useSingleContext, _provideSingleContext] = createContext(namespace);
|
|
1693
|
+
const context = createSingle(options);
|
|
1694
|
+
function provideSingleContext(_context = context, app) {
|
|
1695
|
+
return _provideSingleContext(_context, app);
|
|
1696
|
+
}
|
|
1697
|
+
return createTrinity(useSingleContext, provideSingleContext, context);
|
|
1738
1698
|
}
|
|
1739
1699
|
/**
|
|
1740
|
-
* Returns the current
|
|
1700
|
+
* Returns the current single selection instance.
|
|
1741
1701
|
*
|
|
1742
|
-
* @param namespace The namespace for the
|
|
1743
|
-
* @returns The current
|
|
1702
|
+
* @param namespace The namespace for the single selection context. Defaults to `'v0:single'`.
|
|
1703
|
+
* @returns The current single selection instance.
|
|
1744
1704
|
*
|
|
1745
|
-
* @see https://0.vuetifyjs.com/composables/
|
|
1705
|
+
* @see https://0.vuetifyjs.com/composables/selection/use-single
|
|
1746
1706
|
*
|
|
1747
1707
|
* @example
|
|
1748
1708
|
* ```vue
|
|
1749
1709
|
* <script setup lang="ts">
|
|
1750
|
-
* import {
|
|
1710
|
+
* import { useSingle } from '@vuetify/v0'
|
|
1751
1711
|
*
|
|
1752
|
-
* const
|
|
1712
|
+
* const tabs = useSingle()
|
|
1753
1713
|
* <\/script>
|
|
1754
1714
|
*
|
|
1755
1715
|
* <template>
|
|
1756
1716
|
* <div>
|
|
1757
|
-
* <p>
|
|
1717
|
+
* <p>Selected: {{ tabs.selectedId }}</p>
|
|
1758
1718
|
* </div>
|
|
1759
1719
|
* </template>
|
|
1760
1720
|
* ```
|
|
1761
1721
|
*/
|
|
1762
|
-
function
|
|
1763
|
-
|
|
1764
|
-
if (!getCurrentInstance()) return fallback;
|
|
1765
|
-
try {
|
|
1766
|
-
return useContext(namespace, fallback);
|
|
1767
|
-
} catch {
|
|
1768
|
-
return fallback;
|
|
1769
|
-
}
|
|
1722
|
+
function useSingle(namespace = "v0:single") {
|
|
1723
|
+
return useContext(namespace);
|
|
1770
1724
|
}
|
|
1771
1725
|
|
|
1772
1726
|
//#endregion
|
|
1773
|
-
//#region src/composables/
|
|
1774
|
-
/**
|
|
1775
|
-
* @module useResizeObserver
|
|
1776
|
-
*
|
|
1777
|
-
* @remarks
|
|
1778
|
-
* ResizeObserver composable with lifecycle management.
|
|
1779
|
-
*
|
|
1780
|
-
* Key features:
|
|
1781
|
-
* - ResizeObserver API wrapper
|
|
1782
|
-
* - Pause/resume/stop functionality
|
|
1783
|
-
* - Automatic cleanup on unmount
|
|
1784
|
-
* - SSR-safe (checks SUPPORTS_OBSERVER)
|
|
1785
|
-
* - Hydration-aware
|
|
1786
|
-
* - Box model options (content-box/border-box)
|
|
1787
|
-
*
|
|
1788
|
-
* Perfect for responsive components and size-based rendering.
|
|
1789
|
-
*/
|
|
1727
|
+
//#region src/composables/useTokens/index.ts
|
|
1790
1728
|
/**
|
|
1791
|
-
*
|
|
1792
|
-
* size changes.
|
|
1729
|
+
* Creates a new token instance.
|
|
1793
1730
|
*
|
|
1794
|
-
* @param
|
|
1795
|
-
* @param
|
|
1796
|
-
* @
|
|
1797
|
-
* @
|
|
1731
|
+
* @param tokens The tokens to use.
|
|
1732
|
+
* @param options The options for the token instance.
|
|
1733
|
+
* @template Z The type of the token ticket.
|
|
1734
|
+
* @template E The type of the token context.
|
|
1735
|
+
* @returns A new token instance.
|
|
1798
1736
|
*
|
|
1799
|
-
* @see https://
|
|
1800
|
-
* @see https://0.vuetifyjs.com/composables/
|
|
1737
|
+
* @see https://www.designtokens.org/tr/drafts/format/
|
|
1738
|
+
* @see https://0.vuetifyjs.com/composables/registration/use-tokens
|
|
1801
1739
|
*
|
|
1802
1740
|
* @example
|
|
1803
1741
|
* ```ts
|
|
1804
|
-
* import {
|
|
1805
|
-
* import { useResizeObserver } from '@vuetify/v0'
|
|
1806
|
-
*
|
|
1807
|
-
* const el = ref<HTMLElement>()
|
|
1808
|
-
* const width = ref(0)
|
|
1809
|
-
* const height = ref(0)
|
|
1742
|
+
* import { useTokens } from '@vuetify/v0'
|
|
1810
1743
|
*
|
|
1811
|
-
* const
|
|
1812
|
-
*
|
|
1813
|
-
*
|
|
1814
|
-
*
|
|
1815
|
-
* if (entry) {
|
|
1816
|
-
* width.value = entry.contentRect.width
|
|
1817
|
-
* height.value = entry.contentRect.height
|
|
1818
|
-
* console.log('Size changed:', width.value, 'x', height.value)
|
|
1819
|
-
* }
|
|
1744
|
+
* const tokens = useTokens({
|
|
1745
|
+
* colors: {
|
|
1746
|
+
* primary: '#3b82f6',
|
|
1747
|
+
* secondary: '{colors.primary}', // Alias reference
|
|
1820
1748
|
* },
|
|
1821
|
-
*
|
|
1822
|
-
* )
|
|
1823
|
-
*
|
|
1824
|
-
* // Pause observation
|
|
1825
|
-
* pause()
|
|
1749
|
+
* })
|
|
1826
1750
|
*
|
|
1827
|
-
* //
|
|
1828
|
-
*
|
|
1751
|
+
* console.log(tokens.resolve('{colors.primary}')) // '#3b82f6'
|
|
1752
|
+
* console.log(tokens.resolve('{colors.secondary}')) // '#3b82f6'
|
|
1829
1753
|
* ```
|
|
1830
1754
|
*/
|
|
1831
|
-
function
|
|
1832
|
-
const
|
|
1833
|
-
const
|
|
1834
|
-
const
|
|
1835
|
-
|
|
1836
|
-
function
|
|
1837
|
-
|
|
1838
|
-
observer.value = new ResizeObserver((entries) => {
|
|
1839
|
-
callback(entries.map((entry) => ({
|
|
1840
|
-
contentRect: {
|
|
1841
|
-
width: entry.contentRect.width,
|
|
1842
|
-
height: entry.contentRect.height,
|
|
1843
|
-
top: entry.contentRect.top,
|
|
1844
|
-
left: entry.contentRect.left
|
|
1845
|
-
},
|
|
1846
|
-
target: entry.target
|
|
1847
|
-
})));
|
|
1848
|
-
});
|
|
1849
|
-
observer.value.observe(target.value, { box: options.box || "content-box" });
|
|
1850
|
-
if (options.immediate) {
|
|
1851
|
-
const rect = target.value.getBoundingClientRect();
|
|
1852
|
-
callback([{
|
|
1853
|
-
contentRect: {
|
|
1854
|
-
width: rect.width,
|
|
1855
|
-
height: rect.height,
|
|
1856
|
-
top: rect.top,
|
|
1857
|
-
left: rect.left
|
|
1858
|
-
},
|
|
1859
|
-
target: target.value
|
|
1860
|
-
}]);
|
|
1861
|
-
}
|
|
1862
|
-
}
|
|
1863
|
-
watch([isHydrated, target], () => {
|
|
1864
|
-
cleanup();
|
|
1865
|
-
setup();
|
|
1866
|
-
}, { immediate: true });
|
|
1867
|
-
function cleanup() {
|
|
1868
|
-
if (observer.value) {
|
|
1869
|
-
observer.value.disconnect();
|
|
1870
|
-
observer.value = void 0;
|
|
1871
|
-
}
|
|
1872
|
-
}
|
|
1873
|
-
function pause() {
|
|
1874
|
-
isPaused.value = true;
|
|
1875
|
-
observer.value?.disconnect();
|
|
1755
|
+
function createTokens(tokens = {}, options = {}) {
|
|
1756
|
+
const logger = useLogger();
|
|
1757
|
+
const registry = useRegistry(options);
|
|
1758
|
+
const cache = /* @__PURE__ */ new Map();
|
|
1759
|
+
registry.onboard(flatten(tokens, options.prefix, !!options.flat));
|
|
1760
|
+
function isAlias(token) {
|
|
1761
|
+
return /* @__PURE__ */ isString(token) && token.length > 2 && token[0] === "{" && token.at(-1) === "}";
|
|
1876
1762
|
}
|
|
1877
|
-
function
|
|
1878
|
-
|
|
1879
|
-
setup();
|
|
1763
|
+
function isTokenAlias(value) {
|
|
1764
|
+
return /* @__PURE__ */ isObject(value) && "$value" in value;
|
|
1880
1765
|
}
|
|
1881
|
-
function
|
|
1882
|
-
|
|
1766
|
+
function resolve(token, visited = /* @__PURE__ */ new Set()) {
|
|
1767
|
+
const cacheKey = /* @__PURE__ */ isString(token) ? token : JSON.stringify(token);
|
|
1768
|
+
const cached = cache.get(cacheKey);
|
|
1769
|
+
if (!/* @__PURE__ */ isUndefined(cached)) return cached;
|
|
1770
|
+
const reference = isTokenAlias(token) ? token.$value : token;
|
|
1771
|
+
const isAliasReference = /* @__PURE__ */ isString(reference) && isAlias(reference);
|
|
1772
|
+
const clean = isAliasReference ? reference.slice(1, -1) : String(reference);
|
|
1773
|
+
if (visited.has(clean)) {
|
|
1774
|
+
logger.warn(`Circular alias detected for "${clean}"`);
|
|
1775
|
+
cache.set(cacheKey, void 0);
|
|
1776
|
+
return;
|
|
1777
|
+
}
|
|
1778
|
+
visited.add(clean);
|
|
1779
|
+
let found = registry.get(clean);
|
|
1780
|
+
let segments = [];
|
|
1781
|
+
if (!found && clean.includes(".")) {
|
|
1782
|
+
const parts = clean.split(".");
|
|
1783
|
+
for (let i = parts.length - 1; i > 0; i--) {
|
|
1784
|
+
const prefix = parts.slice(0, i).join(".");
|
|
1785
|
+
const suffix = parts.slice(i);
|
|
1786
|
+
const candidate = registry.get(prefix);
|
|
1787
|
+
if (!/* @__PURE__ */ isUndefined(candidate?.value)) {
|
|
1788
|
+
found = candidate;
|
|
1789
|
+
segments = suffix;
|
|
1790
|
+
break;
|
|
1791
|
+
}
|
|
1792
|
+
}
|
|
1793
|
+
}
|
|
1794
|
+
if (/* @__PURE__ */ isUndefined(found?.value)) {
|
|
1795
|
+
if (isAliasReference) logger.warn(`Alias not found for "${String(reference)}"`);
|
|
1796
|
+
cache.set(cacheKey, void 0);
|
|
1797
|
+
return;
|
|
1798
|
+
}
|
|
1799
|
+
let result;
|
|
1800
|
+
let current = found.value;
|
|
1801
|
+
if (segments.length > 0) {
|
|
1802
|
+
if (isTokenAlias(current)) current = current.$value;
|
|
1803
|
+
for (const segment of segments) {
|
|
1804
|
+
if (!/* @__PURE__ */ isObject(current) || !(segment in current)) {
|
|
1805
|
+
current = void 0;
|
|
1806
|
+
break;
|
|
1807
|
+
}
|
|
1808
|
+
current = current[segment];
|
|
1809
|
+
if (isTokenAlias(current)) current = current.$value;
|
|
1810
|
+
}
|
|
1811
|
+
if (/* @__PURE__ */ isUndefined(current)) {
|
|
1812
|
+
logger.warn(`Path not found inside "${clean}": ${segments.join(".")}`);
|
|
1813
|
+
cache.set(cacheKey, void 0);
|
|
1814
|
+
return;
|
|
1815
|
+
}
|
|
1816
|
+
result = current;
|
|
1817
|
+
} else if (isTokenAlias(current)) {
|
|
1818
|
+
const inner = current.$value;
|
|
1819
|
+
if (/* @__PURE__ */ isString(inner) && isAlias(inner)) return resolve(inner, visited);
|
|
1820
|
+
result = inner;
|
|
1821
|
+
} else if (/* @__PURE__ */ isString(current) && isAlias(current)) return resolve(current, visited);
|
|
1822
|
+
else result = current;
|
|
1823
|
+
cache.set(cacheKey, result);
|
|
1824
|
+
return result;
|
|
1883
1825
|
}
|
|
1884
|
-
onScopeDispose(stop, true);
|
|
1885
1826
|
return {
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1827
|
+
...registry,
|
|
1828
|
+
resolve,
|
|
1829
|
+
isAlias,
|
|
1830
|
+
get size() {
|
|
1831
|
+
return registry.size;
|
|
1832
|
+
}
|
|
1891
1833
|
};
|
|
1892
1834
|
}
|
|
1893
1835
|
/**
|
|
1894
|
-
*
|
|
1895
|
-
* element's size.
|
|
1836
|
+
* Creates a new token context.
|
|
1896
1837
|
*
|
|
1897
|
-
* @param
|
|
1898
|
-
* @
|
|
1838
|
+
* @param namespace The namespace for the token context.
|
|
1839
|
+
* @param tokens The tokens to use.
|
|
1840
|
+
* @template Z The type of the token ticket.
|
|
1841
|
+
* @template E The type of the token context.
|
|
1842
|
+
* @returns A new token context.
|
|
1899
1843
|
*
|
|
1900
|
-
* @see https://0.vuetifyjs.com/composables/
|
|
1844
|
+
* @see https://0.vuetifyjs.com/composables/registration/use-tokens
|
|
1901
1845
|
*
|
|
1902
1846
|
* @example
|
|
1903
1847
|
* ```ts
|
|
1904
|
-
* import {
|
|
1905
|
-
* import { useElementSize } from '@vuetify/v0'
|
|
1906
|
-
*
|
|
1907
|
-
* const box = ref<HTMLElement>()
|
|
1908
|
-
* const { width, height } = useElementSize(box)
|
|
1848
|
+
* import { createTokensContext } from '@vuetify/v0'
|
|
1909
1849
|
*
|
|
1910
|
-
*
|
|
1911
|
-
*
|
|
1912
|
-
*
|
|
1850
|
+
* export const [useTokens, provideTokens, context] = createTokensContext({
|
|
1851
|
+
* namespace: 'v0:tokens',
|
|
1852
|
+
* tokens: {
|
|
1853
|
+
* colors: {
|
|
1854
|
+
* primary: '#3b82f6',
|
|
1855
|
+
* secondary: '{colors.primary}', // Alias reference
|
|
1856
|
+
* },
|
|
1857
|
+
* },
|
|
1913
1858
|
* })
|
|
1914
1859
|
* ```
|
|
1915
1860
|
*/
|
|
1916
|
-
function
|
|
1917
|
-
const
|
|
1918
|
-
const
|
|
1919
|
-
const
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
width.value = entry.contentRect.width;
|
|
1923
|
-
height.value = entry.contentRect.height;
|
|
1924
|
-
}
|
|
1925
|
-
}, { immediate: true });
|
|
1926
|
-
function pause() {
|
|
1927
|
-
width.value = 0;
|
|
1928
|
-
height.value = 0;
|
|
1929
|
-
_pause();
|
|
1861
|
+
function createTokensContext(_options) {
|
|
1862
|
+
const { namespace = "v0:tokens", tokens = {}, ...options } = _options;
|
|
1863
|
+
const [useTokensContext, _provideTokensContext] = createContext(namespace);
|
|
1864
|
+
const context = createTokens(tokens, options);
|
|
1865
|
+
function provideTokensContext(_context = context, app) {
|
|
1866
|
+
return _provideTokensContext(_context, app);
|
|
1930
1867
|
}
|
|
1931
|
-
return
|
|
1932
|
-
width,
|
|
1933
|
-
height,
|
|
1934
|
-
isActive,
|
|
1935
|
-
isPaused,
|
|
1936
|
-
pause,
|
|
1937
|
-
resume,
|
|
1938
|
-
stop
|
|
1939
|
-
};
|
|
1868
|
+
return createTrinity(useTokensContext, provideTokensContext, context);
|
|
1940
1869
|
}
|
|
1941
|
-
|
|
1942
|
-
//#endregion
|
|
1943
|
-
//#region src/composables/useOverflow/index.ts
|
|
1944
1870
|
/**
|
|
1945
|
-
*
|
|
1946
|
-
*
|
|
1947
|
-
* @remarks
|
|
1948
|
-
* Composable for computing how many items fit in a container based on available width.
|
|
1949
|
-
* Enables responsive truncation logic for Pagination, Breadcrumbs, and similar components.
|
|
1871
|
+
* Returns the current tokens instance.
|
|
1950
1872
|
*
|
|
1951
|
-
*
|
|
1952
|
-
*
|
|
1953
|
-
* - Two modes: variable-width (per-item) or uniform-width (sample-based)
|
|
1954
|
-
* - Computes capacity (how many items fit)
|
|
1955
|
-
* - SSR-safe with Infinity fallback
|
|
1956
|
-
* - Supports reserved space for nav buttons, ellipsis, etc.
|
|
1957
|
-
*
|
|
1958
|
-
* Use variable mode (default) for items with different widths like Breadcrumbs.
|
|
1959
|
-
* Use uniform mode (itemWidth option) for same-width items like Pagination buttons.
|
|
1960
|
-
*/
|
|
1961
|
-
/**
|
|
1962
|
-
* Creates a new overflow context for computing how many items fit in a container.
|
|
1873
|
+
* @param namespace The namespace for the tokens context. Defaults to `'v0:tokens'`.
|
|
1874
|
+
* @returns The current tokens instance.
|
|
1963
1875
|
*
|
|
1964
|
-
* @
|
|
1965
|
-
* @returns Overflow context with container ref, capacity, and measurement functions
|
|
1876
|
+
* @see https://0.vuetifyjs.com/composables/registration/use-tokens
|
|
1966
1877
|
*
|
|
1967
|
-
* @example
|
|
1878
|
+
* @example
|
|
1968
1879
|
* ```vue
|
|
1969
|
-
* <script lang="ts"
|
|
1970
|
-
* import {
|
|
1971
|
-
* import { createOverflow } from '@vuetify/v0'
|
|
1880
|
+
* <script setup lang="ts">
|
|
1881
|
+
* import { useTokens } from '@vuetify/v0'
|
|
1972
1882
|
*
|
|
1973
|
-
* const
|
|
1974
|
-
* const overflow = createOverflow({
|
|
1975
|
-
* container: containerRef,
|
|
1976
|
-
* gap: 8,
|
|
1977
|
-
* reserved: 40,
|
|
1978
|
-
* })
|
|
1883
|
+
* const tokens = useTokens()
|
|
1979
1884
|
* <\/script>
|
|
1980
|
-
*
|
|
1981
|
-
* <template>
|
|
1982
|
-
* <div ref="container">
|
|
1983
|
-
* <span
|
|
1984
|
-
* v-for="(item, i) in items.slice(0, overflow.capacity.value)"
|
|
1985
|
-
* :key="i"
|
|
1986
|
-
* :ref="el => overflow.measure(i, el)"
|
|
1987
|
-
* >
|
|
1988
|
-
* {{ item }}
|
|
1989
|
-
* </span>
|
|
1990
|
-
* <span v-if="overflow.isOverflowing.value">...</span>
|
|
1991
|
-
* </div>
|
|
1992
|
-
* </template>
|
|
1993
|
-
* ```
|
|
1994
|
-
*
|
|
1995
|
-
* @example Uniform-width mode (Pagination)
|
|
1996
|
-
* ```ts
|
|
1997
|
-
* const overflow = createOverflow({
|
|
1998
|
-
* container: () => atom.value?.element,
|
|
1999
|
-
* itemWidth: buttonWidth,
|
|
2000
|
-
* reserved: () => buttonWidth.value * 4,
|
|
2001
|
-
* })
|
|
2002
1885
|
* ```
|
|
2003
1886
|
*/
|
|
2004
|
-
function
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
1887
|
+
function useTokens(namespace = "v0:tokens") {
|
|
1888
|
+
return useContext(namespace);
|
|
1889
|
+
}
|
|
1890
|
+
/**
|
|
1891
|
+
* Flattens a nested collection of tokens into a flat array of tokens.
|
|
1892
|
+
* Each token is represented by an object containing its ID & value.
|
|
1893
|
+
* @param tokens The collection of tokens to flatten.
|
|
1894
|
+
* @param prefix An optional prefix to prepend to each token ID.
|
|
1895
|
+
* @returns An array of flattened tokens, each with an ID and value.
|
|
1896
|
+
*/
|
|
1897
|
+
function flatten(tokens, prefix = "", flat = false) {
|
|
1898
|
+
const flattened = [];
|
|
1899
|
+
const stack = [{
|
|
1900
|
+
tokens,
|
|
1901
|
+
prefix,
|
|
1902
|
+
flat
|
|
1903
|
+
}];
|
|
1904
|
+
while (stack.length > 0) {
|
|
1905
|
+
const { tokens: currentTokens, prefix: currentPrefix, flat: flat$1 } = stack.pop();
|
|
1906
|
+
const meta = {};
|
|
1907
|
+
for (const k in currentTokens) if (k.startsWith("$")) meta[k] = currentTokens[k];
|
|
1908
|
+
if (Object.keys(meta).length > 0 && currentPrefix) flattened.push({
|
|
1909
|
+
id: currentPrefix,
|
|
1910
|
+
value: meta
|
|
1911
|
+
});
|
|
1912
|
+
for (const key in currentTokens) {
|
|
1913
|
+
if (key.startsWith("$")) continue;
|
|
1914
|
+
const value = currentTokens[key];
|
|
1915
|
+
const id = currentPrefix ? `${currentPrefix}.${key}` : key;
|
|
1916
|
+
if (!/* @__PURE__ */ isObject(value)) {
|
|
1917
|
+
flattened.push({
|
|
1918
|
+
id,
|
|
1919
|
+
value
|
|
1920
|
+
});
|
|
1921
|
+
continue;
|
|
2015
1922
|
}
|
|
2016
|
-
|
|
1923
|
+
if ("$value" in value) {
|
|
1924
|
+
flattened.push({
|
|
1925
|
+
id,
|
|
1926
|
+
value
|
|
1927
|
+
});
|
|
1928
|
+
const inner = value.$value;
|
|
1929
|
+
if (/* @__PURE__ */ isObject(inner) && !flat$1) for (const innerKey in inner) {
|
|
1930
|
+
if (innerKey.startsWith("$")) continue;
|
|
1931
|
+
const child = inner[innerKey];
|
|
1932
|
+
const childId = `${id}.${innerKey}`;
|
|
1933
|
+
if (!/* @__PURE__ */ isObject(child)) flattened.push({
|
|
1934
|
+
id: childId,
|
|
1935
|
+
value: child
|
|
1936
|
+
});
|
|
1937
|
+
else if ("$value" in child) flattened.push({
|
|
1938
|
+
id: childId,
|
|
1939
|
+
value: child
|
|
1940
|
+
});
|
|
1941
|
+
else stack.push({
|
|
1942
|
+
tokens: child,
|
|
1943
|
+
prefix: childId,
|
|
1944
|
+
flat: flat$1
|
|
1945
|
+
});
|
|
1946
|
+
}
|
|
1947
|
+
continue;
|
|
1948
|
+
}
|
|
1949
|
+
if (flat$1) {
|
|
1950
|
+
flattened.push({
|
|
1951
|
+
id,
|
|
1952
|
+
value
|
|
1953
|
+
});
|
|
1954
|
+
continue;
|
|
1955
|
+
}
|
|
1956
|
+
stack.push({
|
|
1957
|
+
tokens: value,
|
|
1958
|
+
prefix: id,
|
|
1959
|
+
flat: flat$1
|
|
1960
|
+
});
|
|
2017
1961
|
}
|
|
2018
|
-
const style = getComputedStyle(el);
|
|
2019
|
-
const marginX = Number.parseFloat(style.marginLeft) + Number.parseFloat(style.marginRight);
|
|
2020
|
-
const w = el.offsetWidth + marginX;
|
|
2021
|
-
if (widths.value.get(index) !== w) widths.value = new Map(widths.value).set(index, w);
|
|
2022
1962
|
}
|
|
2023
|
-
|
|
2024
|
-
|
|
1963
|
+
return flattened;
|
|
1964
|
+
}
|
|
1965
|
+
|
|
1966
|
+
//#endregion
|
|
1967
|
+
//#region src/composables/useLocale/index.ts
|
|
1968
|
+
/**
|
|
1969
|
+
* Creates a new locale instance.
|
|
1970
|
+
*
|
|
1971
|
+
* @param options The options for the locale instance.
|
|
1972
|
+
* @template Z The type of the locale ticket.
|
|
1973
|
+
* @template E The type of the locale context.
|
|
1974
|
+
* @returns A new locale instance.
|
|
1975
|
+
*
|
|
1976
|
+
* @see https://0.vuetifyjs.com/composables/plugins/use-locale
|
|
1977
|
+
*/
|
|
1978
|
+
function createLocale(_options = {}) {
|
|
1979
|
+
const { adapter = new Vuetify0LocaleAdapter(), messages = {}, ...options } = _options;
|
|
1980
|
+
const tokens = createTokens(messages);
|
|
1981
|
+
const registry = createSingle(options);
|
|
1982
|
+
for (const id in messages) {
|
|
1983
|
+
registry.register({ id });
|
|
1984
|
+
if (id === options.default && !registry.selectedId.value) registry.select(id);
|
|
2025
1985
|
}
|
|
2026
|
-
|
|
2027
|
-
const
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
1986
|
+
function t(key, params, fallback) {
|
|
1987
|
+
const locale = registry.selectedId.value;
|
|
1988
|
+
const args = toArray(params);
|
|
1989
|
+
if (!locale) return adapter.t(fallback ?? key, ...args);
|
|
1990
|
+
const path = `${locale}.${key}`;
|
|
1991
|
+
const message = tokens.get(path)?.value;
|
|
1992
|
+
const template = /* @__PURE__ */ isString(message) ? resolve(locale, message) : fallback ?? key;
|
|
1993
|
+
return adapter.t(template, ...args);
|
|
1994
|
+
}
|
|
1995
|
+
function n(value, ...params) {
|
|
1996
|
+
return adapter.n(value, registry.selectedId.value, ...params);
|
|
1997
|
+
}
|
|
1998
|
+
function resolve(locale, str) {
|
|
1999
|
+
return str.replace(/{([a-zA-Z0-9.-_]+)}/g, (match, key) => {
|
|
2000
|
+
const [prefix, ...rest] = key.split(".");
|
|
2001
|
+
const target = registry.has(prefix) ? prefix : locale;
|
|
2002
|
+
const path = `${target}.${registry.has(prefix) ? rest.join(".") : key}`;
|
|
2003
|
+
const resolved = tokens.get(path)?.value;
|
|
2004
|
+
if (/* @__PURE__ */ isString(resolved)) return resolve(target, resolved);
|
|
2005
|
+
return match;
|
|
2006
|
+
});
|
|
2007
|
+
}
|
|
2008
|
+
return {
|
|
2009
|
+
...registry,
|
|
2010
|
+
t,
|
|
2011
|
+
n,
|
|
2012
|
+
get size() {
|
|
2013
|
+
return registry.size;
|
|
2033
2014
|
}
|
|
2034
|
-
|
|
2035
|
-
|
|
2015
|
+
};
|
|
2016
|
+
}
|
|
2017
|
+
function createLocaleFallback() {
|
|
2036
2018
|
return {
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
const available = width.value - toValue(reserved);
|
|
2041
|
-
if (width.value === 0) return Infinity;
|
|
2042
|
-
if (available <= 0) return 0;
|
|
2043
|
-
const g = toValue(gap);
|
|
2044
|
-
const uniformWidth = toValue(itemWidth);
|
|
2045
|
-
if (uniformWidth && uniformWidth > 0) {
|
|
2046
|
-
const first = uniformWidth;
|
|
2047
|
-
const subsequent = uniformWidth + g;
|
|
2048
|
-
if (available < first) return 0;
|
|
2049
|
-
return Math.max(1, Math.floor((available - first) / subsequent) + 1);
|
|
2050
|
-
}
|
|
2051
|
-
const entries = [...widths.value.entries()].toSorted((a, b) => a[0] - b[0]);
|
|
2052
|
-
if (toValue(reverse)) entries.reverse();
|
|
2053
|
-
let sum = 0;
|
|
2054
|
-
let count = 0;
|
|
2055
|
-
for (const [, w] of entries) {
|
|
2056
|
-
const next = sum + w + (count > 0 ? g : 0);
|
|
2057
|
-
if (next > available) break;
|
|
2058
|
-
sum = next;
|
|
2059
|
-
count++;
|
|
2060
|
-
}
|
|
2061
|
-
return count;
|
|
2062
|
-
}),
|
|
2063
|
-
total,
|
|
2064
|
-
isOverflowing: toRef(() => {
|
|
2065
|
-
return total.value > width.value - toValue(reserved);
|
|
2066
|
-
}),
|
|
2067
|
-
measure,
|
|
2068
|
-
reset
|
|
2019
|
+
size: 0,
|
|
2020
|
+
t: (key, _params, fallback) => fallback ?? key,
|
|
2021
|
+
n: String
|
|
2069
2022
|
};
|
|
2070
2023
|
}
|
|
2071
2024
|
/**
|
|
2072
|
-
* Creates
|
|
2025
|
+
* Creates a new locale context.
|
|
2073
2026
|
*
|
|
2074
|
-
* @param options
|
|
2075
|
-
* @
|
|
2027
|
+
* @param options The options for the locale context.
|
|
2028
|
+
* @template Z The type of the locale ticket.
|
|
2029
|
+
* @template E The type of the locale context.
|
|
2030
|
+
* @returns A new locale context.
|
|
2031
|
+
*
|
|
2032
|
+
* @see https://0.vuetifyjs.com/composables/plugins/use-locale
|
|
2076
2033
|
*
|
|
2077
2034
|
* @example
|
|
2078
2035
|
* ```ts
|
|
2079
|
-
*
|
|
2080
|
-
*
|
|
2081
|
-
*
|
|
2082
|
-
*
|
|
2083
|
-
*
|
|
2036
|
+
* import { createLocaleContext } from '@vuetify/v0'
|
|
2037
|
+
*
|
|
2038
|
+
* export const [useAppLocale, provideAppLocale, appLocale] = createLocaleContext({
|
|
2039
|
+
* namespace: 'app:locale',
|
|
2040
|
+
* messages: {
|
|
2041
|
+
* en: { hello: 'Hello' },
|
|
2042
|
+
* es: { hello: 'Hola' },
|
|
2043
|
+
* },
|
|
2084
2044
|
* })
|
|
2085
2045
|
*
|
|
2086
|
-
* // In parent component
|
|
2087
|
-
*
|
|
2046
|
+
* // In a parent component:
|
|
2047
|
+
* provideAppLocale()
|
|
2088
2048
|
*
|
|
2089
|
-
* // In child component
|
|
2090
|
-
* const
|
|
2049
|
+
* // In a child component:
|
|
2050
|
+
* const locale = useAppLocale()
|
|
2051
|
+
* locale.select('es')
|
|
2091
2052
|
* ```
|
|
2092
2053
|
*/
|
|
2093
|
-
function
|
|
2094
|
-
const { namespace = "v0:
|
|
2095
|
-
const [
|
|
2096
|
-
const context =
|
|
2097
|
-
function
|
|
2098
|
-
return
|
|
2054
|
+
function createLocaleContext(_options = {}) {
|
|
2055
|
+
const { namespace = "v0:locale", ...options } = _options;
|
|
2056
|
+
const [useLocaleContext, _provideLocaleContext] = createContext(namespace);
|
|
2057
|
+
const context = createLocale(options);
|
|
2058
|
+
function provideLocaleContext(_context = context, app) {
|
|
2059
|
+
return _provideLocaleContext(_context, app);
|
|
2099
2060
|
}
|
|
2100
|
-
return createTrinity(
|
|
2061
|
+
return createTrinity(useLocaleContext, provideLocaleContext, context);
|
|
2101
2062
|
}
|
|
2102
2063
|
/**
|
|
2103
|
-
*
|
|
2104
|
-
*
|
|
2105
|
-
* @param namespace The namespace for the overflow context. Defaults to `v0:overflow`.
|
|
2106
|
-
* @returns The current overflow context.
|
|
2107
|
-
*
|
|
2108
|
-
* @example
|
|
2109
|
-
* ```vue
|
|
2110
|
-
* <script lang="ts" setup>
|
|
2111
|
-
* import { useOverflow } from '@vuetify/v0'
|
|
2064
|
+
* Creates a new locale plugin.
|
|
2112
2065
|
*
|
|
2113
|
-
*
|
|
2114
|
-
*
|
|
2115
|
-
*
|
|
2066
|
+
* @param options The options for the locale plugin.
|
|
2067
|
+
* @template Z The type of the locale ticket.
|
|
2068
|
+
* @template E The type of the locale context.
|
|
2069
|
+
* @template R The type of the token ticket.
|
|
2070
|
+
* @template O The type of the token context.
|
|
2071
|
+
* @returns A new locale plugin.
|
|
2116
2072
|
*
|
|
2117
|
-
*
|
|
2118
|
-
* <div>
|
|
2119
|
-
* <p>Capacity: {{ overflow.capacity.value }}</p>
|
|
2120
|
-
* </div>
|
|
2121
|
-
* </template>
|
|
2122
|
-
* ```
|
|
2073
|
+
* @see https://0.vuetifyjs.com/composables/plugins/use-locale
|
|
2123
2074
|
*/
|
|
2124
|
-
function
|
|
2125
|
-
|
|
2075
|
+
function createLocalePlugin(_options = {}) {
|
|
2076
|
+
const { namespace = "v0:locale", adapter = new Vuetify0LocaleAdapter(), messages = {}, ...options } = _options;
|
|
2077
|
+
const [, provideLocaleContext, context] = createLocaleContext({
|
|
2078
|
+
...options,
|
|
2079
|
+
namespace,
|
|
2080
|
+
adapter,
|
|
2081
|
+
messages
|
|
2082
|
+
});
|
|
2083
|
+
return createPlugin({
|
|
2084
|
+
namespace,
|
|
2085
|
+
provide: (app) => {
|
|
2086
|
+
provideLocaleContext(context, app);
|
|
2087
|
+
}
|
|
2088
|
+
});
|
|
2126
2089
|
}
|
|
2127
|
-
|
|
2128
|
-
//#endregion
|
|
2129
|
-
//#region src/composables/usePagination/index.ts
|
|
2130
|
-
/**
|
|
2131
|
-
* @module usePagination
|
|
2132
|
-
*
|
|
2133
|
-
* @remarks
|
|
2134
|
-
* Lightweight pagination composable for navigating through pages.
|
|
2135
|
-
*
|
|
2136
|
-
* Key features:
|
|
2137
|
-
* - No registry overhead - just a bounded integer
|
|
2138
|
-
* - Direct ref support for v-model compatibility
|
|
2139
|
-
* - Navigation methods: next, prev, first, last
|
|
2140
|
-
* - Computed visible items with ellipsis
|
|
2141
|
-
* - Trinity pattern for dependency injection
|
|
2142
|
-
*
|
|
2143
|
-
* Unlike registry-based composables, pagination tracks a single number
|
|
2144
|
-
* within a range, making it efficient for large page counts.
|
|
2145
|
-
*/
|
|
2146
2090
|
/**
|
|
2147
|
-
*
|
|
2148
|
-
*
|
|
2149
|
-
* @param options The options for the pagination instance.
|
|
2150
|
-
* @returns A pagination context with navigation methods.
|
|
2151
|
-
*
|
|
2152
|
-
* @example
|
|
2153
|
-
* ```ts
|
|
2154
|
-
* import { createPagination } from '@vuetify/v0'
|
|
2091
|
+
* Returns the current locale instance.
|
|
2155
2092
|
*
|
|
2156
|
-
*
|
|
2157
|
-
* const pagination = createPagination({ size: 100 })
|
|
2158
|
-
* pagination.next()
|
|
2159
|
-
* pagination.items.value // [{ type: 'page', value: 1 }, { type: 'page', value: 2 }, ...]
|
|
2093
|
+
* @returns The current locale instance.
|
|
2160
2094
|
*
|
|
2161
|
-
*
|
|
2162
|
-
* const page = ref(1)
|
|
2163
|
-
* const pagination = createPagination({ page, size: 100 })
|
|
2164
|
-
* // Mutating pagination.page or the passed ref syncs both
|
|
2165
|
-
* ```
|
|
2095
|
+
* @see https://0.vuetifyjs.com/composables/plugins/use-locale
|
|
2166
2096
|
*/
|
|
2167
|
-
function
|
|
2168
|
-
const
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
return Math.ceil(size / perPage);
|
|
2175
|
-
});
|
|
2176
|
-
function first() {
|
|
2177
|
-
page.value = 1;
|
|
2178
|
-
}
|
|
2179
|
-
function last() {
|
|
2180
|
-
page.value = Math.max(1, pages.value);
|
|
2181
|
-
}
|
|
2182
|
-
function next() {
|
|
2183
|
-
if (page.value < pages.value) page.value++;
|
|
2184
|
-
}
|
|
2185
|
-
function prev() {
|
|
2186
|
-
if (page.value > 1) page.value--;
|
|
2187
|
-
}
|
|
2188
|
-
function select(value) {
|
|
2189
|
-
if (value < 1) page.value = 1;
|
|
2190
|
-
else if (value > pages.value) page.value = Math.max(1, pages.value);
|
|
2191
|
-
else page.value = value;
|
|
2192
|
-
}
|
|
2193
|
-
const isFirst = computed(() => page.value <= 1);
|
|
2194
|
-
const isLast = computed(() => page.value >= pages.value);
|
|
2195
|
-
const pageStart = computed(() => (page.value - 1) * toValue(_itemsPerPage));
|
|
2196
|
-
const pageStop = computed(() => Math.min(pageStart.value + toValue(_itemsPerPage), toValue(_size)));
|
|
2197
|
-
function toPage(value) {
|
|
2198
|
-
return {
|
|
2199
|
-
type: "page",
|
|
2200
|
-
value
|
|
2201
|
-
};
|
|
2202
|
-
}
|
|
2203
|
-
function toEllipsis() {
|
|
2204
|
-
return ellipsis === false ? false : {
|
|
2205
|
-
type: "ellipsis",
|
|
2206
|
-
value: ellipsis
|
|
2207
|
-
};
|
|
2208
|
-
}
|
|
2209
|
-
function filter(array) {
|
|
2210
|
-
return array.filter(Boolean);
|
|
2097
|
+
function useLocale(namespace = "v0:locale") {
|
|
2098
|
+
const fallback = createLocaleFallback();
|
|
2099
|
+
if (!getCurrentInstance()) return fallback;
|
|
2100
|
+
try {
|
|
2101
|
+
return useContext(namespace, fallback);
|
|
2102
|
+
} catch {
|
|
2103
|
+
return fallback;
|
|
2211
2104
|
}
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
toEllipsis(),
|
|
2248
|
-
toPage(pageCount)
|
|
2249
|
-
]) : filter([
|
|
2250
|
-
toPage(1),
|
|
2251
|
-
toEllipsis(),
|
|
2252
|
-
toPage(current),
|
|
2253
|
-
toPage(pageCount)
|
|
2254
|
-
]);
|
|
2255
|
-
}
|
|
2256
|
-
const leftThreshold = boundary - 1;
|
|
2257
|
-
const rightThreshold = pageCount - boundary + 2;
|
|
2258
|
-
if (current <= leftThreshold) return filter([
|
|
2259
|
-
...(/* @__PURE__ */ range(boundary, 1)).map(toPage),
|
|
2260
|
-
toEllipsis(),
|
|
2261
|
-
toPage(pageCount)
|
|
2262
|
-
]);
|
|
2263
|
-
else if (current >= rightThreshold) return filter([
|
|
2264
|
-
toPage(1),
|
|
2265
|
-
toEllipsis(),
|
|
2266
|
-
...(/* @__PURE__ */ range(boundary, pageCount - boundary + 1)).map(toPage)
|
|
2267
|
-
]);
|
|
2268
|
-
else {
|
|
2269
|
-
const start = current - Math.floor(middle / 2);
|
|
2270
|
-
return filter([
|
|
2271
|
-
toPage(1),
|
|
2272
|
-
toEllipsis(),
|
|
2273
|
-
...(/* @__PURE__ */ range(middle, start)).map(toPage),
|
|
2274
|
-
toEllipsis(),
|
|
2275
|
-
toPage(pageCount)
|
|
2276
|
-
]);
|
|
2277
|
-
}
|
|
2278
|
-
}),
|
|
2279
|
-
pageStart,
|
|
2280
|
-
pageStop,
|
|
2281
|
-
isFirst,
|
|
2282
|
-
isLast,
|
|
2283
|
-
first,
|
|
2284
|
-
last,
|
|
2285
|
-
next,
|
|
2286
|
-
prev,
|
|
2287
|
-
select,
|
|
2288
|
-
get itemsPerPage() {
|
|
2289
|
-
return toValue(_itemsPerPage);
|
|
2290
|
-
},
|
|
2291
|
-
get size() {
|
|
2292
|
-
return toValue(_size);
|
|
2293
|
-
},
|
|
2294
|
-
get pages() {
|
|
2295
|
-
return pages.value;
|
|
2296
|
-
}
|
|
2105
|
+
}
|
|
2106
|
+
|
|
2107
|
+
//#endregion
|
|
2108
|
+
//#region src/composables/useHydration/index.ts
|
|
2109
|
+
/**
|
|
2110
|
+
* Creates a new hydration instance.
|
|
2111
|
+
*
|
|
2112
|
+
* @returns A new hydration instance.
|
|
2113
|
+
*
|
|
2114
|
+
* @see https://0.vuetifyjs.com/composables/plugins/use-hydration
|
|
2115
|
+
*
|
|
2116
|
+
* @example
|
|
2117
|
+
* ```ts
|
|
2118
|
+
* import { createHydration } from '@vuetify/v0'
|
|
2119
|
+
*
|
|
2120
|
+
* const hydration = createHydration()
|
|
2121
|
+
* console.log(hydration.isHydrated.value) // false
|
|
2122
|
+
* hydration.hydrate()
|
|
2123
|
+
* console.log(hydration.isHydrated.value) // true
|
|
2124
|
+
* ```
|
|
2125
|
+
*/
|
|
2126
|
+
function createHydration() {
|
|
2127
|
+
const isHydrated = shallowRef(false);
|
|
2128
|
+
function hydrate() {
|
|
2129
|
+
isHydrated.value = true;
|
|
2130
|
+
}
|
|
2131
|
+
return {
|
|
2132
|
+
isHydrated: shallowReadonly(isHydrated),
|
|
2133
|
+
hydrate
|
|
2134
|
+
};
|
|
2135
|
+
}
|
|
2136
|
+
function createFallbackHydration() {
|
|
2137
|
+
return {
|
|
2138
|
+
isHydrated: shallowReadonly(shallowRef(true)),
|
|
2139
|
+
hydrate: () => {}
|
|
2297
2140
|
};
|
|
2298
2141
|
}
|
|
2299
2142
|
/**
|
|
2300
|
-
* Creates a
|
|
2143
|
+
* Creates a new hydration context trinity.
|
|
2301
2144
|
*
|
|
2302
|
-
* @param options
|
|
2303
|
-
* @
|
|
2145
|
+
* @param options Options for creating the hydration context.
|
|
2146
|
+
* @template E The type of the hydration context.
|
|
2147
|
+
* @returns A new hydration context trinity.
|
|
2148
|
+
*
|
|
2149
|
+
* @see https://0.vuetifyjs.com/composables/plugins/use-hydration
|
|
2304
2150
|
*
|
|
2305
2151
|
* @example
|
|
2306
2152
|
* ```ts
|
|
2307
|
-
*
|
|
2308
|
-
* const [usePagination, providePaginationContext] = createPaginationContext({ size: 50 })
|
|
2153
|
+
* import { createHydrationContext } from '@vuetify/v0'
|
|
2309
2154
|
*
|
|
2310
|
-
*
|
|
2311
|
-
*
|
|
2312
|
-
* namespace: 'my-pagination',
|
|
2313
|
-
* size: 50,
|
|
2155
|
+
* export const [useHydrationContext, provideHydrationContext, context] = createHydrationContext({
|
|
2156
|
+
* namespace: 'app:hydration',
|
|
2314
2157
|
* })
|
|
2158
|
+
* ```
|
|
2159
|
+
*/
|
|
2160
|
+
function createHydrationContext(_options = {}) {
|
|
2161
|
+
const { namespace = "v0:hydration" } = _options;
|
|
2162
|
+
const [useHydrationContext, _provideHydrationContext] = createContext(namespace);
|
|
2163
|
+
const context = createHydration();
|
|
2164
|
+
function provideHydrationContext(_context = context, app) {
|
|
2165
|
+
return _provideHydrationContext(_context, app);
|
|
2166
|
+
}
|
|
2167
|
+
return createTrinity(useHydrationContext, provideHydrationContext, context);
|
|
2168
|
+
}
|
|
2169
|
+
/**
|
|
2170
|
+
* Creates a new hydration plugin.
|
|
2315
2171
|
*
|
|
2316
|
-
*
|
|
2317
|
-
*
|
|
2172
|
+
* @param options The options for the hydration plugin.
|
|
2173
|
+
* @template E The type of the hydration context.
|
|
2174
|
+
* @returns A new hydration plugin.
|
|
2318
2175
|
*
|
|
2319
|
-
*
|
|
2320
|
-
*
|
|
2321
|
-
*
|
|
2176
|
+
* @see https://0.vuetifyjs.com/composables/plugins/use-hydration
|
|
2177
|
+
*
|
|
2178
|
+
* @example
|
|
2179
|
+
* ```ts
|
|
2180
|
+
* import { createApp } from 'vue'
|
|
2181
|
+
* import { createHydrationPlugin } from '@vuetify/v0'
|
|
2182
|
+
* import App from './App.vue'
|
|
2183
|
+
*
|
|
2184
|
+
* const app = createApp(App)
|
|
2185
|
+
*
|
|
2186
|
+
* app.use(createHydrationPlugin())
|
|
2187
|
+
*
|
|
2188
|
+
* app.mount('#app')
|
|
2322
2189
|
* ```
|
|
2323
2190
|
*/
|
|
2324
|
-
function
|
|
2325
|
-
const { namespace = "v0:
|
|
2326
|
-
const [
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2191
|
+
function createHydrationPlugin(_options = {}) {
|
|
2192
|
+
const { namespace = "v0:hydration", ...options } = _options;
|
|
2193
|
+
const [, provideHydrationContext, context] = createHydrationContext({
|
|
2194
|
+
...options,
|
|
2195
|
+
namespace
|
|
2196
|
+
});
|
|
2197
|
+
return createPlugin({
|
|
2198
|
+
namespace,
|
|
2199
|
+
provide: (app) => {
|
|
2200
|
+
provideHydrationContext(context, app);
|
|
2201
|
+
},
|
|
2202
|
+
setup: (app) => {
|
|
2203
|
+
app.mixin({ mounted() {
|
|
2204
|
+
if (this.$parent !== null) return;
|
|
2205
|
+
context.hydrate();
|
|
2206
|
+
} });
|
|
2207
|
+
}
|
|
2208
|
+
});
|
|
2332
2209
|
}
|
|
2333
2210
|
/**
|
|
2334
|
-
* Returns the current
|
|
2211
|
+
* Returns the current hydration instance.
|
|
2335
2212
|
*
|
|
2336
|
-
* @param namespace The namespace.
|
|
2337
|
-
* @returns The
|
|
2213
|
+
* @param namespace The namespace for the hydration context. Defaults to `v0:hydration`.
|
|
2214
|
+
* @returns The current hydration instance.
|
|
2215
|
+
*
|
|
2216
|
+
* @see https://0.vuetifyjs.com/composables/plugins/use-hydration
|
|
2338
2217
|
*
|
|
2339
2218
|
* @example
|
|
2340
2219
|
* ```vue
|
|
2341
|
-
* <script setup>
|
|
2342
|
-
*
|
|
2220
|
+
* <script setup lang="ts">
|
|
2221
|
+
* import { useHydration } from '@vuetify/v0'
|
|
2343
2222
|
*
|
|
2344
|
-
*
|
|
2223
|
+
* const hydration = useHydration()
|
|
2345
2224
|
* <\/script>
|
|
2346
2225
|
*
|
|
2347
2226
|
* <template>
|
|
2348
|
-
* <
|
|
2349
|
-
*
|
|
2227
|
+
* <div>
|
|
2228
|
+
* <p>Is hydrated: {{ hydration.isHydrated.value }}</p>
|
|
2229
|
+
* </div>
|
|
2350
2230
|
* </template>
|
|
2351
2231
|
* ```
|
|
2352
2232
|
*/
|
|
2353
|
-
function
|
|
2354
|
-
|
|
2233
|
+
function useHydration(namespace = "v0:hydration") {
|
|
2234
|
+
const fallback = createFallbackHydration();
|
|
2235
|
+
if (!getCurrentInstance()) return fallback;
|
|
2236
|
+
try {
|
|
2237
|
+
return useContext(namespace, fallback);
|
|
2238
|
+
} catch {
|
|
2239
|
+
return fallback;
|
|
2240
|
+
}
|
|
2355
2241
|
}
|
|
2356
2242
|
|
|
2357
2243
|
//#endregion
|
|
2358
|
-
//#region src/composables/
|
|
2359
|
-
/**
|
|
2360
|
-
* @module useSingle
|
|
2361
|
-
*
|
|
2362
|
-
* @remarks
|
|
2363
|
-
* Single-selection composable that extends useSelection to enforce only one selected item.
|
|
2364
|
-
*
|
|
2365
|
-
* Key features:
|
|
2366
|
-
* - Auto-clears previous selection when selecting new item
|
|
2367
|
-
* - Singular computed properties (selectedId, selectedItem, selectedIndex, selectedValue)
|
|
2368
|
-
* - Perfect for tabs, radio buttons, theme selectors
|
|
2369
|
-
*
|
|
2370
|
-
* Inheritance chain: useRegistry → useSelection → useSingle
|
|
2371
|
-
*/
|
|
2244
|
+
//#region src/composables/useResizeObserver/index.ts
|
|
2372
2245
|
/**
|
|
2373
|
-
*
|
|
2374
|
-
*
|
|
2375
|
-
* Extends `createSelection` by automatically clearing previous selections when a new item is selected.
|
|
2376
|
-
* Adds computed singular properties: `selectedId`, `selectedItem`, `selectedIndex`, `selectedValue`.
|
|
2377
|
-
*
|
|
2378
|
-
* @param options The options for the single selection instance.
|
|
2379
|
-
* @template Z The type of the single selection ticket.
|
|
2380
|
-
* @template E The type of the single selection context.
|
|
2381
|
-
* @returns A new single selection instance with single-selection enforcement.
|
|
2382
|
-
*
|
|
2383
|
-
* @remarks
|
|
2384
|
-
* **Key Differences from `createSelection`:**
|
|
2385
|
-
* - Automatically clears `selectedIds` before selecting a new item (enforces single selection)
|
|
2386
|
-
* - Provides singular computed properties instead of plural sets
|
|
2387
|
-
* - Perfect for tabs, radio buttons, theme selectors, and other single-choice UI components
|
|
2388
|
-
*
|
|
2389
|
-
* **Computed Properties:**
|
|
2390
|
-
* - `selectedId`: The ID of the selected item (undefined if none selected)
|
|
2391
|
-
* - `selectedItem`: The selected ticket object (undefined if none selected)
|
|
2392
|
-
* - `selectedIndex`: The index of the selected item (-1 if none selected)
|
|
2393
|
-
* - `selectedValue`: The value of the selected item (undefined if none selected)
|
|
2246
|
+
* A composable that uses the Resize Observer API to detect when an element's
|
|
2247
|
+
* size changes.
|
|
2394
2248
|
*
|
|
2395
|
-
*
|
|
2396
|
-
*
|
|
2249
|
+
* @param target The element to observe.
|
|
2250
|
+
* @param callback The callback to execute when the element's size changes.
|
|
2251
|
+
* @param options The options for the Resize Observer.
|
|
2252
|
+
* @returns An object with methods to control the observer.
|
|
2397
2253
|
*
|
|
2398
|
-
* @see https://
|
|
2254
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver
|
|
2255
|
+
* @see https://0.vuetifyjs.com/composables/system/use-resize-observer
|
|
2399
2256
|
*
|
|
2400
2257
|
* @example
|
|
2401
2258
|
* ```ts
|
|
2402
|
-
* import {
|
|
2403
|
-
*
|
|
2404
|
-
* const tabs = createSingle({ mandatory: true })
|
|
2259
|
+
* import { ref } from 'vue'
|
|
2260
|
+
* import { useResizeObserver } from '@vuetify/v0'
|
|
2405
2261
|
*
|
|
2406
|
-
*
|
|
2407
|
-
*
|
|
2408
|
-
*
|
|
2409
|
-
* { id: 'contact', value: 'Contact' },
|
|
2410
|
-
* ])
|
|
2262
|
+
* const el = ref<HTMLElement>()
|
|
2263
|
+
* const width = ref(0)
|
|
2264
|
+
* const height = ref(0)
|
|
2411
2265
|
*
|
|
2412
|
-
*
|
|
2266
|
+
* const { pause, resume, isPaused } = useResizeObserver(
|
|
2267
|
+
* el,
|
|
2268
|
+
* (entries) => {
|
|
2269
|
+
* const entry = entries[0]
|
|
2270
|
+
* if (entry) {
|
|
2271
|
+
* width.value = entry.contentRect.width
|
|
2272
|
+
* height.value = entry.contentRect.height
|
|
2273
|
+
* console.log('Size changed:', width.value, 'x', height.value)
|
|
2274
|
+
* }
|
|
2275
|
+
* },
|
|
2276
|
+
* { immediate: true }
|
|
2277
|
+
* )
|
|
2413
2278
|
*
|
|
2414
|
-
*
|
|
2415
|
-
*
|
|
2279
|
+
* // Pause observation
|
|
2280
|
+
* pause()
|
|
2416
2281
|
*
|
|
2417
|
-
*
|
|
2418
|
-
*
|
|
2419
|
-
* console.log(tabs.selectedIds.size) // 1 (always enforces single selection)
|
|
2282
|
+
* // Resume observation
|
|
2283
|
+
* resume()
|
|
2420
2284
|
* ```
|
|
2421
2285
|
*/
|
|
2422
|
-
function
|
|
2423
|
-
const {
|
|
2424
|
-
const
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2286
|
+
function useResizeObserver(target, callback, options = {}) {
|
|
2287
|
+
const { isHydrated } = useHydration();
|
|
2288
|
+
const observer = shallowRef();
|
|
2289
|
+
const isPaused = shallowRef(false);
|
|
2290
|
+
const isActive = toRef(() => !!observer.value);
|
|
2291
|
+
function setup() {
|
|
2292
|
+
if (observer.value === null) return;
|
|
2293
|
+
if (!isHydrated.value || !SUPPORTS_OBSERVER || !target.value || isPaused.value) return;
|
|
2294
|
+
observer.value = new ResizeObserver((entries) => {
|
|
2295
|
+
callback(entries.map((entry) => ({
|
|
2296
|
+
contentRect: {
|
|
2297
|
+
width: entry.contentRect.width,
|
|
2298
|
+
height: entry.contentRect.height,
|
|
2299
|
+
top: entry.contentRect.top,
|
|
2300
|
+
left: entry.contentRect.left
|
|
2301
|
+
},
|
|
2302
|
+
target: entry.target
|
|
2303
|
+
})));
|
|
2304
|
+
if (options.once) stop();
|
|
2305
|
+
});
|
|
2306
|
+
observer.value.observe(target.value, { box: options.box || "content-box" });
|
|
2307
|
+
if (options.immediate) {
|
|
2308
|
+
const rect = target.value.getBoundingClientRect();
|
|
2309
|
+
callback([{
|
|
2310
|
+
contentRect: {
|
|
2311
|
+
width: rect.width,
|
|
2312
|
+
height: rect.height,
|
|
2313
|
+
top: rect.top,
|
|
2314
|
+
left: rect.left
|
|
2315
|
+
},
|
|
2316
|
+
target: target.value
|
|
2317
|
+
}]);
|
|
2318
|
+
}
|
|
2319
|
+
}
|
|
2320
|
+
watchEffect(() => {
|
|
2321
|
+
const hydrated = isHydrated.value;
|
|
2322
|
+
const el = target.value;
|
|
2323
|
+
cleanup();
|
|
2324
|
+
if (hydrated && el) setup();
|
|
2428
2325
|
});
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
if (mandatory && registry.selectedIds.size === 1) return;
|
|
2435
|
-
registry.selectedIds.delete(id);
|
|
2326
|
+
function cleanup() {
|
|
2327
|
+
if (observer.value) {
|
|
2328
|
+
observer.value.disconnect();
|
|
2329
|
+
observer.value = void 0;
|
|
2330
|
+
}
|
|
2436
2331
|
}
|
|
2437
|
-
function
|
|
2438
|
-
|
|
2439
|
-
|
|
2332
|
+
function pause() {
|
|
2333
|
+
isPaused.value = true;
|
|
2334
|
+
observer.value?.disconnect();
|
|
2335
|
+
}
|
|
2336
|
+
function resume() {
|
|
2337
|
+
isPaused.value = false;
|
|
2338
|
+
setup();
|
|
2339
|
+
}
|
|
2340
|
+
function stop() {
|
|
2341
|
+
cleanup();
|
|
2342
|
+
observer.value = null;
|
|
2440
2343
|
}
|
|
2344
|
+
onScopeDispose(stop, true);
|
|
2441
2345
|
return {
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
unselect,
|
|
2448
|
-
toggle,
|
|
2449
|
-
get size() {
|
|
2450
|
-
return registry.size;
|
|
2451
|
-
}
|
|
2346
|
+
isActive: shallowReadonly(isActive),
|
|
2347
|
+
isPaused: shallowReadonly(isPaused),
|
|
2348
|
+
pause,
|
|
2349
|
+
resume,
|
|
2350
|
+
stop
|
|
2452
2351
|
};
|
|
2453
2352
|
}
|
|
2454
2353
|
/**
|
|
2455
|
-
*
|
|
2354
|
+
* A convenience composable that uses the Resize Observer API to track an
|
|
2355
|
+
* element's size.
|
|
2456
2356
|
*
|
|
2457
|
-
* @param
|
|
2458
|
-
* @
|
|
2459
|
-
* @template E The type of the single selection context.
|
|
2460
|
-
* @returns A new single selection context.
|
|
2357
|
+
* @param target The element to observe.
|
|
2358
|
+
* @returns An object with the element's width and height.
|
|
2461
2359
|
*
|
|
2462
|
-
* @see https://0.vuetifyjs.com/composables/
|
|
2360
|
+
* @see https://0.vuetifyjs.com/composables/system/use-resize-observer#use-element-size
|
|
2463
2361
|
*
|
|
2464
2362
|
* @example
|
|
2465
2363
|
* ```ts
|
|
2466
|
-
* import {
|
|
2467
|
-
*
|
|
2468
|
-
* // With default namespace 'v0:single'
|
|
2469
|
-
* export const [useSingle, provideSingle, context] = createSingleContext()
|
|
2364
|
+
* import { ref, watchEffect } from 'vue'
|
|
2365
|
+
* import { useElementSize } from '@vuetify/v0'
|
|
2470
2366
|
*
|
|
2471
|
-
*
|
|
2472
|
-
*
|
|
2367
|
+
* const box = ref<HTMLElement>()
|
|
2368
|
+
* const { width, height } = useElementSize(box)
|
|
2473
2369
|
*
|
|
2474
|
-
* //
|
|
2475
|
-
*
|
|
2476
|
-
*
|
|
2370
|
+
* // Width and height are reactive refs
|
|
2371
|
+
* watchEffect(() => {
|
|
2372
|
+
* console.log('Box size:', width.value, 'x', height.value)
|
|
2373
|
+
* })
|
|
2477
2374
|
* ```
|
|
2478
2375
|
*/
|
|
2479
|
-
function
|
|
2480
|
-
const
|
|
2481
|
-
const
|
|
2482
|
-
const
|
|
2483
|
-
|
|
2484
|
-
|
|
2376
|
+
function useElementSize(target) {
|
|
2377
|
+
const width = shallowRef(0);
|
|
2378
|
+
const height = shallowRef(0);
|
|
2379
|
+
const { pause: _pause, resume, stop, isActive, isPaused } = useResizeObserver(target, (entries) => {
|
|
2380
|
+
const entry = entries[0];
|
|
2381
|
+
if (entry) {
|
|
2382
|
+
width.value = entry.contentRect.width;
|
|
2383
|
+
height.value = entry.contentRect.height;
|
|
2384
|
+
}
|
|
2385
|
+
}, { immediate: true });
|
|
2386
|
+
function pause() {
|
|
2387
|
+
width.value = 0;
|
|
2388
|
+
height.value = 0;
|
|
2389
|
+
_pause();
|
|
2485
2390
|
}
|
|
2486
|
-
return
|
|
2391
|
+
return {
|
|
2392
|
+
width,
|
|
2393
|
+
height,
|
|
2394
|
+
isActive,
|
|
2395
|
+
isPaused,
|
|
2396
|
+
pause,
|
|
2397
|
+
resume,
|
|
2398
|
+
stop
|
|
2399
|
+
};
|
|
2487
2400
|
}
|
|
2401
|
+
|
|
2402
|
+
//#endregion
|
|
2403
|
+
//#region src/composables/useOverflow/index.ts
|
|
2488
2404
|
/**
|
|
2489
|
-
*
|
|
2490
|
-
*
|
|
2491
|
-
* @param namespace The namespace for the single selection context. Defaults to `'v0:single'`.
|
|
2492
|
-
* @returns The current single selection instance.
|
|
2405
|
+
* Creates a new overflow context for computing how many items fit in a container.
|
|
2493
2406
|
*
|
|
2494
|
-
* @
|
|
2407
|
+
* @param options Configuration options
|
|
2408
|
+
* @returns Overflow context with container ref, capacity, and measurement functions
|
|
2495
2409
|
*
|
|
2496
|
-
* @example
|
|
2410
|
+
* @example Variable-width mode (Breadcrumbs)
|
|
2497
2411
|
* ```vue
|
|
2498
|
-
* <script
|
|
2499
|
-
* import {
|
|
2412
|
+
* <script lang="ts" setup>
|
|
2413
|
+
* import { useTemplateRef } from 'vue'
|
|
2414
|
+
* import { createOverflow } from '@vuetify/v0'
|
|
2500
2415
|
*
|
|
2501
|
-
* const
|
|
2416
|
+
* const containerRef = useTemplateRef('container')
|
|
2417
|
+
* const overflow = createOverflow({
|
|
2418
|
+
* container: containerRef,
|
|
2419
|
+
* gap: 8,
|
|
2420
|
+
* reserved: 40,
|
|
2421
|
+
* })
|
|
2502
2422
|
* <\/script>
|
|
2503
2423
|
*
|
|
2504
2424
|
* <template>
|
|
2505
|
-
* <div>
|
|
2506
|
-
* <
|
|
2425
|
+
* <div ref="container">
|
|
2426
|
+
* <span
|
|
2427
|
+
* v-for="(item, i) in items.slice(0, overflow.capacity.value)"
|
|
2428
|
+
* :key="i"
|
|
2429
|
+
* :ref="el => overflow.measure(i, el)"
|
|
2430
|
+
* >
|
|
2431
|
+
* {{ item }}
|
|
2432
|
+
* </span>
|
|
2433
|
+
* <span v-if="overflow.isOverflowing.value">...</span>
|
|
2507
2434
|
* </div>
|
|
2508
2435
|
* </template>
|
|
2509
2436
|
* ```
|
|
2510
|
-
*/
|
|
2511
|
-
function useSingle(namespace = "v0:single") {
|
|
2512
|
-
return useContext(namespace);
|
|
2513
|
-
}
|
|
2514
|
-
|
|
2515
|
-
//#endregion
|
|
2516
|
-
//#region src/composables/useTokens/index.ts
|
|
2517
|
-
/**
|
|
2518
|
-
* @module useTokens
|
|
2519
|
-
*
|
|
2520
|
-
* @see https://0.vuetifyjs.com/composables/registration/use-tokens
|
|
2521
|
-
*
|
|
2522
|
-
* @remarks
|
|
2523
|
-
* Design token registry with alias resolution and W3C Design Tokens format support.
|
|
2524
|
-
*
|
|
2525
|
-
* Key features:
|
|
2526
|
-
* - Alias resolution with circular reference detection
|
|
2527
|
-
* - Nested token flattening with dot notation
|
|
2528
|
-
* - W3C Design Tokens format ($value, $type, $description, $extensions)
|
|
2529
|
-
* - Path-based resolution (e.g., {colors}.blue.500)
|
|
2530
|
-
* - Resolution caching for performance (~28,590 ops/sec)
|
|
2531
|
-
*
|
|
2532
|
-
* Used by useTheme, useLocale, and useFeatures for token-based configuration.
|
|
2533
|
-
*/
|
|
2534
|
-
/**
|
|
2535
|
-
* Creates a new token instance.
|
|
2536
2437
|
*
|
|
2537
|
-
* @
|
|
2538
|
-
* @param options The options for the token instance.
|
|
2539
|
-
* @template Z The type of the token ticket.
|
|
2540
|
-
* @template E The type of the token context.
|
|
2541
|
-
* @returns A new token instance.
|
|
2542
|
-
*
|
|
2543
|
-
* @see https://www.designtokens.org/tr/drafts/format/
|
|
2544
|
-
* @see https://0.vuetifyjs.com/composables/registration/use-tokens
|
|
2545
|
-
*
|
|
2546
|
-
* @example
|
|
2438
|
+
* @example Uniform-width mode (Pagination)
|
|
2547
2439
|
* ```ts
|
|
2548
|
-
*
|
|
2549
|
-
*
|
|
2550
|
-
*
|
|
2551
|
-
*
|
|
2552
|
-
* primary: '#3b82f6',
|
|
2553
|
-
* secondary: '{colors.primary}', // Alias reference
|
|
2554
|
-
* },
|
|
2440
|
+
* const overflow = createOverflow({
|
|
2441
|
+
* container: () => atom.value?.element,
|
|
2442
|
+
* itemWidth: buttonWidth,
|
|
2443
|
+
* reserved: () => buttonWidth.value * 4,
|
|
2555
2444
|
* })
|
|
2556
|
-
*
|
|
2557
|
-
* console.log(tokens.resolve('{colors.primary}')) // '#3b82f6'
|
|
2558
|
-
* console.log(tokens.resolve('{colors.secondary}')) // '#3b82f6'
|
|
2559
2445
|
* ```
|
|
2560
2446
|
*/
|
|
2561
|
-
function
|
|
2562
|
-
const
|
|
2563
|
-
const
|
|
2564
|
-
const
|
|
2565
|
-
|
|
2566
|
-
function
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
function resolve(token, visited = /* @__PURE__ */ new Set()) {
|
|
2573
|
-
const cacheKey = /* @__PURE__ */ isString(token) ? token : JSON.stringify(token);
|
|
2574
|
-
const cached = cache.get(cacheKey);
|
|
2575
|
-
if (!/* @__PURE__ */ isUndefined(cached)) return cached;
|
|
2576
|
-
const reference = isTokenAlias(token) ? token.$value : token;
|
|
2577
|
-
const isAliasReference = /* @__PURE__ */ isString(reference) && isAlias(reference);
|
|
2578
|
-
const clean = isAliasReference ? reference.slice(1, -1) : String(reference);
|
|
2579
|
-
if (visited.has(clean)) {
|
|
2580
|
-
logger.warn(`Circular alias detected for "${clean}"`);
|
|
2581
|
-
cache.set(cacheKey, void 0);
|
|
2582
|
-
return;
|
|
2583
|
-
}
|
|
2584
|
-
visited.add(clean);
|
|
2585
|
-
let found = registry.get(clean);
|
|
2586
|
-
let segments = [];
|
|
2587
|
-
if (!found && clean.includes(".")) {
|
|
2588
|
-
const parts = clean.split(".");
|
|
2589
|
-
for (let i = parts.length - 1; i > 0; i--) {
|
|
2590
|
-
const prefix = parts.slice(0, i).join(".");
|
|
2591
|
-
const suffix = parts.slice(i);
|
|
2592
|
-
const candidate = registry.get(prefix);
|
|
2593
|
-
if (!/* @__PURE__ */ isUndefined(candidate?.value)) {
|
|
2594
|
-
found = candidate;
|
|
2595
|
-
segments = suffix;
|
|
2596
|
-
break;
|
|
2597
|
-
}
|
|
2447
|
+
function createOverflow(options = {}) {
|
|
2448
|
+
const { container: _container, gap = 0, reserved = 0, itemWidth, reverse } = options;
|
|
2449
|
+
const container = /* @__PURE__ */ isUndefined(_container) ? shallowRef() : toRef(_container);
|
|
2450
|
+
const widths = shallowRef(/* @__PURE__ */ new Map());
|
|
2451
|
+
const { width } = useElementSize(container);
|
|
2452
|
+
function measure(index, el) {
|
|
2453
|
+
if (!el) {
|
|
2454
|
+
if (widths.value.has(index)) {
|
|
2455
|
+
const next = new Map(widths.value);
|
|
2456
|
+
next.delete(index);
|
|
2457
|
+
widths.value = next;
|
|
2598
2458
|
}
|
|
2599
|
-
}
|
|
2600
|
-
if (/* @__PURE__ */ isUndefined(found?.value)) {
|
|
2601
|
-
if (isAliasReference) logger.warn(`Alias not found for "${String(reference)}"`);
|
|
2602
|
-
cache.set(cacheKey, void 0);
|
|
2603
2459
|
return;
|
|
2604
2460
|
}
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2461
|
+
const style = getComputedStyle(el);
|
|
2462
|
+
const marginX = Number.parseFloat(style.marginLeft) + Number.parseFloat(style.marginRight);
|
|
2463
|
+
const w = el.offsetWidth + marginX;
|
|
2464
|
+
if (widths.value.get(index) !== w) widths.value = new Map(widths.value).set(index, w);
|
|
2465
|
+
}
|
|
2466
|
+
function reset() {
|
|
2467
|
+
widths.value = /* @__PURE__ */ new Map();
|
|
2468
|
+
}
|
|
2469
|
+
const total = computed(() => {
|
|
2470
|
+
const g = toValue(gap);
|
|
2471
|
+
let sum = 0;
|
|
2472
|
+
let count = 0;
|
|
2473
|
+
for (const w of widths.value.values()) {
|
|
2474
|
+
sum += w + (count > 0 ? g : 0);
|
|
2475
|
+
count++;
|
|
2476
|
+
}
|
|
2477
|
+
return sum;
|
|
2478
|
+
});
|
|
2479
|
+
return {
|
|
2480
|
+
container,
|
|
2481
|
+
width,
|
|
2482
|
+
capacity: computed(() => {
|
|
2483
|
+
const available = width.value - toValue(reserved);
|
|
2484
|
+
if (width.value === 0) return Infinity;
|
|
2485
|
+
if (available <= 0) return 0;
|
|
2486
|
+
const g = toValue(gap);
|
|
2487
|
+
const uniformWidth = toValue(itemWidth);
|
|
2488
|
+
if (uniformWidth && uniformWidth > 0) {
|
|
2489
|
+
const first = uniformWidth;
|
|
2490
|
+
const subsequent = uniformWidth + g;
|
|
2491
|
+
if (available < first) return 0;
|
|
2492
|
+
return Math.max(1, Math.floor((available - first) / subsequent) + 1);
|
|
2616
2493
|
}
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2494
|
+
const entries = [...widths.value.entries()].toSorted((a, b) => a[0] - b[0]);
|
|
2495
|
+
if (toValue(reverse)) entries.reverse();
|
|
2496
|
+
let sum = 0;
|
|
2497
|
+
let count = 0;
|
|
2498
|
+
for (const [, w] of entries) {
|
|
2499
|
+
const next = sum + w + (count > 0 ? g : 0);
|
|
2500
|
+
if (next > available) break;
|
|
2501
|
+
sum = next;
|
|
2502
|
+
count++;
|
|
2621
2503
|
}
|
|
2622
|
-
|
|
2623
|
-
}
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
}
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
return result;
|
|
2631
|
-
}
|
|
2632
|
-
return {
|
|
2633
|
-
...registry,
|
|
2634
|
-
resolve,
|
|
2635
|
-
isAlias,
|
|
2636
|
-
get size() {
|
|
2637
|
-
return registry.size;
|
|
2638
|
-
}
|
|
2504
|
+
return count;
|
|
2505
|
+
}),
|
|
2506
|
+
total,
|
|
2507
|
+
isOverflowing: toRef(() => {
|
|
2508
|
+
return total.value > width.value - toValue(reserved);
|
|
2509
|
+
}),
|
|
2510
|
+
measure,
|
|
2511
|
+
reset
|
|
2639
2512
|
};
|
|
2640
2513
|
}
|
|
2641
2514
|
/**
|
|
2642
|
-
* Creates
|
|
2643
|
-
*
|
|
2644
|
-
* @param namespace The namespace for the token context.
|
|
2645
|
-
* @param tokens The tokens to use.
|
|
2646
|
-
* @template Z The type of the token ticket.
|
|
2647
|
-
* @template E The type of the token context.
|
|
2648
|
-
* @returns A new token context.
|
|
2515
|
+
* Creates an overflow context with dependency injection support.
|
|
2649
2516
|
*
|
|
2650
|
-
* @
|
|
2517
|
+
* @param options Configuration options including namespace
|
|
2518
|
+
* @returns Trinity tuple: [useContext, provideContext, defaultContext]
|
|
2651
2519
|
*
|
|
2652
2520
|
* @example
|
|
2653
2521
|
* ```ts
|
|
2654
|
-
*
|
|
2655
|
-
*
|
|
2656
|
-
*
|
|
2657
|
-
*
|
|
2658
|
-
*
|
|
2659
|
-
* colors: {
|
|
2660
|
-
* primary: '#3b82f6',
|
|
2661
|
-
* secondary: '{colors.primary}', // Alias reference
|
|
2662
|
-
* },
|
|
2663
|
-
* },
|
|
2522
|
+
* // Create injectable context
|
|
2523
|
+
* const [useOverflow, provideOverflow, overflow] = createOverflowContext({
|
|
2524
|
+
* namespace: 'my-overflow',
|
|
2525
|
+
* gap: 8,
|
|
2526
|
+
* reserved: 160,
|
|
2664
2527
|
* })
|
|
2528
|
+
*
|
|
2529
|
+
* // In parent component
|
|
2530
|
+
* provideOverflow()
|
|
2531
|
+
*
|
|
2532
|
+
* // In child component
|
|
2533
|
+
* const overflow = useOverflow()
|
|
2665
2534
|
* ```
|
|
2666
2535
|
*/
|
|
2667
|
-
function
|
|
2668
|
-
const { namespace = "v0:
|
|
2669
|
-
const [
|
|
2670
|
-
const context =
|
|
2671
|
-
function
|
|
2672
|
-
return
|
|
2536
|
+
function createOverflowContext(_options = {}) {
|
|
2537
|
+
const { namespace = "v0:overflow", ...options } = _options;
|
|
2538
|
+
const [useOverflowContext, _provideOverflowContext] = createContext(namespace);
|
|
2539
|
+
const context = createOverflow(options);
|
|
2540
|
+
function provideOverflowContext(_context = context, app) {
|
|
2541
|
+
return _provideOverflowContext(_context, app);
|
|
2673
2542
|
}
|
|
2674
|
-
return createTrinity(
|
|
2543
|
+
return createTrinity(useOverflowContext, provideOverflowContext, context);
|
|
2675
2544
|
}
|
|
2676
2545
|
/**
|
|
2677
|
-
* Returns the current
|
|
2678
|
-
*
|
|
2679
|
-
* @param namespace The namespace for the tokens context. Defaults to `'v0:tokens'`.
|
|
2680
|
-
* @returns The current tokens instance.
|
|
2546
|
+
* Returns the current overflow context from dependency injection.
|
|
2681
2547
|
*
|
|
2682
|
-
* @
|
|
2548
|
+
* @param namespace The namespace for the overflow context. Defaults to `v0:overflow`.
|
|
2549
|
+
* @returns The current overflow context.
|
|
2683
2550
|
*
|
|
2684
2551
|
* @example
|
|
2685
2552
|
* ```vue
|
|
2686
|
-
* <script
|
|
2687
|
-
* import {
|
|
2553
|
+
* <script lang="ts" setup>
|
|
2554
|
+
* import { useOverflow } from '@vuetify/v0'
|
|
2688
2555
|
*
|
|
2689
|
-
*
|
|
2556
|
+
* // Inject overflow context provided by parent
|
|
2557
|
+
* const overflow = useOverflow()
|
|
2690
2558
|
* <\/script>
|
|
2559
|
+
*
|
|
2560
|
+
* <template>
|
|
2561
|
+
* <div>
|
|
2562
|
+
* <p>Capacity: {{ overflow.capacity.value }}</p>
|
|
2563
|
+
* </div>
|
|
2564
|
+
* </template>
|
|
2691
2565
|
* ```
|
|
2692
2566
|
*/
|
|
2693
|
-
function
|
|
2567
|
+
function useOverflow(namespace = "v0:overflow") {
|
|
2694
2568
|
return useContext(namespace);
|
|
2695
2569
|
}
|
|
2696
|
-
/**
|
|
2697
|
-
* Flattens a nested collection of tokens into a flat array of tokens.
|
|
2698
|
-
* Each token is represented by an object containing its ID & value.
|
|
2699
|
-
* @param tokens The collection of tokens to flatten.
|
|
2700
|
-
* @param prefix An optional prefix to prepend to each token ID.
|
|
2701
|
-
* @returns An array of flattened tokens, each with an ID and value.
|
|
2702
|
-
*/
|
|
2703
|
-
function flatten(tokens, prefix = "", flat = false) {
|
|
2704
|
-
const flattened = [];
|
|
2705
|
-
const stack = [{
|
|
2706
|
-
tokens,
|
|
2707
|
-
prefix,
|
|
2708
|
-
flat
|
|
2709
|
-
}];
|
|
2710
|
-
while (stack.length > 0) {
|
|
2711
|
-
const { tokens: currentTokens, prefix: currentPrefix, flat: flat$1 } = stack.pop();
|
|
2712
|
-
const meta = {};
|
|
2713
|
-
for (const k in currentTokens) if (k.startsWith("$")) meta[k] = currentTokens[k];
|
|
2714
|
-
if (Object.keys(meta).length > 0 && currentPrefix) flattened.push({
|
|
2715
|
-
id: currentPrefix,
|
|
2716
|
-
value: meta
|
|
2717
|
-
});
|
|
2718
|
-
for (const key in currentTokens) {
|
|
2719
|
-
if (key.startsWith("$")) continue;
|
|
2720
|
-
const value = currentTokens[key];
|
|
2721
|
-
const id = currentPrefix ? `${currentPrefix}.${key}` : key;
|
|
2722
|
-
if (!/* @__PURE__ */ isObject(value)) {
|
|
2723
|
-
flattened.push({
|
|
2724
|
-
id,
|
|
2725
|
-
value
|
|
2726
|
-
});
|
|
2727
|
-
continue;
|
|
2728
|
-
}
|
|
2729
|
-
if ("$value" in value) {
|
|
2730
|
-
flattened.push({
|
|
2731
|
-
id,
|
|
2732
|
-
value
|
|
2733
|
-
});
|
|
2734
|
-
const inner = value.$value;
|
|
2735
|
-
if (/* @__PURE__ */ isObject(inner) && !flat$1) for (const innerKey in inner) {
|
|
2736
|
-
if (innerKey.startsWith("$")) continue;
|
|
2737
|
-
const child = inner[innerKey];
|
|
2738
|
-
const childId = `${id}.${innerKey}`;
|
|
2739
|
-
if (!/* @__PURE__ */ isObject(child)) flattened.push({
|
|
2740
|
-
id: childId,
|
|
2741
|
-
value: child
|
|
2742
|
-
});
|
|
2743
|
-
else if ("$value" in child) flattened.push({
|
|
2744
|
-
id: childId,
|
|
2745
|
-
value: child
|
|
2746
|
-
});
|
|
2747
|
-
else stack.push({
|
|
2748
|
-
tokens: child,
|
|
2749
|
-
prefix: childId,
|
|
2750
|
-
flat: flat$1
|
|
2751
|
-
});
|
|
2752
|
-
}
|
|
2753
|
-
continue;
|
|
2754
|
-
}
|
|
2755
|
-
if (flat$1) {
|
|
2756
|
-
flattened.push({
|
|
2757
|
-
id,
|
|
2758
|
-
value
|
|
2759
|
-
});
|
|
2760
|
-
continue;
|
|
2761
|
-
}
|
|
2762
|
-
stack.push({
|
|
2763
|
-
tokens: value,
|
|
2764
|
-
prefix: id,
|
|
2765
|
-
flat: flat$1
|
|
2766
|
-
});
|
|
2767
|
-
}
|
|
2768
|
-
}
|
|
2769
|
-
return flattened;
|
|
2770
|
-
}
|
|
2771
|
-
|
|
2772
|
-
//#endregion
|
|
2773
|
-
//#region src/composables/useLocale/adapters/v0.ts
|
|
2774
|
-
/**
|
|
2775
|
-
* Vuetify0.x locale adapter implementation
|
|
2776
|
-
*
|
|
2777
|
-
* This adapter provides translation and number formatting
|
|
2778
|
-
* capabilities using the Intl API and supports both
|
|
2779
|
-
* numbered ({0}, {1}) and named ({name}) variables in translation strings.
|
|
2780
|
-
*/
|
|
2781
|
-
var Vuetify0LocaleAdapter = class {
|
|
2782
|
-
t(message, ...params) {
|
|
2783
|
-
let resolvedMessage = message;
|
|
2784
|
-
if (params.length > 0 && /* @__PURE__ */ isObject(params[0])) {
|
|
2785
|
-
const variables = params[0];
|
|
2786
|
-
resolvedMessage = resolvedMessage.replace(/{([a-zA-Z][a-zA-Z0-9_]*)}/g, (match, name) => {
|
|
2787
|
-
return /* @__PURE__ */ isUndefined(variables[name]) ? match : String(variables[name]);
|
|
2788
|
-
});
|
|
2789
|
-
params = params.slice(1);
|
|
2790
|
-
}
|
|
2791
|
-
resolvedMessage = resolvedMessage.replace(/\{(\d+)\}/g, (match, index) => {
|
|
2792
|
-
const idx = Number.parseInt(index, 10);
|
|
2793
|
-
if (!/* @__PURE__ */ isUndefined(params[idx])) return String(params[idx]);
|
|
2794
|
-
return match;
|
|
2795
|
-
});
|
|
2796
|
-
return resolvedMessage;
|
|
2797
|
-
}
|
|
2798
|
-
n(value, locale, ...params) {
|
|
2799
|
-
if (!IN_BROWSER || !locale) return value.toString();
|
|
2800
|
-
const options = params[0];
|
|
2801
|
-
return new Intl.NumberFormat(String(locale), options).format(value);
|
|
2802
|
-
}
|
|
2803
|
-
};
|
|
2804
2570
|
|
|
2805
2571
|
//#endregion
|
|
2806
|
-
//#region src/composables/
|
|
2572
|
+
//#region src/composables/usePagination/index.ts
|
|
2807
2573
|
/**
|
|
2808
|
-
*
|
|
2809
|
-
*
|
|
2810
|
-
* @remarks
|
|
2811
|
-
* Internationalization (i18n) composable with adapter pattern for message translation.
|
|
2574
|
+
* Creates a pagination instance.
|
|
2812
2575
|
*
|
|
2813
|
-
*
|
|
2814
|
-
*
|
|
2815
|
-
* - Token-based message storage with useTokens
|
|
2816
|
-
* - Numbered and named placeholder support ({0}, {name})
|
|
2817
|
-
* - Number formatting with Intl.NumberFormat
|
|
2818
|
-
* - Adapter pattern for integration with i18n providers
|
|
2576
|
+
* @param options The options for the pagination instance.
|
|
2577
|
+
* @returns A pagination context with navigation methods.
|
|
2819
2578
|
*
|
|
2820
|
-
*
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
* Creates a new locale instance.
|
|
2579
|
+
* @example
|
|
2580
|
+
* ```ts
|
|
2581
|
+
* import { createPagination } from '@vuetify/v0'
|
|
2824
2582
|
*
|
|
2825
|
-
*
|
|
2826
|
-
*
|
|
2827
|
-
*
|
|
2828
|
-
*
|
|
2583
|
+
* // Basic usage
|
|
2584
|
+
* const pagination = createPagination({ size: 100 })
|
|
2585
|
+
* pagination.next()
|
|
2586
|
+
* pagination.items.value // [{ type: 'page', value: 1 }, { type: 'page', value: 2 }, ...]
|
|
2829
2587
|
*
|
|
2830
|
-
*
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
2588
|
+
* // With v-model (pass a ref)
|
|
2589
|
+
* const page = ref(1)
|
|
2590
|
+
* const pagination = createPagination({ page, size: 100 })
|
|
2591
|
+
* // Mutating pagination.page or the passed ref syncs both
|
|
2592
|
+
* ```
|
|
2593
|
+
*/
|
|
2594
|
+
function createPagination(_options = {}) {
|
|
2595
|
+
const { page: _page = 1, itemsPerPage: _itemsPerPage = 10, size: _size = 0, visible: _visible = 7, ellipsis = "..." } = _options;
|
|
2596
|
+
const page = isRef(_page) ? _page : shallowRef(_page);
|
|
2597
|
+
const pages = computed(() => {
|
|
2598
|
+
const size = toValue(_size);
|
|
2599
|
+
const perPage = toValue(_itemsPerPage);
|
|
2600
|
+
if (size <= 0 || /* @__PURE__ */ isNaN(size)) return 0;
|
|
2601
|
+
return Math.ceil(size / perPage);
|
|
2602
|
+
});
|
|
2603
|
+
function first() {
|
|
2604
|
+
page.value = 1;
|
|
2839
2605
|
}
|
|
2840
|
-
function
|
|
2841
|
-
|
|
2842
|
-
const args = toArray(params);
|
|
2843
|
-
if (!locale) return adapter.t(fallback ?? key, ...args);
|
|
2844
|
-
const path = `${locale}.${key}`;
|
|
2845
|
-
const message = tokens.get(path)?.value;
|
|
2846
|
-
const template = /* @__PURE__ */ isString(message) ? resolve(locale, message) : fallback ?? key;
|
|
2847
|
-
return adapter.t(template, ...args);
|
|
2606
|
+
function last() {
|
|
2607
|
+
page.value = Math.max(1, pages.value);
|
|
2848
2608
|
}
|
|
2849
|
-
function
|
|
2850
|
-
|
|
2609
|
+
function next() {
|
|
2610
|
+
if (page.value < pages.value) page.value++;
|
|
2851
2611
|
}
|
|
2852
|
-
function
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2612
|
+
function prev() {
|
|
2613
|
+
if (page.value > 1) page.value--;
|
|
2614
|
+
}
|
|
2615
|
+
function select(value) {
|
|
2616
|
+
if (value < 1) page.value = 1;
|
|
2617
|
+
else if (value > pages.value) page.value = Math.max(1, pages.value);
|
|
2618
|
+
else page.value = value;
|
|
2619
|
+
}
|
|
2620
|
+
const isFirst = computed(() => page.value <= 1);
|
|
2621
|
+
const isLast = computed(() => page.value >= pages.value);
|
|
2622
|
+
const pageStart = computed(() => (page.value - 1) * toValue(_itemsPerPage));
|
|
2623
|
+
const pageStop = computed(() => Math.min(pageStart.value + toValue(_itemsPerPage), toValue(_size)));
|
|
2624
|
+
function toPage(value) {
|
|
2625
|
+
return {
|
|
2626
|
+
type: "page",
|
|
2627
|
+
value
|
|
2628
|
+
};
|
|
2629
|
+
}
|
|
2630
|
+
function toEllipsis() {
|
|
2631
|
+
return ellipsis === false ? false : {
|
|
2632
|
+
type: "ellipsis",
|
|
2633
|
+
value: ellipsis
|
|
2634
|
+
};
|
|
2635
|
+
}
|
|
2636
|
+
function filter(array) {
|
|
2637
|
+
return array.filter((item) => item !== false);
|
|
2861
2638
|
}
|
|
2862
2639
|
return {
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2640
|
+
page,
|
|
2641
|
+
ellipsis,
|
|
2642
|
+
items: computed(() => {
|
|
2643
|
+
const pageCount = pages.value;
|
|
2644
|
+
const visible = toValue(_visible);
|
|
2645
|
+
const current = page.value;
|
|
2646
|
+
if (pageCount <= 0 || /* @__PURE__ */ isNaN(pageCount) || pageCount > Number.MAX_SAFE_INTEGER) return [];
|
|
2647
|
+
if (visible <= 0) return [];
|
|
2648
|
+
if (visible <= 2) return [toPage(current)];
|
|
2649
|
+
if (pageCount <= visible) return (/* @__PURE__ */ range(pageCount, 1)).map(toPage);
|
|
2650
|
+
if (visible === 3) {
|
|
2651
|
+
const mid = current <= 1 ? 2 : current >= pageCount ? pageCount - 1 : current;
|
|
2652
|
+
return [
|
|
2653
|
+
toPage(1),
|
|
2654
|
+
toPage(mid),
|
|
2655
|
+
toPage(pageCount)
|
|
2656
|
+
];
|
|
2657
|
+
}
|
|
2658
|
+
const boundary = visible - 2;
|
|
2659
|
+
const middle = visible - 4;
|
|
2660
|
+
if (middle <= 0) {
|
|
2661
|
+
if (current <= boundary) return filter([
|
|
2662
|
+
...(/* @__PURE__ */ range(boundary, 1)).map(toPage),
|
|
2663
|
+
toEllipsis(),
|
|
2664
|
+
toPage(pageCount)
|
|
2665
|
+
]);
|
|
2666
|
+
if (current > pageCount - boundary) return filter([
|
|
2667
|
+
toPage(1),
|
|
2668
|
+
toEllipsis(),
|
|
2669
|
+
...(/* @__PURE__ */ range(boundary, pageCount - boundary + 1)).map(toPage)
|
|
2670
|
+
]);
|
|
2671
|
+
return current <= Math.ceil(pageCount / 2) ? filter([
|
|
2672
|
+
toPage(1),
|
|
2673
|
+
toPage(current),
|
|
2674
|
+
toEllipsis(),
|
|
2675
|
+
toPage(pageCount)
|
|
2676
|
+
]) : filter([
|
|
2677
|
+
toPage(1),
|
|
2678
|
+
toEllipsis(),
|
|
2679
|
+
toPage(current),
|
|
2680
|
+
toPage(pageCount)
|
|
2681
|
+
]);
|
|
2682
|
+
}
|
|
2683
|
+
const leftThreshold = boundary - 1;
|
|
2684
|
+
const rightThreshold = pageCount - boundary + 2;
|
|
2685
|
+
if (current <= leftThreshold) return filter([
|
|
2686
|
+
...(/* @__PURE__ */ range(boundary, 1)).map(toPage),
|
|
2687
|
+
toEllipsis(),
|
|
2688
|
+
toPage(pageCount)
|
|
2689
|
+
]);
|
|
2690
|
+
else if (current >= rightThreshold) return filter([
|
|
2691
|
+
toPage(1),
|
|
2692
|
+
toEllipsis(),
|
|
2693
|
+
...(/* @__PURE__ */ range(boundary, pageCount - boundary + 1)).map(toPage)
|
|
2694
|
+
]);
|
|
2695
|
+
else {
|
|
2696
|
+
const start = current - Math.floor(middle / 2);
|
|
2697
|
+
return filter([
|
|
2698
|
+
toPage(1),
|
|
2699
|
+
toEllipsis(),
|
|
2700
|
+
...(/* @__PURE__ */ range(middle, start)).map(toPage),
|
|
2701
|
+
toEllipsis(),
|
|
2702
|
+
toPage(pageCount)
|
|
2703
|
+
]);
|
|
2704
|
+
}
|
|
2705
|
+
}),
|
|
2706
|
+
pageStart,
|
|
2707
|
+
pageStop,
|
|
2708
|
+
isFirst,
|
|
2709
|
+
isLast,
|
|
2710
|
+
first,
|
|
2711
|
+
last,
|
|
2712
|
+
next,
|
|
2713
|
+
prev,
|
|
2714
|
+
select,
|
|
2715
|
+
get itemsPerPage() {
|
|
2716
|
+
return toValue(_itemsPerPage);
|
|
2717
|
+
},
|
|
2866
2718
|
get size() {
|
|
2867
|
-
return
|
|
2719
|
+
return toValue(_size);
|
|
2720
|
+
},
|
|
2721
|
+
get pages() {
|
|
2722
|
+
return pages.value;
|
|
2868
2723
|
}
|
|
2869
2724
|
};
|
|
2870
2725
|
}
|
|
2871
|
-
function createLocaleFallback() {
|
|
2872
|
-
return {
|
|
2873
|
-
size: 0,
|
|
2874
|
-
t: (key, _params, fallback) => fallback ?? key,
|
|
2875
|
-
n: String
|
|
2876
|
-
};
|
|
2877
|
-
}
|
|
2878
2726
|
/**
|
|
2879
|
-
* Creates a
|
|
2880
|
-
*
|
|
2881
|
-
* @param options The options for the locale context.
|
|
2882
|
-
* @template Z The type of the locale ticket.
|
|
2883
|
-
* @template E The type of the locale context.
|
|
2884
|
-
* @returns A new locale context.
|
|
2727
|
+
* Creates a pagination context for dependency injection.
|
|
2885
2728
|
*
|
|
2886
|
-
* @
|
|
2729
|
+
* @param options The options including namespace.
|
|
2730
|
+
* @returns A trinity: [usePagination, providePagination, defaultContext]
|
|
2887
2731
|
*
|
|
2888
2732
|
* @example
|
|
2889
2733
|
* ```ts
|
|
2890
|
-
*
|
|
2734
|
+
* // With default namespace 'v0:pagination'
|
|
2735
|
+
* const [usePagination, providePaginationContext] = createPaginationContext({ size: 50 })
|
|
2891
2736
|
*
|
|
2892
|
-
*
|
|
2893
|
-
*
|
|
2894
|
-
*
|
|
2895
|
-
*
|
|
2896
|
-
* es: { hello: 'Hola' },
|
|
2897
|
-
* },
|
|
2737
|
+
* // Or with custom namespace
|
|
2738
|
+
* const [usePagination, providePaginationContext] = createPaginationContext({
|
|
2739
|
+
* namespace: 'my-pagination',
|
|
2740
|
+
* size: 50,
|
|
2898
2741
|
* })
|
|
2899
2742
|
*
|
|
2900
|
-
* //
|
|
2901
|
-
*
|
|
2743
|
+
* // Parent component
|
|
2744
|
+
* providePaginationContext()
|
|
2902
2745
|
*
|
|
2903
|
-
* //
|
|
2904
|
-
* const
|
|
2905
|
-
*
|
|
2746
|
+
* // Child component
|
|
2747
|
+
* const pagination = usePagination()
|
|
2748
|
+
* pagination.next()
|
|
2906
2749
|
* ```
|
|
2907
2750
|
*/
|
|
2908
|
-
function
|
|
2909
|
-
const { namespace = "v0:
|
|
2910
|
-
const [
|
|
2911
|
-
const context =
|
|
2912
|
-
function
|
|
2913
|
-
return
|
|
2751
|
+
function createPaginationContext(_options = {}) {
|
|
2752
|
+
const { namespace = "v0:pagination", ...options } = _options;
|
|
2753
|
+
const [usePaginationContext, _providePaginationContext] = createContext(namespace);
|
|
2754
|
+
const context = createPagination(options);
|
|
2755
|
+
function providePaginationContext(_context = context, app) {
|
|
2756
|
+
return _providePaginationContext(_context, app);
|
|
2914
2757
|
}
|
|
2915
|
-
return createTrinity(
|
|
2758
|
+
return createTrinity(usePaginationContext, providePaginationContext, context);
|
|
2916
2759
|
}
|
|
2917
2760
|
/**
|
|
2918
|
-
*
|
|
2761
|
+
* Returns the current pagination instance from context.
|
|
2919
2762
|
*
|
|
2920
|
-
* @param
|
|
2921
|
-
* @
|
|
2922
|
-
* @template E The type of the locale context.
|
|
2923
|
-
* @template R The type of the token ticket.
|
|
2924
|
-
* @template O The type of the token context.
|
|
2925
|
-
* @returns A new locale plugin.
|
|
2763
|
+
* @param namespace The namespace. @default 'v0:pagination'
|
|
2764
|
+
* @returns The pagination context.
|
|
2926
2765
|
*
|
|
2927
|
-
* @
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
const [, provideLocaleContext, context] = createLocaleContext({
|
|
2932
|
-
...options,
|
|
2933
|
-
namespace,
|
|
2934
|
-
adapter,
|
|
2935
|
-
messages
|
|
2936
|
-
});
|
|
2937
|
-
return createPlugin({
|
|
2938
|
-
namespace,
|
|
2939
|
-
provide: (app) => {
|
|
2940
|
-
provideLocaleContext(context, app);
|
|
2941
|
-
}
|
|
2942
|
-
});
|
|
2943
|
-
}
|
|
2944
|
-
/**
|
|
2945
|
-
* Returns the current locale instance.
|
|
2766
|
+
* @example
|
|
2767
|
+
* ```vue
|
|
2768
|
+
* <script setup lang="ts">
|
|
2769
|
+
* import { usePagination } from '@vuetify/v0'
|
|
2946
2770
|
*
|
|
2947
|
-
*
|
|
2771
|
+
* const pagination = usePagination()
|
|
2772
|
+
* <\/script>
|
|
2948
2773
|
*
|
|
2949
|
-
*
|
|
2774
|
+
* <template>
|
|
2775
|
+
* <button @click="pagination.prev()" :disabled="pagination.isFirst.value">Prev</button>
|
|
2776
|
+
* <button @click="pagination.next()" :disabled="pagination.isLast.value">Next</button>
|
|
2777
|
+
* </template>
|
|
2778
|
+
* ```
|
|
2950
2779
|
*/
|
|
2951
|
-
function
|
|
2952
|
-
|
|
2953
|
-
if (!getCurrentInstance()) return fallback;
|
|
2954
|
-
try {
|
|
2955
|
-
return useContext(namespace, fallback);
|
|
2956
|
-
} catch {
|
|
2957
|
-
return fallback;
|
|
2958
|
-
}
|
|
2780
|
+
function usePagination(namespace = "v0:pagination") {
|
|
2781
|
+
return useContext(namespace);
|
|
2959
2782
|
}
|
|
2960
2783
|
|
|
2961
2784
|
//#endregion
|
|
2962
2785
|
//#region src/composables/useStep/index.ts
|
|
2963
2786
|
/**
|
|
2964
|
-
* @module useStep
|
|
2965
|
-
*
|
|
2966
|
-
* @remarks
|
|
2967
|
-
* Navigation composable that extends useSingle with first/last/next/prev/step methods.
|
|
2968
|
-
*
|
|
2969
|
-
* Key features:
|
|
2970
|
-
* - Configurable circular or bounded navigation
|
|
2971
|
-
* - Automatic disabled item skipping
|
|
2972
|
-
* - Arbitrary step counts (positive/negative)
|
|
2973
|
-
* - Perfect for wizards, carousels, pagination, onboarding flows
|
|
2974
|
-
*
|
|
2975
|
-
* Inheritance chain: useRegistry → useSelection → useSingle → useStep
|
|
2976
|
-
*/
|
|
2977
|
-
/**
|
|
2978
2787
|
* Creates a new step instance with navigation through items.
|
|
2979
2788
|
*
|
|
2980
2789
|
* Extends `createSingle` with `first()`, `last()`, `next()`, `prev()`, and `step(count)` methods
|
|
@@ -3043,7 +2852,7 @@ function useLocale(namespace = "v0:locale") {
|
|
|
3043
2852
|
* ```
|
|
3044
2853
|
*/
|
|
3045
2854
|
function createStep(_options = {}) {
|
|
3046
|
-
const { circular = false
|
|
2855
|
+
const { circular = false, ...options } = _options;
|
|
3047
2856
|
const registry = createSingle(options);
|
|
3048
2857
|
function first() {
|
|
3049
2858
|
const ticket = registry.seek("first");
|
|
@@ -3119,7 +2928,7 @@ function createStep(_options = {}) {
|
|
|
3119
2928
|
* ```
|
|
3120
2929
|
*/
|
|
3121
2930
|
function createStepContext(_options = {}) {
|
|
3122
|
-
const { namespace = "v0:step"
|
|
2931
|
+
const { namespace = "v0:step", ...options } = _options;
|
|
3123
2932
|
const [useStepContext, _provideStepContext] = createContext(namespace);
|
|
3124
2933
|
const context = createStep(options);
|
|
3125
2934
|
function provideStepContext(_context = context, app) {
|
|
@@ -3156,4 +2965,4 @@ function useStep(namespace = "v0:step") {
|
|
|
3156
2965
|
}
|
|
3157
2966
|
|
|
3158
2967
|
//#endregion
|
|
3159
|
-
export { createGroupContext as A, createLogger as B,
|
|
2968
|
+
export { createGroupContext as A, createLogger as B, createTokensContext as C, useSingle as D, createSingleContext as E, createSelection as F, PinoLoggerAdapter as G, createLoggerPlugin as H, createSelectionContext as I, createTrinity as J, ConsolaLoggerAdapter as K, useSelection as L, useProxyRegistry as M, useProxyModel as N, Vuetify0LocaleAdapter as O, toArray as P, createRegistryContext as R, createTokens as S, createSingle as T, useLogger as U, createLoggerContext as V, Vuetify0LoggerAdapter as W, provideContext as X, createContext as Y, useContext as Z, createLocale as _, createPaginationContext as a, createLocalePlugin as b, createOverflowContext as c, useResizeObserver as d, createFallbackHydration as f, useHydration as g, createHydrationPlugin as h, createPagination as i, useGroup as j, createGroup as k, useOverflow as l, createHydrationContext as m, createStepContext as n, usePagination as o, createHydration as p, createPlugin as q, useStep as r, createOverflow as s, createStep as t, useElementSize as u, createLocaleContext as v, useTokens as w, useLocale as x, createLocaleFallback as y, useRegistry as z };
|