@vuecs/navigation 3.0.2 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/item/module.d.ts +115 -2
- package/dist/components/item/module.d.ts.map +1 -1
- package/dist/components/items/module.d.ts +234 -19
- package/dist/components/items/module.d.ts.map +1 -1
- package/dist/components/items/theme.d.ts.map +1 -1
- package/dist/components/select-context.d.ts +30 -0
- package/dist/components/select-context.d.ts.map +1 -0
- package/dist/components/stepper/Stepper.vue.d.ts +1 -1
- package/dist/components/stepper/StepperDescription.vue.d.ts +1 -1
- package/dist/components/stepper/StepperIndicator.vue.d.ts +1 -1
- package/dist/components/stepper/StepperSeparator.vue.d.ts +1 -1
- package/dist/components/stepper/StepperTitle.vue.d.ts +1 -1
- package/dist/components/stepper/StepperTrigger.vue.d.ts +1 -1
- package/dist/components/type.d.ts +12 -5
- package/dist/components/type.d.ts.map +1 -1
- package/dist/helpers/component/types.d.ts +6 -0
- package/dist/helpers/component/types.d.ts.map +1 -1
- package/dist/helpers/index.d.ts +2 -1
- package/dist/helpers/index.d.ts.map +1 -1
- package/dist/helpers/normalize.d.ts +2 -6
- package/dist/helpers/normalize.d.ts.map +1 -1
- package/dist/helpers/reset.d.ts.map +1 -1
- package/dist/helpers/submenu.d.ts +9 -0
- package/dist/helpers/submenu.d.ts.map +1 -0
- package/dist/helpers/trail.d.ts +12 -0
- package/dist/helpers/trail.d.ts.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +521 -272
- package/dist/index.mjs.map +1 -1
- package/dist/registry/index.d.ts.map +1 -0
- package/dist/registry/module.d.ts +42 -0
- package/dist/registry/module.d.ts.map +1 -0
- package/dist/registry/singleton.d.ts +6 -0
- package/dist/registry/singleton.d.ts.map +1 -0
- package/dist/registry/types.d.ts +22 -0
- package/dist/registry/types.d.ts.map +1 -0
- package/dist/style.css +83 -0
- package/dist/types.d.ts +30 -15
- package/dist/types.d.ts.map +1 -1
- package/package.json +6 -2
- package/dist/helpers/level.d.ts +0 -11
- package/dist/helpers/level.d.ts.map +0 -1
- package/dist/manager/index.d.ts.map +0 -1
- package/dist/manager/module.d.ts +0 -23
- package/dist/manager/module.d.ts.map +0 -1
- package/dist/manager/singleton.d.ts +0 -5
- package/dist/manager/singleton.d.ts.map +0 -1
- package/dist/manager/types.d.ts +0 -8
- package/dist/manager/types.d.ts.map +0 -1
- /package/dist/{manager → registry}/index.d.ts +0 -0
package/dist/index.mjs
CHANGED
|
@@ -1,8 +1,87 @@
|
|
|
1
|
-
import { hasNormalizedSlot, inject, installDefaultsManager, installThemeManager, normalizeSlot, provide, useArrowNavigation, useComponentTheme } from "@vuecs/core";
|
|
2
|
-
import {
|
|
1
|
+
import { hasNormalizedSlot, inject, installDefaultsManager, installThemeManager, isPromise, normalizeSlot, provide, useArrowNavigation, useComponentTheme } from "@vuecs/core";
|
|
2
|
+
import { computed, defineComponent, getCurrentInstance, h, inject as inject$1, mergeProps, onMounted, onUnmounted, provide as provide$1, ref, resolveComponent, shallowReactive, toRef, watch, watchEffect } from "vue";
|
|
3
3
|
import { VCLink } from "@vuecs/link";
|
|
4
|
-
import {
|
|
5
|
-
|
|
4
|
+
import { CollapsibleContent, CollapsibleRoot, CollapsibleTrigger, NavigationMenuContent, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuRoot, NavigationMenuTrigger, StepperDescription, StepperIndicator, StepperItem, StepperRoot, StepperSeparator, StepperTitle, StepperTrigger } from "reka-ui";
|
|
5
|
+
//#region src/registry/module.ts
|
|
6
|
+
function createEmptyEntry() {
|
|
7
|
+
return {
|
|
8
|
+
items: ref([]),
|
|
9
|
+
active: computed(() => []),
|
|
10
|
+
activeTrail: computed(() => [])
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Reactive, app-wide navigation registry. `<VCNavItems registry>`
|
|
15
|
+
* publishes its resolved output here under a `registry-id`; other navs
|
|
16
|
+
* read it reactively + empty-safe via the resolver context's
|
|
17
|
+
* `registry(id)`.
|
|
18
|
+
*
|
|
19
|
+
* The backing map is `shallowReactive`, so membership changes
|
|
20
|
+
* (register + the returned unregister closure) are tracked dependencies
|
|
21
|
+
* — a consumer reading `get(id)` inside a `computed` / `watchEffect`
|
|
22
|
+
* re-runs when the id's occupancy flips.
|
|
23
|
+
*/
|
|
24
|
+
var NavigationRegistry = class {
|
|
25
|
+
map = shallowReactive(/* @__PURE__ */ new Map());
|
|
26
|
+
/**
|
|
27
|
+
* Stable empty entries handed out for absent ids, memoized per id so
|
|
28
|
+
* the SAME reactive handle is returned every call — a consumer
|
|
29
|
+
* subscribed to an absent id keeps its dependency and lights up the
|
|
30
|
+
* moment an occupant registers.
|
|
31
|
+
*/
|
|
32
|
+
empties = /* @__PURE__ */ new Map();
|
|
33
|
+
/**
|
|
34
|
+
* Claim `id`. Last-wins: a newer occupant replaces the current one
|
|
35
|
+
* (dev warning on collision). Returns a token-guarded unregister
|
|
36
|
+
* closure: it releases `id` ONLY if this registration is still the
|
|
37
|
+
* occupant. During a route handoff (Vue mounts the new page before
|
|
38
|
+
* unmounting the old) the departing nav's closure holds a stale token
|
|
39
|
+
* and cannot evict the incoming occupant.
|
|
40
|
+
*/
|
|
41
|
+
register(id, entry) {
|
|
42
|
+
if (this.map.has(id)) console.warn(`[vuecs] navigation registry id "${id}" reassigned to a new occupant.`);
|
|
43
|
+
const token = Symbol("vc-nav-registry-token");
|
|
44
|
+
this.map.set(id, {
|
|
45
|
+
token,
|
|
46
|
+
entry
|
|
47
|
+
});
|
|
48
|
+
return () => {
|
|
49
|
+
const occupant = this.map.get(id);
|
|
50
|
+
if (occupant && occupant.token === token) this.map.delete(id);
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
/** Reactive, empty-safe read. Never returns `undefined`. */
|
|
54
|
+
get(id) {
|
|
55
|
+
const occupant = this.map.get(id);
|
|
56
|
+
if (occupant) return occupant.entry;
|
|
57
|
+
let empty = this.empties.get(id);
|
|
58
|
+
if (!empty) {
|
|
59
|
+
empty = createEmptyEntry();
|
|
60
|
+
this.empties.set(id, empty);
|
|
61
|
+
}
|
|
62
|
+
return empty;
|
|
63
|
+
}
|
|
64
|
+
/** True when an occupant currently holds `id`. */
|
|
65
|
+
has(id) {
|
|
66
|
+
return this.map.has(id);
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
//#endregion
|
|
70
|
+
//#region src/registry/singleton.ts
|
|
71
|
+
const sym = Symbol.for("VCNavigationRegistry");
|
|
72
|
+
function tryInjectNavigationRegistry(app) {
|
|
73
|
+
return inject(sym, app);
|
|
74
|
+
}
|
|
75
|
+
function injectNavigationRegistry(app) {
|
|
76
|
+
const instance = tryInjectNavigationRegistry(app);
|
|
77
|
+
if (!instance) throw new Error("A navigation registry has not been provided.");
|
|
78
|
+
return instance;
|
|
79
|
+
}
|
|
80
|
+
function provideNavigationRegistry(registry = new NavigationRegistry(), app) {
|
|
81
|
+
provide(sym, registry, app);
|
|
82
|
+
return registry;
|
|
83
|
+
}
|
|
84
|
+
//#endregion
|
|
6
85
|
//#region src/helpers/match.ts
|
|
7
86
|
function calculateItemScoreForPath(item, currentPath) {
|
|
8
87
|
if (item.url === "/") return 1;
|
|
@@ -41,23 +120,22 @@ function findBestItemMatches(items, options = {}) {
|
|
|
41
120
|
}
|
|
42
121
|
//#endregion
|
|
43
122
|
//#region src/helpers/normalize.ts
|
|
44
|
-
function normalizeItemIF(item,
|
|
123
|
+
function normalizeItemIF(item, trace) {
|
|
45
124
|
const output = {
|
|
46
125
|
...item,
|
|
47
|
-
level: defaults.level,
|
|
48
126
|
children: [],
|
|
49
127
|
trace: [...trace, item.name],
|
|
50
128
|
meta: item.meta || {}
|
|
51
129
|
};
|
|
52
130
|
if (!item.children) return output;
|
|
53
|
-
for (let i = 0; i < item.children.length; i++) output.children.push(normalizeItemIF(item.children[i],
|
|
131
|
+
for (let i = 0; i < item.children.length; i++) output.children.push(normalizeItemIF(item.children[i], output.trace));
|
|
54
132
|
return output;
|
|
55
133
|
}
|
|
56
|
-
function normalizeItem(item
|
|
57
|
-
return normalizeItemIF(item,
|
|
134
|
+
function normalizeItem(item) {
|
|
135
|
+
return normalizeItemIF(item, []);
|
|
58
136
|
}
|
|
59
|
-
function normalizeItems(items
|
|
60
|
-
return items.map((item) => normalizeItem(item
|
|
137
|
+
function normalizeItems(items) {
|
|
138
|
+
return items.map((item) => normalizeItem(item));
|
|
61
139
|
}
|
|
62
140
|
//#endregion
|
|
63
141
|
//#region src/helpers/trace.ts
|
|
@@ -77,8 +155,14 @@ function resetItemsByTraceIF(items, trace) {
|
|
|
77
155
|
const isEqual = isTraceEqual(item.trace, trace);
|
|
78
156
|
item.active = isEqual;
|
|
79
157
|
item.display = true;
|
|
80
|
-
if (isEqual)
|
|
81
|
-
|
|
158
|
+
if (isEqual) {
|
|
159
|
+
item.activeWithin = false;
|
|
160
|
+
item.displayChildren = true;
|
|
161
|
+
} else {
|
|
162
|
+
const isAncestor = isTracePartOf(item.trace, trace);
|
|
163
|
+
item.activeWithin = isAncestor;
|
|
164
|
+
item.displayChildren = isAncestor;
|
|
165
|
+
}
|
|
82
166
|
item.children = resetItemsByTraceIF(item.children, trace);
|
|
83
167
|
}
|
|
84
168
|
return items;
|
|
@@ -87,27 +171,45 @@ function resetItemsByTrace(items, trace) {
|
|
|
87
171
|
return resetItemsByTraceIF(items, trace);
|
|
88
172
|
}
|
|
89
173
|
//#endregion
|
|
90
|
-
//#region src/helpers/
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
return
|
|
174
|
+
//#region src/helpers/submenu.ts
|
|
175
|
+
/**
|
|
176
|
+
* Resolve the effective submenu presentation. An explicit `collapse` /
|
|
177
|
+
* `dropdown` wins; `auto` derives from orientation — only an explicit
|
|
178
|
+
* `horizontal` opts into the dropdown (NavigationMenu) path, everything
|
|
179
|
+
* else collapses (Collapsible).
|
|
180
|
+
*/
|
|
181
|
+
function resolveSubmenuMode(submenu, orientation) {
|
|
182
|
+
if (submenu === "collapse" || submenu === "dropdown") return submenu;
|
|
183
|
+
return orientation === "horizontal" ? "dropdown" : "collapse";
|
|
100
184
|
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
185
|
+
//#endregion
|
|
186
|
+
//#region src/helpers/trail.ts
|
|
187
|
+
/**
|
|
188
|
+
* Walk a normalized tree along `trace` (an ordered list of item names,
|
|
189
|
+
* root → leaf) and collect the item at each depth. Returns the ordered
|
|
190
|
+
* active trail: `[0]` is the top-level section, `.at(-1)` is the leaf.
|
|
191
|
+
*/
|
|
192
|
+
function collectTrail(items, trace) {
|
|
193
|
+
const output = [];
|
|
194
|
+
let level = items;
|
|
195
|
+
for (const name of trace) {
|
|
196
|
+
const found = level.find((item) => item.name === name);
|
|
197
|
+
if (!found) break;
|
|
198
|
+
output.push(found);
|
|
199
|
+
level = found.children;
|
|
106
200
|
}
|
|
107
201
|
return output;
|
|
108
202
|
}
|
|
109
|
-
|
|
110
|
-
|
|
203
|
+
/**
|
|
204
|
+
* Depth-first collect of every item in the tree matching `predicate`.
|
|
205
|
+
*/
|
|
206
|
+
function flattenWhere(items, predicate) {
|
|
207
|
+
const output = [];
|
|
208
|
+
for (const item of items) {
|
|
209
|
+
if (predicate(item)) output.push(item);
|
|
210
|
+
if (item.children.length > 0) output.push(...flattenWhere(item.children, predicate));
|
|
211
|
+
}
|
|
212
|
+
return output;
|
|
111
213
|
}
|
|
112
214
|
//#endregion
|
|
113
215
|
//#region src/helpers/url.ts
|
|
@@ -115,119 +217,6 @@ function isAbsoluteURL(str) {
|
|
|
115
217
|
return str.substring(0, 7) === "http://" || str.substring(0, 8) === "https://";
|
|
116
218
|
}
|
|
117
219
|
//#endregion
|
|
118
|
-
//#region src/manager/module.ts
|
|
119
|
-
var NavigationManager = class extends EventEmitter {
|
|
120
|
-
itemsActive;
|
|
121
|
-
items;
|
|
122
|
-
itemsFn;
|
|
123
|
-
built;
|
|
124
|
-
building;
|
|
125
|
-
constructor(options) {
|
|
126
|
-
super();
|
|
127
|
-
let itemsFn;
|
|
128
|
-
if (typeof options.items === "function") itemsFn = options.items;
|
|
129
|
-
else itemsFn = async ({ level }) => {
|
|
130
|
-
if (level > 0) return [];
|
|
131
|
-
return options.items;
|
|
132
|
-
};
|
|
133
|
-
this.itemsFn = itemsFn;
|
|
134
|
-
this.items = [];
|
|
135
|
-
this.itemsActive = [];
|
|
136
|
-
this.built = false;
|
|
137
|
-
this.building = false;
|
|
138
|
-
}
|
|
139
|
-
getItems(tier) {
|
|
140
|
-
if (typeof tier === "undefined") return this.items;
|
|
141
|
-
return this.items.filter((item) => item.level === tier);
|
|
142
|
-
}
|
|
143
|
-
reset() {
|
|
144
|
-
this.built = false;
|
|
145
|
-
this.items = [];
|
|
146
|
-
this.itemsActive = [];
|
|
147
|
-
}
|
|
148
|
-
async build(options) {
|
|
149
|
-
if (this.built || this.building) return;
|
|
150
|
-
this.building = true;
|
|
151
|
-
this.emit("building");
|
|
152
|
-
let parent;
|
|
153
|
-
let level = 0;
|
|
154
|
-
while (true) {
|
|
155
|
-
const raw = await this.itemsFn({
|
|
156
|
-
level,
|
|
157
|
-
parent
|
|
158
|
-
});
|
|
159
|
-
if (!raw || raw.length === 0) break;
|
|
160
|
-
const [match] = findBestItemMatches(normalizeItems(raw, { level }), { path: options.path });
|
|
161
|
-
if (!match) break;
|
|
162
|
-
this.itemsActive.push(match);
|
|
163
|
-
await this.buildLevel(level);
|
|
164
|
-
parent = match;
|
|
165
|
-
level++;
|
|
166
|
-
}
|
|
167
|
-
this.building = false;
|
|
168
|
-
this.built = true;
|
|
169
|
-
this.emit("built");
|
|
170
|
-
this.emit("updated", this.items);
|
|
171
|
-
}
|
|
172
|
-
async select(level, itemNew) {
|
|
173
|
-
const itemOld = findItemWithLevel(level, this.itemsActive);
|
|
174
|
-
if (itemOld && isTraceEqual(itemOld.trace, itemNew.trace)) return;
|
|
175
|
-
this.itemsActive = this.itemsActive.filter((el) => el.level < level);
|
|
176
|
-
this.itemsActive.push(itemNew);
|
|
177
|
-
const startLevel = level;
|
|
178
|
-
while (true) {
|
|
179
|
-
if (!await this.buildLevel(level, startLevel === level)) break;
|
|
180
|
-
level++;
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
async toggle(level, item) {
|
|
184
|
-
let isMatch;
|
|
185
|
-
if (item.displayChildren) isMatch = true;
|
|
186
|
-
else {
|
|
187
|
-
const itemOld = findItemWithLevel(level, this.itemsActive);
|
|
188
|
-
isMatch = !!itemOld && isTraceEqual(item.trace, itemOld.trace);
|
|
189
|
-
}
|
|
190
|
-
if (isMatch) this.itemsActive = removeItemsWithLevel(level, this.itemsActive);
|
|
191
|
-
else this.itemsActive = replaceLevelItem(level, this.itemsActive, item);
|
|
192
|
-
await this.buildLevel(level, true);
|
|
193
|
-
}
|
|
194
|
-
async buildLevel(level, useCache) {
|
|
195
|
-
let items;
|
|
196
|
-
if (useCache) items = findItemsWithLevel(this.items, level);
|
|
197
|
-
else {
|
|
198
|
-
const parent = findItemWithLevel(level - 1, this.itemsActive);
|
|
199
|
-
const raw = await this.itemsFn({
|
|
200
|
-
level,
|
|
201
|
-
parent
|
|
202
|
-
});
|
|
203
|
-
items = raw && raw.length > 0 ? normalizeItems(raw, { level }) : [];
|
|
204
|
-
}
|
|
205
|
-
if (!items || items.length === 0) {
|
|
206
|
-
this.items = this.items.filter((item) => item.level < level);
|
|
207
|
-
this.emit("levelUpdated", level, []);
|
|
208
|
-
return false;
|
|
209
|
-
}
|
|
210
|
-
let trace = [];
|
|
211
|
-
const item = findItemWithLevel(level, this.itemsActive);
|
|
212
|
-
if (item) trace = item.trace;
|
|
213
|
-
resetItemsByTrace(items, trace);
|
|
214
|
-
this.items = replaceLevelItems(level, this.items, items);
|
|
215
|
-
this.emit("levelUpdated", level, items);
|
|
216
|
-
return true;
|
|
217
|
-
}
|
|
218
|
-
};
|
|
219
|
-
//#endregion
|
|
220
|
-
//#region src/manager/singleton.ts
|
|
221
|
-
const sym = Symbol.for("VCNavigationManager");
|
|
222
|
-
function injectNavigationManager(app) {
|
|
223
|
-
const instance = inject(sym, app);
|
|
224
|
-
if (!instance) throw new Error("A navigation provider has not been provided.");
|
|
225
|
-
return instance;
|
|
226
|
-
}
|
|
227
|
-
function provideNavigationManager(manager, app) {
|
|
228
|
-
provide(sym, manager, app);
|
|
229
|
-
}
|
|
230
|
-
//#endregion
|
|
231
220
|
//#region src/components/items/theme.ts
|
|
232
221
|
/**
|
|
233
222
|
* Default classes for the `navigation` theme entry. Shared between
|
|
@@ -235,16 +224,55 @@ function provideNavigationManager(manager, app) {
|
|
|
235
224
|
* component) — both call `useComponentTheme('navigation', …)` with
|
|
236
225
|
* the same slot defaults, so the source of truth lives here.
|
|
237
226
|
*/
|
|
238
|
-
const navigationThemeDefaults = {
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
227
|
+
const navigationThemeDefaults = {
|
|
228
|
+
classes: {
|
|
229
|
+
group: "vc-nav-items",
|
|
230
|
+
item: "vc-nav-item",
|
|
231
|
+
itemNested: "vc-nav-item-nested",
|
|
232
|
+
separator: "vc-nav-separator",
|
|
233
|
+
link: "vc-nav-link",
|
|
234
|
+
linkRoot: "vc-nav-link-root",
|
|
235
|
+
linkIcon: "vc-nav-link-icon",
|
|
236
|
+
linkText: "vc-nav-link-text",
|
|
237
|
+
trigger: "vc-nav-trigger",
|
|
238
|
+
content: "vc-nav-content",
|
|
239
|
+
viewport: "vc-nav-viewport"
|
|
240
|
+
},
|
|
241
|
+
variants: {
|
|
242
|
+
variant: {
|
|
243
|
+
list: {},
|
|
244
|
+
pills: {
|
|
245
|
+
group: "vc-nav-items--pills",
|
|
246
|
+
item: "vc-nav-item--pills",
|
|
247
|
+
link: "vc-nav-link--pills"
|
|
248
|
+
}
|
|
249
|
+
},
|
|
250
|
+
orientation: {
|
|
251
|
+
horizontal: {},
|
|
252
|
+
vertical: { group: "vc-nav-items--vertical" }
|
|
253
|
+
}
|
|
254
|
+
},
|
|
255
|
+
defaultVariants: {
|
|
256
|
+
variant: "list",
|
|
257
|
+
orientation: "horizontal"
|
|
258
|
+
}
|
|
259
|
+
};
|
|
260
|
+
//#endregion
|
|
261
|
+
//#region src/components/select-context.ts
|
|
262
|
+
/**
|
|
263
|
+
* Channels a `<VCNavItem>`'s already-normalized + scored `children` down
|
|
264
|
+
* to the nested `<VCNavItems>` that renders its submenu.
|
|
265
|
+
*
|
|
266
|
+
* The top-level nav scores the WHOLE tree once; nested lists must render
|
|
267
|
+
* those results as-is rather than re-resolving / re-scoring a subtree
|
|
268
|
+
* (which would clobber traces and lose whole-tree active context). The
|
|
269
|
+
* nested `<VCNavItems>` reads this when it has no own `data` prop —
|
|
270
|
+
* presence of the injected nodes is what marks it as a nested renderer
|
|
271
|
+
* rather than a resolving root. Each `<VCNavItem>` re-provides its own
|
|
272
|
+
* children, so the value is correctly scoped per nesting level.
|
|
273
|
+
*/
|
|
274
|
+
const NAVIGATION_NODES_KEY = Symbol("vc-navigation-nodes");
|
|
275
|
+
const NAVIGATION_SELECT_KEY = Symbol("vc-navigation-select");
|
|
248
276
|
const VCNavItem = defineComponent({
|
|
249
277
|
name: "VCNavItem",
|
|
250
278
|
props: {
|
|
@@ -252,6 +280,42 @@ const VCNavItem = defineComponent({
|
|
|
252
280
|
type: Object,
|
|
253
281
|
required: true
|
|
254
282
|
},
|
|
283
|
+
variant: {
|
|
284
|
+
type: String,
|
|
285
|
+
default: void 0
|
|
286
|
+
},
|
|
287
|
+
orientation: {
|
|
288
|
+
type: String,
|
|
289
|
+
default: void 0
|
|
290
|
+
},
|
|
291
|
+
/**
|
|
292
|
+
* Resolved submenu presentation handed down by the parent
|
|
293
|
+
* `<VCNavItems>`. `collapse` renders groups as an inline
|
|
294
|
+
* Reka `Collapsible`; `dropdown` renders them as Reka
|
|
295
|
+
* `NavigationMenu` flyouts.
|
|
296
|
+
*/
|
|
297
|
+
submenu: {
|
|
298
|
+
type: String,
|
|
299
|
+
default: "collapse"
|
|
300
|
+
},
|
|
301
|
+
/**
|
|
302
|
+
* The tag (or component) this item renders as — its own wrapper
|
|
303
|
+
* (`<li>` by default). Receives `<VCNavItems>`' `itemAs`. Honored in
|
|
304
|
+
* collapse mode only.
|
|
305
|
+
*/
|
|
306
|
+
as: {
|
|
307
|
+
type: [String, Object],
|
|
308
|
+
default: "li"
|
|
309
|
+
},
|
|
310
|
+
/**
|
|
311
|
+
* The list-container tag for this item's nested submenu
|
|
312
|
+
* `<VCNavItems>` (`<ul>` by default). Receives `<VCNavItems>`' `as`.
|
|
313
|
+
* Honored in collapse mode only.
|
|
314
|
+
*/
|
|
315
|
+
itemsAs: {
|
|
316
|
+
type: [String, Object],
|
|
317
|
+
default: "ul"
|
|
318
|
+
},
|
|
255
319
|
themeClass: {
|
|
256
320
|
type: Object,
|
|
257
321
|
default: void 0
|
|
@@ -264,120 +328,229 @@ const VCNavItem = defineComponent({
|
|
|
264
328
|
slots: Object,
|
|
265
329
|
setup(props, { slots }) {
|
|
266
330
|
const itemsNode = resolveComponent("VCNavItems");
|
|
267
|
-
const theme = useComponentTheme("navigation",
|
|
268
|
-
|
|
331
|
+
const theme = useComponentTheme("navigation", {
|
|
332
|
+
get themeClass() {
|
|
333
|
+
return props.themeClass;
|
|
334
|
+
},
|
|
335
|
+
get themeVariant() {
|
|
336
|
+
return {
|
|
337
|
+
...props.themeVariant ?? {},
|
|
338
|
+
...props.variant !== void 0 ? { variant: props.variant } : {}
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
}, navigationThemeDefaults);
|
|
269
342
|
const data = toRef(props, "data");
|
|
270
343
|
const hasChildren = computed(() => data.value.children && data.value.children.length > 0);
|
|
271
|
-
|
|
272
|
-
|
|
344
|
+
provide$1(NAVIGATION_NODES_KEY, computed(() => data.value.children));
|
|
345
|
+
const open = ref(!!data.value.displayChildren);
|
|
346
|
+
watch(() => data.value.displayChildren, (value) => {
|
|
347
|
+
open.value = !!value;
|
|
348
|
+
});
|
|
349
|
+
const selectContext = inject$1(NAVIGATION_SELECT_KEY, null);
|
|
350
|
+
const select = () => {
|
|
351
|
+
selectContext?.select(data.value);
|
|
352
|
+
};
|
|
353
|
+
const toggle = () => {
|
|
354
|
+
open.value = !open.value;
|
|
273
355
|
};
|
|
274
356
|
const renderIcon = (icon) => {
|
|
275
357
|
if (icon.includes(":")) return h(resolveComponent("VCIcon"), { name: icon });
|
|
276
358
|
return h("i", { class: icon });
|
|
277
359
|
};
|
|
278
|
-
const
|
|
279
|
-
|
|
360
|
+
const renderTitleInner = (resolved) => [...data.value.icon ? [h("div", { class: resolved.linkIcon || void 0 }, [renderIcon(data.value.icon)])] : [], h("div", { class: resolved.linkText || void 0 }, [data.value.name])];
|
|
361
|
+
const renderLeaf = (resolved) => {
|
|
362
|
+
if (hasNormalizedSlot("link", slots)) return normalizeSlot("link", {
|
|
363
|
+
data: data.value,
|
|
364
|
+
select,
|
|
365
|
+
isActive: data.value.active
|
|
366
|
+
}, slots);
|
|
367
|
+
const linkProps = {
|
|
368
|
+
active: data.value.active,
|
|
369
|
+
disabled: false,
|
|
370
|
+
prefetch: true
|
|
371
|
+
};
|
|
372
|
+
if (data.value.url) if (isAbsoluteURL(data.value.url) || data.value.url.startsWith("#")) {
|
|
373
|
+
linkProps.href = data.value.url;
|
|
374
|
+
if (data.value.urlTarget) linkProps.target = data.value.urlTarget;
|
|
375
|
+
} else linkProps.to = data.value.url;
|
|
376
|
+
return h(VCLink, {
|
|
377
|
+
class: [resolved.link],
|
|
378
|
+
"data-vc-collection-item": "",
|
|
379
|
+
...linkProps,
|
|
380
|
+
onClicked: select
|
|
381
|
+
}, { default: () => renderTitleInner(resolved) });
|
|
382
|
+
};
|
|
383
|
+
const renderChildren = () => {
|
|
384
|
+
if (hasNormalizedSlot("sub-items", slots)) return normalizeSlot("sub-items", {
|
|
385
|
+
data: data.value,
|
|
386
|
+
select,
|
|
387
|
+
toggle
|
|
388
|
+
});
|
|
389
|
+
return h(itemsNode, {
|
|
390
|
+
variant: props.variant,
|
|
391
|
+
orientation: props.orientation,
|
|
392
|
+
submenu: props.submenu === "dropdown" ? "collapse" : props.submenu,
|
|
393
|
+
as: props.itemsAs,
|
|
394
|
+
itemAs: props.as,
|
|
395
|
+
themeClass: props.themeClass,
|
|
396
|
+
themeVariant: props.themeVariant
|
|
397
|
+
});
|
|
280
398
|
};
|
|
281
399
|
return () => {
|
|
282
400
|
const resolved = theme.value;
|
|
283
|
-
const
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
...linkProps,
|
|
307
|
-
onClicked() {
|
|
308
|
-
if (!data.value.url) return select.call(null, data.value);
|
|
309
|
-
},
|
|
310
|
-
onClick() {
|
|
311
|
-
return select.call(null, data.value);
|
|
312
|
-
}
|
|
313
|
-
}, { default: () => [...data.value.icon ? [h("div", { class: resolved.linkIcon || void 0 }, [renderIcon(data.value.icon)])] : [], h("div", { class: resolved.linkText || void 0 }, [data.value.name])] });
|
|
314
|
-
}
|
|
315
|
-
if (hasNormalizedSlot("sub", slots)) return normalizeSlot("sub", {
|
|
401
|
+
const isDropdown = props.submenu === "dropdown";
|
|
402
|
+
const isActive = data.value.active || data.value.activeWithin;
|
|
403
|
+
if (data.value.type === "separator") {
|
|
404
|
+
const body = hasNormalizedSlot("separator", slots) ? normalizeSlot("separator", { data: data.value }, slots) : h("div", { class: resolved.separator || void 0 }, data.value.name);
|
|
405
|
+
if (isDropdown) return h(NavigationMenuItem, { class: [resolved.item] }, { default: () => body });
|
|
406
|
+
return h(props.as, { class: [resolved.item] }, [body]);
|
|
407
|
+
}
|
|
408
|
+
if (!hasChildren.value) {
|
|
409
|
+
const leaf = renderLeaf(resolved);
|
|
410
|
+
if (isDropdown) return h(NavigationMenuItem, {
|
|
411
|
+
class: [resolved.item],
|
|
412
|
+
"data-active": data.value.active ? "" : void 0
|
|
413
|
+
}, { default: () => h(NavigationMenuLink, {
|
|
414
|
+
active: data.value.active,
|
|
415
|
+
asChild: true
|
|
416
|
+
}, { default: () => leaf }) });
|
|
417
|
+
return h(props.as, {
|
|
418
|
+
class: [resolved.item, { active: data.value.active }],
|
|
419
|
+
"data-active": data.value.active ? "" : void 0
|
|
420
|
+
}, [leaf]);
|
|
421
|
+
}
|
|
422
|
+
if (hasNormalizedSlot("sub", slots)) {
|
|
423
|
+
const body = normalizeSlot("sub", {
|
|
316
424
|
data: data.value,
|
|
317
425
|
select,
|
|
318
426
|
toggle
|
|
319
427
|
}, slots);
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
data:
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
"data-active":
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
data: data.value,
|
|
349
|
-
select,
|
|
350
|
-
toggle
|
|
351
|
-
});
|
|
352
|
-
else vNodes = h(itemsNode, {
|
|
353
|
-
level: data.value.level,
|
|
354
|
-
data: data.value.children
|
|
355
|
-
});
|
|
356
|
-
return [title, vNodes];
|
|
357
|
-
};
|
|
358
|
-
return h("li", {
|
|
428
|
+
if (isDropdown) return h(NavigationMenuItem, {
|
|
429
|
+
class: [resolved.item, resolved.itemNested],
|
|
430
|
+
"data-active": isActive ? "" : void 0
|
|
431
|
+
}, { default: () => body });
|
|
432
|
+
return h(props.as, {
|
|
433
|
+
class: [
|
|
434
|
+
resolved.item,
|
|
435
|
+
resolved.itemNested,
|
|
436
|
+
{ active: isActive }
|
|
437
|
+
],
|
|
438
|
+
"data-active": isActive ? "" : void 0
|
|
439
|
+
}, [body]);
|
|
440
|
+
}
|
|
441
|
+
const title = hasNormalizedSlot("sub-title", slots) ? normalizeSlot("sub-title", {
|
|
442
|
+
data: data.value,
|
|
443
|
+
select,
|
|
444
|
+
toggle
|
|
445
|
+
}) : renderTitleInner(resolved);
|
|
446
|
+
if (isDropdown) return h(NavigationMenuItem, {
|
|
447
|
+
class: [resolved.item, resolved.itemNested],
|
|
448
|
+
"data-active": isActive ? "" : void 0
|
|
449
|
+
}, { default: () => [h(NavigationMenuTrigger, {
|
|
450
|
+
class: resolved.trigger || void 0,
|
|
451
|
+
"data-vc-collection-item": "",
|
|
452
|
+
"data-active": isActive ? "" : void 0
|
|
453
|
+
}, { default: () => title }), h(NavigationMenuContent, { class: resolved.content || void 0 }, { default: () => renderChildren() })] });
|
|
454
|
+
return h(CollapsibleRoot, {
|
|
455
|
+
as: props.as,
|
|
359
456
|
class: [
|
|
360
457
|
resolved.item,
|
|
361
|
-
|
|
362
|
-
{ active: data.value.active ||
|
|
458
|
+
resolved.itemNested,
|
|
459
|
+
{ active: data.value.active || open.value }
|
|
363
460
|
],
|
|
364
|
-
"data-active":
|
|
365
|
-
|
|
366
|
-
|
|
461
|
+
"data-active": isActive ? "" : void 0,
|
|
462
|
+
open: open.value,
|
|
463
|
+
"onUpdate:open": (value) => {
|
|
464
|
+
open.value = value;
|
|
465
|
+
}
|
|
466
|
+
}, { default: () => [h(CollapsibleTrigger, {
|
|
467
|
+
class: resolved.trigger || void 0,
|
|
468
|
+
"data-vc-collection-item": "",
|
|
469
|
+
"data-active": isActive ? "" : void 0
|
|
470
|
+
}, { default: () => title }), h(CollapsibleContent, { class: resolved.content || void 0 }, { default: () => renderChildren() })] });
|
|
367
471
|
};
|
|
368
472
|
}
|
|
369
473
|
});
|
|
370
474
|
const VCNavItems = defineComponent({
|
|
371
475
|
name: "VCNavItems",
|
|
372
476
|
props: {
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
477
|
+
/**
|
|
478
|
+
* The source of this nav's items. Plain array, sync fn, or async fn.
|
|
479
|
+
* A fn receives a NavigationResolverContext and may read reactive
|
|
480
|
+
* state freely — the nav re-runs it automatically when that state
|
|
481
|
+
* changes.
|
|
482
|
+
*
|
|
483
|
+
* When omitted, the nav checks whether it is a nested submenu of a
|
|
484
|
+
* parent `<VCNavItem>` (via the {@link NAVIGATION_NODES_KEY} inject)
|
|
485
|
+
* and, if so, renders that parent's already-scored children as-is.
|
|
486
|
+
*/
|
|
377
487
|
data: {
|
|
488
|
+
type: [Array, Function],
|
|
489
|
+
default: void 0
|
|
490
|
+
},
|
|
491
|
+
/** Opt in to publishing this nav's resolved output into the registry. */
|
|
492
|
+
registry: {
|
|
493
|
+
type: Boolean,
|
|
494
|
+
default: false
|
|
495
|
+
},
|
|
496
|
+
/** The key under which to publish. Required when `registry` is true. */
|
|
497
|
+
registryId: {
|
|
498
|
+
type: String,
|
|
499
|
+
default: void 0
|
|
500
|
+
},
|
|
501
|
+
/**
|
|
502
|
+
* Current path for active-state matching. When omitted, the nav softly
|
|
503
|
+
* reads vue-router's current route (via the `$route` global property)
|
|
504
|
+
* if a router is installed; router-free apps simply get `undefined`.
|
|
505
|
+
*/
|
|
506
|
+
path: {
|
|
507
|
+
type: String,
|
|
508
|
+
default: void 0
|
|
509
|
+
},
|
|
510
|
+
/**
|
|
511
|
+
* Extra reactive deps that should retrigger the resolver — for state
|
|
512
|
+
* read only AFTER the first `await` in an async resolver (auto-track
|
|
513
|
+
* can't see past an await).
|
|
514
|
+
*/
|
|
515
|
+
watch: {
|
|
378
516
|
type: Array,
|
|
379
517
|
default: void 0
|
|
380
518
|
},
|
|
519
|
+
variant: {
|
|
520
|
+
type: String,
|
|
521
|
+
default: void 0
|
|
522
|
+
},
|
|
523
|
+
orientation: {
|
|
524
|
+
type: String,
|
|
525
|
+
default: void 0
|
|
526
|
+
},
|
|
527
|
+
/**
|
|
528
|
+
* How items with children render their submenu. `auto` derives from
|
|
529
|
+
* orientation (horizontal → dropdown, otherwise collapse).
|
|
530
|
+
*/
|
|
531
|
+
submenu: {
|
|
532
|
+
type: String,
|
|
533
|
+
default: "auto"
|
|
534
|
+
},
|
|
535
|
+
/**
|
|
536
|
+
* The tag (or component) for this nav's list container. Defaults to
|
|
537
|
+
* `'ul'`. Forwarded unchanged to every nesting level so the whole tree
|
|
538
|
+
* renders the same container tag. Honored in collapse mode only —
|
|
539
|
+
* dropdown mode keeps Reka's NavigationMenu primitives.
|
|
540
|
+
*/
|
|
541
|
+
as: {
|
|
542
|
+
type: [String, Object],
|
|
543
|
+
default: "ul"
|
|
544
|
+
},
|
|
545
|
+
/**
|
|
546
|
+
* The tag (or component) for each item wrapper. Defaults to `'li'`.
|
|
547
|
+
* Forwarded unchanged to every nesting level. Honored in collapse mode
|
|
548
|
+
* only — dropdown mode keeps Reka's NavigationMenu primitives.
|
|
549
|
+
*/
|
|
550
|
+
itemAs: {
|
|
551
|
+
type: [String, Object],
|
|
552
|
+
default: "li"
|
|
553
|
+
},
|
|
381
554
|
themeClass: {
|
|
382
555
|
type: Object,
|
|
383
556
|
default: void 0
|
|
@@ -388,8 +561,19 @@ const VCNavItems = defineComponent({
|
|
|
388
561
|
}
|
|
389
562
|
},
|
|
390
563
|
slots: Object,
|
|
391
|
-
setup(props, { slots }) {
|
|
392
|
-
const theme = useComponentTheme("navigation",
|
|
564
|
+
setup(props, { slots, expose }) {
|
|
565
|
+
const theme = useComponentTheme("navigation", {
|
|
566
|
+
get themeClass() {
|
|
567
|
+
return props.themeClass;
|
|
568
|
+
},
|
|
569
|
+
get themeVariant() {
|
|
570
|
+
return {
|
|
571
|
+
...props.themeVariant ?? {},
|
|
572
|
+
...props.variant !== void 0 ? { variant: props.variant } : {},
|
|
573
|
+
...props.orientation !== void 0 ? { orientation: props.orientation } : {}
|
|
574
|
+
};
|
|
575
|
+
}
|
|
576
|
+
}, navigationThemeDefaults);
|
|
393
577
|
const rootRef = ref(null);
|
|
394
578
|
const onKeyDown = (event) => {
|
|
395
579
|
useArrowNavigation(event, event.target, rootRef.value, {
|
|
@@ -398,44 +582,109 @@ const VCNavItems = defineComponent({
|
|
|
398
582
|
loop: true
|
|
399
583
|
});
|
|
400
584
|
};
|
|
401
|
-
const
|
|
402
|
-
const
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
onMounted(() => {
|
|
407
|
-
removeListener = manager.on("levelUpdated", (level, items) => {
|
|
408
|
-
if (level !== props.level) return;
|
|
409
|
-
managerItems.value = items;
|
|
410
|
-
counter.value++;
|
|
411
|
-
});
|
|
585
|
+
const registry = tryInjectNavigationRegistry() ?? new NavigationRegistry();
|
|
586
|
+
const globals = getCurrentInstance()?.appContext.config.globalProperties;
|
|
587
|
+
const currentPath = computed(() => {
|
|
588
|
+
if (typeof props.path !== "undefined") return props.path;
|
|
589
|
+
return (globals?.$route)?.path;
|
|
412
590
|
});
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
591
|
+
const injectedNodes = inject$1(NAVIGATION_NODES_KEY, null);
|
|
592
|
+
const isNested = computed(() => typeof props.data === "undefined" && injectedNodes !== null);
|
|
593
|
+
const selectedTrace = ref(null);
|
|
594
|
+
if (!isNested.value) {
|
|
595
|
+
provide$1(NAVIGATION_SELECT_KEY, { select: (item) => {
|
|
596
|
+
selectedTrace.value = item.trace;
|
|
597
|
+
} });
|
|
598
|
+
watch(currentPath, () => {
|
|
599
|
+
selectedTrace.value = null;
|
|
600
|
+
});
|
|
601
|
+
}
|
|
602
|
+
const raw = ref([]);
|
|
603
|
+
let runToken = 0;
|
|
604
|
+
async function run() {
|
|
605
|
+
const token = ++runToken;
|
|
606
|
+
const value = typeof props.data === "function" ? props.data({
|
|
607
|
+
path: currentPath.value,
|
|
608
|
+
registry: (id) => registry.get(id)
|
|
609
|
+
}) : props.data ?? [];
|
|
610
|
+
if (!isPromise(value)) {
|
|
611
|
+
raw.value = value ?? [];
|
|
612
|
+
return;
|
|
417
613
|
}
|
|
614
|
+
try {
|
|
615
|
+
const awaited = await value ?? [];
|
|
616
|
+
if (token === runToken) raw.value = awaited;
|
|
617
|
+
} catch (error) {
|
|
618
|
+
if (token === runToken) console.error("[vuecs] <VCNavItems> resolver rejected:", error);
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
if (!isNested.value) {
|
|
622
|
+
watchEffect(run);
|
|
623
|
+
if (props.watch) watch(props.watch, run);
|
|
624
|
+
}
|
|
625
|
+
expose({ refresh: run });
|
|
626
|
+
const resolved = computed(() => {
|
|
627
|
+
if (isNested.value && injectedNodes) return {
|
|
628
|
+
items: injectedNodes.value,
|
|
629
|
+
trace: []
|
|
630
|
+
};
|
|
631
|
+
const normalized = normalizeItems(raw.value);
|
|
632
|
+
const [match] = findBestItemMatches(normalized, { path: currentPath.value });
|
|
633
|
+
const trace = selectedTrace.value ?? (match ? match.trace : []);
|
|
634
|
+
resetItemsByTrace(normalized, trace);
|
|
635
|
+
return {
|
|
636
|
+
items: normalized,
|
|
637
|
+
trace
|
|
638
|
+
};
|
|
418
639
|
});
|
|
419
|
-
const
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
640
|
+
const tree = computed(() => resolved.value.items);
|
|
641
|
+
const active = computed(() => flattenWhere(tree.value, (item) => !!item.active));
|
|
642
|
+
const activeTrail = computed(() => collectTrail(tree.value, resolved.value.trace));
|
|
643
|
+
if (props.registry) {
|
|
644
|
+
let unsubscribeFn;
|
|
645
|
+
const entry = {
|
|
646
|
+
items: tree,
|
|
647
|
+
active,
|
|
648
|
+
activeTrail
|
|
649
|
+
};
|
|
650
|
+
onMounted(() => {
|
|
651
|
+
if (!props.registryId) {
|
|
652
|
+
console.warn("[vuecs] <VCNavItems registry> requires a `registry-id`.");
|
|
653
|
+
return;
|
|
654
|
+
}
|
|
655
|
+
unsubscribeFn = registry.register(props.registryId, entry);
|
|
656
|
+
});
|
|
657
|
+
onUnmounted(() => {
|
|
658
|
+
if (!props.registryId || !unsubscribeFn) return;
|
|
659
|
+
unsubscribeFn();
|
|
660
|
+
});
|
|
661
|
+
}
|
|
662
|
+
const submenuMode = computed(() => resolveSubmenuMode(props.submenu, props.orientation));
|
|
423
663
|
return () => {
|
|
424
|
-
const
|
|
664
|
+
const resolvedTheme = theme.value;
|
|
425
665
|
const vNodes = [];
|
|
426
|
-
for (let i = 0; i <
|
|
427
|
-
|
|
666
|
+
for (let i = 0; i < tree.value.length; i++) {
|
|
667
|
+
const item = tree.value[i];
|
|
668
|
+
if (!item.display && !item.displayChildren) continue;
|
|
428
669
|
let vNode;
|
|
429
|
-
if (hasNormalizedSlot("item", slots)) vNode = normalizeSlot("item", { data:
|
|
670
|
+
if (hasNormalizedSlot("item", slots)) vNode = normalizeSlot("item", { data: item }, slots);
|
|
430
671
|
else vNode = h(VCNavItem, {
|
|
431
|
-
key:
|
|
432
|
-
data:
|
|
672
|
+
key: item.trace.join("/") || i,
|
|
673
|
+
data: item,
|
|
674
|
+
variant: props.variant,
|
|
675
|
+
orientation: props.orientation,
|
|
676
|
+
submenu: submenuMode.value,
|
|
677
|
+
as: props.itemAs,
|
|
678
|
+
itemsAs: props.as,
|
|
679
|
+
themeClass: props.themeClass,
|
|
680
|
+
themeVariant: props.themeVariant
|
|
433
681
|
});
|
|
434
682
|
vNodes.push(vNode);
|
|
435
683
|
}
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
684
|
+
if (submenuMode.value === "dropdown") return h(NavigationMenuRoot, { orientation: "horizontal" }, { default: () => h(NavigationMenuList, { class: resolvedTheme.group || void 0 }, { default: () => vNodes }) });
|
|
685
|
+
const isRoot = !isNested.value;
|
|
686
|
+
return h(props.as, {
|
|
687
|
+
class: resolvedTheme.group || void 0,
|
|
439
688
|
...isRoot ? {
|
|
440
689
|
ref: rootRef,
|
|
441
690
|
onKeydown: onKeyDown
|
|
@@ -834,7 +1083,7 @@ var StepperSeparator_default = defineComponent({
|
|
|
834
1083
|
//#endregion
|
|
835
1084
|
//#region src/index.ts
|
|
836
1085
|
function install(instance, options = {}) {
|
|
837
|
-
|
|
1086
|
+
provideNavigationRegistry(new NavigationRegistry(), instance);
|
|
838
1087
|
installThemeManager(instance, options);
|
|
839
1088
|
installDefaultsManager(instance, options);
|
|
840
1089
|
Object.entries({
|
|
@@ -853,6 +1102,6 @@ function install(instance, options = {}) {
|
|
|
853
1102
|
}
|
|
854
1103
|
var src_default = { install };
|
|
855
1104
|
//#endregion
|
|
856
|
-
export {
|
|
1105
|
+
export { NAVIGATION_NODES_KEY, NAVIGATION_SELECT_KEY, NavigationRegistry, VCNavItem, VCNavItems, Stepper_default as VCStepper, StepperDescription_default as VCStepperDescription, StepperIndicator_default as VCStepperIndicator, StepperItem_default as VCStepperItem, StepperSeparator_default as VCStepperSeparator, StepperTitle_default as VCStepperTitle, StepperTrigger_default as VCStepperTrigger, src_default as default, injectNavigationRegistry, install, navigationThemeDefaults, provideNavigationRegistry, provideStepperContext, stepperThemeDefaults, tryInjectNavigationRegistry, useStepperContext };
|
|
857
1106
|
|
|
858
1107
|
//# sourceMappingURL=index.mjs.map
|