@vuetify/v0 0.0.18 → 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 +1483 -1499
- package/dist/components/index.d.mts +3 -3
- package/dist/components/index.mjs +4 -4
- package/dist/{components-DRdenC8b.mjs → components-D590hSY0.mjs} +3 -3
- package/dist/composables/index.d.mts +4 -4
- package/dist/composables/index.mjs +5 -5
- package/dist/{composables-DG1MHp-R.mjs → composables-FE6B8JUW.mjs} +240 -274
- package/dist/constants/index.mjs +1 -1
- package/dist/{globals-BGVqrlN7.mjs → globals-exvZ8fiO.mjs} +1 -1
- package/dist/index-4jSy8KIt.d.mts +73 -0
- package/dist/{index-CH7DpIK8.d.mts → index-BYyEPh1S.d.mts} +127 -10
- package/dist/index-CjzlIAtF.d.mts +296 -0
- package/dist/{index-oQuVnpOj.d.mts → index-DahjxaTj.d.mts} +251 -204
- package/dist/{index-DaX9-kmY.d.mts → index-Gr6XPRWt.d.mts} +7 -5
- package/dist/index.d.mts +6 -6
- package/dist/index.mjs +6 -6
- package/dist/types/index.d.mts +1 -1
- package/dist/{useStep-DC_JvZpy.mjs → useStep-Dw7XloDM.mjs} +996 -1202
- 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-B-jVvwsm.d.mts +0 -71
- package/dist/index-C5LQZd3v.d.mts +0 -11
- package/dist/utilities-JxCe-nF2.mjs +0 -139
|
@@ -1,25 +1,9 @@
|
|
|
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-
|
|
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.
|
|
@@ -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.
|
|
@@ -616,17 +585,21 @@ function useRegistry(options) {
|
|
|
616
585
|
}
|
|
617
586
|
function on(event, cb) {
|
|
618
587
|
if (!events) {
|
|
619
|
-
logger.warn(`
|
|
588
|
+
logger.warn(`Events are disabled. Initialize with \`useRegistry({ events: true })\` to enable.`);
|
|
620
589
|
return;
|
|
621
590
|
}
|
|
622
591
|
if (!listeners.has(event)) listeners.set(event, /* @__PURE__ */ new Set());
|
|
623
592
|
listeners.get(event).add(cb);
|
|
624
593
|
}
|
|
625
594
|
function off(event, cb) {
|
|
595
|
+
if (!events) {
|
|
596
|
+
logger.warn(`Events are disabled. Initialize with \`useRegistry({ events: true })\` to enable.`);
|
|
597
|
+
return;
|
|
598
|
+
}
|
|
626
599
|
listeners.get(event)?.delete(cb);
|
|
627
600
|
}
|
|
628
601
|
function dispose() {
|
|
629
|
-
|
|
602
|
+
listeners.clear();
|
|
630
603
|
clear();
|
|
631
604
|
}
|
|
632
605
|
function get(id) {
|
|
@@ -715,9 +688,9 @@ function useRegistry(options) {
|
|
|
715
688
|
return entries$1;
|
|
716
689
|
}
|
|
717
690
|
function clear() {
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
691
|
+
collection.clear();
|
|
692
|
+
catalog.clear();
|
|
693
|
+
directory.clear();
|
|
721
694
|
invalidate();
|
|
722
695
|
indexDependentCount = 0;
|
|
723
696
|
needsReindex = false;
|
|
@@ -726,7 +699,7 @@ function useRegistry(options) {
|
|
|
726
699
|
}
|
|
727
700
|
function invalidate() {
|
|
728
701
|
if (batching) return;
|
|
729
|
-
|
|
702
|
+
cache.clear();
|
|
730
703
|
}
|
|
731
704
|
function queueEmit(event, data) {
|
|
732
705
|
if (batching) pendingEmits.push({
|
|
@@ -741,7 +714,7 @@ function useRegistry(options) {
|
|
|
741
714
|
pendingEmits = [];
|
|
742
715
|
try {
|
|
743
716
|
const result = fn();
|
|
744
|
-
|
|
717
|
+
cache.clear();
|
|
745
718
|
for (const { event, data } of pendingEmits) emit(event, data);
|
|
746
719
|
return result;
|
|
747
720
|
} finally {
|
|
@@ -752,8 +725,8 @@ function useRegistry(options) {
|
|
|
752
725
|
function reindex() {
|
|
753
726
|
const startIndex = minDirtyIndex === Infinity ? 0 : minDirtyIndex;
|
|
754
727
|
if (startIndex === 0) {
|
|
755
|
-
|
|
756
|
-
|
|
728
|
+
catalog.clear();
|
|
729
|
+
directory.clear();
|
|
757
730
|
}
|
|
758
731
|
invalidate();
|
|
759
732
|
let index = 0;
|
|
@@ -780,7 +753,7 @@ function useRegistry(options) {
|
|
|
780
753
|
const size = collection.size;
|
|
781
754
|
const id = registration.id ?? /* @__PURE__ */ genId();
|
|
782
755
|
if (has(id)) {
|
|
783
|
-
logger.warn(`Ticket
|
|
756
|
+
logger.warn(`Ticket "${id}" already exists. Use \`upsert()\` to update or check \`has()\` before registering.`);
|
|
784
757
|
return get(id);
|
|
785
758
|
}
|
|
786
759
|
const valueIsUndefined = /* @__PURE__ */ isUndefined(registration.value);
|
|
@@ -830,12 +803,16 @@ function useRegistry(options) {
|
|
|
830
803
|
}
|
|
831
804
|
if (removed.length === 0) return;
|
|
832
805
|
invalidate();
|
|
833
|
-
|
|
806
|
+
for (const ticket of removed) queueEmit("unregister:ticket", ticket);
|
|
834
807
|
needsReindex = true;
|
|
835
808
|
}
|
|
836
809
|
function seek(direction = "first", from, predicate) {
|
|
837
810
|
if (collection.size === 0) return void 0;
|
|
838
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
|
+
}
|
|
839
816
|
const tickets = values();
|
|
840
817
|
const index = /* @__PURE__ */ isUndefined(from) ? void 0 : Math.max(0, Math.min(from, tickets.length - 1));
|
|
841
818
|
if (direction === "last") {
|
|
@@ -922,21 +899,6 @@ function createRegistryContext(_options = {}) {
|
|
|
922
899
|
//#endregion
|
|
923
900
|
//#region src/composables/useSelection/index.ts
|
|
924
901
|
/**
|
|
925
|
-
* @module useSelection
|
|
926
|
-
*
|
|
927
|
-
* @remarks
|
|
928
|
-
* Base composable for managing selected items in a collection with Set-based tracking.
|
|
929
|
-
*
|
|
930
|
-
* Key features:
|
|
931
|
-
* - Set-based selectedIds for O(1) selection checks
|
|
932
|
-
* - Mandatory selection mode (prevents deselecting last item)
|
|
933
|
-
* - Auto-enrollment option (selects non-disabled items on register)
|
|
934
|
-
* - Disabled item filtering
|
|
935
|
-
* - Computed selectedItems and selectedValues Sets
|
|
936
|
-
*
|
|
937
|
-
* Extends useRegistry and serves as the base for useSingle, useGroup, useStep, and useFeatures.
|
|
938
|
-
*/
|
|
939
|
-
/**
|
|
940
902
|
* Creates a new selection instance for managing multiple selected items.
|
|
941
903
|
*
|
|
942
904
|
* Extends `useRegistry` with selection tracking via a reactive `Set` of selected IDs.
|
|
@@ -1176,20 +1138,6 @@ function toArray(value) {
|
|
|
1176
1138
|
//#endregion
|
|
1177
1139
|
//#region src/composables/useProxyModel/index.ts
|
|
1178
1140
|
/**
|
|
1179
|
-
* @module useProxyModel
|
|
1180
|
-
*
|
|
1181
|
-
* @remarks
|
|
1182
|
-
* Proxy composable for bidirectional sync between selection registry and v-model.
|
|
1183
|
-
*
|
|
1184
|
-
* Key features:
|
|
1185
|
-
* - Bidirectional synchronization
|
|
1186
|
-
* - Array and single-value modes
|
|
1187
|
-
* - Automatic cleanup on scope disposal
|
|
1188
|
-
* - Perfect for form controls with selection backing
|
|
1189
|
-
*
|
|
1190
|
-
* Bridges the gap between selection composables and Vue's v-model.
|
|
1191
|
-
*/
|
|
1192
|
-
/**
|
|
1193
1141
|
* Syncs a ref with a selection registry bidirectionally.
|
|
1194
1142
|
*
|
|
1195
1143
|
* @param registry The selection registry to bind to.
|
|
@@ -1262,7 +1210,8 @@ function useProxyModel(registry, model, options) {
|
|
|
1262
1210
|
flush: "sync",
|
|
1263
1211
|
deep: multiple
|
|
1264
1212
|
});
|
|
1265
|
-
function onRegister(
|
|
1213
|
+
function onRegister(data) {
|
|
1214
|
+
const ticket = data;
|
|
1266
1215
|
if (!pending.has(ticket.value) || ticket.disabled) return;
|
|
1267
1216
|
registryWatch.pause();
|
|
1268
1217
|
modelWatch.pause();
|
|
@@ -1284,21 +1233,6 @@ function useProxyModel(registry, model, options) {
|
|
|
1284
1233
|
//#endregion
|
|
1285
1234
|
//#region src/composables/useProxyRegistry/index.ts
|
|
1286
1235
|
/**
|
|
1287
|
-
* @module useProxyRegistry
|
|
1288
|
-
*
|
|
1289
|
-
* @remarks
|
|
1290
|
-
* Proxy composable for reactive registry keys, values, entries, and size.
|
|
1291
|
-
*
|
|
1292
|
-
* Key features:
|
|
1293
|
-
* - Reactive proxy for registry data
|
|
1294
|
-
* - Deep or shallow reactivity options
|
|
1295
|
-
* - Event-based updates
|
|
1296
|
-
* - Automatic cleanup on scope disposal
|
|
1297
|
-
* - Transforms Map-based registry into reactive refs
|
|
1298
|
-
*
|
|
1299
|
-
* Perfect for exposing registry data as reactive computed properties.
|
|
1300
|
-
*/
|
|
1301
|
-
/**
|
|
1302
1236
|
* Creates a proxy registry that provides reactive objects for registry data.
|
|
1303
1237
|
*
|
|
1304
1238
|
* @param registry The registry instance to proxy.
|
|
@@ -1348,26 +1282,6 @@ function useProxyRegistry(registry, options) {
|
|
|
1348
1282
|
//#endregion
|
|
1349
1283
|
//#region src/composables/useGroup/index.ts
|
|
1350
1284
|
/**
|
|
1351
|
-
* @module useGroup
|
|
1352
|
-
*
|
|
1353
|
-
* @remarks
|
|
1354
|
-
* Multi-selection composable that extends useSelection with batch operations and tri-state support.
|
|
1355
|
-
*
|
|
1356
|
-
* Key features:
|
|
1357
|
-
* - Batch operations (select/unselect/toggle accept ID | ID[])
|
|
1358
|
-
* - Tri-state support via mixed/indeterminate state (mix/unmix)
|
|
1359
|
-
* - selectedIndexes computed Set for position-based tracking
|
|
1360
|
-
* - Perfect for checkbox trees, multi-select dropdowns, filter panels
|
|
1361
|
-
*
|
|
1362
|
-
* Tri-state behavior:
|
|
1363
|
-
* - Items can be selected, mixed (indeterminate), or unselected
|
|
1364
|
-
* - select() clears mixed state, mix() clears selected state (mutually exclusive)
|
|
1365
|
-
* - toggle() on a mixed item selects it (resolves positively)
|
|
1366
|
-
*
|
|
1367
|
-
* Inheritance chain: useRegistry → useSelection → useGroup
|
|
1368
|
-
* Extended by: useFeatures
|
|
1369
|
-
*/
|
|
1370
|
-
/**
|
|
1371
1285
|
* Creates a new group instance with batch selection and tri-state support.
|
|
1372
1286
|
*
|
|
1373
1287
|
* Extends `createSelection` to support selecting, unselecting, and toggling multiple items
|
|
@@ -1632,1364 +1546,1244 @@ function useGroup(namespace = "v0:group") {
|
|
|
1632
1546
|
}
|
|
1633
1547
|
|
|
1634
1548
|
//#endregion
|
|
1635
|
-
//#region src/composables/
|
|
1549
|
+
//#region src/composables/useLocale/adapters/v0.ts
|
|
1636
1550
|
/**
|
|
1637
|
-
*
|
|
1551
|
+
* Vuetify0.x locale adapter implementation
|
|
1638
1552
|
*
|
|
1639
|
-
*
|
|
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.
|
|
1640
1585
|
*
|
|
1641
|
-
*
|
|
1642
|
-
*
|
|
1586
|
+
* Extends `createSelection` by automatically clearing previous selections when a new item is selected.
|
|
1587
|
+
* Adds computed singular properties: `selectedId`, `selectedItem`, `selectedIndex`, `selectedValue`.
|
|
1643
1588
|
*
|
|
1644
|
-
*
|
|
1645
|
-
*
|
|
1646
|
-
*
|
|
1647
|
-
*
|
|
1648
|
-
* - Plugin installation support
|
|
1649
|
-
* - 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.
|
|
1650
1593
|
*
|
|
1651
|
-
*
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
*
|
|
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
|
|
1655
1599
|
*
|
|
1656
|
-
*
|
|
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)
|
|
1657
1605
|
*
|
|
1658
|
-
*
|
|
1606
|
+
* **Inheritance Chain:**
|
|
1607
|
+
* `useRegistry` → `createSelection` → `createSingle` → `createStep`
|
|
1608
|
+
*
|
|
1609
|
+
* @see https://0.vuetifyjs.com/composables/selection/use-single
|
|
1659
1610
|
*
|
|
1660
1611
|
* @example
|
|
1661
1612
|
* ```ts
|
|
1662
|
-
* import {
|
|
1613
|
+
* import { createSingle } from '@vuetify/v0'
|
|
1663
1614
|
*
|
|
1664
|
-
* const
|
|
1665
|
-
* console.log(hydration.isHydrated.value) // false
|
|
1666
|
-
* hydration.hydrate()
|
|
1667
|
-
* console.log(hydration.isHydrated.value) // true
|
|
1668
|
-
* ```
|
|
1669
|
-
*/
|
|
1670
|
-
function createHydration() {
|
|
1671
|
-
const isHydrated = shallowRef(false);
|
|
1672
|
-
function hydrate() {
|
|
1673
|
-
isHydrated.value = true;
|
|
1674
|
-
}
|
|
1675
|
-
return {
|
|
1676
|
-
isHydrated: shallowReadonly(isHydrated),
|
|
1677
|
-
hydrate
|
|
1678
|
-
};
|
|
1679
|
-
}
|
|
1680
|
-
function createFallbackHydration() {
|
|
1681
|
-
return {
|
|
1682
|
-
isHydrated: shallowReadonly(shallowRef(true)),
|
|
1683
|
-
hydrate: () => {}
|
|
1684
|
-
};
|
|
1685
|
-
}
|
|
1686
|
-
/**
|
|
1687
|
-
* Creates a new hydration context trinity.
|
|
1615
|
+
* const tabs = createSingle({ mandatory: true })
|
|
1688
1616
|
*
|
|
1689
|
-
*
|
|
1690
|
-
*
|
|
1691
|
-
*
|
|
1617
|
+
* tabs.onboard([
|
|
1618
|
+
* { id: 'home', value: 'Home' },
|
|
1619
|
+
* { id: 'about', value: 'About' },
|
|
1620
|
+
* { id: 'contact', value: 'Contact' },
|
|
1621
|
+
* ])
|
|
1692
1622
|
*
|
|
1693
|
-
*
|
|
1623
|
+
* tabs.first() // Select first tab
|
|
1694
1624
|
*
|
|
1695
|
-
*
|
|
1696
|
-
*
|
|
1697
|
-
* import { createHydrationContext } from '@vuetify/v0'
|
|
1625
|
+
* console.log(tabs.selectedId.value) // 'home'
|
|
1626
|
+
* console.log(tabs.selectedIndex.value) // 0
|
|
1698
1627
|
*
|
|
1699
|
-
*
|
|
1700
|
-
*
|
|
1701
|
-
*
|
|
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)
|
|
1702
1631
|
* ```
|
|
1703
1632
|
*/
|
|
1704
|
-
function
|
|
1705
|
-
const {
|
|
1706
|
-
const
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
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);
|
|
1710
1647
|
}
|
|
1711
|
-
|
|
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
|
+
};
|
|
1712
1664
|
}
|
|
1713
1665
|
/**
|
|
1714
|
-
* Creates a new
|
|
1666
|
+
* Creates a new single selection context.
|
|
1715
1667
|
*
|
|
1716
|
-
* @param options The options for the
|
|
1717
|
-
* @template
|
|
1718
|
-
* @
|
|
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.
|
|
1719
1672
|
*
|
|
1720
|
-
* @see https://0.vuetifyjs.com/composables/
|
|
1673
|
+
* @see https://0.vuetifyjs.com/composables/selection/use-single
|
|
1721
1674
|
*
|
|
1722
1675
|
* @example
|
|
1723
1676
|
* ```ts
|
|
1724
|
-
* import {
|
|
1725
|
-
* import { createHydrationPlugin } from '@vuetify/v0'
|
|
1726
|
-
* import App from './App.vue'
|
|
1677
|
+
* import { createSingleContext } from '@vuetify/v0'
|
|
1727
1678
|
*
|
|
1728
|
-
*
|
|
1679
|
+
* // With default namespace 'v0:single'
|
|
1680
|
+
* export const [useSingle, provideSingle, context] = createSingleContext()
|
|
1729
1681
|
*
|
|
1730
|
-
*
|
|
1682
|
+
* // In a parent component:
|
|
1683
|
+
* provideSingle()
|
|
1731
1684
|
*
|
|
1732
|
-
*
|
|
1685
|
+
* // In a child component:
|
|
1686
|
+
* const single = useSingle()
|
|
1687
|
+
* single.select('tab-1')
|
|
1733
1688
|
* ```
|
|
1734
1689
|
*/
|
|
1735
|
-
function
|
|
1736
|
-
const { namespace = "v0:
|
|
1737
|
-
const [,
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
provide: (app) => {
|
|
1744
|
-
provideHydrationContext(context, app);
|
|
1745
|
-
},
|
|
1746
|
-
setup: (app) => {
|
|
1747
|
-
app.mixin({ mounted() {
|
|
1748
|
-
if (this.$parent !== null) return;
|
|
1749
|
-
context.hydrate();
|
|
1750
|
-
} });
|
|
1751
|
-
}
|
|
1752
|
-
});
|
|
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);
|
|
1753
1698
|
}
|
|
1754
1699
|
/**
|
|
1755
|
-
* Returns the current
|
|
1700
|
+
* Returns the current single selection instance.
|
|
1756
1701
|
*
|
|
1757
|
-
* @param namespace The namespace for the
|
|
1758
|
-
* @returns The current
|
|
1702
|
+
* @param namespace The namespace for the single selection context. Defaults to `'v0:single'`.
|
|
1703
|
+
* @returns The current single selection instance.
|
|
1759
1704
|
*
|
|
1760
|
-
* @see https://0.vuetifyjs.com/composables/
|
|
1705
|
+
* @see https://0.vuetifyjs.com/composables/selection/use-single
|
|
1761
1706
|
*
|
|
1762
1707
|
* @example
|
|
1763
1708
|
* ```vue
|
|
1764
1709
|
* <script setup lang="ts">
|
|
1765
|
-
* import {
|
|
1710
|
+
* import { useSingle } from '@vuetify/v0'
|
|
1766
1711
|
*
|
|
1767
|
-
* const
|
|
1712
|
+
* const tabs = useSingle()
|
|
1768
1713
|
* <\/script>
|
|
1769
1714
|
*
|
|
1770
1715
|
* <template>
|
|
1771
1716
|
* <div>
|
|
1772
|
-
* <p>
|
|
1717
|
+
* <p>Selected: {{ tabs.selectedId }}</p>
|
|
1773
1718
|
* </div>
|
|
1774
1719
|
* </template>
|
|
1775
1720
|
* ```
|
|
1776
1721
|
*/
|
|
1777
|
-
function
|
|
1778
|
-
|
|
1779
|
-
if (!getCurrentInstance()) return fallback;
|
|
1780
|
-
try {
|
|
1781
|
-
return useContext(namespace, fallback);
|
|
1782
|
-
} catch {
|
|
1783
|
-
return fallback;
|
|
1784
|
-
}
|
|
1722
|
+
function useSingle(namespace = "v0:single") {
|
|
1723
|
+
return useContext(namespace);
|
|
1785
1724
|
}
|
|
1786
1725
|
|
|
1787
1726
|
//#endregion
|
|
1788
|
-
//#region src/composables/
|
|
1789
|
-
/**
|
|
1790
|
-
* @module useResizeObserver
|
|
1791
|
-
*
|
|
1792
|
-
* @remarks
|
|
1793
|
-
* ResizeObserver composable with lifecycle management.
|
|
1794
|
-
*
|
|
1795
|
-
* Key features:
|
|
1796
|
-
* - ResizeObserver API wrapper
|
|
1797
|
-
* - Pause/resume/stop functionality
|
|
1798
|
-
* - Automatic cleanup on unmount
|
|
1799
|
-
* - SSR-safe (checks SUPPORTS_OBSERVER)
|
|
1800
|
-
* - Hydration-aware
|
|
1801
|
-
* - Box model options (content-box/border-box)
|
|
1802
|
-
*
|
|
1803
|
-
* Perfect for responsive components and size-based rendering.
|
|
1804
|
-
*/
|
|
1727
|
+
//#region src/composables/useTokens/index.ts
|
|
1805
1728
|
/**
|
|
1806
|
-
*
|
|
1807
|
-
* size changes.
|
|
1729
|
+
* Creates a new token instance.
|
|
1808
1730
|
*
|
|
1809
|
-
* @param
|
|
1810
|
-
* @param
|
|
1811
|
-
* @
|
|
1812
|
-
* @
|
|
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.
|
|
1813
1736
|
*
|
|
1814
|
-
* @see https://
|
|
1815
|
-
* @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
|
|
1816
1739
|
*
|
|
1817
1740
|
* @example
|
|
1818
1741
|
* ```ts
|
|
1819
|
-
* import {
|
|
1820
|
-
* import { useResizeObserver } from '@vuetify/v0'
|
|
1821
|
-
*
|
|
1822
|
-
* const el = ref<HTMLElement>()
|
|
1823
|
-
* const width = ref(0)
|
|
1824
|
-
* const height = ref(0)
|
|
1742
|
+
* import { useTokens } from '@vuetify/v0'
|
|
1825
1743
|
*
|
|
1826
|
-
* const
|
|
1827
|
-
*
|
|
1828
|
-
*
|
|
1829
|
-
*
|
|
1830
|
-
* if (entry) {
|
|
1831
|
-
* width.value = entry.contentRect.width
|
|
1832
|
-
* height.value = entry.contentRect.height
|
|
1833
|
-
* console.log('Size changed:', width.value, 'x', height.value)
|
|
1834
|
-
* }
|
|
1744
|
+
* const tokens = useTokens({
|
|
1745
|
+
* colors: {
|
|
1746
|
+
* primary: '#3b82f6',
|
|
1747
|
+
* secondary: '{colors.primary}', // Alias reference
|
|
1835
1748
|
* },
|
|
1836
|
-
*
|
|
1837
|
-
* )
|
|
1838
|
-
*
|
|
1839
|
-
* // Pause observation
|
|
1840
|
-
* pause()
|
|
1749
|
+
* })
|
|
1841
1750
|
*
|
|
1842
|
-
* //
|
|
1843
|
-
*
|
|
1751
|
+
* console.log(tokens.resolve('{colors.primary}')) // '#3b82f6'
|
|
1752
|
+
* console.log(tokens.resolve('{colors.secondary}')) // '#3b82f6'
|
|
1844
1753
|
* ```
|
|
1845
1754
|
*/
|
|
1846
|
-
function
|
|
1847
|
-
const
|
|
1848
|
-
const
|
|
1849
|
-
const
|
|
1850
|
-
|
|
1851
|
-
function
|
|
1852
|
-
|
|
1853
|
-
observer.value = new ResizeObserver((entries) => {
|
|
1854
|
-
callback(entries.map((entry) => ({
|
|
1855
|
-
contentRect: {
|
|
1856
|
-
width: entry.contentRect.width,
|
|
1857
|
-
height: entry.contentRect.height,
|
|
1858
|
-
top: entry.contentRect.top,
|
|
1859
|
-
left: entry.contentRect.left
|
|
1860
|
-
},
|
|
1861
|
-
target: entry.target
|
|
1862
|
-
})));
|
|
1863
|
-
});
|
|
1864
|
-
observer.value.observe(target.value, { box: options.box || "content-box" });
|
|
1865
|
-
if (options.immediate) {
|
|
1866
|
-
const rect = target.value.getBoundingClientRect();
|
|
1867
|
-
callback([{
|
|
1868
|
-
contentRect: {
|
|
1869
|
-
width: rect.width,
|
|
1870
|
-
height: rect.height,
|
|
1871
|
-
top: rect.top,
|
|
1872
|
-
left: rect.left
|
|
1873
|
-
},
|
|
1874
|
-
target: target.value
|
|
1875
|
-
}]);
|
|
1876
|
-
}
|
|
1877
|
-
}
|
|
1878
|
-
watch([isHydrated, target], () => {
|
|
1879
|
-
cleanup();
|
|
1880
|
-
setup();
|
|
1881
|
-
}, { immediate: true });
|
|
1882
|
-
function cleanup() {
|
|
1883
|
-
if (observer.value) {
|
|
1884
|
-
observer.value.disconnect();
|
|
1885
|
-
observer.value = void 0;
|
|
1886
|
-
}
|
|
1887
|
-
}
|
|
1888
|
-
function pause() {
|
|
1889
|
-
isPaused.value = true;
|
|
1890
|
-
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) === "}";
|
|
1891
1762
|
}
|
|
1892
|
-
function
|
|
1893
|
-
|
|
1894
|
-
setup();
|
|
1763
|
+
function isTokenAlias(value) {
|
|
1764
|
+
return /* @__PURE__ */ isObject(value) && "$value" in value;
|
|
1895
1765
|
}
|
|
1896
|
-
function
|
|
1897
|
-
|
|
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;
|
|
1898
1825
|
}
|
|
1899
|
-
onScopeDispose(stop, true);
|
|
1900
1826
|
return {
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1827
|
+
...registry,
|
|
1828
|
+
resolve,
|
|
1829
|
+
isAlias,
|
|
1830
|
+
get size() {
|
|
1831
|
+
return registry.size;
|
|
1832
|
+
}
|
|
1906
1833
|
};
|
|
1907
1834
|
}
|
|
1908
1835
|
/**
|
|
1909
|
-
*
|
|
1910
|
-
* element's size.
|
|
1836
|
+
* Creates a new token context.
|
|
1911
1837
|
*
|
|
1912
|
-
* @param
|
|
1913
|
-
* @
|
|
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.
|
|
1914
1843
|
*
|
|
1915
|
-
* @see https://0.vuetifyjs.com/composables/
|
|
1844
|
+
* @see https://0.vuetifyjs.com/composables/registration/use-tokens
|
|
1916
1845
|
*
|
|
1917
1846
|
* @example
|
|
1918
1847
|
* ```ts
|
|
1919
|
-
* import {
|
|
1920
|
-
* import { useElementSize } from '@vuetify/v0'
|
|
1921
|
-
*
|
|
1922
|
-
* const box = ref<HTMLElement>()
|
|
1923
|
-
* const { width, height } = useElementSize(box)
|
|
1848
|
+
* import { createTokensContext } from '@vuetify/v0'
|
|
1924
1849
|
*
|
|
1925
|
-
*
|
|
1926
|
-
*
|
|
1927
|
-
*
|
|
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
|
+
* },
|
|
1928
1858
|
* })
|
|
1929
1859
|
* ```
|
|
1930
1860
|
*/
|
|
1931
|
-
function
|
|
1932
|
-
const
|
|
1933
|
-
const
|
|
1934
|
-
const
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
width.value = entry.contentRect.width;
|
|
1938
|
-
height.value = entry.contentRect.height;
|
|
1939
|
-
}
|
|
1940
|
-
}, { immediate: true });
|
|
1941
|
-
function pause() {
|
|
1942
|
-
width.value = 0;
|
|
1943
|
-
height.value = 0;
|
|
1944
|
-
_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);
|
|
1945
1867
|
}
|
|
1946
|
-
return
|
|
1947
|
-
width,
|
|
1948
|
-
height,
|
|
1949
|
-
isActive,
|
|
1950
|
-
isPaused,
|
|
1951
|
-
pause,
|
|
1952
|
-
resume,
|
|
1953
|
-
stop
|
|
1954
|
-
};
|
|
1868
|
+
return createTrinity(useTokensContext, provideTokensContext, context);
|
|
1955
1869
|
}
|
|
1956
|
-
|
|
1957
|
-
//#endregion
|
|
1958
|
-
//#region src/composables/useOverflow/index.ts
|
|
1959
1870
|
/**
|
|
1960
|
-
*
|
|
1871
|
+
* Returns the current tokens instance.
|
|
1961
1872
|
*
|
|
1962
|
-
* @
|
|
1963
|
-
*
|
|
1964
|
-
* Enables responsive truncation logic for Pagination, Breadcrumbs, and similar components.
|
|
1965
|
-
*
|
|
1966
|
-
* Key features:
|
|
1967
|
-
* - Container width tracking via ResizeObserver
|
|
1968
|
-
* - Two modes: variable-width (per-item) or uniform-width (sample-based)
|
|
1969
|
-
* - Computes capacity (how many items fit)
|
|
1970
|
-
* - SSR-safe with Infinity fallback
|
|
1971
|
-
* - Supports reserved space for nav buttons, ellipsis, etc.
|
|
1972
|
-
*
|
|
1973
|
-
* Use variable mode (default) for items with different widths like Breadcrumbs.
|
|
1974
|
-
* Use uniform mode (itemWidth option) for same-width items like Pagination buttons.
|
|
1975
|
-
*/
|
|
1976
|
-
/**
|
|
1977
|
-
* 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.
|
|
1978
1875
|
*
|
|
1979
|
-
* @
|
|
1980
|
-
* @returns Overflow context with container ref, capacity, and measurement functions
|
|
1876
|
+
* @see https://0.vuetifyjs.com/composables/registration/use-tokens
|
|
1981
1877
|
*
|
|
1982
|
-
* @example
|
|
1878
|
+
* @example
|
|
1983
1879
|
* ```vue
|
|
1984
|
-
* <script lang="ts"
|
|
1985
|
-
* import {
|
|
1986
|
-
* import { createOverflow } from '@vuetify/v0'
|
|
1880
|
+
* <script setup lang="ts">
|
|
1881
|
+
* import { useTokens } from '@vuetify/v0'
|
|
1987
1882
|
*
|
|
1988
|
-
* const
|
|
1989
|
-
* const overflow = createOverflow({
|
|
1990
|
-
* container: containerRef,
|
|
1991
|
-
* gap: 8,
|
|
1992
|
-
* reserved: 40,
|
|
1993
|
-
* })
|
|
1883
|
+
* const tokens = useTokens()
|
|
1994
1884
|
* <\/script>
|
|
1995
|
-
*
|
|
1996
|
-
* <template>
|
|
1997
|
-
* <div ref="container">
|
|
1998
|
-
* <span
|
|
1999
|
-
* v-for="(item, i) in items.slice(0, overflow.capacity.value)"
|
|
2000
|
-
* :key="i"
|
|
2001
|
-
* :ref="el => overflow.measure(i, el)"
|
|
2002
|
-
* >
|
|
2003
|
-
* {{ item }}
|
|
2004
|
-
* </span>
|
|
2005
|
-
* <span v-if="overflow.isOverflowing.value">...</span>
|
|
2006
|
-
* </div>
|
|
2007
|
-
* </template>
|
|
2008
|
-
* ```
|
|
2009
|
-
*
|
|
2010
|
-
* @example Uniform-width mode (Pagination)
|
|
2011
|
-
* ```ts
|
|
2012
|
-
* const overflow = createOverflow({
|
|
2013
|
-
* container: () => atom.value?.element,
|
|
2014
|
-
* itemWidth: buttonWidth,
|
|
2015
|
-
* reserved: () => buttonWidth.value * 4,
|
|
2016
|
-
* })
|
|
2017
1885
|
* ```
|
|
2018
1886
|
*/
|
|
2019
|
-
function
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
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;
|
|
2030
1922
|
}
|
|
2031
|
-
|
|
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
|
+
});
|
|
2032
1961
|
}
|
|
2033
|
-
const style = getComputedStyle(el);
|
|
2034
|
-
const marginX = Number.parseFloat(style.marginLeft) + Number.parseFloat(style.marginRight);
|
|
2035
|
-
const w = el.offsetWidth + marginX;
|
|
2036
|
-
if (widths.value.get(index) !== w) widths.value = new Map(widths.value).set(index, w);
|
|
2037
1962
|
}
|
|
2038
|
-
|
|
2039
|
-
|
|
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);
|
|
2040
1985
|
}
|
|
2041
|
-
|
|
2042
|
-
const
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
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;
|
|
2048
2014
|
}
|
|
2049
|
-
|
|
2050
|
-
|
|
2015
|
+
};
|
|
2016
|
+
}
|
|
2017
|
+
function createLocaleFallback() {
|
|
2051
2018
|
return {
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
const available = width.value - toValue(reserved);
|
|
2056
|
-
if (width.value === 0) return Infinity;
|
|
2057
|
-
if (available <= 0) return 0;
|
|
2058
|
-
const g = toValue(gap);
|
|
2059
|
-
const uniformWidth = toValue(itemWidth);
|
|
2060
|
-
if (uniformWidth && uniformWidth > 0) {
|
|
2061
|
-
const first = uniformWidth;
|
|
2062
|
-
const subsequent = uniformWidth + g;
|
|
2063
|
-
if (available < first) return 0;
|
|
2064
|
-
return Math.max(1, Math.floor((available - first) / subsequent) + 1);
|
|
2065
|
-
}
|
|
2066
|
-
const entries = [...widths.value.entries()].toSorted((a, b) => a[0] - b[0]);
|
|
2067
|
-
if (toValue(reverse)) entries.reverse();
|
|
2068
|
-
let sum = 0;
|
|
2069
|
-
let count = 0;
|
|
2070
|
-
for (const [, w] of entries) {
|
|
2071
|
-
const next = sum + w + (count > 0 ? g : 0);
|
|
2072
|
-
if (next > available) break;
|
|
2073
|
-
sum = next;
|
|
2074
|
-
count++;
|
|
2075
|
-
}
|
|
2076
|
-
return count;
|
|
2077
|
-
}),
|
|
2078
|
-
total,
|
|
2079
|
-
isOverflowing: toRef(() => {
|
|
2080
|
-
return total.value > width.value - toValue(reserved);
|
|
2081
|
-
}),
|
|
2082
|
-
measure,
|
|
2083
|
-
reset
|
|
2019
|
+
size: 0,
|
|
2020
|
+
t: (key, _params, fallback) => fallback ?? key,
|
|
2021
|
+
n: String
|
|
2084
2022
|
};
|
|
2085
2023
|
}
|
|
2086
2024
|
/**
|
|
2087
|
-
* Creates
|
|
2025
|
+
* Creates a new locale context.
|
|
2088
2026
|
*
|
|
2089
|
-
* @param options
|
|
2090
|
-
* @
|
|
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
|
|
2091
2033
|
*
|
|
2092
2034
|
* @example
|
|
2093
2035
|
* ```ts
|
|
2094
|
-
*
|
|
2095
|
-
*
|
|
2096
|
-
*
|
|
2097
|
-
*
|
|
2098
|
-
*
|
|
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
|
+
* },
|
|
2099
2044
|
* })
|
|
2100
2045
|
*
|
|
2101
|
-
* // In parent component
|
|
2102
|
-
*
|
|
2046
|
+
* // In a parent component:
|
|
2047
|
+
* provideAppLocale()
|
|
2103
2048
|
*
|
|
2104
|
-
* // In child component
|
|
2105
|
-
* const
|
|
2049
|
+
* // In a child component:
|
|
2050
|
+
* const locale = useAppLocale()
|
|
2051
|
+
* locale.select('es')
|
|
2106
2052
|
* ```
|
|
2107
2053
|
*/
|
|
2108
|
-
function
|
|
2109
|
-
const { namespace = "v0:
|
|
2110
|
-
const [
|
|
2111
|
-
const context =
|
|
2112
|
-
function
|
|
2113
|
-
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);
|
|
2114
2060
|
}
|
|
2115
|
-
return createTrinity(
|
|
2061
|
+
return createTrinity(useLocaleContext, provideLocaleContext, context);
|
|
2116
2062
|
}
|
|
2117
2063
|
/**
|
|
2118
|
-
*
|
|
2064
|
+
* Creates a new locale plugin.
|
|
2119
2065
|
*
|
|
2120
|
-
* @param
|
|
2121
|
-
* @
|
|
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.
|
|
2122
2072
|
*
|
|
2123
|
-
* @
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2073
|
+
* @see https://0.vuetifyjs.com/composables/plugins/use-locale
|
|
2074
|
+
*/
|
|
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
|
+
});
|
|
2089
|
+
}
|
|
2090
|
+
/**
|
|
2091
|
+
* Returns the current locale instance.
|
|
2127
2092
|
*
|
|
2128
|
-
*
|
|
2129
|
-
* const overflow = useOverflow()
|
|
2130
|
-
* <\/script>
|
|
2093
|
+
* @returns The current locale instance.
|
|
2131
2094
|
*
|
|
2132
|
-
*
|
|
2133
|
-
* <div>
|
|
2134
|
-
* <p>Capacity: {{ overflow.capacity.value }}</p>
|
|
2135
|
-
* </div>
|
|
2136
|
-
* </template>
|
|
2137
|
-
* ```
|
|
2095
|
+
* @see https://0.vuetifyjs.com/composables/plugins/use-locale
|
|
2138
2096
|
*/
|
|
2139
|
-
function
|
|
2140
|
-
|
|
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;
|
|
2104
|
+
}
|
|
2141
2105
|
}
|
|
2142
2106
|
|
|
2143
2107
|
//#endregion
|
|
2144
|
-
//#region src/composables/
|
|
2108
|
+
//#region src/composables/useHydration/index.ts
|
|
2145
2109
|
/**
|
|
2146
|
-
*
|
|
2147
|
-
*
|
|
2148
|
-
* @remarks
|
|
2149
|
-
* Lightweight pagination composable for navigating through pages.
|
|
2110
|
+
* Creates a new hydration instance.
|
|
2150
2111
|
*
|
|
2151
|
-
*
|
|
2152
|
-
* - No registry overhead - just a bounded integer
|
|
2153
|
-
* - Direct ref support for v-model compatibility
|
|
2154
|
-
* - Navigation methods: next, prev, first, last
|
|
2155
|
-
* - Computed visible items with ellipsis
|
|
2156
|
-
* - Trinity pattern for dependency injection
|
|
2157
|
-
*
|
|
2158
|
-
* Unlike registry-based composables, pagination tracks a single number
|
|
2159
|
-
* within a range, making it efficient for large page counts.
|
|
2160
|
-
*/
|
|
2161
|
-
/**
|
|
2162
|
-
* Creates a pagination instance.
|
|
2112
|
+
* @returns A new hydration instance.
|
|
2163
2113
|
*
|
|
2164
|
-
* @
|
|
2165
|
-
* @returns A pagination context with navigation methods.
|
|
2114
|
+
* @see https://0.vuetifyjs.com/composables/plugins/use-hydration
|
|
2166
2115
|
*
|
|
2167
2116
|
* @example
|
|
2168
2117
|
* ```ts
|
|
2169
|
-
* import {
|
|
2170
|
-
*
|
|
2171
|
-
*
|
|
2172
|
-
*
|
|
2173
|
-
*
|
|
2174
|
-
*
|
|
2175
|
-
*
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
function first() {
|
|
2192
|
-
page.value = 1;
|
|
2193
|
-
}
|
|
2194
|
-
function last() {
|
|
2195
|
-
page.value = Math.max(1, pages.value);
|
|
2196
|
-
}
|
|
2197
|
-
function next() {
|
|
2198
|
-
if (page.value < pages.value) page.value++;
|
|
2199
|
-
}
|
|
2200
|
-
function prev() {
|
|
2201
|
-
if (page.value > 1) page.value--;
|
|
2202
|
-
}
|
|
2203
|
-
function select(value) {
|
|
2204
|
-
if (value < 1) page.value = 1;
|
|
2205
|
-
else if (value > pages.value) page.value = Math.max(1, pages.value);
|
|
2206
|
-
else page.value = value;
|
|
2207
|
-
}
|
|
2208
|
-
const isFirst = computed(() => page.value <= 1);
|
|
2209
|
-
const isLast = computed(() => page.value >= pages.value);
|
|
2210
|
-
const pageStart = computed(() => (page.value - 1) * toValue(_itemsPerPage));
|
|
2211
|
-
const pageStop = computed(() => Math.min(pageStart.value + toValue(_itemsPerPage), toValue(_size)));
|
|
2212
|
-
function toPage(value) {
|
|
2213
|
-
return {
|
|
2214
|
-
type: "page",
|
|
2215
|
-
value
|
|
2216
|
-
};
|
|
2217
|
-
}
|
|
2218
|
-
function toEllipsis() {
|
|
2219
|
-
return ellipsis === false ? false : {
|
|
2220
|
-
type: "ellipsis",
|
|
2221
|
-
value: ellipsis
|
|
2222
|
-
};
|
|
2223
|
-
}
|
|
2224
|
-
function filter(array) {
|
|
2225
|
-
return array.filter((item) => item !== false);
|
|
2226
|
-
}
|
|
2227
|
-
return {
|
|
2228
|
-
page,
|
|
2229
|
-
ellipsis,
|
|
2230
|
-
items: computed(() => {
|
|
2231
|
-
const pageCount = pages.value;
|
|
2232
|
-
const visible = toValue(_visible);
|
|
2233
|
-
const current = page.value;
|
|
2234
|
-
if (pageCount <= 0 || /* @__PURE__ */ isNaN(pageCount) || pageCount > Number.MAX_SAFE_INTEGER) return [];
|
|
2235
|
-
if (visible <= 0) return [];
|
|
2236
|
-
if (visible <= 2) return [toPage(current)];
|
|
2237
|
-
if (pageCount <= visible) return (/* @__PURE__ */ range(pageCount, 1)).map(toPage);
|
|
2238
|
-
if (visible === 3) {
|
|
2239
|
-
const mid = current <= 1 ? 2 : current >= pageCount ? pageCount - 1 : current;
|
|
2240
|
-
return [
|
|
2241
|
-
toPage(1),
|
|
2242
|
-
toPage(mid),
|
|
2243
|
-
toPage(pageCount)
|
|
2244
|
-
];
|
|
2245
|
-
}
|
|
2246
|
-
const boundary = visible - 2;
|
|
2247
|
-
const middle = visible - 4;
|
|
2248
|
-
if (middle <= 0) {
|
|
2249
|
-
if (current <= boundary) return filter([
|
|
2250
|
-
...(/* @__PURE__ */ range(boundary, 1)).map(toPage),
|
|
2251
|
-
toEllipsis(),
|
|
2252
|
-
toPage(pageCount)
|
|
2253
|
-
]);
|
|
2254
|
-
if (current > pageCount - boundary) return filter([
|
|
2255
|
-
toPage(1),
|
|
2256
|
-
toEllipsis(),
|
|
2257
|
-
...(/* @__PURE__ */ range(boundary, pageCount - boundary + 1)).map(toPage)
|
|
2258
|
-
]);
|
|
2259
|
-
return current <= Math.ceil(pageCount / 2) ? filter([
|
|
2260
|
-
toPage(1),
|
|
2261
|
-
toPage(current),
|
|
2262
|
-
toEllipsis(),
|
|
2263
|
-
toPage(pageCount)
|
|
2264
|
-
]) : filter([
|
|
2265
|
-
toPage(1),
|
|
2266
|
-
toEllipsis(),
|
|
2267
|
-
toPage(current),
|
|
2268
|
-
toPage(pageCount)
|
|
2269
|
-
]);
|
|
2270
|
-
}
|
|
2271
|
-
const leftThreshold = boundary - 1;
|
|
2272
|
-
const rightThreshold = pageCount - boundary + 2;
|
|
2273
|
-
if (current <= leftThreshold) return filter([
|
|
2274
|
-
...(/* @__PURE__ */ range(boundary, 1)).map(toPage),
|
|
2275
|
-
toEllipsis(),
|
|
2276
|
-
toPage(pageCount)
|
|
2277
|
-
]);
|
|
2278
|
-
else if (current >= rightThreshold) return filter([
|
|
2279
|
-
toPage(1),
|
|
2280
|
-
toEllipsis(),
|
|
2281
|
-
...(/* @__PURE__ */ range(boundary, pageCount - boundary + 1)).map(toPage)
|
|
2282
|
-
]);
|
|
2283
|
-
else {
|
|
2284
|
-
const start = current - Math.floor(middle / 2);
|
|
2285
|
-
return filter([
|
|
2286
|
-
toPage(1),
|
|
2287
|
-
toEllipsis(),
|
|
2288
|
-
...(/* @__PURE__ */ range(middle, start)).map(toPage),
|
|
2289
|
-
toEllipsis(),
|
|
2290
|
-
toPage(pageCount)
|
|
2291
|
-
]);
|
|
2292
|
-
}
|
|
2293
|
-
}),
|
|
2294
|
-
pageStart,
|
|
2295
|
-
pageStop,
|
|
2296
|
-
isFirst,
|
|
2297
|
-
isLast,
|
|
2298
|
-
first,
|
|
2299
|
-
last,
|
|
2300
|
-
next,
|
|
2301
|
-
prev,
|
|
2302
|
-
select,
|
|
2303
|
-
get itemsPerPage() {
|
|
2304
|
-
return toValue(_itemsPerPage);
|
|
2305
|
-
},
|
|
2306
|
-
get size() {
|
|
2307
|
-
return toValue(_size);
|
|
2308
|
-
},
|
|
2309
|
-
get pages() {
|
|
2310
|
-
return pages.value;
|
|
2311
|
-
}
|
|
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: () => {}
|
|
2312
2140
|
};
|
|
2313
2141
|
}
|
|
2314
2142
|
/**
|
|
2315
|
-
* Creates a
|
|
2143
|
+
* Creates a new hydration context trinity.
|
|
2316
2144
|
*
|
|
2317
|
-
* @param options
|
|
2318
|
-
* @
|
|
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
|
|
2319
2150
|
*
|
|
2320
2151
|
* @example
|
|
2321
2152
|
* ```ts
|
|
2322
|
-
*
|
|
2323
|
-
* const [usePagination, providePaginationContext] = createPaginationContext({ size: 50 })
|
|
2153
|
+
* import { createHydrationContext } from '@vuetify/v0'
|
|
2324
2154
|
*
|
|
2325
|
-
*
|
|
2326
|
-
*
|
|
2327
|
-
* namespace: 'my-pagination',
|
|
2328
|
-
* size: 50,
|
|
2155
|
+
* export const [useHydrationContext, provideHydrationContext, context] = createHydrationContext({
|
|
2156
|
+
* namespace: 'app:hydration',
|
|
2329
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.
|
|
2330
2171
|
*
|
|
2331
|
-
*
|
|
2332
|
-
*
|
|
2172
|
+
* @param options The options for the hydration plugin.
|
|
2173
|
+
* @template E The type of the hydration context.
|
|
2174
|
+
* @returns A new hydration plugin.
|
|
2333
2175
|
*
|
|
2334
|
-
*
|
|
2335
|
-
*
|
|
2336
|
-
*
|
|
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')
|
|
2337
2189
|
* ```
|
|
2338
2190
|
*/
|
|
2339
|
-
function
|
|
2340
|
-
const { namespace = "v0:
|
|
2341
|
-
const [
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
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
|
+
});
|
|
2347
2209
|
}
|
|
2348
2210
|
/**
|
|
2349
|
-
* Returns the current
|
|
2211
|
+
* Returns the current hydration instance.
|
|
2350
2212
|
*
|
|
2351
|
-
* @param namespace The namespace.
|
|
2352
|
-
* @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
|
|
2353
2217
|
*
|
|
2354
2218
|
* @example
|
|
2355
2219
|
* ```vue
|
|
2356
|
-
* <script setup>
|
|
2357
|
-
*
|
|
2220
|
+
* <script setup lang="ts">
|
|
2221
|
+
* import { useHydration } from '@vuetify/v0'
|
|
2358
2222
|
*
|
|
2359
|
-
*
|
|
2223
|
+
* const hydration = useHydration()
|
|
2360
2224
|
* <\/script>
|
|
2361
2225
|
*
|
|
2362
2226
|
* <template>
|
|
2363
|
-
* <
|
|
2364
|
-
*
|
|
2227
|
+
* <div>
|
|
2228
|
+
* <p>Is hydrated: {{ hydration.isHydrated.value }}</p>
|
|
2229
|
+
* </div>
|
|
2365
2230
|
* </template>
|
|
2366
2231
|
* ```
|
|
2367
2232
|
*/
|
|
2368
|
-
function
|
|
2369
|
-
|
|
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
|
+
}
|
|
2370
2241
|
}
|
|
2371
2242
|
|
|
2372
2243
|
//#endregion
|
|
2373
|
-
//#region src/composables/
|
|
2374
|
-
/**
|
|
2375
|
-
* @module useSingle
|
|
2376
|
-
*
|
|
2377
|
-
* @remarks
|
|
2378
|
-
* Single-selection composable that extends useSelection to enforce only one selected item.
|
|
2379
|
-
*
|
|
2380
|
-
* Key features:
|
|
2381
|
-
* - Auto-clears previous selection when selecting new item
|
|
2382
|
-
* - Singular computed properties (selectedId, selectedItem, selectedIndex, selectedValue)
|
|
2383
|
-
* - Perfect for tabs, radio buttons, theme selectors
|
|
2384
|
-
*
|
|
2385
|
-
* Inheritance chain: useRegistry → useSelection → useSingle
|
|
2386
|
-
*/
|
|
2244
|
+
//#region src/composables/useResizeObserver/index.ts
|
|
2387
2245
|
/**
|
|
2388
|
-
*
|
|
2389
|
-
*
|
|
2390
|
-
* Extends `createSelection` by automatically clearing previous selections when a new item is selected.
|
|
2391
|
-
* Adds computed singular properties: `selectedId`, `selectedItem`, `selectedIndex`, `selectedValue`.
|
|
2392
|
-
*
|
|
2393
|
-
* @param options The options for the single selection instance.
|
|
2394
|
-
* @template Z The type of the single selection ticket.
|
|
2395
|
-
* @template E The type of the single selection context.
|
|
2396
|
-
* @returns A new single selection instance with single-selection enforcement.
|
|
2397
|
-
*
|
|
2398
|
-
* @remarks
|
|
2399
|
-
* **Key Differences from `createSelection`:**
|
|
2400
|
-
* - Automatically clears `selectedIds` before selecting a new item (enforces single selection)
|
|
2401
|
-
* - Provides singular computed properties instead of plural sets
|
|
2402
|
-
* - Perfect for tabs, radio buttons, theme selectors, and other single-choice UI components
|
|
2403
|
-
*
|
|
2404
|
-
* **Computed Properties:**
|
|
2405
|
-
* - `selectedId`: The ID of the selected item (undefined if none selected)
|
|
2406
|
-
* - `selectedItem`: The selected ticket object (undefined if none selected)
|
|
2407
|
-
* - `selectedIndex`: The index of the selected item (-1 if none selected)
|
|
2408
|
-
* - `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.
|
|
2409
2248
|
*
|
|
2410
|
-
*
|
|
2411
|
-
*
|
|
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.
|
|
2412
2253
|
*
|
|
2413
|
-
* @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
|
|
2414
2256
|
*
|
|
2415
2257
|
* @example
|
|
2416
2258
|
* ```ts
|
|
2417
|
-
* import {
|
|
2418
|
-
*
|
|
2419
|
-
* const tabs = createSingle({ mandatory: true })
|
|
2259
|
+
* import { ref } from 'vue'
|
|
2260
|
+
* import { useResizeObserver } from '@vuetify/v0'
|
|
2420
2261
|
*
|
|
2421
|
-
*
|
|
2422
|
-
*
|
|
2423
|
-
*
|
|
2424
|
-
* { id: 'contact', value: 'Contact' },
|
|
2425
|
-
* ])
|
|
2262
|
+
* const el = ref<HTMLElement>()
|
|
2263
|
+
* const width = ref(0)
|
|
2264
|
+
* const height = ref(0)
|
|
2426
2265
|
*
|
|
2427
|
-
*
|
|
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
|
+
* )
|
|
2428
2278
|
*
|
|
2429
|
-
*
|
|
2430
|
-
*
|
|
2279
|
+
* // Pause observation
|
|
2280
|
+
* pause()
|
|
2431
2281
|
*
|
|
2432
|
-
*
|
|
2433
|
-
*
|
|
2434
|
-
* console.log(tabs.selectedIds.size) // 1 (always enforces single selection)
|
|
2282
|
+
* // Resume observation
|
|
2283
|
+
* resume()
|
|
2435
2284
|
* ```
|
|
2436
2285
|
*/
|
|
2437
|
-
function
|
|
2438
|
-
const {
|
|
2439
|
-
const
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
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();
|
|
2443
2325
|
});
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2326
|
+
function cleanup() {
|
|
2327
|
+
if (observer.value) {
|
|
2328
|
+
observer.value.disconnect();
|
|
2329
|
+
observer.value = void 0;
|
|
2330
|
+
}
|
|
2331
|
+
}
|
|
2332
|
+
function pause() {
|
|
2333
|
+
isPaused.value = true;
|
|
2334
|
+
observer.value?.disconnect();
|
|
2451
2335
|
}
|
|
2452
|
-
function
|
|
2453
|
-
|
|
2454
|
-
|
|
2336
|
+
function resume() {
|
|
2337
|
+
isPaused.value = false;
|
|
2338
|
+
setup();
|
|
2455
2339
|
}
|
|
2340
|
+
function stop() {
|
|
2341
|
+
cleanup();
|
|
2342
|
+
observer.value = null;
|
|
2343
|
+
}
|
|
2344
|
+
onScopeDispose(stop, true);
|
|
2456
2345
|
return {
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
unselect,
|
|
2463
|
-
toggle,
|
|
2464
|
-
get size() {
|
|
2465
|
-
return registry.size;
|
|
2466
|
-
}
|
|
2346
|
+
isActive: shallowReadonly(isActive),
|
|
2347
|
+
isPaused: shallowReadonly(isPaused),
|
|
2348
|
+
pause,
|
|
2349
|
+
resume,
|
|
2350
|
+
stop
|
|
2467
2351
|
};
|
|
2468
2352
|
}
|
|
2469
2353
|
/**
|
|
2470
|
-
*
|
|
2354
|
+
* A convenience composable that uses the Resize Observer API to track an
|
|
2355
|
+
* element's size.
|
|
2471
2356
|
*
|
|
2472
|
-
* @param
|
|
2473
|
-
* @
|
|
2474
|
-
* @template E The type of the single selection context.
|
|
2475
|
-
* @returns A new single selection context.
|
|
2357
|
+
* @param target The element to observe.
|
|
2358
|
+
* @returns An object with the element's width and height.
|
|
2476
2359
|
*
|
|
2477
|
-
* @see https://0.vuetifyjs.com/composables/
|
|
2360
|
+
* @see https://0.vuetifyjs.com/composables/system/use-resize-observer#use-element-size
|
|
2478
2361
|
*
|
|
2479
2362
|
* @example
|
|
2480
2363
|
* ```ts
|
|
2481
|
-
* import {
|
|
2482
|
-
*
|
|
2483
|
-
* // With default namespace 'v0:single'
|
|
2484
|
-
* export const [useSingle, provideSingle, context] = createSingleContext()
|
|
2364
|
+
* import { ref, watchEffect } from 'vue'
|
|
2365
|
+
* import { useElementSize } from '@vuetify/v0'
|
|
2485
2366
|
*
|
|
2486
|
-
*
|
|
2487
|
-
*
|
|
2367
|
+
* const box = ref<HTMLElement>()
|
|
2368
|
+
* const { width, height } = useElementSize(box)
|
|
2488
2369
|
*
|
|
2489
|
-
* //
|
|
2490
|
-
*
|
|
2491
|
-
*
|
|
2370
|
+
* // Width and height are reactive refs
|
|
2371
|
+
* watchEffect(() => {
|
|
2372
|
+
* console.log('Box size:', width.value, 'x', height.value)
|
|
2373
|
+
* })
|
|
2492
2374
|
* ```
|
|
2493
2375
|
*/
|
|
2494
|
-
function
|
|
2495
|
-
const
|
|
2496
|
-
const
|
|
2497
|
-
const
|
|
2498
|
-
|
|
2499
|
-
|
|
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();
|
|
2500
2390
|
}
|
|
2501
|
-
return
|
|
2391
|
+
return {
|
|
2392
|
+
width,
|
|
2393
|
+
height,
|
|
2394
|
+
isActive,
|
|
2395
|
+
isPaused,
|
|
2396
|
+
pause,
|
|
2397
|
+
resume,
|
|
2398
|
+
stop
|
|
2399
|
+
};
|
|
2502
2400
|
}
|
|
2401
|
+
|
|
2402
|
+
//#endregion
|
|
2403
|
+
//#region src/composables/useOverflow/index.ts
|
|
2503
2404
|
/**
|
|
2504
|
-
*
|
|
2505
|
-
*
|
|
2506
|
-
* @param namespace The namespace for the single selection context. Defaults to `'v0:single'`.
|
|
2507
|
-
* @returns The current single selection instance.
|
|
2405
|
+
* Creates a new overflow context for computing how many items fit in a container.
|
|
2508
2406
|
*
|
|
2509
|
-
* @
|
|
2407
|
+
* @param options Configuration options
|
|
2408
|
+
* @returns Overflow context with container ref, capacity, and measurement functions
|
|
2510
2409
|
*
|
|
2511
|
-
* @example
|
|
2410
|
+
* @example Variable-width mode (Breadcrumbs)
|
|
2512
2411
|
* ```vue
|
|
2513
|
-
* <script
|
|
2514
|
-
* import {
|
|
2412
|
+
* <script lang="ts" setup>
|
|
2413
|
+
* import { useTemplateRef } from 'vue'
|
|
2414
|
+
* import { createOverflow } from '@vuetify/v0'
|
|
2515
2415
|
*
|
|
2516
|
-
* const
|
|
2416
|
+
* const containerRef = useTemplateRef('container')
|
|
2417
|
+
* const overflow = createOverflow({
|
|
2418
|
+
* container: containerRef,
|
|
2419
|
+
* gap: 8,
|
|
2420
|
+
* reserved: 40,
|
|
2421
|
+
* })
|
|
2517
2422
|
* <\/script>
|
|
2518
2423
|
*
|
|
2519
2424
|
* <template>
|
|
2520
|
-
* <div>
|
|
2521
|
-
* <
|
|
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>
|
|
2522
2434
|
* </div>
|
|
2523
2435
|
* </template>
|
|
2524
2436
|
* ```
|
|
2525
|
-
*/
|
|
2526
|
-
function useSingle(namespace = "v0:single") {
|
|
2527
|
-
return useContext(namespace);
|
|
2528
|
-
}
|
|
2529
|
-
|
|
2530
|
-
//#endregion
|
|
2531
|
-
//#region src/composables/useTokens/index.ts
|
|
2532
|
-
/**
|
|
2533
|
-
* @module useTokens
|
|
2534
|
-
*
|
|
2535
|
-
* @see https://0.vuetifyjs.com/composables/registration/use-tokens
|
|
2536
|
-
*
|
|
2537
|
-
* @remarks
|
|
2538
|
-
* Design token registry with alias resolution and W3C Design Tokens format support.
|
|
2539
|
-
*
|
|
2540
|
-
* Key features:
|
|
2541
|
-
* - Alias resolution with circular reference detection
|
|
2542
|
-
* - Nested token flattening with dot notation
|
|
2543
|
-
* - W3C Design Tokens format ($value, $type, $description, $extensions)
|
|
2544
|
-
* - Path-based resolution (e.g., {colors}.blue.500)
|
|
2545
|
-
* - Resolution caching for performance (~28,590 ops/sec)
|
|
2546
|
-
*
|
|
2547
|
-
* Used by useTheme, useLocale, and useFeatures for token-based configuration.
|
|
2548
|
-
*/
|
|
2549
|
-
/**
|
|
2550
|
-
* Creates a new token instance.
|
|
2551
|
-
*
|
|
2552
|
-
* @param tokens The tokens to use.
|
|
2553
|
-
* @param options The options for the token instance.
|
|
2554
|
-
* @template Z The type of the token ticket.
|
|
2555
|
-
* @template E The type of the token context.
|
|
2556
|
-
* @returns A new token instance.
|
|
2557
|
-
*
|
|
2558
|
-
* @see https://www.designtokens.org/tr/drafts/format/
|
|
2559
|
-
* @see https://0.vuetifyjs.com/composables/registration/use-tokens
|
|
2560
2437
|
*
|
|
2561
|
-
* @example
|
|
2438
|
+
* @example Uniform-width mode (Pagination)
|
|
2562
2439
|
* ```ts
|
|
2563
|
-
*
|
|
2564
|
-
*
|
|
2565
|
-
*
|
|
2566
|
-
*
|
|
2567
|
-
* primary: '#3b82f6',
|
|
2568
|
-
* secondary: '{colors.primary}', // Alias reference
|
|
2569
|
-
* },
|
|
2440
|
+
* const overflow = createOverflow({
|
|
2441
|
+
* container: () => atom.value?.element,
|
|
2442
|
+
* itemWidth: buttonWidth,
|
|
2443
|
+
* reserved: () => buttonWidth.value * 4,
|
|
2570
2444
|
* })
|
|
2571
|
-
*
|
|
2572
|
-
* console.log(tokens.resolve('{colors.primary}')) // '#3b82f6'
|
|
2573
|
-
* console.log(tokens.resolve('{colors.secondary}')) // '#3b82f6'
|
|
2574
2445
|
* ```
|
|
2575
2446
|
*/
|
|
2576
|
-
function
|
|
2577
|
-
const
|
|
2578
|
-
const
|
|
2579
|
-
const
|
|
2580
|
-
|
|
2581
|
-
function
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
function resolve(token, visited = /* @__PURE__ */ new Set()) {
|
|
2588
|
-
const cacheKey = /* @__PURE__ */ isString(token) ? token : JSON.stringify(token);
|
|
2589
|
-
const cached = cache.get(cacheKey);
|
|
2590
|
-
if (!/* @__PURE__ */ isUndefined(cached)) return cached;
|
|
2591
|
-
const reference = isTokenAlias(token) ? token.$value : token;
|
|
2592
|
-
const isAliasReference = /* @__PURE__ */ isString(reference) && isAlias(reference);
|
|
2593
|
-
const clean = isAliasReference ? reference.slice(1, -1) : String(reference);
|
|
2594
|
-
if (visited.has(clean)) {
|
|
2595
|
-
logger.warn(`Circular alias detected for "${clean}"`);
|
|
2596
|
-
cache.set(cacheKey, void 0);
|
|
2597
|
-
return;
|
|
2598
|
-
}
|
|
2599
|
-
visited.add(clean);
|
|
2600
|
-
let found = registry.get(clean);
|
|
2601
|
-
let segments = [];
|
|
2602
|
-
if (!found && clean.includes(".")) {
|
|
2603
|
-
const parts = clean.split(".");
|
|
2604
|
-
for (let i = parts.length - 1; i > 0; i--) {
|
|
2605
|
-
const prefix = parts.slice(0, i).join(".");
|
|
2606
|
-
const suffix = parts.slice(i);
|
|
2607
|
-
const candidate = registry.get(prefix);
|
|
2608
|
-
if (!/* @__PURE__ */ isUndefined(candidate?.value)) {
|
|
2609
|
-
found = candidate;
|
|
2610
|
-
segments = suffix;
|
|
2611
|
-
break;
|
|
2612
|
-
}
|
|
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;
|
|
2613
2458
|
}
|
|
2614
|
-
}
|
|
2615
|
-
if (/* @__PURE__ */ isUndefined(found?.value)) {
|
|
2616
|
-
if (isAliasReference) logger.warn(`Alias not found for "${String(reference)}"`);
|
|
2617
|
-
cache.set(cacheKey, void 0);
|
|
2618
2459
|
return;
|
|
2619
2460
|
}
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
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);
|
|
2631
2493
|
}
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
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++;
|
|
2636
2503
|
}
|
|
2637
|
-
|
|
2638
|
-
}
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
}
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
return result;
|
|
2646
|
-
}
|
|
2647
|
-
return {
|
|
2648
|
-
...registry,
|
|
2649
|
-
resolve,
|
|
2650
|
-
isAlias,
|
|
2651
|
-
get size() {
|
|
2652
|
-
return registry.size;
|
|
2653
|
-
}
|
|
2504
|
+
return count;
|
|
2505
|
+
}),
|
|
2506
|
+
total,
|
|
2507
|
+
isOverflowing: toRef(() => {
|
|
2508
|
+
return total.value > width.value - toValue(reserved);
|
|
2509
|
+
}),
|
|
2510
|
+
measure,
|
|
2511
|
+
reset
|
|
2654
2512
|
};
|
|
2655
2513
|
}
|
|
2656
2514
|
/**
|
|
2657
|
-
* Creates
|
|
2658
|
-
*
|
|
2659
|
-
* @param namespace The namespace for the token context.
|
|
2660
|
-
* @param tokens The tokens to use.
|
|
2661
|
-
* @template Z The type of the token ticket.
|
|
2662
|
-
* @template E The type of the token context.
|
|
2663
|
-
* @returns A new token context.
|
|
2515
|
+
* Creates an overflow context with dependency injection support.
|
|
2664
2516
|
*
|
|
2665
|
-
* @
|
|
2517
|
+
* @param options Configuration options including namespace
|
|
2518
|
+
* @returns Trinity tuple: [useContext, provideContext, defaultContext]
|
|
2666
2519
|
*
|
|
2667
2520
|
* @example
|
|
2668
2521
|
* ```ts
|
|
2669
|
-
*
|
|
2670
|
-
*
|
|
2671
|
-
*
|
|
2672
|
-
*
|
|
2673
|
-
*
|
|
2674
|
-
* colors: {
|
|
2675
|
-
* primary: '#3b82f6',
|
|
2676
|
-
* secondary: '{colors.primary}', // Alias reference
|
|
2677
|
-
* },
|
|
2678
|
-
* },
|
|
2522
|
+
* // Create injectable context
|
|
2523
|
+
* const [useOverflow, provideOverflow, overflow] = createOverflowContext({
|
|
2524
|
+
* namespace: 'my-overflow',
|
|
2525
|
+
* gap: 8,
|
|
2526
|
+
* reserved: 160,
|
|
2679
2527
|
* })
|
|
2528
|
+
*
|
|
2529
|
+
* // In parent component
|
|
2530
|
+
* provideOverflow()
|
|
2531
|
+
*
|
|
2532
|
+
* // In child component
|
|
2533
|
+
* const overflow = useOverflow()
|
|
2680
2534
|
* ```
|
|
2681
2535
|
*/
|
|
2682
|
-
function
|
|
2683
|
-
const { namespace = "v0:
|
|
2684
|
-
const [
|
|
2685
|
-
const context =
|
|
2686
|
-
function
|
|
2687
|
-
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);
|
|
2688
2542
|
}
|
|
2689
|
-
return createTrinity(
|
|
2543
|
+
return createTrinity(useOverflowContext, provideOverflowContext, context);
|
|
2690
2544
|
}
|
|
2691
2545
|
/**
|
|
2692
|
-
* Returns the current
|
|
2693
|
-
*
|
|
2694
|
-
* @param namespace The namespace for the tokens context. Defaults to `'v0:tokens'`.
|
|
2695
|
-
* @returns The current tokens instance.
|
|
2546
|
+
* Returns the current overflow context from dependency injection.
|
|
2696
2547
|
*
|
|
2697
|
-
* @
|
|
2548
|
+
* @param namespace The namespace for the overflow context. Defaults to `v0:overflow`.
|
|
2549
|
+
* @returns The current overflow context.
|
|
2698
2550
|
*
|
|
2699
2551
|
* @example
|
|
2700
2552
|
* ```vue
|
|
2701
|
-
* <script
|
|
2702
|
-
* import {
|
|
2553
|
+
* <script lang="ts" setup>
|
|
2554
|
+
* import { useOverflow } from '@vuetify/v0'
|
|
2703
2555
|
*
|
|
2704
|
-
*
|
|
2556
|
+
* // Inject overflow context provided by parent
|
|
2557
|
+
* const overflow = useOverflow()
|
|
2705
2558
|
* <\/script>
|
|
2559
|
+
*
|
|
2560
|
+
* <template>
|
|
2561
|
+
* <div>
|
|
2562
|
+
* <p>Capacity: {{ overflow.capacity.value }}</p>
|
|
2563
|
+
* </div>
|
|
2564
|
+
* </template>
|
|
2706
2565
|
* ```
|
|
2707
2566
|
*/
|
|
2708
|
-
function
|
|
2567
|
+
function useOverflow(namespace = "v0:overflow") {
|
|
2709
2568
|
return useContext(namespace);
|
|
2710
2569
|
}
|
|
2711
|
-
/**
|
|
2712
|
-
* Flattens a nested collection of tokens into a flat array of tokens.
|
|
2713
|
-
* Each token is represented by an object containing its ID & value.
|
|
2714
|
-
* @param tokens The collection of tokens to flatten.
|
|
2715
|
-
* @param prefix An optional prefix to prepend to each token ID.
|
|
2716
|
-
* @returns An array of flattened tokens, each with an ID and value.
|
|
2717
|
-
*/
|
|
2718
|
-
function flatten(tokens, prefix = "", flat = false) {
|
|
2719
|
-
const flattened = [];
|
|
2720
|
-
const stack = [{
|
|
2721
|
-
tokens,
|
|
2722
|
-
prefix,
|
|
2723
|
-
flat
|
|
2724
|
-
}];
|
|
2725
|
-
while (stack.length > 0) {
|
|
2726
|
-
const { tokens: currentTokens, prefix: currentPrefix, flat: flat$1 } = stack.pop();
|
|
2727
|
-
const meta = {};
|
|
2728
|
-
for (const k in currentTokens) if (k.startsWith("$")) meta[k] = currentTokens[k];
|
|
2729
|
-
if (Object.keys(meta).length > 0 && currentPrefix) flattened.push({
|
|
2730
|
-
id: currentPrefix,
|
|
2731
|
-
value: meta
|
|
2732
|
-
});
|
|
2733
|
-
for (const key in currentTokens) {
|
|
2734
|
-
if (key.startsWith("$")) continue;
|
|
2735
|
-
const value = currentTokens[key];
|
|
2736
|
-
const id = currentPrefix ? `${currentPrefix}.${key}` : key;
|
|
2737
|
-
if (!/* @__PURE__ */ isObject(value)) {
|
|
2738
|
-
flattened.push({
|
|
2739
|
-
id,
|
|
2740
|
-
value
|
|
2741
|
-
});
|
|
2742
|
-
continue;
|
|
2743
|
-
}
|
|
2744
|
-
if ("$value" in value) {
|
|
2745
|
-
flattened.push({
|
|
2746
|
-
id,
|
|
2747
|
-
value
|
|
2748
|
-
});
|
|
2749
|
-
const inner = value.$value;
|
|
2750
|
-
if (/* @__PURE__ */ isObject(inner) && !flat$1) for (const innerKey in inner) {
|
|
2751
|
-
if (innerKey.startsWith("$")) continue;
|
|
2752
|
-
const child = inner[innerKey];
|
|
2753
|
-
const childId = `${id}.${innerKey}`;
|
|
2754
|
-
if (!/* @__PURE__ */ isObject(child)) flattened.push({
|
|
2755
|
-
id: childId,
|
|
2756
|
-
value: child
|
|
2757
|
-
});
|
|
2758
|
-
else if ("$value" in child) flattened.push({
|
|
2759
|
-
id: childId,
|
|
2760
|
-
value: child
|
|
2761
|
-
});
|
|
2762
|
-
else stack.push({
|
|
2763
|
-
tokens: child,
|
|
2764
|
-
prefix: childId,
|
|
2765
|
-
flat: flat$1
|
|
2766
|
-
});
|
|
2767
|
-
}
|
|
2768
|
-
continue;
|
|
2769
|
-
}
|
|
2770
|
-
if (flat$1) {
|
|
2771
|
-
flattened.push({
|
|
2772
|
-
id,
|
|
2773
|
-
value
|
|
2774
|
-
});
|
|
2775
|
-
continue;
|
|
2776
|
-
}
|
|
2777
|
-
stack.push({
|
|
2778
|
-
tokens: value,
|
|
2779
|
-
prefix: id,
|
|
2780
|
-
flat: flat$1
|
|
2781
|
-
});
|
|
2782
|
-
}
|
|
2783
|
-
}
|
|
2784
|
-
return flattened;
|
|
2785
|
-
}
|
|
2786
|
-
|
|
2787
|
-
//#endregion
|
|
2788
|
-
//#region src/composables/useLocale/adapters/v0.ts
|
|
2789
|
-
/**
|
|
2790
|
-
* Vuetify0.x locale adapter implementation
|
|
2791
|
-
*
|
|
2792
|
-
* This adapter provides translation and number formatting
|
|
2793
|
-
* capabilities using the Intl API and supports both
|
|
2794
|
-
* numbered ({0}, {1}) and named ({name}) variables in translation strings.
|
|
2795
|
-
*/
|
|
2796
|
-
var Vuetify0LocaleAdapter = class {
|
|
2797
|
-
t(message, ...params) {
|
|
2798
|
-
let resolvedMessage = message;
|
|
2799
|
-
if (params.length > 0 && /* @__PURE__ */ isObject(params[0])) {
|
|
2800
|
-
const variables = params[0];
|
|
2801
|
-
resolvedMessage = resolvedMessage.replace(/{([a-zA-Z][a-zA-Z0-9_]*)}/g, (match, name) => {
|
|
2802
|
-
return /* @__PURE__ */ isUndefined(variables[name]) ? match : String(variables[name]);
|
|
2803
|
-
});
|
|
2804
|
-
params = params.slice(1);
|
|
2805
|
-
}
|
|
2806
|
-
resolvedMessage = resolvedMessage.replace(/\{(\d+)\}/g, (match, index) => {
|
|
2807
|
-
const idx = Number.parseInt(index, 10);
|
|
2808
|
-
if (!/* @__PURE__ */ isUndefined(params[idx])) return String(params[idx]);
|
|
2809
|
-
return match;
|
|
2810
|
-
});
|
|
2811
|
-
return resolvedMessage;
|
|
2812
|
-
}
|
|
2813
|
-
n(value, locale, ...params) {
|
|
2814
|
-
if (!IN_BROWSER || !locale) return value.toString();
|
|
2815
|
-
const options = params[0];
|
|
2816
|
-
return new Intl.NumberFormat(String(locale), options).format(value);
|
|
2817
|
-
}
|
|
2818
|
-
};
|
|
2819
2570
|
|
|
2820
2571
|
//#endregion
|
|
2821
|
-
//#region src/composables/
|
|
2572
|
+
//#region src/composables/usePagination/index.ts
|
|
2822
2573
|
/**
|
|
2823
|
-
*
|
|
2824
|
-
*
|
|
2825
|
-
* @remarks
|
|
2826
|
-
* Internationalization (i18n) composable with adapter pattern for message translation.
|
|
2574
|
+
* Creates a pagination instance.
|
|
2827
2575
|
*
|
|
2828
|
-
*
|
|
2829
|
-
*
|
|
2830
|
-
* - Token-based message storage with useTokens
|
|
2831
|
-
* - Numbered and named placeholder support ({0}, {name})
|
|
2832
|
-
* - Number formatting with Intl.NumberFormat
|
|
2833
|
-
* - Adapter pattern for integration with i18n providers
|
|
2576
|
+
* @param options The options for the pagination instance.
|
|
2577
|
+
* @returns A pagination context with navigation methods.
|
|
2834
2578
|
*
|
|
2835
|
-
*
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
* Creates a new locale instance.
|
|
2579
|
+
* @example
|
|
2580
|
+
* ```ts
|
|
2581
|
+
* import { createPagination } from '@vuetify/v0'
|
|
2839
2582
|
*
|
|
2840
|
-
*
|
|
2841
|
-
*
|
|
2842
|
-
*
|
|
2843
|
-
*
|
|
2583
|
+
* // Basic usage
|
|
2584
|
+
* const pagination = createPagination({ size: 100 })
|
|
2585
|
+
* pagination.next()
|
|
2586
|
+
* pagination.items.value // [{ type: 'page', value: 1 }, { type: 'page', value: 2 }, ...]
|
|
2844
2587
|
*
|
|
2845
|
-
*
|
|
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
|
+
* ```
|
|
2846
2593
|
*/
|
|
2847
|
-
function
|
|
2848
|
-
const {
|
|
2849
|
-
const
|
|
2850
|
-
const
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
if (
|
|
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;
|
|
2854
2605
|
}
|
|
2855
|
-
function
|
|
2856
|
-
|
|
2857
|
-
const args = toArray(params);
|
|
2858
|
-
if (!locale) return adapter.t(fallback ?? key, ...args);
|
|
2859
|
-
const path = `${locale}.${key}`;
|
|
2860
|
-
const message = tokens.get(path)?.value;
|
|
2861
|
-
const template = /* @__PURE__ */ isString(message) ? resolve(locale, message) : fallback ?? key;
|
|
2862
|
-
return adapter.t(template, ...args);
|
|
2606
|
+
function last() {
|
|
2607
|
+
page.value = Math.max(1, pages.value);
|
|
2863
2608
|
}
|
|
2864
|
-
function
|
|
2865
|
-
|
|
2609
|
+
function next() {
|
|
2610
|
+
if (page.value < pages.value) page.value++;
|
|
2866
2611
|
}
|
|
2867
|
-
function
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
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);
|
|
2876
2638
|
}
|
|
2877
2639
|
return {
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
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
|
+
},
|
|
2881
2718
|
get size() {
|
|
2882
|
-
return
|
|
2719
|
+
return toValue(_size);
|
|
2720
|
+
},
|
|
2721
|
+
get pages() {
|
|
2722
|
+
return pages.value;
|
|
2883
2723
|
}
|
|
2884
2724
|
};
|
|
2885
2725
|
}
|
|
2886
|
-
function createLocaleFallback() {
|
|
2887
|
-
return {
|
|
2888
|
-
size: 0,
|
|
2889
|
-
t: (key, _params, fallback) => fallback ?? key,
|
|
2890
|
-
n: String
|
|
2891
|
-
};
|
|
2892
|
-
}
|
|
2893
2726
|
/**
|
|
2894
|
-
* Creates a
|
|
2895
|
-
*
|
|
2896
|
-
* @param options The options for the locale context.
|
|
2897
|
-
* @template Z The type of the locale ticket.
|
|
2898
|
-
* @template E The type of the locale context.
|
|
2899
|
-
* @returns A new locale context.
|
|
2727
|
+
* Creates a pagination context for dependency injection.
|
|
2900
2728
|
*
|
|
2901
|
-
* @
|
|
2729
|
+
* @param options The options including namespace.
|
|
2730
|
+
* @returns A trinity: [usePagination, providePagination, defaultContext]
|
|
2902
2731
|
*
|
|
2903
2732
|
* @example
|
|
2904
2733
|
* ```ts
|
|
2905
|
-
*
|
|
2734
|
+
* // With default namespace 'v0:pagination'
|
|
2735
|
+
* const [usePagination, providePaginationContext] = createPaginationContext({ size: 50 })
|
|
2906
2736
|
*
|
|
2907
|
-
*
|
|
2908
|
-
*
|
|
2909
|
-
*
|
|
2910
|
-
*
|
|
2911
|
-
* es: { hello: 'Hola' },
|
|
2912
|
-
* },
|
|
2737
|
+
* // Or with custom namespace
|
|
2738
|
+
* const [usePagination, providePaginationContext] = createPaginationContext({
|
|
2739
|
+
* namespace: 'my-pagination',
|
|
2740
|
+
* size: 50,
|
|
2913
2741
|
* })
|
|
2914
2742
|
*
|
|
2915
|
-
* //
|
|
2916
|
-
*
|
|
2743
|
+
* // Parent component
|
|
2744
|
+
* providePaginationContext()
|
|
2917
2745
|
*
|
|
2918
|
-
* //
|
|
2919
|
-
* const
|
|
2920
|
-
*
|
|
2746
|
+
* // Child component
|
|
2747
|
+
* const pagination = usePagination()
|
|
2748
|
+
* pagination.next()
|
|
2921
2749
|
* ```
|
|
2922
2750
|
*/
|
|
2923
|
-
function
|
|
2924
|
-
const { namespace = "v0:
|
|
2925
|
-
const [
|
|
2926
|
-
const context =
|
|
2927
|
-
function
|
|
2928
|
-
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);
|
|
2929
2757
|
}
|
|
2930
|
-
return createTrinity(
|
|
2758
|
+
return createTrinity(usePaginationContext, providePaginationContext, context);
|
|
2931
2759
|
}
|
|
2932
2760
|
/**
|
|
2933
|
-
*
|
|
2761
|
+
* Returns the current pagination instance from context.
|
|
2934
2762
|
*
|
|
2935
|
-
* @param
|
|
2936
|
-
* @
|
|
2937
|
-
* @template E The type of the locale context.
|
|
2938
|
-
* @template R The type of the token ticket.
|
|
2939
|
-
* @template O The type of the token context.
|
|
2940
|
-
* @returns A new locale plugin.
|
|
2763
|
+
* @param namespace The namespace. @default 'v0:pagination'
|
|
2764
|
+
* @returns The pagination context.
|
|
2941
2765
|
*
|
|
2942
|
-
* @
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
const [, provideLocaleContext, context] = createLocaleContext({
|
|
2947
|
-
...options,
|
|
2948
|
-
namespace,
|
|
2949
|
-
adapter,
|
|
2950
|
-
messages
|
|
2951
|
-
});
|
|
2952
|
-
return createPlugin({
|
|
2953
|
-
namespace,
|
|
2954
|
-
provide: (app) => {
|
|
2955
|
-
provideLocaleContext(context, app);
|
|
2956
|
-
}
|
|
2957
|
-
});
|
|
2958
|
-
}
|
|
2959
|
-
/**
|
|
2960
|
-
* Returns the current locale instance.
|
|
2766
|
+
* @example
|
|
2767
|
+
* ```vue
|
|
2768
|
+
* <script setup lang="ts">
|
|
2769
|
+
* import { usePagination } from '@vuetify/v0'
|
|
2961
2770
|
*
|
|
2962
|
-
*
|
|
2771
|
+
* const pagination = usePagination()
|
|
2772
|
+
* <\/script>
|
|
2963
2773
|
*
|
|
2964
|
-
*
|
|
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
|
+
* ```
|
|
2965
2779
|
*/
|
|
2966
|
-
function
|
|
2967
|
-
|
|
2968
|
-
if (!getCurrentInstance()) return fallback;
|
|
2969
|
-
try {
|
|
2970
|
-
return useContext(namespace, fallback);
|
|
2971
|
-
} catch {
|
|
2972
|
-
return fallback;
|
|
2973
|
-
}
|
|
2780
|
+
function usePagination(namespace = "v0:pagination") {
|
|
2781
|
+
return useContext(namespace);
|
|
2974
2782
|
}
|
|
2975
2783
|
|
|
2976
2784
|
//#endregion
|
|
2977
2785
|
//#region src/composables/useStep/index.ts
|
|
2978
2786
|
/**
|
|
2979
|
-
* @module useStep
|
|
2980
|
-
*
|
|
2981
|
-
* @remarks
|
|
2982
|
-
* Navigation composable that extends useSingle with first/last/next/prev/step methods.
|
|
2983
|
-
*
|
|
2984
|
-
* Key features:
|
|
2985
|
-
* - Configurable circular or bounded navigation
|
|
2986
|
-
* - Automatic disabled item skipping
|
|
2987
|
-
* - Arbitrary step counts (positive/negative)
|
|
2988
|
-
* - Perfect for wizards, carousels, pagination, onboarding flows
|
|
2989
|
-
*
|
|
2990
|
-
* Inheritance chain: useRegistry → useSelection → useSingle → useStep
|
|
2991
|
-
*/
|
|
2992
|
-
/**
|
|
2993
2787
|
* Creates a new step instance with navigation through items.
|
|
2994
2788
|
*
|
|
2995
2789
|
* Extends `createSingle` with `first()`, `last()`, `next()`, `prev()`, and `step(count)` methods
|
|
@@ -3171,4 +2965,4 @@ function useStep(namespace = "v0:step") {
|
|
|
3171
2965
|
}
|
|
3172
2966
|
|
|
3173
2967
|
//#endregion
|
|
3174
|
-
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 };
|