@neuronection/assistant-ui 0.15.0 → 0.17.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.
@@ -0,0 +1,442 @@
1
+ import { cn } from './chunk-BLJWR4ZV.js';
2
+ import * as React from 'react';
3
+ import * as PopoverPrimitive from '@radix-ui/react-popover';
4
+ import { ChevronRight, ChevronLeft, ChevronDown } from 'lucide-react';
5
+ import { jsxs, jsx } from 'react/jsx-runtime';
6
+
7
+ var FLYOUT_DELAY_MS = 150;
8
+ var itemButtonClass = (active, compact) => cn(
9
+ "flex w-full cursor-pointer items-center rounded-[var(--as-radius)] text-left transition-colors focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)] disabled:pointer-events-none disabled:opacity-50",
10
+ compact ? "gap-2 px-2.5 py-1.5 text-xs" : "gap-3 px-3 py-2.5 text-sm",
11
+ active ? "bg-[color-mix(in_srgb,var(--as-primary)_12%,transparent)] font-bold text-[var(--as-primary)]" : "font-medium text-[var(--as-fg)] hover:bg-[var(--as-muted)]"
12
+ );
13
+ var flyoutContentClass = "as-anim-pop z-[var(--as-z-popover)] min-w-44 rounded-[var(--as-radius-lg)] border border-[var(--as-border)] bg-[var(--as-surface-raised)] p-1 text-[var(--as-fg)] shadow-[var(--as-shadow-3)] focus:outline-none";
14
+ function Badge({ value, active }) {
15
+ return /* @__PURE__ */ jsx(
16
+ "span",
17
+ {
18
+ className: cn(
19
+ "inline-flex min-w-5 shrink-0 items-center justify-center rounded-full px-1.5 py-0.5 text-[11px] font-bold leading-none",
20
+ active ? "bg-[var(--as-primary)] text-[var(--as-primary-fg)]" : "bg-[var(--as-muted)] text-[var(--as-muted-fg)]"
21
+ ),
22
+ children: value
23
+ }
24
+ );
25
+ }
26
+ function ItemBadge({ badge, active }) {
27
+ if (badge === void 0) return null;
28
+ return /* @__PURE__ */ jsx("span", { className: "ml-auto", children: /* @__PURE__ */ jsx(Badge, { value: badge, active }) });
29
+ }
30
+ var SidebarNav = React.forwardRef(
31
+ function SidebarNav2({
32
+ items,
33
+ secondaryItems,
34
+ activeId,
35
+ onNavigate,
36
+ collapsed = false,
37
+ onCollapsedChange,
38
+ collapsible = false,
39
+ expandedIds,
40
+ onExpandedIdsChange,
41
+ header,
42
+ footer,
43
+ compact = false,
44
+ labels,
45
+ className,
46
+ navClassName
47
+ }, ref) {
48
+ const baseId = React.useId();
49
+ const listRef = React.useRef(null);
50
+ const secondaryRef = React.useRef(null);
51
+ const flyoutTimer = React.useRef(null);
52
+ const [openFlyout, setOpenFlyout] = React.useState(null);
53
+ const [internalExpanded, setInternalExpanded] = React.useState([]);
54
+ const controlledExpanded = expandedIds !== void 0 && onExpandedIdsChange !== void 0;
55
+ const expanded = controlledExpanded ? expandedIds : internalExpanded;
56
+ const setExpandedList = React.useCallback(
57
+ (next) => {
58
+ if (controlledExpanded) onExpandedIdsChange?.(next);
59
+ else setInternalExpanded(next);
60
+ },
61
+ [controlledExpanded, onExpandedIdsChange]
62
+ );
63
+ const toggleGroup = React.useCallback(
64
+ (id) => {
65
+ setExpandedList(
66
+ expanded.includes(id) ? expanded.filter((g) => g !== id) : [...expanded, id]
67
+ );
68
+ },
69
+ [expanded, setExpandedList]
70
+ );
71
+ React.useEffect(() => {
72
+ if (controlledExpanded || activeId == null) return;
73
+ const owner = items.find((it) => it.children?.some((c) => c.id === activeId)) ?? secondaryItems?.find((it) => it.children?.some((c) => c.id === activeId));
74
+ if (owner && !expanded.includes(owner.id)) {
75
+ setExpandedList([...expanded, owner.id]);
76
+ }
77
+ }, [activeId, items, secondaryItems, controlledExpanded]);
78
+ React.useEffect(() => {
79
+ return () => {
80
+ if (flyoutTimer.current) clearTimeout(flyoutTimer.current);
81
+ };
82
+ }, []);
83
+ const flyoutEnter = (id) => {
84
+ if (flyoutTimer.current) clearTimeout(flyoutTimer.current);
85
+ flyoutTimer.current = setTimeout(() => setOpenFlyout(id), FLYOUT_DELAY_MS);
86
+ };
87
+ const flyoutLeave = () => {
88
+ if (flyoutTimer.current) clearTimeout(flyoutTimer.current);
89
+ flyoutTimer.current = setTimeout(() => setOpenFlyout(null), FLYOUT_DELAY_MS);
90
+ };
91
+ const flyoutEnterCancel = () => {
92
+ if (flyoutTimer.current) clearTimeout(flyoutTimer.current);
93
+ };
94
+ const navigate = (id) => {
95
+ setOpenFlyout(null);
96
+ onNavigate?.(id);
97
+ };
98
+ const navRegions = () => [listRef.current, secondaryRef.current].filter(
99
+ (r) => r !== null
100
+ );
101
+ const visibleItems = () => {
102
+ return navRegions().flatMap(
103
+ (region) => Array.from(
104
+ region.querySelectorAll("[data-as-nav-item]")
105
+ ).filter((el) => el.closest("[hidden]") === null)
106
+ );
107
+ };
108
+ const focusSibling = (current, offset) => {
109
+ const all = visibleItems();
110
+ const index = all.indexOf(current);
111
+ if (index === -1) return;
112
+ const next = all[Math.min(Math.max(index + offset, 0), all.length - 1)];
113
+ next?.focus();
114
+ };
115
+ const handleFlyoutArrowKeys = (e) => {
116
+ if (e.key !== "ArrowDown" && e.key !== "ArrowUp") return;
117
+ e.preventDefault();
118
+ const buttons = Array.from(
119
+ e.currentTarget.querySelectorAll(
120
+ "button[data-as-flyout-item]:not([disabled])"
121
+ )
122
+ );
123
+ const index = buttons.indexOf(document.activeElement);
124
+ const step = e.key === "ArrowDown" ? 1 : buttons.length - 1;
125
+ buttons[(index + step) % buttons.length]?.focus();
126
+ };
127
+ const groupTriggerFor = (id) => navRegions().flatMap(
128
+ (r) => Array.from(r.querySelectorAll("[data-as-nav-group-id]"))
129
+ ).find((b) => b.dataset.asNavGroupId === id);
130
+ const firstChildFor = (id) => navRegions().flatMap(
131
+ (r) => Array.from(r.querySelectorAll("[data-as-nav-parent-id]"))
132
+ ).find((b) => b.dataset.asNavParentId === id && !b.disabled);
133
+ const handleListKeyDown = (e) => {
134
+ const button = e.target.closest(
135
+ "[data-as-nav-item]"
136
+ );
137
+ if (!button) return;
138
+ const groupId = button.dataset.asNavGroupId;
139
+ const parentId = button.dataset.asNavParentId;
140
+ switch (e.key) {
141
+ case "ArrowDown":
142
+ e.preventDefault();
143
+ focusSibling(button, 1);
144
+ break;
145
+ case "ArrowUp":
146
+ e.preventDefault();
147
+ focusSibling(button, -1);
148
+ break;
149
+ case "Home": {
150
+ e.preventDefault();
151
+ visibleItems()[0]?.focus();
152
+ break;
153
+ }
154
+ case "End": {
155
+ e.preventDefault();
156
+ const all = visibleItems();
157
+ all[all.length - 1]?.focus();
158
+ break;
159
+ }
160
+ case "ArrowRight":
161
+ if (groupId) {
162
+ e.preventDefault();
163
+ if (!expanded.includes(groupId)) {
164
+ setExpandedList([...expanded, groupId]);
165
+ } else {
166
+ firstChildFor(groupId)?.focus();
167
+ }
168
+ }
169
+ break;
170
+ case "ArrowLeft":
171
+ if (parentId) {
172
+ e.preventDefault();
173
+ groupTriggerFor(parentId)?.focus();
174
+ } else if (groupId && expanded.includes(groupId)) {
175
+ e.preventDefault();
176
+ toggleGroup(groupId);
177
+ }
178
+ break;
179
+ }
180
+ };
181
+ const navAria = labels?.navAria ?? "Main navigation";
182
+ const rail = collapsed;
183
+ const flyoutHeader = (text) => /* @__PURE__ */ jsx("div", { className: "border-b border-[var(--as-border)] px-2 py-1.5 text-xs font-bold text-[var(--as-muted-fg)]", children: text });
184
+ const sectionDividerClass = compact ? "mt-1 border-t border-[var(--as-border)] px-3 pb-0.5 pt-2 text-[10px] font-bold uppercase tracking-wide text-[var(--as-muted-fg)]" : "mt-2 border-t border-[var(--as-border)] px-3 pb-1 pt-3 text-[11px] font-bold uppercase tracking-wide text-[var(--as-muted-fg)]";
185
+ const listGapClass = compact ? "space-y-0.5" : "space-y-1";
186
+ const iconClass = compact ? "size-3.5" : "size-4";
187
+ const regionClass = compact ? "px-2.5 py-2" : "px-3 py-3";
188
+ const renderItem = (item, index, list) => {
189
+ if (item.children !== void 0 && item.children.length === 0) {
190
+ return null;
191
+ }
192
+ const sectionSeen = !rail && item.section !== void 0 && list.findIndex((i) => i.section === item.section) === index;
193
+ const sectionDivider = sectionSeen ? /* @__PURE__ */ jsx("div", { role: "presentation", className: sectionDividerClass, children: item.section }) : null;
194
+ const active = item.id === activeId;
195
+ const childActive = item.children?.some((c) => c.id === activeId) ?? false;
196
+ const isExpanded = expanded.includes(item.id);
197
+ const Icon = item.icon;
198
+ const groupId = `${baseId}-group-${item.id}`;
199
+ if (item.children && item.children.length > 0 && rail) {
200
+ return /* @__PURE__ */ jsxs("li", { children: [
201
+ sectionDivider,
202
+ /* @__PURE__ */ jsxs(
203
+ PopoverPrimitive.Root,
204
+ {
205
+ open: openFlyout === item.id,
206
+ onOpenChange: (open) => {
207
+ if (!open) setOpenFlyout(null);
208
+ },
209
+ children: [
210
+ /* @__PURE__ */ jsx(PopoverPrimitive.Anchor, { asChild: true, children: /* @__PURE__ */ jsx(
211
+ "button",
212
+ {
213
+ type: "button",
214
+ "data-as-nav-item": true,
215
+ "data-as-nav-group-id": item.id,
216
+ disabled: item.disabled,
217
+ "aria-label": labels?.openGroup ?? `Open ${item.label} menu`,
218
+ "aria-haspopup": "true",
219
+ "aria-expanded": openFlyout === item.id,
220
+ onClick: () => setOpenFlyout(item.id),
221
+ onKeyDown: (e) => {
222
+ if (e.key === "Enter" || e.key === " ") {
223
+ e.preventDefault();
224
+ setOpenFlyout(item.id);
225
+ }
226
+ },
227
+ onMouseEnter: () => flyoutEnter(item.id),
228
+ onMouseLeave: flyoutLeave,
229
+ className: cn(itemButtonClass(active || childActive, compact), "justify-center px-0"),
230
+ children: Icon ? /* @__PURE__ */ jsx(
231
+ Icon,
232
+ {
233
+ className: cn(
234
+ "size-5 shrink-0",
235
+ active || childActive ? "text-[var(--as-primary)]" : "text-[var(--as-muted-fg)]"
236
+ ),
237
+ "aria-hidden": true
238
+ }
239
+ ) : null
240
+ }
241
+ ) }),
242
+ /* @__PURE__ */ jsx(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsxs(
243
+ PopoverPrimitive.Content,
244
+ {
245
+ side: "right",
246
+ sideOffset: 8,
247
+ "aria-label": item.label,
248
+ onCloseAutoFocus: (e) => {
249
+ e.preventDefault();
250
+ groupTriggerFor(item.id)?.focus();
251
+ },
252
+ onMouseEnter: flyoutEnterCancel,
253
+ onMouseLeave: flyoutLeave,
254
+ onKeyDown: handleFlyoutArrowKeys,
255
+ className: flyoutContentClass,
256
+ children: [
257
+ flyoutHeader(item.label),
258
+ /* @__PURE__ */ jsx("ul", { className: "mt-1 space-y-0.5", children: item.children.map((child) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs(
259
+ "button",
260
+ {
261
+ type: "button",
262
+ "data-as-flyout-item": true,
263
+ disabled: child.disabled,
264
+ onClick: () => navigate(child.id),
265
+ "aria-current": child.id === activeId ? "page" : void 0,
266
+ className: cn(
267
+ "flex w-full cursor-pointer items-center gap-2 rounded-[calc(var(--as-radius-sm)-2px)] px-2 py-1.5 text-left text-sm outline-none transition-colors focus:bg-[var(--as-secondary)] disabled:pointer-events-none disabled:opacity-50",
268
+ child.id === activeId && "font-bold text-[var(--as-primary)]"
269
+ ),
270
+ children: [
271
+ child.icon ? /* @__PURE__ */ jsx(child.icon, { "aria-hidden": true }) : null,
272
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate", children: child.label }),
273
+ /* @__PURE__ */ jsx(ItemBadge, { badge: child.badge, active: child.id === activeId })
274
+ ]
275
+ }
276
+ ) }, child.id)) })
277
+ ]
278
+ }
279
+ ) })
280
+ ]
281
+ }
282
+ )
283
+ ] }, item.id);
284
+ }
285
+ if (item.children && item.children.length > 0) {
286
+ return /* @__PURE__ */ jsxs("li", { children: [
287
+ sectionDivider,
288
+ /* @__PURE__ */ jsxs(
289
+ "button",
290
+ {
291
+ type: "button",
292
+ "data-as-nav-item": true,
293
+ "data-as-nav-group-id": item.id,
294
+ disabled: item.disabled,
295
+ "aria-expanded": isExpanded,
296
+ "aria-controls": groupId,
297
+ onClick: () => toggleGroup(item.id),
298
+ className: itemButtonClass(active || childActive, compact),
299
+ children: [
300
+ Icon ? /* @__PURE__ */ jsx(
301
+ Icon,
302
+ {
303
+ className: cn(
304
+ iconClass,
305
+ "shrink-0",
306
+ active || childActive ? "text-[var(--as-primary)]" : "text-[var(--as-muted-fg)]"
307
+ ),
308
+ "aria-hidden": true
309
+ }
310
+ ) : null,
311
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate", children: item.label }),
312
+ /* @__PURE__ */ jsx(ItemBadge, { badge: item.badge, active: active || childActive }),
313
+ isExpanded ? /* @__PURE__ */ jsx(ChevronDown, { className: cn(iconClass, "shrink-0 text-[var(--as-muted-fg)]"), "aria-hidden": true }) : /* @__PURE__ */ jsx(ChevronRight, { className: cn(iconClass, "shrink-0 text-[var(--as-muted-fg)]"), "aria-hidden": true })
314
+ ]
315
+ }
316
+ ),
317
+ /* @__PURE__ */ jsx("ul", { id: groupId, hidden: !isExpanded, className: cn("mt-1 space-y-0.5", compact ? "pl-4" : "pl-6"), children: item.children.map((child) => {
318
+ const childActiveItem = child.id === activeId;
319
+ const ChildIcon = child.icon;
320
+ const sectionSeen2 = child.section !== void 0 && item.children.findIndex(
321
+ (c) => c.section === child.section
322
+ ) === item.children.indexOf(child);
323
+ return /* @__PURE__ */ jsxs("li", { children: [
324
+ sectionSeen2 ? /* @__PURE__ */ jsx("div", { role: "presentation", className: sectionDividerClass, children: child.section }) : null,
325
+ /* @__PURE__ */ jsxs(
326
+ "button",
327
+ {
328
+ type: "button",
329
+ "data-as-nav-item": true,
330
+ "data-as-nav-parent-id": item.id,
331
+ disabled: child.disabled,
332
+ "aria-current": childActiveItem ? "page" : void 0,
333
+ onClick: () => navigate(child.id),
334
+ className: cn(
335
+ itemButtonClass(childActiveItem, compact),
336
+ compact ? "py-1.5 pl-2.5 pr-1.5" : "py-2 pl-3 pr-2"
337
+ ),
338
+ children: [
339
+ ChildIcon ? /* @__PURE__ */ jsx(ChildIcon, { className: cn(iconClass, "shrink-0"), "aria-hidden": true }) : null,
340
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate", children: child.label }),
341
+ /* @__PURE__ */ jsx(ItemBadge, { badge: child.badge, active: childActiveItem })
342
+ ]
343
+ }
344
+ )
345
+ ] }, child.id);
346
+ }) })
347
+ ] }, item.id);
348
+ }
349
+ return /* @__PURE__ */ jsxs("li", { children: [
350
+ sectionDivider,
351
+ /* @__PURE__ */ jsxs(
352
+ "button",
353
+ {
354
+ type: "button",
355
+ "data-as-nav-item": true,
356
+ disabled: item.disabled,
357
+ title: rail ? item.label : void 0,
358
+ "aria-label": rail ? item.label : void 0,
359
+ "aria-current": active ? "page" : void 0,
360
+ onClick: () => navigate(item.id),
361
+ className: cn(itemButtonClass(active, compact), rail && "justify-center px-0"),
362
+ children: [
363
+ Icon ? /* @__PURE__ */ jsx(
364
+ Icon,
365
+ {
366
+ className: cn(
367
+ "shrink-0",
368
+ rail ? "size-5" : iconClass,
369
+ active ? "text-[var(--as-primary)]" : "text-[var(--as-muted-fg)]"
370
+ ),
371
+ "aria-hidden": true
372
+ }
373
+ ) : null,
374
+ !rail ? /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate", children: item.label }) : null,
375
+ !rail ? /* @__PURE__ */ jsx(ItemBadge, { badge: item.badge, active }) : null
376
+ ]
377
+ }
378
+ )
379
+ ] }, item.id);
380
+ };
381
+ return /* @__PURE__ */ jsxs(
382
+ "nav",
383
+ {
384
+ ref,
385
+ "data-as": "sidebar-nav",
386
+ "data-as-compact": compact ? "" : void 0,
387
+ "aria-label": navAria,
388
+ className: cn(
389
+ "relative flex h-full flex-col border-r border-[var(--as-border)] bg-[var(--as-surface)] text-[var(--as-fg)] transition-[width] duration-200",
390
+ rail ? "w-20" : "w-64",
391
+ className
392
+ ),
393
+ children: [
394
+ collapsible ? /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-y-0 -right-3 z-10 hidden flex-col justify-center lg:flex", children: /* @__PURE__ */ jsx(
395
+ "button",
396
+ {
397
+ type: "button",
398
+ onClick: () => onCollapsedChange?.(!collapsed),
399
+ title: collapsed ? labels?.expand ?? "Expand sidebar" : labels?.collapse ?? "Collapse sidebar",
400
+ "aria-label": collapsed ? labels?.expand ?? "Expand sidebar" : labels?.collapse ?? "Collapse sidebar",
401
+ className: "pointer-events-auto flex size-6 items-center justify-center rounded-lg border border-[var(--as-border)] bg-[var(--as-surface-raised)] text-[var(--as-muted-fg)] shadow-[var(--as-shadow-2)] transition-colors hover:text-[var(--as-fg)] focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)]",
402
+ children: collapsed ? /* @__PURE__ */ jsx(ChevronRight, { className: "size-3.5", "aria-hidden": true }) : /* @__PURE__ */ jsx(ChevronLeft, { className: "size-3.5", "aria-hidden": true })
403
+ }
404
+ ) }) : null,
405
+ header ? /* @__PURE__ */ jsx("div", { className: "shrink-0", children: header }) : null,
406
+ /* @__PURE__ */ jsx(
407
+ "div",
408
+ {
409
+ ref: listRef,
410
+ onKeyDown: handleListKeyDown,
411
+ className: cn("min-h-0 flex-1 overflow-y-auto", regionClass, navClassName),
412
+ children: /* @__PURE__ */ jsx("ul", { className: listGapClass, children: items.map((item, index) => renderItem(item, index, items)) })
413
+ }
414
+ ),
415
+ secondaryItems && secondaryItems.length > 0 ? /* @__PURE__ */ jsx(
416
+ "div",
417
+ {
418
+ ref: secondaryRef,
419
+ onKeyDown: handleListKeyDown,
420
+ className: cn("shrink-0 border-t border-[var(--as-border)]", regionClass),
421
+ children: /* @__PURE__ */ jsx("ul", { className: listGapClass, children: secondaryItems.map((item, index) => renderItem(item, index, secondaryItems)) })
422
+ }
423
+ ) : null,
424
+ footer ? /* @__PURE__ */ jsx(
425
+ "div",
426
+ {
427
+ className: cn(
428
+ "shrink-0 border-t border-[var(--as-border)]",
429
+ compact ? "px-2.5 py-2" : "p-3"
430
+ ),
431
+ children: footer
432
+ }
433
+ ) : null
434
+ ]
435
+ }
436
+ );
437
+ }
438
+ );
439
+
440
+ export { SidebarNav };
441
+ //# sourceMappingURL=chunk-SW3YNICQ.js.map
442
+ //# sourceMappingURL=chunk-SW3YNICQ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/sidebar-nav/SidebarNav.tsx"],"names":["SidebarNav","sectionSeen"],"mappings":"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","file":"chunk-SW3YNICQ.js","sourcesContent":["import * as React from 'react'\nimport * as PopoverPrimitive from '@radix-ui/react-popover'\nimport {\n ChevronDown,\n ChevronLeft,\n ChevronRight,\n type LucideIcon,\n} from 'lucide-react'\nimport { cn } from '../../lib/utils'\n\nexport interface NavChild {\n id: string\n label: string\n icon?: LucideIcon\n badge?: string | number\n /** Divider label rendered above this child (first occurrence only). */\n section?: string\n disabled?: boolean\n}\n\nexport interface NavItem {\n id: string\n label: string\n icon?: LucideIcon\n badge?: string | number\n /** One nesting level; deeper trees stay app-side. */\n children?: NavChild[]\n disabled?: boolean\n /** Divider label rendered above this item (first occurrence only) —\n * for flat sidebars with visual groups. Ignored in the collapsed rail. */\n section?: string\n}\n\nexport interface SidebarNavLabels {\n /** aria-label on the <nav> element. */\n navAria?: string\n /** Collapsed-rail toggle title when collapsed. */\n expand?: string\n /** Collapsed-rail toggle title when expanded. */\n collapse?: string\n /** aria-label for a collapsed group's flyout trigger. */\n openGroup?: string\n}\n\nexport interface SidebarNavProps {\n /** Pre-filtered by the app (roles, feature flags); order = render order. */\n items: NavItem[]\n /** Flat items pinned below the scroll area, above `footer` (the\n * Settings/About pattern). Same rendering, active state, rail behavior\n * and keyboard traversal order as `items`. */\n secondaryItems?: NavItem[]\n /** The app resolves route → id; matching logic stays app-side. */\n activeId?: string | null\n /** Fires for leaves only; group triggers toggle expansion instead. */\n onNavigate?: (id: string) => void\n /** Controlled icon rail. */\n collapsed?: boolean\n onCollapsedChange?: (collapsed: boolean) => void\n /** Renders the rail collapse/expand toggle handle (desktop only). */\n collapsible?: boolean\n /** Controlled group expansion; uncontrolled defaults to internal\n * state + auto-expand when activeId enters a group. */\n expandedIds?: string[]\n onExpandedIdsChange?: (ids: string[]) => void\n /** Slot above the list (brand, logo). */\n header?: React.ReactNode\n /** Slot below the list and pinned items (version, legal links). */\n footer?: React.ReactNode\n /** Denser layout for short viewports: tighter item padding, smaller\n * icons/typography, slimmer regions. Presentational only — the app\n * decides when (e.g. a `max-height` media query). Composes with\n * `collapsed`. */\n compact?: boolean\n labels?: SidebarNavLabels\n className?: string\n /** Targets the scrollable list region. */\n navClassName?: string\n}\n\nconst FLYOUT_DELAY_MS = 150\n\nconst itemButtonClass = (active: boolean, compact: boolean) =>\n cn(\n 'flex w-full cursor-pointer items-center rounded-[var(--as-radius)] text-left transition-colors focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)] disabled:pointer-events-none disabled:opacity-50',\n compact\n ? 'gap-2 px-2.5 py-1.5 text-xs'\n : 'gap-3 px-3 py-2.5 text-sm',\n active\n ? 'bg-[color-mix(in_srgb,var(--as-primary)_12%,transparent)] font-bold text-[var(--as-primary)]'\n : 'font-medium text-[var(--as-fg)] hover:bg-[var(--as-muted)]',\n )\n\nconst flyoutContentClass =\n 'as-anim-pop z-[var(--as-z-popover)] min-w-44 rounded-[var(--as-radius-lg)] border border-[var(--as-border)] bg-[var(--as-surface-raised)] p-1 text-[var(--as-fg)] shadow-[var(--as-shadow-3)] focus:outline-none'\n\nfunction Badge({ value, active }: { value: string | number; active: boolean }) {\n return (\n <span\n className={cn(\n 'inline-flex min-w-5 shrink-0 items-center justify-center rounded-full px-1.5 py-0.5 text-[11px] font-bold leading-none',\n active\n ? 'bg-[var(--as-primary)] text-[var(--as-primary-fg)]'\n : 'bg-[var(--as-muted)] text-[var(--as-muted-fg)]',\n )}\n >\n {value}\n </span>\n )\n}\n\nfunction ItemBadge({ badge, active }: { badge?: string | number; active: boolean }) {\n if (badge === undefined) return null\n return (\n <span className=\"ml-auto\">\n <Badge value={badge} active={active} />\n </span>\n )\n}\n\nexport const SidebarNav = React.forwardRef<HTMLElement, SidebarNavProps>(\n function SidebarNav(\n {\n items,\n secondaryItems,\n activeId,\n onNavigate,\n collapsed = false,\n onCollapsedChange,\n collapsible = false,\n expandedIds,\n onExpandedIdsChange,\n header,\n footer,\n compact = false,\n labels,\n className,\n navClassName,\n },\n ref,\n ) {\n const baseId = React.useId()\n const listRef = React.useRef<HTMLDivElement>(null)\n const secondaryRef = React.useRef<HTMLDivElement>(null)\n const flyoutTimer = React.useRef<ReturnType<typeof setTimeout> | null>(null)\n const [openFlyout, setOpenFlyout] = React.useState<string | null>(null)\n const [internalExpanded, setInternalExpanded] = React.useState<string[]>([])\n\n const controlledExpanded =\n expandedIds !== undefined && onExpandedIdsChange !== undefined\n const expanded = controlledExpanded ? (expandedIds as string[]) : internalExpanded\n\n const setExpandedList = React.useCallback(\n (next: string[]) => {\n if (controlledExpanded) onExpandedIdsChange?.(next)\n else setInternalExpanded(next)\n },\n [controlledExpanded, onExpandedIdsChange],\n )\n\n const toggleGroup = React.useCallback(\n (id: string) => {\n setExpandedList(\n expanded.includes(id)\n ? expanded.filter((g) => g !== id)\n : [...expanded, id],\n )\n },\n [expanded, setExpandedList],\n )\n\n // Auto-expand the group containing the active item so the highlighted\n // entry is always visible (uncontrolled mode only — the app owns\n // expansion when controlled).\n React.useEffect(() => {\n if (controlledExpanded || activeId == null) return\n const owner =\n items.find((it) => it.children?.some((c) => c.id === activeId)) ??\n secondaryItems?.find((it) => it.children?.some((c) => c.id === activeId))\n if (owner && !expanded.includes(owner.id)) {\n setExpandedList([...expanded, owner.id])\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [activeId, items, secondaryItems, controlledExpanded])\n\n React.useEffect(() => {\n return () => {\n if (flyoutTimer.current) clearTimeout(flyoutTimer.current)\n }\n }, [])\n\n const flyoutEnter = (id: string) => {\n if (flyoutTimer.current) clearTimeout(flyoutTimer.current)\n flyoutTimer.current = setTimeout(() => setOpenFlyout(id), FLYOUT_DELAY_MS)\n }\n const flyoutLeave = () => {\n if (flyoutTimer.current) clearTimeout(flyoutTimer.current)\n flyoutTimer.current = setTimeout(() => setOpenFlyout(null), FLYOUT_DELAY_MS)\n }\n const flyoutEnterCancel = () => {\n if (flyoutTimer.current) clearTimeout(flyoutTimer.current)\n }\n\n const navigate = (id: string) => {\n setOpenFlyout(null)\n onNavigate?.(id)\n }\n\n // ---- keyboard navigation over the visible list ----\n const navRegions = () =>\n [listRef.current, secondaryRef.current].filter(\n (r): r is HTMLDivElement => r !== null,\n )\n\n const visibleItems = (): HTMLButtonElement[] => {\n return navRegions().flatMap((region) =>\n Array.from(\n region.querySelectorAll<HTMLButtonElement>('[data-as-nav-item]'),\n ).filter((el) => el.closest('[hidden]') === null),\n )\n }\n\n const focusSibling = (current: HTMLElement, offset: number) => {\n const all = visibleItems()\n const index = all.indexOf(current as HTMLButtonElement)\n if (index === -1) return\n const next = all[Math.min(Math.max(index + offset, 0), all.length - 1)]\n next?.focus()\n }\n\n const handleFlyoutArrowKeys = (e: React.KeyboardEvent) => {\n if (e.key !== 'ArrowDown' && e.key !== 'ArrowUp') return\n e.preventDefault()\n const buttons = Array.from(\n (e.currentTarget as HTMLElement).querySelectorAll<HTMLButtonElement>(\n 'button[data-as-flyout-item]:not([disabled])',\n ),\n )\n const index = buttons.indexOf(document.activeElement as HTMLButtonElement)\n const step = e.key === 'ArrowDown' ? 1 : buttons.length - 1\n buttons[(index + step) % buttons.length]?.focus()\n }\n\n const groupTriggerFor = (id: string) =>\n navRegions()\n .flatMap((r) =>\n Array.from(r.querySelectorAll<HTMLButtonElement>('[data-as-nav-group-id]')),\n )\n .find((b) => b.dataset.asNavGroupId === id)\n\n const firstChildFor = (id: string) =>\n navRegions()\n .flatMap((r) =>\n Array.from(r.querySelectorAll<HTMLButtonElement>('[data-as-nav-parent-id]')),\n )\n .find((b) => b.dataset.asNavParentId === id && !b.disabled)\n\n const handleListKeyDown = (e: React.KeyboardEvent) => {\n const button = (e.target as HTMLElement).closest<HTMLButtonElement>(\n '[data-as-nav-item]',\n )\n if (!button) return\n const groupId = button.dataset.asNavGroupId\n const parentId = button.dataset.asNavParentId\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault()\n focusSibling(button, 1)\n break\n case 'ArrowUp':\n e.preventDefault()\n focusSibling(button, -1)\n break\n case 'Home': {\n e.preventDefault()\n visibleItems()[0]?.focus()\n break\n }\n case 'End': {\n e.preventDefault()\n const all = visibleItems()\n all[all.length - 1]?.focus()\n break\n }\n case 'ArrowRight':\n if (groupId) {\n e.preventDefault()\n if (!expanded.includes(groupId)) {\n setExpandedList([...expanded, groupId])\n } else {\n firstChildFor(groupId)?.focus()\n }\n }\n break\n case 'ArrowLeft':\n if (parentId) {\n e.preventDefault()\n groupTriggerFor(parentId)?.focus()\n } else if (groupId && expanded.includes(groupId)) {\n e.preventDefault()\n toggleGroup(groupId)\n }\n break\n }\n }\n\n const navAria = labels?.navAria ?? 'Main navigation'\n const rail = collapsed\n\n const flyoutHeader = (text: string) => (\n <div className=\"border-b border-[var(--as-border)] px-2 py-1.5 text-xs font-bold text-[var(--as-muted-fg)]\">\n {text}\n </div>\n )\n\n const sectionDividerClass = compact\n ? 'mt-1 border-t border-[var(--as-border)] px-3 pb-0.5 pt-2 text-[10px] font-bold uppercase tracking-wide text-[var(--as-muted-fg)]'\n : 'mt-2 border-t border-[var(--as-border)] px-3 pb-1 pt-3 text-[11px] font-bold uppercase tracking-wide text-[var(--as-muted-fg)]'\n const listGapClass = compact ? 'space-y-0.5' : 'space-y-1'\n const iconClass = compact ? 'size-3.5' : 'size-4'\n const regionClass = compact ? 'px-2.5 py-2' : 'px-3 py-3'\n\n const renderItem = (item: NavItem, index: number, list: NavItem[]) => {\n // Group whose children were all filtered out app-side renders\n // nothing (presentational).\n if (item.children !== undefined && item.children.length === 0) {\n return null\n }\n const sectionSeen =\n !rail &&\n item.section !== undefined &&\n list.findIndex((i) => i.section === item.section) === index\n const sectionDivider = sectionSeen ? (\n <div role=\"presentation\" className={sectionDividerClass}>\n {item.section}\n </div>\n ) : null\n const active = item.id === activeId\n const childActive = item.children?.some((c) => c.id === activeId) ?? false\n const isExpanded = expanded.includes(item.id)\n const Icon = item.icon\n const groupId = `${baseId}-group-${item.id}`\n\n if (item.children && item.children.length > 0 && rail) {\n return (\n <li key={item.id}>\n {sectionDivider}\n <PopoverPrimitive.Root\n open={openFlyout === item.id}\n onOpenChange={(open) => {\n if (!open) setOpenFlyout(null)\n }}\n >\n <PopoverPrimitive.Anchor asChild>\n <button\n type=\"button\"\n data-as-nav-item\n data-as-nav-group-id={item.id}\n disabled={item.disabled}\n aria-label={labels?.openGroup ?? `Open ${item.label} menu`}\n aria-haspopup=\"true\"\n aria-expanded={openFlyout === item.id}\n onClick={() => setOpenFlyout(item.id)}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n setOpenFlyout(item.id)\n }\n }}\n onMouseEnter={() => flyoutEnter(item.id)}\n onMouseLeave={flyoutLeave}\n className={cn(itemButtonClass(active || childActive, compact), 'justify-center px-0')}\n >\n {Icon ? (\n <Icon\n className={cn(\n 'size-5 shrink-0',\n active || childActive\n ? 'text-[var(--as-primary)]'\n : 'text-[var(--as-muted-fg)]',\n )}\n aria-hidden\n />\n ) : null}\n </button>\n </PopoverPrimitive.Anchor>\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Content\n side=\"right\"\n sideOffset={8}\n aria-label={item.label}\n onCloseAutoFocus={(e) => {\n // Menu-standard: focus returns to the trigger.\n e.preventDefault()\n groupTriggerFor(item.id)?.focus()\n }}\n onMouseEnter={flyoutEnterCancel}\n onMouseLeave={flyoutLeave}\n onKeyDown={handleFlyoutArrowKeys}\n className={flyoutContentClass}\n >\n {flyoutHeader(item.label)}\n <ul className=\"mt-1 space-y-0.5\">\n {item.children.map((child) => (\n <li key={child.id}>\n <button\n type=\"button\"\n data-as-flyout-item\n disabled={child.disabled}\n onClick={() => navigate(child.id)}\n aria-current={child.id === activeId ? 'page' : undefined}\n className={cn(\n 'flex w-full cursor-pointer items-center gap-2 rounded-[calc(var(--as-radius-sm)-2px)] px-2 py-1.5 text-left text-sm outline-none transition-colors focus:bg-[var(--as-secondary)] disabled:pointer-events-none disabled:opacity-50',\n child.id === activeId && 'font-bold text-[var(--as-primary)]',\n )}\n >\n {child.icon ? <child.icon aria-hidden /> : null}\n <span className=\"min-w-0 flex-1 truncate\">{child.label}</span>\n <ItemBadge badge={child.badge} active={child.id === activeId} />\n </button>\n </li>\n ))}\n </ul>\n </PopoverPrimitive.Content>\n </PopoverPrimitive.Portal>\n </PopoverPrimitive.Root>\n </li>\n )\n }\n\n if (item.children && item.children.length > 0) {\n return (\n <li key={item.id}>\n {sectionDivider}\n <button\n type=\"button\"\n data-as-nav-item\n data-as-nav-group-id={item.id}\n disabled={item.disabled}\n aria-expanded={isExpanded}\n aria-controls={groupId}\n onClick={() => toggleGroup(item.id)}\n className={itemButtonClass(active || childActive, compact)}\n >\n {Icon ? (\n <Icon\n className={cn(\n iconClass,\n 'shrink-0',\n active || childActive\n ? 'text-[var(--as-primary)]'\n : 'text-[var(--as-muted-fg)]',\n )}\n aria-hidden\n />\n ) : null}\n <span className=\"min-w-0 flex-1 truncate\">{item.label}</span>\n <ItemBadge badge={item.badge} active={active || childActive} />\n {isExpanded ? (\n <ChevronDown className={cn(iconClass, 'shrink-0 text-[var(--as-muted-fg)]')} aria-hidden />\n ) : (\n <ChevronRight className={cn(iconClass, 'shrink-0 text-[var(--as-muted-fg)]')} aria-hidden />\n )}\n </button>\n <ul id={groupId} hidden={!isExpanded} className={cn(\"mt-1 space-y-0.5\", compact ? \"pl-4\" : \"pl-6\")}>\n {item.children.map((child) => {\n const childActiveItem = child.id === activeId\n const ChildIcon = child.icon\n const sectionSeen =\n child.section !== undefined &&\n item.children!.findIndex(\n (c) => c.section === child.section,\n ) === item.children!.indexOf(child)\n return (\n <li key={child.id}>\n {sectionSeen ? (\n <div role=\"presentation\" className={sectionDividerClass}>\n {child.section}\n </div>\n ) : null}\n <button\n type=\"button\"\n data-as-nav-item\n data-as-nav-parent-id={item.id}\n disabled={child.disabled}\n aria-current={childActiveItem ? 'page' : undefined}\n onClick={() => navigate(child.id)}\n className={cn(\n itemButtonClass(childActiveItem, compact),\n compact ? 'py-1.5 pl-2.5 pr-1.5' : 'py-2 pl-3 pr-2',\n )}\n >\n {ChildIcon ? (\n <ChildIcon className={cn(iconClass, 'shrink-0')} aria-hidden />\n ) : null}\n <span className=\"min-w-0 flex-1 truncate\">{child.label}</span>\n <ItemBadge badge={child.badge} active={childActiveItem} />\n </button>\n </li>\n )\n })}\n </ul>\n </li>\n )\n }\n\n return (\n <li key={item.id}>\n {sectionDivider}\n <button\n type=\"button\"\n data-as-nav-item\n disabled={item.disabled}\n title={rail ? item.label : undefined}\n aria-label={rail ? item.label : undefined}\n aria-current={active ? 'page' : undefined}\n onClick={() => navigate(item.id)}\n className={cn(itemButtonClass(active, compact), rail && 'justify-center px-0')}\n >\n {Icon ? (\n <Icon\n className={cn(\n 'shrink-0',\n rail ? 'size-5' : iconClass,\n active ? 'text-[var(--as-primary)]' : 'text-[var(--as-muted-fg)]',\n )}\n aria-hidden\n />\n ) : null}\n {!rail ? <span className=\"min-w-0 flex-1 truncate\">{item.label}</span> : null}\n {!rail ? <ItemBadge badge={item.badge} active={active} /> : null}\n </button>\n </li>\n )\n }\n\n return (\n <nav\n ref={ref}\n data-as=\"sidebar-nav\"\n data-as-compact={compact ? '' : undefined}\n aria-label={navAria}\n className={cn(\n 'relative flex h-full flex-col border-r border-[var(--as-border)] bg-[var(--as-surface)] text-[var(--as-fg)] transition-[width] duration-200',\n rail ? 'w-20' : 'w-64',\n className,\n )}\n >\n {collapsible ? (\n <div className=\"pointer-events-none absolute inset-y-0 -right-3 z-10 hidden flex-col justify-center lg:flex\">\n <button\n type=\"button\"\n onClick={() => onCollapsedChange?.(!collapsed)}\n title={\n collapsed\n ? (labels?.expand ?? 'Expand sidebar')\n : (labels?.collapse ?? 'Collapse sidebar')\n }\n aria-label={\n collapsed\n ? (labels?.expand ?? 'Expand sidebar')\n : (labels?.collapse ?? 'Collapse sidebar')\n }\n className=\"pointer-events-auto flex size-6 items-center justify-center rounded-lg border border-[var(--as-border)] bg-[var(--as-surface-raised)] text-[var(--as-muted-fg)] shadow-[var(--as-shadow-2)] transition-colors hover:text-[var(--as-fg)] focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)]\"\n >\n {collapsed ? (\n <ChevronRight className=\"size-3.5\" aria-hidden />\n ) : (\n <ChevronLeft className=\"size-3.5\" aria-hidden />\n )}\n </button>\n </div>\n ) : null}\n\n {header ? <div className=\"shrink-0\">{header}</div> : null}\n\n <div\n ref={listRef}\n onKeyDown={handleListKeyDown}\n className={cn('min-h-0 flex-1 overflow-y-auto', regionClass, navClassName)}\n >\n <ul className={listGapClass}>\n {items.map((item, index) => renderItem(item, index, items))}\n </ul>\n </div>\n\n {secondaryItems && secondaryItems.length > 0 ? (\n <div\n ref={secondaryRef}\n onKeyDown={handleListKeyDown}\n className={cn('shrink-0 border-t border-[var(--as-border)]', regionClass)}\n >\n <ul className={listGapClass}>\n {secondaryItems.map((item, index) => renderItem(item, index, secondaryItems))}\n </ul>\n </div>\n ) : null}\n\n {footer ? (\n <div\n className={cn(\n 'shrink-0 border-t border-[var(--as-border)]',\n compact ? 'px-2.5 py-2' : 'p-3',\n )}\n >\n {footer}\n </div>\n ) : null}\n </nav>\n )\n },\n)\n"]}
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  export { ViewToggle } from './chunk-MXOBOS4Y.js';
2
2
  export { Stepper, Wizard } from './chunk-YMCMUAIF.js';
