camelmind 0.2.5 → 0.2.7
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,11 +102,14 @@ export function MobileDrawer({
|
|
|
102
102
|
<nav className="flex-1 px-3 py-4 space-y-1">
|
|
103
103
|
{nav.map((item) => {
|
|
104
104
|
if (isNavGroup(item)) {
|
|
105
|
-
|
|
105
|
+
const visibleItems = (item.items ?? []).filter((i) => canSee(i.roles))
|
|
106
|
+
const directHref = item.slug ?? visibleItems[0]?.slug
|
|
107
|
+
|
|
108
|
+
if ((item.noDropdown || !item.items) && directHref) {
|
|
106
109
|
return (
|
|
107
110
|
<Link
|
|
108
111
|
key={item.label}
|
|
109
|
-
href={
|
|
112
|
+
href={directHref}
|
|
110
113
|
className="block px-3 py-2.5 text-sm font-medium text-gray-200 hover:text-white hover:bg-gray-800 rounded-lg"
|
|
111
114
|
>
|
|
112
115
|
{item.label}
|
|
@@ -114,7 +117,6 @@ export function MobileDrawer({
|
|
|
114
117
|
)
|
|
115
118
|
}
|
|
116
119
|
|
|
117
|
-
const visibleItems = (item.items ?? []).filter((i) => canSee(i.roles))
|
|
118
120
|
if (visibleItems.length === 0) return null
|
|
119
121
|
const isExpanded = expandedGroup === item.label
|
|
120
122
|
|
|
@@ -60,15 +60,17 @@ export function TopNav({ nav, userRoles, userName, authEnabled = false, versions
|
|
|
60
60
|
<div className="hidden md:flex items-center gap-6 flex-1">
|
|
61
61
|
{nav.map((item) => {
|
|
62
62
|
if (isNavGroup(item)) {
|
|
63
|
-
|
|
63
|
+
const visibleItems = (item.items ?? []).filter((i) => canSee(i.roles))
|
|
64
|
+
const directHref = item.slug ?? visibleItems[0]?.slug
|
|
65
|
+
|
|
66
|
+
if ((item.noDropdown || !item.items) && directHref) {
|
|
64
67
|
return (
|
|
65
|
-
<Link key={item.label} href={
|
|
68
|
+
<Link key={item.label} href={directHref} className="text-sm font-medium hover:text-gray-300">
|
|
66
69
|
{item.label}
|
|
67
70
|
</Link>
|
|
68
71
|
)
|
|
69
72
|
}
|
|
70
73
|
|
|
71
|
-
const visibleItems = (item.items ?? []).filter((i) => canSee(i.roles))
|
|
72
74
|
if (visibleItems.length === 0) return null
|
|
73
75
|
|
|
74
76
|
return (
|
|
@@ -164,15 +164,25 @@ function GroupSidebar({
|
|
|
164
164
|
return (
|
|
165
165
|
<aside className="hidden md:block w-72 shrink-0 border-r border-gray-200 dark:border-gray-800 overflow-y-auto bg-white dark:bg-gray-950">
|
|
166
166
|
<div className="px-4 py-4">
|
|
167
|
-
{visibleItems.map((entry) =>
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
167
|
+
{visibleItems.map((entry) =>
|
|
168
|
+
entry.section ? (
|
|
169
|
+
<CategoryBlock
|
|
170
|
+
key={entry.slug}
|
|
171
|
+
entry={entry}
|
|
172
|
+
currentSlug={currentSlug}
|
|
173
|
+
userRoles={userRoles}
|
|
174
|
+
authEnabled={authEnabled}
|
|
175
|
+
/>
|
|
176
|
+
) : (
|
|
177
|
+
<SectionRow
|
|
178
|
+
key={entry.slug}
|
|
179
|
+
section={entry as NavChild}
|
|
180
|
+
currentSlug={currentSlug}
|
|
181
|
+
userRoles={userRoles}
|
|
182
|
+
authEnabled={authEnabled}
|
|
183
|
+
/>
|
|
184
|
+
)
|
|
185
|
+
)}
|
|
176
186
|
</div>
|
|
177
187
|
</aside>
|
|
178
188
|
)
|
|
@@ -11,14 +11,15 @@ export type NavEntry = {
|
|
|
11
11
|
slug: string
|
|
12
12
|
file: string
|
|
13
13
|
roles: string[]
|
|
14
|
-
section?: NavChild[]
|
|
14
|
+
section?: NavChild[] // renders as ALL CAPS category block with children below
|
|
15
|
+
children?: NavChild[] // renders as a plain collapsible row (no category label)
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
export type NavGroup = {
|
|
18
19
|
label: string
|
|
19
20
|
dropdown: boolean
|
|
20
21
|
noDropdown?: boolean // show as direct link in top nav, not a dropdown button
|
|
21
|
-
slug?: string // href
|
|
22
|
+
slug?: string // optional direct-link href; falls back to the first visible item
|
|
22
23
|
items: NavEntry[]
|
|
23
24
|
}
|
|
24
25
|
|
package/template/lib/nav.ts
CHANGED
|
@@ -29,6 +29,7 @@ function stripNavPrefix(nav: NavConfig, prefix: string): NavConfig {
|
|
|
29
29
|
...e,
|
|
30
30
|
slug: s(e.slug),
|
|
31
31
|
section: e.section ? walkChildren(e.section) : undefined,
|
|
32
|
+
children: e.children ? walkChildren(e.children) : undefined,
|
|
32
33
|
}))
|
|
33
34
|
|
|
34
35
|
return {
|
|
@@ -83,6 +84,11 @@ export function getSlugsFromConfig(nav: NavConfig): string[] {
|
|
|
83
84
|
slugs.push(child.slug)
|
|
84
85
|
}
|
|
85
86
|
}
|
|
87
|
+
if (entry.children) {
|
|
88
|
+
for (const child of flattenChildren(entry.children)) {
|
|
89
|
+
slugs.push(child.slug)
|
|
90
|
+
}
|
|
91
|
+
}
|
|
86
92
|
}
|
|
87
93
|
} else if ("slug" in item) {
|
|
88
94
|
slugs.push((item as NavEntry).slug)
|
|
@@ -112,6 +118,10 @@ export function getEntryBySlugFromConfig(nav: NavConfig, slug: string): (NavEntr
|
|
|
112
118
|
const match = flattenChildren(entry.section).find((c) => c.slug === normalized)
|
|
113
119
|
if (match) return match
|
|
114
120
|
}
|
|
121
|
+
if (entry.children) {
|
|
122
|
+
const match = flattenChildren(entry.children).find((c) => c.slug === normalized)
|
|
123
|
+
if (match) return match
|
|
124
|
+
}
|
|
115
125
|
}
|
|
116
126
|
} else if ("slug" in item) {
|
|
117
127
|
const entry = item as NavEntry
|
|
@@ -140,6 +150,10 @@ export function getGroupForSlugFromConfig(nav: NavConfig, slug: string): NavGrou
|
|
|
140
150
|
const match = flattenChildren(entry.section).find((c) => c.slug === normalized)
|
|
141
151
|
if (match) return group
|
|
142
152
|
}
|
|
153
|
+
if (entry.children) {
|
|
154
|
+
const match = flattenChildren(entry.children).find((c) => c.slug === normalized)
|
|
155
|
+
if (match) return group
|
|
156
|
+
}
|
|
143
157
|
}
|
|
144
158
|
}
|
|
145
159
|
|
|
@@ -162,6 +176,10 @@ export function getSectionForSlugFromConfig(nav: NavConfig, slug: string): NavEn
|
|
|
162
176
|
const match = flattenChildren(entry.section).find((c) => c.slug === normalized)
|
|
163
177
|
if (match) return entry
|
|
164
178
|
}
|
|
179
|
+
if (entry.children) {
|
|
180
|
+
const match = flattenChildren(entry.children).find((c) => c.slug === normalized)
|
|
181
|
+
if (match) return entry
|
|
182
|
+
}
|
|
165
183
|
}
|
|
166
184
|
}
|
|
167
185
|
|
|
@@ -184,6 +202,11 @@ export function getAllPublicEntries(nav: NavConfig): (NavEntry | NavChild)[] {
|
|
|
184
202
|
if (child.roles.length === 0) entries.push(child)
|
|
185
203
|
}
|
|
186
204
|
}
|
|
205
|
+
if (entry.children) {
|
|
206
|
+
for (const child of flattenChildren(entry.children)) {
|
|
207
|
+
if (child.roles.length === 0) entries.push(child)
|
|
208
|
+
}
|
|
209
|
+
}
|
|
187
210
|
}
|
|
188
211
|
} else if ("slug" in item) {
|
|
189
212
|
const entry = item as NavEntry
|