@vuecs/navigation 1.1.0 → 2.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.
Files changed (100) hide show
  1. package/README.md +54 -142
  2. package/core/index.cjs +1 -1
  3. package/core/index.mjs +1 -1
  4. package/dist/components/index.d.ts +1 -1
  5. package/dist/components/index.d.ts.map +1 -1
  6. package/dist/components/item/index.d.ts +2 -0
  7. package/dist/components/item/index.d.ts.map +1 -0
  8. package/dist/components/item/module.d.ts +16 -0
  9. package/dist/components/item/module.d.ts.map +1 -0
  10. package/dist/components/items/index.d.ts +2 -0
  11. package/dist/components/items/index.d.ts.map +1 -0
  12. package/dist/components/items/module.d.ts +27 -0
  13. package/dist/components/items/module.d.ts.map +1 -0
  14. package/dist/helpers/component/build.d.ts +3 -0
  15. package/dist/helpers/component/build.d.ts.map +1 -0
  16. package/dist/helpers/component/index.d.ts +3 -0
  17. package/dist/helpers/component/index.d.ts.map +1 -0
  18. package/dist/helpers/component/types.d.ts +17 -0
  19. package/dist/helpers/component/types.d.ts.map +1 -0
  20. package/dist/helpers/index.d.ts +8 -0
  21. package/dist/helpers/index.d.ts.map +1 -0
  22. package/dist/helpers/level.d.ts +11 -0
  23. package/dist/helpers/level.d.ts.map +1 -0
  24. package/dist/helpers/match.d.ts +7 -0
  25. package/dist/helpers/match.d.ts.map +1 -0
  26. package/dist/helpers/normalize.d.ts +8 -0
  27. package/dist/helpers/normalize.d.ts.map +1 -0
  28. package/dist/helpers/reset.d.ts +3 -0
  29. package/dist/helpers/reset.d.ts.map +1 -0
  30. package/dist/helpers/trace.d.ts +3 -0
  31. package/dist/helpers/trace.d.ts.map +1 -0
  32. package/dist/helpers/url.d.ts.map +1 -0
  33. package/dist/index.cjs +455 -459
  34. package/dist/index.cjs.map +1 -1
  35. package/dist/index.css +87 -0
  36. package/dist/index.d.ts +4 -6
  37. package/dist/index.d.ts.map +1 -1
  38. package/dist/index.mjs +454 -455
  39. package/dist/index.mjs.map +1 -1
  40. package/dist/manager/index.d.ts +4 -0
  41. package/dist/manager/index.d.ts.map +1 -0
  42. package/dist/manager/module.d.ts +19 -0
  43. package/dist/manager/module.d.ts.map +1 -0
  44. package/dist/manager/singleton.d.ts +5 -0
  45. package/dist/manager/singleton.d.ts.map +1 -0
  46. package/dist/manager/types.d.ts +8 -0
  47. package/dist/manager/types.d.ts.map +1 -0
  48. package/dist/types.d.ts +33 -0
  49. package/dist/types.d.ts.map +1 -0
  50. package/package.json +10 -6
  51. package/dist/components/item.d.ts +0 -26
  52. package/dist/components/item.d.ts.map +0 -1
  53. package/dist/components/items.d.ts +0 -27
  54. package/dist/components/items.d.ts.map +0 -1
  55. package/dist/core/build.d.ts +0 -4
  56. package/dist/core/build.d.ts.map +0 -1
  57. package/dist/core/check.d.ts +0 -3
  58. package/dist/core/check.d.ts.map +0 -1
  59. package/dist/core/expansion.d.ts +0 -6
  60. package/dist/core/expansion.d.ts.map +0 -1
  61. package/dist/core/flatten.d.ts +0 -3
  62. package/dist/core/flatten.d.ts.map +0 -1
  63. package/dist/core/index.d.ts +0 -12
  64. package/dist/core/index.d.ts.map +0 -1
  65. package/dist/core/match.d.ts +0 -3
  66. package/dist/core/match.d.ts.map +0 -1
  67. package/dist/core/reduce.d.ts +0 -8
  68. package/dist/core/reduce.d.ts.map +0 -1
  69. package/dist/core/refresh.d.ts +0 -3
  70. package/dist/core/refresh.d.ts.map +0 -1
  71. package/dist/core/replace.d.ts +0 -6
  72. package/dist/core/replace.d.ts.map +0 -1
  73. package/dist/core/reset.d.ts +0 -3
  74. package/dist/core/reset.d.ts.map +0 -1
  75. package/dist/core/select.d.ts +0 -4
  76. package/dist/core/select.d.ts.map +0 -1
  77. package/dist/core/tier.d.ts +0 -7
  78. package/dist/core/tier.d.ts.map +0 -1
  79. package/dist/core/toggle.d.ts +0 -4
  80. package/dist/core/toggle.d.ts.map +0 -1
  81. package/dist/module.d.ts +0 -3
  82. package/dist/module.d.ts.map +0 -1
  83. package/dist/provider/index.d.ts +0 -3
  84. package/dist/provider/index.d.ts.map +0 -1
  85. package/dist/provider/module.d.ts +0 -5
  86. package/dist/provider/module.d.ts.map +0 -1
  87. package/dist/provider/type.d.ts +0 -8
  88. package/dist/provider/type.d.ts.map +0 -1
  89. package/dist/store/index.d.ts +0 -3
  90. package/dist/store/index.d.ts.map +0 -1
  91. package/dist/store/module.d.ts +0 -7
  92. package/dist/store/module.d.ts.map +0 -1
  93. package/dist/store/type.d.ts +0 -16
  94. package/dist/store/type.d.ts.map +0 -1
  95. package/dist/type.d.ts +0 -27
  96. package/dist/type.d.ts.map +0 -1
  97. package/dist/utils/index.d.ts +0 -2
  98. package/dist/utils/index.d.ts.map +0 -1
  99. package/dist/utils/url.d.ts.map +0 -1
  100. /package/dist/{utils → helpers}/url.d.ts +0 -0