3
3
  export { SettingsShell } from './chunk-AHLNXCP2.js';
4
- export { SidebarNav } from './chunk-EZTQMJ5I.js';
4
+ export { SidebarNav } from './chunk-SW3YNICQ.js';
5
5
  export { UserMenu } from './chunk-535TM7SK.js';
6
6
  export { ThemeScope } from './chunk-TGU3PKNM.js';
7
7
  export { TimeList } from './chunk-GVOC3ARM.js';
@@ -41,7 +41,7 @@ export { Combobox, ComboboxMulti } from './chunk-AATZUVW4.js';
41
41
  export { ConfirmationModal } from './chunk-2YQSA5AE.js';
42
42
  export { rawTokens, semanticTokens } from './chunk-GDGKARRB.js';
43
43
  export { AiActionsDropdown } from './chunk-I37SYHM7.js';
44
- export { AboutCard, AboutFooterLine, AboutLinkList, AboutNote, AboutPanel, FamilyBadge, SponsorCard, TechChips } from './chunk-7RTSSBBR.js';
44
+ export { AboutCard, AboutFooterLine, AboutLinkList, AboutNote, AboutPanel, FamilyBadge, SponsorCard, TechChips } from './chunk-INMAUGBK.js';
45
45
  export { CareerMark, HealthMark, NeuronectionMark, NeuronectionWordmark, StudyMark, useLogoId } from './chunk-Q2JMEAKN.js';
