ketekny-ui-kit 1.0.142 → 1.0.144
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/package.json
CHANGED
|
@@ -102,8 +102,12 @@ export default {
|
|
|
102
102
|
default: null,
|
|
103
103
|
validator: value => value === null || ['dark', 'light'].includes(value),
|
|
104
104
|
},
|
|
105
|
+
favorites: {
|
|
106
|
+
type: Array,
|
|
107
|
+
default: null,
|
|
108
|
+
},
|
|
105
109
|
},
|
|
106
|
-
emits: ['select', 'logo-click', 'signin', 'signup', 'signout', 'edit-profile', 'item-click'],
|
|
110
|
+
emits: ['select', 'logo-click', 'signin', 'signup', 'signout', 'edit-profile', 'item-click', 'update:favorites'],
|
|
107
111
|
data() {
|
|
108
112
|
return {
|
|
109
113
|
demoAvatarUrl,
|
|
@@ -142,6 +146,9 @@ export default {
|
|
|
142
146
|
hasAccount() {
|
|
143
147
|
return Boolean(this.account)
|
|
144
148
|
},
|
|
149
|
+
isControlledFavorites() {
|
|
150
|
+
return Array.isArray(this.favorites)
|
|
151
|
+
},
|
|
145
152
|
accountDisplayName() {
|
|
146
153
|
if (!this.account) return ''
|
|
147
154
|
return [this.account.firstName, this.account.lastName].filter(Boolean).join(' ') || 'Account'
|
|
@@ -158,6 +165,7 @@ export default {
|
|
|
158
165
|
const favorites = []
|
|
159
166
|
const collect = (items) => {
|
|
160
167
|
for (const item of items) {
|
|
168
|
+
if (item?.isDivider) continue
|
|
161
169
|
if (item?.children?.length) {
|
|
162
170
|
collect(item.children)
|
|
163
171
|
continue
|
|
@@ -242,12 +250,18 @@ export default {
|
|
|
242
250
|
deep: true,
|
|
243
251
|
immediate: true,
|
|
244
252
|
},
|
|
253
|
+
favorites: {
|
|
254
|
+
handler() {
|
|
255
|
+
this.syncFavoritesFromMenu()
|
|
256
|
+
},
|
|
257
|
+
deep: true,
|
|
258
|
+
},
|
|
245
259
|
$route() {
|
|
246
260
|
this.syncActiveFromMenu()
|
|
247
261
|
},
|
|
248
262
|
favoriteIds: {
|
|
249
263
|
handler(value) {
|
|
250
|
-
this.persistFavorites(value)
|
|
264
|
+
if (!this.isControlledFavorites) this.persistFavorites(value)
|
|
251
265
|
if (!value.size && this.activeMenuTab === 'favorites') this.activeMenuTab = 'all'
|
|
252
266
|
},
|
|
253
267
|
deep: false,
|
|
@@ -300,19 +314,33 @@ export default {
|
|
|
300
314
|
}
|
|
301
315
|
return ids
|
|
302
316
|
},
|
|
317
|
+
normalizeFavorite(value) {
|
|
318
|
+
return String(value ?? '').replace(/^\/+/, '').trim()
|
|
319
|
+
},
|
|
320
|
+
favoriteValue(item) {
|
|
321
|
+
const value = item?.link?.to ?? item?.to ?? item?.link?.href ?? item?.href
|
|
322
|
+
return this.normalizeFavorite(typeof value === 'string' ? value : item?.id)
|
|
323
|
+
},
|
|
303
324
|
syncFavoritesFromMenu() {
|
|
304
|
-
const storedFavorites = this.readStoredFavorites()
|
|
325
|
+
const storedFavorites = this.isControlledFavorites ? this.favorites : this.readStoredFavorites()
|
|
305
326
|
const storedTab = this.readStoredActiveMenuTab()
|
|
327
|
+
const controlledFavorites = new Set(storedFavorites.map(value => this.normalizeFavorite(value)))
|
|
306
328
|
const discovered = []
|
|
307
329
|
const collect = (items) => {
|
|
308
330
|
for (const item of items) {
|
|
309
|
-
if (
|
|
331
|
+
if (
|
|
332
|
+
!item?.children?.length
|
|
333
|
+
&& (this.isControlledFavorites
|
|
334
|
+
? controlledFavorites.has(this.favoriteValue(item))
|
|
335
|
+
|| controlledFavorites.has(this.normalizeFavorite(item?.id))
|
|
336
|
+
: item?.favorite)
|
|
337
|
+
) discovered.push(item.id)
|
|
310
338
|
if (item?.children?.length) collect(item.children)
|
|
311
339
|
}
|
|
312
340
|
}
|
|
313
341
|
collect(this.mainMenu)
|
|
314
|
-
this.favoriteIds = new Set([...discovered, ...storedFavorites])
|
|
315
|
-
if (storedTab === 'favorites' &&
|
|
342
|
+
this.favoriteIds = new Set(this.isControlledFavorites ? discovered : [...discovered, ...storedFavorites])
|
|
343
|
+
if (storedTab === 'favorites' && this.favoriteIds.size > 0) {
|
|
316
344
|
this.activeMenuTab = 'favorites'
|
|
317
345
|
} else {
|
|
318
346
|
this.activeMenuTab = 'all'
|
|
@@ -329,7 +357,7 @@ export default {
|
|
|
329
357
|
(routeFullPath && itemPath === routeFullPath) ||
|
|
330
358
|
(routePath && normalizedItemPath === routePath)
|
|
331
359
|
|
|
332
|
-
if (matchesPath) {
|
|
360
|
+
if (matchesPath && item.selectable !== false) {
|
|
333
361
|
return {
|
|
334
362
|
id: item.id,
|
|
335
363
|
parentIds,
|
|
@@ -350,8 +378,9 @@ export default {
|
|
|
350
378
|
return
|
|
351
379
|
}
|
|
352
380
|
|
|
353
|
-
if (!this.activeId
|
|
354
|
-
|
|
381
|
+
if (!this.activeId) {
|
|
382
|
+
const firstSelectableItem = this.mainMenu.find((item) => !item.isDivider && item.selectable !== false)
|
|
383
|
+
if (firstSelectableItem?.id) this.activeId = firstSelectableItem.id
|
|
355
384
|
}
|
|
356
385
|
},
|
|
357
386
|
toggleCollapsed() {
|
|
@@ -375,6 +404,7 @@ export default {
|
|
|
375
404
|
this.openIds = new Set([...this.openIds, id])
|
|
376
405
|
},
|
|
377
406
|
select(itemOrId) {
|
|
407
|
+
if (typeof itemOrId !== 'string' && (itemOrId?.isDivider || itemOrId?.selectable === false)) return
|
|
378
408
|
const id = typeof itemOrId === 'string' ? itemOrId : itemOrId?.id
|
|
379
409
|
if (!id) return
|
|
380
410
|
this.activeId = id
|
|
@@ -399,7 +429,8 @@ export default {
|
|
|
399
429
|
filterTree(nodes, q) {
|
|
400
430
|
const result = []
|
|
401
431
|
for (const node of nodes) {
|
|
402
|
-
|
|
432
|
+
if (node.isDivider) continue
|
|
433
|
+
const matches = String(node.label ?? '').toLowerCase().includes(q)
|
|
403
434
|
const matchedChildren = node.children ? this.filterTree(node.children, q) : []
|
|
404
435
|
if (matches) result.push(node)
|
|
405
436
|
else if (matchedChildren.length) result.push({ ...node, children: matchedChildren })
|
|
@@ -440,6 +471,16 @@ export default {
|
|
|
440
471
|
if (next.has(item.id)) next.delete(item.id)
|
|
441
472
|
else next.add(item.id)
|
|
442
473
|
this.favoriteIds = next
|
|
474
|
+
if (this.isControlledFavorites) {
|
|
475
|
+
const favorites = new Set(this.favorites.map(value => this.normalizeFavorite(value)))
|
|
476
|
+
const value = this.favoriteValue(item)
|
|
477
|
+
if (next.has(item.id)) favorites.add(value)
|
|
478
|
+
else {
|
|
479
|
+
favorites.delete(value)
|
|
480
|
+
favorites.delete(this.normalizeFavorite(item.id))
|
|
481
|
+
}
|
|
482
|
+
this.$emit('update:favorites', Array.from(favorites))
|
|
483
|
+
}
|
|
443
484
|
if (next.size && this.activeMenuTab !== 'favorites' && this.activeMenuTab !== 'all') {
|
|
444
485
|
this.activeMenuTab = 'all'
|
|
445
486
|
}
|
|
@@ -30,6 +30,9 @@ export default {
|
|
|
30
30
|
hasChildren() {
|
|
31
31
|
return Array.isArray(this.item.children) && this.item.children.length > 0
|
|
32
32
|
},
|
|
33
|
+
isDivider() {
|
|
34
|
+
return this.item.isDivider === true
|
|
35
|
+
},
|
|
33
36
|
isOpen() {
|
|
34
37
|
return this.openIds.has(this.item.id)
|
|
35
38
|
},
|
|
@@ -41,7 +44,7 @@ export default {
|
|
|
41
44
|
return this.hasChildren && this.containsActive(this.item)
|
|
42
45
|
},
|
|
43
46
|
isActiveLeaf() {
|
|
44
|
-
return !this.hasChildren && this.item.id === this.activeId
|
|
47
|
+
return !this.hasChildren && this.item.selectable !== false && this.item.id === this.activeId
|
|
45
48
|
},
|
|
46
49
|
isActive() {
|
|
47
50
|
return this.isActiveLeaf || this.isActiveTrail
|
|
@@ -82,7 +85,7 @@ export default {
|
|
|
82
85
|
},
|
|
83
86
|
methods: {
|
|
84
87
|
containsActive(node) {
|
|
85
|
-
if (node.id === this.activeId) return true
|
|
88
|
+
if (node.selectable !== false && node.id === this.activeId) return true
|
|
86
89
|
if (!node.children) return false
|
|
87
90
|
return node.children.some((child) => this.containsActive(child))
|
|
88
91
|
},
|
|
@@ -125,7 +128,18 @@ export default {
|
|
|
125
128
|
</script>
|
|
126
129
|
|
|
127
130
|
<template>
|
|
128
|
-
<li
|
|
131
|
+
<li v-if="isDivider" role="separator" :aria-label="item.label || undefined" class="py-2">
|
|
132
|
+
<div v-if="isCollapsedTop" class="mx-2 border-t border-[var(--sidebar-border)]" />
|
|
133
|
+
<div v-else class="flex items-center gap-2 px-3">
|
|
134
|
+
<span class="h-px flex-1 bg-[var(--sidebar-border)]" />
|
|
135
|
+
<span v-if="item.label" class="shrink-0 text-xs font-medium uppercase tracking-wider text-[var(--sidebar-text-muted)]">
|
|
136
|
+
{{ item.label }}
|
|
137
|
+
</span>
|
|
138
|
+
<span v-if="item.label" class="h-px flex-1 bg-[var(--sidebar-border)]" />
|
|
139
|
+
</div>
|
|
140
|
+
</li>
|
|
141
|
+
|
|
142
|
+
<li v-else :class="isCollapsedTop ? 'group/fly relative' : ''">
|
|
129
143
|
<button
|
|
130
144
|
type="button"
|
|
131
145
|
:style="isCollapsedTop ? undefined : indentStyle"
|
|
@@ -16,6 +16,8 @@
|
|
|
16
16
|
:account-menu-items="accountMenuItems"
|
|
17
17
|
:contact-email="contactEmail"
|
|
18
18
|
:help-url="helpUrl"
|
|
19
|
+
:favorites="favorites"
|
|
20
|
+
@update:favorites="$emit('update:favorites', $event)"
|
|
19
21
|
@logo-click="handleLogoClick"
|
|
20
22
|
@signin="handleSignin"
|
|
21
23
|
@signup="handleSignup"
|
|
@@ -118,8 +120,12 @@ export default {
|
|
|
118
120
|
default: null,
|
|
119
121
|
validator: value => value === null || ["dark", "light"].includes(value),
|
|
120
122
|
},
|
|
123
|
+
favorites: {
|
|
124
|
+
type: Array,
|
|
125
|
+
default: null,
|
|
126
|
+
},
|
|
121
127
|
},
|
|
122
|
-
emits: ["select-menu", "logo-click", "signin", "signup", "signout", "edit-profile", "item-click"],
|
|
128
|
+
emits: ["select-menu", "logo-click", "signin", "signup", "signout", "edit-profile", "item-click", "update:favorites"],
|
|
123
129
|
data() {
|
|
124
130
|
return {
|
|
125
131
|
mobileMenuOpen: false,
|