package/dist/index.cjs CHANGED
@@ -3,438 +3,489 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var core = require('@vuecs/core');
6
- var vue = require('vue');
6
+ var eventEmitter = require('@posva/event-emitter');
7
7
  var link = require('@vuecs/link');
8
+ var vue = require('vue');
8
9
 
9
- let instance;
10
- function useNavigationProvider(module) {
11
- if (typeof instance !== 'undefined') {
12
- return instance;
13
- }
14
- if (typeof module === 'undefined') {
15
- throw new Error('A Navigation Provider must be set!');
16
- }
17
- instance = module;
18
- return instance;
19
- }
20
- function setNavigationProvider(module) {
21
- instance = module;
22
- }
23
- function createNavigationProvider(input) {
24
- return input;
10
+ function buildComponentOptions() {
11
+ const manager = core.createComponentOptionsManager({
12
+ name: 'navigation'
13
+ });
14
+ return {
15
+ groupClass: core.mergeOption('class', manager.get('groupClass'), 'vc-nav-items'),
16
+ groupTag: manager.get('groupTag') || 'ul',
17
+ itemClass: core.mergeOption('class', manager.get('itemClass'), 'vc-nav-item'),
18
+ itemTag: manager.get('itemTag') || 'li',
19
+ subGroupTitleClass: core.mergeOption('class', manager.get('subGroupTitleClass'), 'vc-nav-sub-level-title'),
20
+ subGroupItemsClass: core.mergeOption('class', manager.get('subGroupTitleClass'), 'vc-nav-sub-level-items'),
21
+ separatorTag: manager.get('separatorTag') || 'div',
22
+ separatorClass: core.mergeOption('class', manager.get('iconClass'), 'vc-nav-separator'),
23
+ iconClass: core.mergeOption('class', manager.get('iconClass'), 'vc-nav-icon'),
24
+ linkClass: core.mergeOption('class', manager.get('linkClass'), 'vc-nav-link'),
25
+ linkRootClass: core.mergeOption('class', manager.get('linkRootClass'), 'vc-nav-link-root'),
26
+ linkTextTag: manager.get('linkTextTag') || 'span',
27
+ linkTextClass: core.mergeOption('class', manager.get('linkTextClass'), 'vc-nav-link-text')
28
+ };
25
29
  }
26
30
 
27
- const StoreSymbol = Symbol.for('VLNavigationStore');
28
- function isStoreInjected() {
29
- if (!vue.hasInjectionContext()) {
30
- return false;
31
+ function findItemMatchesIF(items, options, parent) {
32
+ const output = [];
33
+ for(let i = 0; i < items.length; i++){
34
+ const item = items[i];
35
+ let { score } = parent;
36
+ if (options.path) {
37
+ if (item.activeMatch) {
38
+ if (item.activeMatch === options.path) {
39
+ score += 3;
40
+ } else if (options.path.startsWith(item.activeMatch)) {
41
+ score += 2;
42
+ }
43
+ }
44
+ if (item.url && item.url !== '/') {
45
+ if (item.url === options.path) {
46
+ score += 3;
47
+ } else if (options.path.startsWith(item.url)) {
48
+ score += 2;
49
+ }
50
+ }
51
+ }
52
+ if (item.default) {
53
+ score += 1;
54
+ }
55
+ if (item.children) {
56
+ const childMatches = findItemMatchesIF(item.children, options, {
57
+ score
58
+ });
59
+ output.push(...childMatches);
60
+ }
61
+ output.push({
62
+ data: item,
63
+ score
64
+ });
65
+ }
66
+ return output.sort((a, b)=>b.score - a.score);
67
+ }
68
+ function findBestItemMatches(items, options = {}) {
69
+ const result = findItemMatchesIF(items, options, {
70
+ score: 0
71
+ });
72
+ const [first] = result;
73
+ if (!first) {
74
+ return [];
31
75
  }
32
- const instance = vue.inject(StoreSymbol);
33
- return !!instance;
76
+ return result.filter((match)=>match.score === first.score).map((match)=>match.data);
34
77
  }
35
- function setupStore(app) {
36
- const store = {
37
- items: vue.ref([]),
38
- itemsActive: vue.ref([])
78
+
79
+ /*
80
+ * Copyright (c) 2024.
81
+ * Author Peter Placzek (tada5hi)
82
+ * For the full copyright and license information,
83
+ * view the LICENSE file that was distributed with this source code.
84
+ */ function normalizeItemIF(item, defaults, trace) {
85
+ const output = {
86
+ ...item,
87
+ level: defaults.level,
88
+ children: [],
89
+ trace: [
90
+ ...trace,
91
+ item.name
92
+ ]
39
93
  };
40
- if (typeof app === 'undefined') {
41
- if (isStoreInjected()) {
42
- return;
43
- }
44
- vue.provide(StoreSymbol, store);
45
- return;
94
+ if (!item.children) {
95
+ return output;
46
96
  }
47
- if (app._context && app._context.provides && app._context.provides[StoreSymbol]) {
48
- return;
97
+ for(let i = 0; i < item.children.length; i++){
98
+ output.children.push(normalizeItemIF(item.children[i], defaults, output.trace));
49
99
  }
50
- app.provide(StoreSymbol, store);
100
+ return output;
51
101
  }
52
- function injectStore() {
53
- const instance = vue.inject(StoreSymbol);
54
- if (!instance) {
55
- throw new Error('The Store is not set.');
56
- }
57
- return instance;
102
+ function normalizeItem(item, defaults) {
103
+ return normalizeItemIF(item, defaults, []);
104
+ }
105
+ function normalizeItems(items, options) {
106
+ return items.map((item)=>normalizeItem(item, options));
58
107
  }
59
108
 
60
- function isNavigationItemMatch(one, two) {
61
- if (!one || !two) {
109
+ /*
110
+ * Copyright (c) 2024.
111
+ * Author Peter Placzek (tada5hi)
112
+ * For the full copyright and license information,
113
+ * view the LICENSE file that was distributed with this source code.
114
+ */ function isTraceEqual(a, b) {
115
+ if (a.length !== b.length) {
62
116
  return false;
63
117
  }
64
- if (one.id && two.id && one.id === two.id) {
65
- return true;
66
- }
67
- if (one.name && two.name && one.name === two.name) {
68
- return true;
69
- }
70
- if (one.url && two.url && one.url === two.url) {
71
- return true;
72
- }
73
- if (one.children && two.children && one.children.length === two.children.length) {
74
- for(let i = 0; i < one.children.length; i++){
75
- if (!isNavigationItemMatch(one.children[i], two.children[i])) {
76
- return false;
77
- }
118
+ for(let i = 0; i < a.length; i++){
119
+ if (a[i] !== b[i]) {
120
+ return false;
78
121
  }
79
- return true;
80
122
  }
81
- return false;
123
+ return true;
82
124
  }
83
-
84
- // --------------------------------------------------
85
- function setNavigationExpansion(items, item, parentMatch = false) {
86
- let matchInIteration = false;
87
- for(let i = 0; i < items.length; i++){
88
- const isMatch = isNavigationItemMatch(items[i], item);
89
- let isChildMatch = false;
90
- const { children } = items[i];
91
- if (typeof children !== 'undefined') {
92
- const { items: childItems, match: childMatch } = setNavigationExpansion(children, item, isMatch);
93
- items[i].children = childItems;
94
- isChildMatch = childMatch;
95
- }
96
- if (isMatch) {
97
- items[i].active = true;
98
- }
99
- if (isMatch || isChildMatch) {
100
- items[i].display = true;
101
- items[i].displayChildren = true;
102
- }
103
- if (parentMatch) {
104
- items[i].display = true;
105
- }
106
- if (!matchInIteration) {
107
- matchInIteration = isMatch || isChildMatch;
125
+ function isTracePartOf(item, parent) {
126
+ for(let i = 0; i < item.length; i++){
127
+ if (parent[i] !== item[i]) {
128
+ return false;
108
129
  }
109
130
  }
110
- if (matchInIteration) {
111
- for(let i = 0; i < items.length; i++){
112
- items[i].display = true;
113
- }
114
- }
115
- return {
116
- items,
117
- match: matchInIteration
118
- };
131
+ return true;
119
132
  }
120
133
 
121
- function resetNavigationItem(items, root = true) {
134
+ function resetItemsByTraceIF(items, trace) {
122
135
  for(let i = 0; i < items.length; i++){
123
- items[i].display = root;
124
- items[i].displayChildren = false;
125
- items[i].active = false;
126
- const { children } = items[i];
127
- if (typeof children !== 'undefined') {
128
- items[i].children = resetNavigationItem(children, false);
136
+ const item = items[i];
137
+ const isEqual = isTraceEqual(items[i].trace, trace);
138
+ item.active = isEqual;
139
+ item.display = true;
140
+ if (isEqual) {
141
+ item.displayChildren = true;
142
+ } else {
143
+ item.displayChildren = isTracePartOf(item.trace, trace);
129
144
  }
145
+ item.children = resetItemsByTraceIF(item.children, trace);
130
146
  }
131
147
  return items;
132
148
  }
149
+ function resetItemsByTrace(items, trace) {
150
+ return resetItemsByTraceIF(items, trace);
151
+ }
133
152
 
134
- function findNavigationItemsForTier(items, tier) {
135
- const filterFn = (component)=>typeof component.tier !== 'undefined' && component.tier === tier;
136
- return items.filter(filterFn);
153
+ function findItemsWithLevel(items, tier) {
154
+ return items.filter((item)=>item.level === tier);
137
155
  }
138
- function findNavigationItemForTier(items, tier) {
139
- const data = findNavigationItemsForTier(items, tier);
156
+ function findItemWithLevel(tier, items) {
157
+ const data = findItemsWithLevel(items, tier);
140
158
  if (data.length >= 1) {
141
159
  return data[0];
142
160
  }
143
161
  return undefined;
144
162
  }
145
- function setTierForNavigationItems(items, tier) {
146
- const mapFn = (component)=>{
147
- component.tier = tier;
148
- return component;
149
- };
150
- if (vue.isRef(items)) {
151
- return items.value.map(mapFn);
152
- }
153
- return items.map(mapFn);
154
- }
155
- function removeTierFromNavigationItems(items, tier) {
156
- const filterFn = (items)=>typeof items.tier === 'undefined' || items.tier !== tier;
157
- if (vue.isRef(items)) {
158
- return items.value.filter(filterFn);
159
- }
160
- return items.filter(filterFn);
163
+ function removeItemsWithLevel(tier, items) {
164
+ return items.filter((item)=>item.level !== tier);
161
165
  }
162
-
163
- function replaceNavigationTierItemActive(store, tier, item) {
164
- const items = removeTierFromNavigationItems(store.itemsActive.value, tier);
165
- if (item) {
166
- item.tier = tier;
167
- store.itemsActive.value = [
168
- ...items,
169
- item
166
+ function replaceLevelItem(tier, input, next) {
167
+ const output = removeItemsWithLevel(tier, input);
168
+ if (next) {
169
+ next.level = tier;
170
+ return [
171
+ ...output,
172
+ next
170
173
  ];
171
- } else {
172
- store.itemsActive.value = items;
173
174
  }
175
+ return output;
174
176
  }
175
- function replaceNavigationTierItems(store, tier, items) {
176
- const componentsExisting = removeTierFromNavigationItems(store.items.value, tier);
177
- store.items.value = [
177
+ function replaceLevelItems(tier, src, next) {
178
+ const componentsExisting = removeItemsWithLevel(tier, src);
179
+ return [
178
180
  ...componentsExisting,
179
- ...setTierForNavigationItems(items, tier)
181
+ ...next
180
182
  ];
181
183
  }
182
184
 
183
- function refreshNavigationTierItems(store, tier) {
184
- const components = resetNavigationItem(findNavigationItemsForTier(store.items.value, tier));
185
- const component = findNavigationItemForTier(store.itemsActive.value, tier);
186
- if (component) {
187
- const { items } = setNavigationExpansion(components, component);
188
- replaceNavigationTierItems(store, tier, items);
189
- return;
190
- }
191
- replaceNavigationTierItems(store, tier, components);
185
+ function isAbsoluteURL(str) {
186
+ return str.substring(0, 7) === 'http://' || str.substring(0, 8) === 'https://';
192
187
  }
193
188
 
194
- async function buildNavigationForTier(store, tier, itemsActive) {
195
- if (typeof itemsActive === 'undefined' || itemsActive.length === 0) {
196
- let tierStartIndex = 0;
197
- const tierEndIndex = tier;
198
- itemsActive = [];
199
- while(tierStartIndex <= tierEndIndex){
200
- const component = findNavigationItemForTier(store.itemsActive.value, tierStartIndex);
201
- if (!component) {
189
+ class NavigationManager extends eventEmitter.EventEmitter {
190
+ getItems(tier) {
191
+ if (typeof tier === 'undefined') {
192
+ return this.items;
193
+ }
194
+ return this.items.filter((item)=>item.level === tier);
195
+ }
196
+ async build(options) {
197
+ if (this.built) {
198
+ return this.items;
199
+ }
200
+ this.built = true;
201
+ this.items = [];
202
+ this.itemsActive = [];
203
+ let parent;
204
+ let level = 0;
205
+ while(true){
206
+ const raw = await this.itemsFn({
207
+ level,
208
+ parent
209
+ });
210
+ if (!raw || raw.length === 0) {
202
211
  break;
203
212
  }
204
- itemsActive.push(component);
205
- tierStartIndex++;
213
+ const items = normalizeItems(raw, {
214
+ level
215
+ });
216
+ const matches = findBestItemMatches(items, {
217
+ path: options.path
218
+ });
219
+ const [match] = matches;
220
+ if (!match) {
221
+ break;
222
+ }
223
+ this.itemsActive.push(match);
224
+ await this.buildLevel(level);
225
+ parent = match;
226
+ level++;
206
227
  }
228
+ this.emit('updated', this.items);
229
+ return this.items;
207
230
  }
208
- const items = await useNavigationProvider().getItems(tier, itemsActive);
209
- if (typeof items === 'undefined') {
210
- return false;
211
- }
212
- replaceNavigationTierItems(store, tier, items);
213
- refreshNavigationTierItems(store, tier);
214
- return true;
215
- }
216
-
217
- function flattenNestedNavigationItems(items) {
218
- const output = [];
219
- for(let i = 0; i < items.length; i++){
220
- const { children, ...data } = items[i];
221
- output.push(data);
222
- if (children && children.length > 0) {
223
- output.push(...flattenNestedNavigationItems([
224
- ...children
225
- ]));
231
+ async select(level, itemNew) {
232
+ const itemOld = findItemWithLevel(level, this.itemsActive);
233
+ if (itemOld && isTraceEqual(itemOld.trace, itemNew.trace)) {
234
+ return;
235
+ }
236
+ this.itemsActive = this.itemsActive.filter((el)=>el.level < level);
237
+ this.itemsActive.push(itemNew);
238
+ const startLevel = level;
239
+ while(true){
240
+ const built = await this.buildLevel(level, startLevel === level);
241
+ if (!built) {
242
+ break;
243
+ }
244
+ level++;
226
245
  }
227
246
  }
228
- return output;
229
- }
230
-
231
- async function selectNavigationTierItem(store, tier, component) {
232
- const isMatch = isNavigationItemMatch(findNavigationItemForTier(store.itemsActive.value, tier), component);
233
- if (isMatch) {
234
- return;
247
+ async toggle(level, item) {
248
+ let isMatch;
249
+ if (item.displayChildren) {
250
+ isMatch = true;
251
+ } else {
252
+ const itemOld = findItemWithLevel(level, this.itemsActive);
253
+ isMatch = !!itemOld && isTraceEqual(item.trace, itemOld.trace);
254
+ }
255
+ if (isMatch) {
256
+ this.itemsActive = removeItemsWithLevel(level, this.itemsActive);
257
+ } else {
258
+ this.itemsActive = replaceLevelItem(level, this.itemsActive, item);
259
+ }
260
+ await this.buildLevel(level, true);
261
+ }
262
+ async buildLevel(level, cached) {
263
+ let items;
264
+ if (cached) {
265
+ items = findItemsWithLevel(this.items, level);
266
+ } else {
267
+ const parent = findItemWithLevel(level - 1, this.itemsActive);
268
+ const raw = await this.itemsFn({
269
+ level,
270
+ parent
271
+ });
272
+ items = raw && raw.length > 0 ? normalizeItems(raw, {
273
+ level
274
+ }) : [];
275
+ }
276
+ if (!items || items.length === 0) {
277
+ this.items = this.items.filter((item)=>item.level < level);
278
+ this.emit('tierUpdated', level, []);
279
+ return false;
280
+ }
281
+ let trace = [];
282
+ const item = findItemWithLevel(level, this.itemsActive);
283
+ if (item) {
284
+ trace = item.trace;
285
+ }
286
+ resetItemsByTrace(items, trace);
287
+ this.items = replaceLevelItems(level, this.items, items);
288
+ this.emit('tierUpdated', level, items);
289
+ return true;
235
290
  }
236
- replaceNavigationTierItemActive(store, tier, component);
237
- refreshNavigationTierItems(store, tier);
238
- tier++;
239
- // eslint-disable-next-line no-constant-condition
240
- while(true){
241
- const built = await buildNavigationForTier(store, tier);
242
- if (!built) {
243
- break;
291
+ constructor(options){
292
+ super();
293
+ let itemsFn;
294
+ if (typeof options.items === 'function') {
295
+ itemsFn = options.items;
296
+ } else {
297
+ itemsFn = async ({ level })=>{
298
+ if (level > 0) {
299
+ return [];
300
+ }
301
+ return options.items;
302
+ };
244
303
  }
245
- tier++;
304
+ this.itemsFn = itemsFn;
305
+ this.items = [];
306
+ this.itemsActive = [];
307
+ this.built = false;
246
308
  }
247
309
  }
248
310
 
249
- function toggleNavigation(store, tier, component) {
250
- const isMatch = component.displayChildren || isNavigationItemMatch(findNavigationItemForTier(store.itemsActive.value, tier), component);
251
- if (isMatch) {
252
- replaceNavigationTierItemActive(store, tier, undefined);
253
- } else {
254
- replaceNavigationTierItemActive(store, tier, component);
311
+ const sym = Symbol.for('VCNavigationManager');
312
+ function injectNavigationManager(app) {
313
+ const instance = core.inject(sym, app);
314
+ if (!instance) {
315
+ throw new Error('A navigation provider has not been provided.');
255
316
  }
256
- refreshNavigationTierItems(store, tier);
317
+ return instance;
257
318
  }
258
-
259
- function isAbsoluteURL(str) {
260
- return str.substring(0, 7) === 'http://' || str.substring(0, 8) === 'https://';
319
+ function provideNavigationManager(manager, app) {
320
+ core.provide(sym, manager, app);
261
321
  }
262
322
 
263
- var SlotName;
264
- (function(SlotName) {
323
+ var SlotName = /*#__PURE__*/ function(SlotName) {
265
324
  SlotName["ITEM"] = "item";
266
325
  SlotName["SEPARATOR"] = "separator";
267
326
  SlotName["LINK"] = "link";
268
327
  SlotName["SUB"] = "sub";
269
328
  SlotName["SUB_TITLE"] = "sub-title";
270
329
  SlotName["SUB_ITEMS"] = "sub-items";
271
- })(SlotName || (SlotName = {}));
272
- var ElementType;
273
- (function(ElementType) {
330
+ return SlotName;
331
+ }({});
332
+ var ElementType = /*#__PURE__*/ function(ElementType) {
274
333
  ElementType["LINK"] = "link";
275
334
  ElementType["SEPARATOR"] = "separator";
276
- })(ElementType || (ElementType = {}));
335
+ return ElementType;
336
+ }({});
277
337
 
278
338
  const VCNavItem = vue.defineComponent({
279
339
  props: {
280
- tier: {
281
- type: Number,
282
- default: 0
283
- },
284
- component: {
340
+ data: {
285
341
  type: Object,
286
342
  required: true
287
343
  }
288
344
  },
289
345
  setup (props, { slots }) {
290
- const store = injectStore();
291
- const component = vue.toRef(props, 'component');
292
- const selectComponent = async (value)=>{
293
- await selectNavigationTierItem(store, props.tier, value);
346
+ const itemsNode = vue.resolveComponent('VCNavItems');
347
+ const options = buildComponentOptions();
348
+ const manager = injectNavigationManager();
349
+ const data = vue.toRef(props, 'data');
350
+ const select = async (value)=>{
351
+ await manager.select(data.value.level, value);
352
+ };
353
+ const toggle = async (value)=>{
354
+ await manager.toggle(data.value.level, value);
294
355
  };
295
- const toggleComponentExpansion = async (value)=>toggleNavigation(store, props.tier, value);
296
356
  return ()=>{
297
357
  const buildItem = ()=>{
298
- let item;
299
- switch(component.value.type){
300
- case ElementType.SEPARATOR:
301
- {
302
- const hasSlot = core.hasNormalizedSlot(SlotName.SEPARATOR, slots);
303
- if (hasSlot) {
304
- item = core.normalizeSlot(SlotName.SEPARATOR, {
305
- component: component.value
306
- }, slots);
307
- } else {
308
- item = vue.h('div', {
309
- class: 'nav-separator'
310
- }, component.value.name);
358
+ // type: separator
359
+ if (data.value.type === ElementType.SEPARATOR) {
360
+ const hasSlot = core.hasNormalizedSlot(SlotName.SEPARATOR, slots);
361
+ if (hasSlot) {
362
+ return core.normalizeSlot(SlotName.SEPARATOR, {
363
+ data: data.value
364
+ }, slots);
365
+ }
366
+ return vue.h(options.separatorTag, {
367
+ class: options.separatorClass
368
+ }, data.value.name);
369
+ }
370
+ // type: group
371
+ if (!data.value.children || data.value.children.length === 0) {
372
+ const hasSlot = core.hasNormalizedSlot(SlotName.LINK, slots);
373
+ if (hasSlot) {
374
+ return core.normalizeSlot(SlotName.LINK, {
375
+ data: data.value,
376
+ select,
377
+ isActive: data.value.active
378
+ }, slots);
379
+ }
380
+ const linkProps = {
381
+ active: data.value.active,
382
+ disabled: false,
383
+ prefetch: true
384
+ };
385
+ if (data.value.url) {
386
+ if (isAbsoluteURL(data.value.url) || data.value.url.startsWith('#')) {
387
+ linkProps.href = data.value.url;
388
+ if (data.value.urlTarget) {
389
+ linkProps.target = data.value.urlTarget;
311
390
  }
312
- break;
391
+ } else {
392
+ linkProps.to = data.value.url;
313
393
  }
314
- default:
315
- {
316
- if (typeof component.value.children === 'undefined') {
317
- const hasSlot = core.hasNormalizedSlot(SlotName.LINK, slots);
318
- if (hasSlot) {
319
- item = core.normalizeSlot(SlotName.LINK, {
320
- component: component.value,
321
- selectComponent,
322
- isActive: component.value.active
323
- }, slots);
324
- } else {
325
- const linkProps = {
326
- active: component.value.active,
327
- disabled: false,
328
- prefetch: true
329
- };
330
- if (component.value.url) {
331
- if (isAbsoluteURL(component.value.url) || component.value.url.startsWith('#')) {
332
- linkProps.href = component.value.url;
333
- if (component.value.urlTarget) {
334
- linkProps.target = component.value.urlTarget;
335
- }
336
- } else {
337
- linkProps.to = component.value.url;
338
- }
339
- }
340
- item = vue.h(link.VCLink, {
341
- class: [
342
- 'nav-link',
343
- {
344
- 'root-link': component.value.root
345
- }
346
- ],
347
- ...linkProps,
348
- onClicked () {
349
- if (!component.value.url) {
350
- return selectComponent.call(null, component.value);
351
- }
352
- return undefined;
353
- },
354
- onClick () {
355
- return selectComponent.call(null, component.value);
356
- }
357
- }, {
358
- default: ()=>[
359
- ...component.value.icon ? [
360
- vue.h('i', {
361
- class: component.value.icon
362
- })
363
- ] : [],
364
- vue.h('span', {
365
- class: 'nav-link-text'
366
- }, [
367
- component.value.name
368
- ])
369
- ]
370
- });
371
- }
372
- } else if (core.hasNormalizedSlot(SlotName.SUB, slots)) {
373
- item = core.normalizeSlot(SlotName.SUB, {
374
- component: component.value,
375
- selectComponent,
376
- toggleComponentExpansion
377
- }, slots);
378
- } else {
379
- let title;
380
- if (core.hasNormalizedSlot(SlotName.SUB_TITLE, slots)) {
381
- title = core.normalizeSlot(SlotName.SUB_TITLE, {
382
- component: component.value,
383
- selectComponent,
384
- toggleComponentExpansion
385
- });
386
- } else {
387
- title = vue.h('div', {
388
- class: 'nav-sub-title',
389
- onClick ($event) {
390
- $event.preventDefault();
391
- return toggleComponentExpansion.call(null, component.value);
392
- }
393
- }, [
394
- [
395
- ...component.value.icon ? [
396
- vue.h('i', {
397
- class: component.value.icon
398
- })
399
- ] : [],
400
- vue.h('span', {
401
- class: 'nav-link-text'
402
- }, [
403
- component.value.name
404
- ])
405
- ]
406
- ]);
407
- }
408
- let items;
409
- if (core.hasNormalizedSlot(SlotName.SUB_ITEMS, slots)) {
410
- items = core.normalizeSlot(SlotName.SUB_ITEMS, {
411
- component: component.value,
412
- selectComponent,
413
- toggleComponentExpansion
414
- });
415
- } else if (component.value.displayChildren) {
416
- const navigationComponents = vue.resolveComponent('VCNavItems');
417
- items = vue.h(navigationComponents, {
418
- class: 'list-unstyled nav-sub-items',
419
- tier: props.tier,
420
- entities: component.value.children
421
- });
422
- }
423
- item = [
424
- title,
425
- items
426
- ];
394
+ }
395
+ return vue.h(link.VCLink, {
396
+ class: [
397
+ options.linkClass,
398
+ data.value.url && data.value.url === '/' ? [
399
+ options.linkRootClass
400
+ ] : []
401
+ ],
402
+ ...linkProps,
403
+ onClicked () {
404
+ if (!data.value.url) {
405
+ return select.call(null, data.value);
427
406
  }
428
- break;
407
+ return undefined;
408
+ },
409
+ onClick () {
410
+ return select.call(null, data.value);
411
+ }
412
+ }, {
413
+ default: ()=>[
414
+ ...data.value.icon ? [
415
+ vue.h('i', {
416
+ class: data.value.icon
417
+ })
418
+ ] : [],
419
+ vue.h(options.linkTextTag, {
420
+ class: options.linkTextClass
421
+ }, [
422
+ data.value.name
423
+ ])
424
+ ]
425
+ });
426
+ }
427
+ if (core.hasNormalizedSlot(SlotName.SUB, slots)) {
428
+ return core.normalizeSlot(SlotName.SUB, {
429
+ data: data.value,
430
+ select,
431
+ toggle
432
+ }, slots);
433
+ }
434
+ let title;
435
+ if (core.hasNormalizedSlot(SlotName.SUB_TITLE, slots)) {
436
+ title = core.normalizeSlot(SlotName.SUB_TITLE, {
437
+ data: data.value,
438
+ select,
439
+ toggle
440
+ });
441
+ } else {
442
+ title = vue.h('div', {
443
+ class: options.subGroupTitleClass,
444
+ onClick ($event) {
445
+ $event.preventDefault();
446
+ return toggle(data.value);
429
447
  }
448
+ }, [
449
+ [
450
+ ...data.value.icon ? [
451
+ vue.h('i', {
452
+ class: data.value.icon
453
+ })
454
+ ] : [],
455
+ vue.h(options.linkTextTag, {
456
+ class: options.linkTextClass
457
+ }, [
458
+ data.value.name
459
+ ])
460
+ ]
461
+ ]);
430
462
  }
431
- return item;
463
+ if (!data.value.displayChildren) {
464
+ return title;
465
+ }
466
+ let vNodes;
467
+ if (core.hasNormalizedSlot(SlotName.SUB_ITEMS, slots)) {
468
+ vNodes = core.normalizeSlot(SlotName.SUB_ITEMS, {
469
+ data: data.value,
470
+ select,
471
+ toggle
472
+ });
473
+ } else {
474
+ vNodes = vue.h(itemsNode, {
475
+ level: data.value.level,
476
+ data: data.value.children
477
+ });
478
+ }
479
+ return [
480
+ title,
481
+ vNodes
482
+ ];
432
483
  };
433
- return vue.h('div', {
484
+ return vue.h(options.itemTag, {
434
485
  class: [
435
- 'nav-item',
486
+ options.itemClass,
436
487
  {
437
- active: component.value.active || component.value.displayChildren
488
+ active: data.value.active || data.value.displayChildren
438
489
  }
439
490
  ]
440
491
  }, [
@@ -446,131 +497,79 @@ const VCNavItem = vue.defineComponent({
446
497
 
447
498
  const VCNavItems = vue.defineComponent({
448
499
  props: {
449
- tier: {
500
+ level: {
450
501
  type: Number,
451
502
  default: 0
452
503
  },
453
- entities: {
504
+ data: {
454
505
  type: Array,
455
506
  default: undefined
456
507
  }
457
508
  },
458
509
  setup (props, { slots }) {
459
- const store = injectStore();
460
- const items = vue.computed(()=>{
461
- if (typeof props.entities !== 'undefined') {
462
- return props.entities;
463
- }
464
- return findNavigationItemsForTier(store.items.value, props.tier);
465
- });
466
- const buildChild = (context)=>{
467
- if (core.hasNormalizedSlot(SlotName.ITEM, slots)) {
468
- return core.normalizeSlot(SlotName.ITEM, context, slots);
469
- }
470
- return vue.h(VCNavItem, context);
471
- };
472
- const buildChildren = ()=>{
473
- const entities = [];
474
- if (items.value) {
475
- for(let i = 0; i < items.value.length; i++){
476
- if (items.value[i].display) {
477
- entities.push(vue.h('li', {
478
- key: i
479
- }, [
480
- buildChild({
481
- tier: props.tier,
482
- component: items.value[i]
483
- })
484
- ]));
485
- }
510
+ const options = buildComponentOptions();
511
+ const manager = injectNavigationManager();
512
+ const managerItems = vue.ref([]);
513
+ if (!props.data) {
514
+ managerItems.value = manager.getItems(props.level);
515
+ }
516
+ const counter = vue.ref(0);
517
+ let removeListener;
518
+ vue.onMounted(()=>{
519
+ removeListener = manager.on('tierUpdated', (tier, items)=>{
520
+ if (tier !== props.level) {
521
+ return;
486
522
  }
523
+ managerItems.value = items;
524
+ counter.value++;
525
+ });
526
+ });
527
+ vue.onUnmounted(()=>{
528
+ if (typeof removeListener === 'function') {
529
+ removeListener();
530
+ removeListener = undefined;
487
531
  }
488
- return entities;
489
- };
490
- return ()=>vue.h('ul', {
491
- class: 'nav-items'
492
- }, [
493
- buildChildren()
494
- ]);
495
- }
496
- });
497
-
498
- async function buildNavigation(context = {}) {
499
- const store = injectStore();
500
- const navigationProvider = useNavigationProvider();
501
- let itemsActive = [];
502
- if (typeof context.itemsActive !== 'undefined') {
503
- itemsActive = context.itemsActive;
504
- } else if (context.route) {
505
- if (typeof navigationProvider.getItemsActiveByRoute !== 'undefined') {
506
- itemsActive = await navigationProvider.getItemsActiveByRoute(context.route);
507
- } else if (typeof navigationProvider.getItemsActiveByURL !== 'undefined') {
508
- itemsActive = await navigationProvider.getItemsActiveByURL(context.route.fullPath);
509
- }
510
- } else if (context.url && typeof navigationProvider.getItemsActiveByURL !== 'undefined') {
511
- itemsActive = await navigationProvider.getItemsActiveByURL(context.url);
512
- }
513
- if (itemsActive.length > 0) {
514
- for(let i = 0; i < itemsActive.length; i++){
515
- if (typeof itemsActive[i].tier === 'undefined') {
516
- itemsActive[i].tier = i;
532
+ });
533
+ const items = vue.computed(()=>{
534
+ if (typeof props.data !== 'undefined') {
535
+ return props.data;
517
536
  }
518
- }
519
- }
520
- let tierIndex = 0;
521
- let url;
522
- if (typeof context.url === 'string') {
523
- url = context.url;
524
- } else if (typeof context.route !== 'undefined') {
525
- url = context.route.fullPath;
526
- }
527
- // eslint-disable-next-line no-constant-condition
528
- while(true){
529
- let items = await navigationProvider.getItems(tierIndex, itemsActive);
530
- if (!items || items.length === 0) {
531
- break;
532
- }
533
- // ensure tier property
534
- items = setTierForNavigationItems(items, tierIndex);
535
- let currentItem = findNavigationItemForTier(itemsActive, tierIndex);
536
- if (!currentItem) {
537
- if (url) {
538
- const urlMatches = items.filter((item)=>isNavigationItemMatch(item, {
539
- url
540
- }));
541
- if (urlMatches.length > 0) {
542
- [currentItem] = urlMatches;
537
+ return managerItems.value;
538
+ });
539
+ return ()=>{
540
+ const vNodes = [];
541
+ for(let i = 0; i < items.value.length; i++){
542
+ if (!items.value[i].display && !items.value[i].displayChildren) {
543
+ continue;
543
544
  }
544
- }
545
- if (!currentItem) {
546
- const defaultItem = items.filter((item)=>item.default);
547
- if (defaultItem.length > 0) {
548
- currentItem = defaultItem;
545
+ let vNode;
546
+ if (core.hasNormalizedSlot(SlotName.ITEM, slots)) {
547
+ vNode = core.normalizeSlot(SlotName.ITEM, {
548
+ data: items.value[i]
549
+ }, slots);
549
550
  } else {
550
- [currentItem] = items;
551
+ vNode = vue.h(VCNavItem, {
552
+ key: `${i}:${counter.value}`,
553
+ data: items.value[i]
554
+ });
551
555
  }
556
+ vNodes.push(vNode);
552
557
  }
553
- currentItem.tier = tierIndex;
554
- itemsActive.push(currentItem);
555
- }
556
- if (!currentItem) {
557
- continue;
558
- }
559
- replaceNavigationTierItemActive(store, tierIndex, currentItem);
560
- await buildNavigationForTier(store, tierIndex, itemsActive);
561
- tierIndex++;
558
+ return vue.h(options.groupTag, {
559
+ class: props.data ? options.subGroupItemsClass : options.groupClass
560
+ }, vNodes);
561
+ };
562
562
  }
563
- }
563
+ });
564
564
 
565
565
  function install(instance, options) {
566
- if (options.provider) {
567
- setNavigationProvider(options.provider);
568
- }
569
- setupStore(instance);
566
+ const manager = new NavigationManager({
567
+ items: options.items
568
+ });
569
+ provideNavigationManager(manager, instance);
570
+ const storeManager = core.installStoreManager(instance);
570
571
  if (options.storeManager) {
571
- core.applyStoreManagerOptions(instance, options.storeManager);
572
- } else {
573
- core.installStoreManager(instance);
572
+ core.applyStoreManagerOptions(storeManager, options.storeManager);
574
573
  }
575
574
  Object.entries({
576
575
  VCNavItem,
@@ -583,15 +582,12 @@ var index = {
583
582
  install
584
583
  };
585
584
 
585
+ exports.NavigationManager = NavigationManager;
586
586
  exports.VCNavItem = VCNavItem;
587
587
  exports.VCNavItems = VCNavItems;
588
- exports.buildNavigation = buildNavigation;
589
- exports.buildNavigationForTier = buildNavigationForTier;
590
- exports.createNavigationProvider = createNavigationProvider;
591
588
  exports.default = index;
592
- exports.flattenNestedNavigationItems = flattenNestedNavigationItems;
589
+ exports.injectNavigationManager = injectNavigationManager;
593
590
  exports.install = install;
594
- exports.setNavigationProvider = setNavigationProvider;
595
- exports.useNavigationProvider = useNavigationProvider;
591
+ exports.provideNavigationManager = provideNavigationManager;
596
592
  module.exports = Object.assign(exports.default, exports);
597
593
  //# sourceMappingURL=index.cjs.map