46
46
  export { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from './chunk-RYE5YCFF.js';
47
47
  export { ChipList } from './chunk-QUPGIPTT.js';
@@ -35,6 +35,10 @@ interface SidebarNavLabels {
35
35
  interface SidebarNavProps {
36
36
  /** Pre-filtered by the app (roles, feature flags); order = render order. */
37
37
  items: NavItem[];
38
+ /** Flat items pinned below the scroll area, above `footer` (the
39
+ * Settings/About pattern). Same rendering, active state, rail behavior
40
+ * and keyboard traversal order as `items`. */
41
+ secondaryItems?: NavItem[];
38
42
  /** The app resolves route → id; matching logic stays app-side. */
39
43
  activeId?: string | null;
40
44
  /** Fires for leaves only; group triggers toggle expansion instead. */
@@ -50,8 +54,13 @@ interface SidebarNavProps {
50
54
  onExpandedIdsChange?: (ids: string[]) => void;
51
55
  /** Slot above the list (brand, logo). */
52
56
  header?: React.ReactNode;
53
- /** Slot below the list (settings, profile, version). */
57
+ /** Slot below the list and pinned items (version, legal links). */
54
58
  footer?: React.ReactNode;
59
+ /** Denser layout for short viewports: tighter item padding, smaller
60
+ * icons/typography, slimmer regions. Presentational only — the app
61
+ * decides when (e.g. a `max-height` media query). Composes with
62
+ * `collapsed`. */
63
+ compact?: boolean;
55
64
  labels?: SidebarNavLabels;
56
65
  className?: string;
57
66
  /** Targets the scrollable list region. */
@@ -1,3 +1,3 @@
1
- export { SidebarNav } from './chunk-EZTQMJ5I.js';
1
+ export { SidebarNav } from './chunk-SW3YNICQ.js';
2
2
  //# sourceMappingURL=sidebar-nav.js.map
3
3
  //# sourceMappingURL=sidebar-nav.js.map