laif-ds 0.2.90 → 0.2.92

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/dist/CHANGELOG.md CHANGED
@@ -5,6 +5,32 @@ All notable technical changes to the laif-ds core will be documented in this fil
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [laif-ds@0.2.92]
9
+
10
+ ### 🐛 Fixed
11
+
12
+ - **Badge / Alert**: Fixed `variant="success"` and `variant="warning"` rendering with insufficient text contrast — the `bg-d-success-background` and `bg-d-warning-background` utilities were painting the foreground (text) color as the background instead of the intended surface color, collapsing contrast against the paired `-foreground` text. Contrast now resolves correctly to surface + on-surface in both light and dark themes
13
+
14
+ ## [laif-ds@0.2.91]
15
+
16
+ ### 🚀 Added
17
+
18
+ - **AppSidebar**: Added `collapsible` prop (`"offcanvas" | "icon" | "none"`, default `"offcanvas"`, forwarded to `Sidebar`) to support an icon-only collapsed rail instead of sliding the sidebar fully off-screen
19
+ - **AppSidebar**: In icon mode, top-level items show a tooltip with their title (suppressed while expanded and on mobile), and items with `subItems` open a click-triggered dropdown anchored to the icon with one entry per sub-item; items without `iconName` fall back to showing the initial of their title instead of a blank square
20
+ - **Sheet**: `SheetContent` `side` accepts `"full"`, a viewport-covering sheet that fades and scales up (`zoom-in-95`) instead of sliding in from an edge
21
+
22
+ ### 🔧 Changed
23
+
24
+ - **AppSidebar**: Items whose own `isActive` or one of whose `subItems` is active now start expanded at mount (in both `navigation` and `navigationFooter`); manually collapsing such an item is remembered and not re-expanded on re-render
25
+ - **AppSidebar**: Expansion state is now keyed by group + url + title, so items with duplicate titles in different groups track their expanded state independently
26
+ - **AppSidebar**: `NavItem.url` is now ignored on items that have `subItems` — the button toggles the submenu/dropdown instead of navigating; only sub-items' own `url`s are used
27
+ - **AppSidebar**: Menu buttons for items with `subItems` no longer render an `<a>` inside a `<button>`
28
+ - **Sidebar**: The mobile sidebar now covers the full screen instead of a ~18rem panel, and opens with a fade + scale-up rather than sliding in from the side; since no page content stays visible behind it, its close button is now shown (with a 44px hit area) and the header reserves room for it
29
+
30
+ ### 🐛 Fixed
31
+
32
+ - **Sidebar**: In icon collapse mode (`collapsible="icon"`), navigation taller than the viewport is now reachable — content was previously clipped on both axes, not just the horizontal axis intended to hide overflowing labels on the collapsed rail, so vertical scrolling is now allowed
33
+
8
34
  ## [laif-ds@0.2.90]
9
35
 
10
36
  ### 🐛 Fixed
@@ -1,8 +1,8 @@
1
1
  "use client";
2
- import { getDefaultExportFromCjs as r } from "./_commonjsHelpers.js";
3
- import { __require as e } from "../node_modules/style-to-js/cjs/index.js";
4
- var t = e();
5
- const a = /* @__PURE__ */ r(t);
2
+ import { getDefaultExportFromCjs as e } from "./_commonjsHelpers.js";
3
+ import { __require as t } from "../node_modules/eventemitter3/index2.js";
4
+ var r = t();
5
+ const m = /* @__PURE__ */ e(r);
6
6
  export {
7
- a as default
7
+ m as default
8
8
  };
@@ -1,8 +1,8 @@
1
1
  "use client";
2
- import { getDefaultExportFromCjs as e } from "./_commonjsHelpers.js";
3
- import { __require as r } from "../node_modules/extend/index.js";
4
- var t = r();
5
- const x = /* @__PURE__ */ e(t);
2
+ import { getDefaultExportFromCjs as r } from "./_commonjsHelpers.js";
3
+ import { __require as e } from "../node_modules/style-to-js/cjs/index.js";
4
+ var t = e();
5
+ const a = /* @__PURE__ */ r(t);
6
6
  export {
7
- x as default
7
+ a as default
8
8
  };
@@ -1,8 +1,8 @@
1
1
  "use client";
2
2
  import { getDefaultExportFromCjs as e } from "./_commonjsHelpers.js";
3
- import { __require as t } from "../node_modules/eventemitter3/index2.js";
4
- var r = t();
5
- const m = /* @__PURE__ */ e(r);
3
+ import { __require as r } from "../node_modules/extend/index.js";
4
+ var t = r();
5
+ const x = /* @__PURE__ */ e(t);
6
6
  export {
7
- m as default
7
+ x as default
8
8
  };
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "schemaVersion": "1.0.0",
3
- "generatedAt": "2026-08-19T08:50:48.383Z",
3
+ "generatedAt": "2026-08-20T15:52:41.132Z",
4
4
  "package": {
5
5
  "name": "laif-ds",
6
- "version": "0.2.90"
6
+ "version": "0.2.92"
7
7
  },
8
8
  "summary": {
9
9
  "scannedFiles": 398,
@@ -352,7 +352,7 @@
352
352
  "repeatedClassNames": [
353
353
  {
354
354
  "className": "flex items-center gap-2",
355
- "occurrences": 36,
355
+ "occurrences": 35,
356
356
  "files": [
357
357
  "src/components/stories/app-checkbox.stories.tsx",
358
358
  "src/components/stories/app-dialog.stories.tsx",
@@ -368,7 +368,6 @@
368
368
  "src/components/stories/truncated-cell.stories.tsx",
369
369
  "src/components/ui/app-form.tsx",
370
370
  "src/components/ui/app-kanban.tsx",
371
- "src/components/ui/app-sidebar.tsx",
372
371
  "src/components/ui/file-previewer.tsx",
373
372
  "src/components/ui/weekly-calendar/calendar-header.tsx"
374
373
  ]
@@ -498,20 +497,6 @@
498
497
  "src/components/stories/theme-switcher.stories.tsx"
499
498
  ]
500
499
  },
501
- {
502
- "className": "text-d-muted-foreground",
503
- "occurrences": 8,
504
- "files": [
505
- "src/components/stories/app-dialog.stories.tsx",
506
- "src/components/stories/app-time-picker.stories.tsx",
507
- "src/components/ui/app-form.tsx",
508
- "src/components/ui/app-multiple-select-dropdown.tsx",
509
- "src/components/ui/app-select.tsx",
510
- "src/components/ui/app-sidebar.tsx",
511
- "src/components/ui/date-picker.tsx",
512
- "src/components/ui/weekly-calendar/calendar-header.tsx"
513
- ]
514
- },
515
500
  {
516
501
  "className": "text-muted-foreground text-xs",
517
502
  "occurrences": 8,
@@ -535,6 +520,19 @@
535
520
  "src/components/ui/multiple-selector.tsx"
536
521
  ]
537
522
  },
523
+ {
524
+ "className": "text-d-muted-foreground",
525
+ "occurrences": 7,
526
+ "files": [
527
+ "src/components/stories/app-dialog.stories.tsx",
528
+ "src/components/stories/app-time-picker.stories.tsx",
529
+ "src/components/ui/app-form.tsx",
530
+ "src/components/ui/app-multiple-select-dropdown.tsx",
531
+ "src/components/ui/app-select.tsx",
532
+ "src/components/ui/date-picker.tsx",
533
+ "src/components/ui/weekly-calendar/calendar-header.tsx"
534
+ ]
535
+ },
538
536
  {
539
537
  "className": "bg-muted/50 rounded p-4 text-sm",
540
538
  "occurrences": 7,
@@ -579,6 +577,14 @@
579
577
  "src/components/stories/playground.stories.tsx"
580
578
  ]
581
579
  },
580
+ {
581
+ "className": "flex h-full overflow-hidden",
582
+ "occurrences": 6,
583
+ "files": [
584
+ "src/components/stories/app-sidebar.stories.tsx",
585
+ "src/components/stories/sidebar.stories.tsx"
586
+ ]
587
+ },
582
588
  {
583
589
  "className": "mb-2 text-sm font-medium",
584
590
  "occurrences": 6,
@@ -604,14 +610,6 @@
604
610
  "src/components/stories/data-table-no-utils-example.stories.tsx",
605
611
  "src/components/stories/data-table-utils-example.stories.tsx"
606
612
  ]
607
- },
608
- {
609
- "className": "flex min-h-0 min-w-0 flex-1",
610
- "occurrences": 6,
611
- "files": [
612
- "src/components/stories/data-table-no-utils-example.stories.tsx",
613
- "src/components/stories/data-table-utils-example.stories.tsx"
614
- ]
615
613
  }
616
614
  ]
617
615
  }
@@ -8,17 +8,18 @@ High-level app sidebar built on top of `Sidebar` primitives. Renders navigation
8
8
 
9
9
  ## Props
10
10
 
11
- | Prop | Type | Default | Description |
12
- | ------------------ | -------------------------- | ------------ | ----------------------------------------- |
13
- | `navigation` | `NavGroup[]` | **required** | Main navigation groups. |
14
- | `navigationFooter` | `NavGroup[]` | `undefined` | Footer navigation groups. |
15
- | `versions` | `string[]` | `undefined` | Optional versions list. |
16
- | `defaultVersion` | `string` | `undefined` | Default selected version. |
17
- | `headerContent` | `React.ReactNode` | `undefined` | Custom content at the top. |
18
- | `footerContent` | `React.ReactNode` | `undefined` | Custom content at the bottom. |
19
- | `showRail` | `boolean` | `true` | Show the draggable sidebar rail. |
20
- | `linkComponent` | `React.ComponentType<any>` | `undefined` | Custom link component for items. |
21
- | `linkProps` | `Record<string, any>` | `{}` | Extra props passed to the link component. |
11
+ | Prop | Type | Default | Description |
12
+ | ------------------ | --------------------------------- | ------------- | ------------------------------------------ |
13
+ | `navigation` | `NavGroup[]` | **required** | Main navigation groups. |
14
+ | `navigationFooter` | `NavGroup[]` | `undefined` | Footer navigation groups. |
15
+ | `versions` | `string[]` | `undefined` | Optional versions list. |
16
+ | `defaultVersion` | `string` | `undefined` | Default selected version. |
17
+ | `headerContent` | `React.ReactNode` | `undefined` | Custom content at the top. |
18
+ | `footerContent` | `React.ReactNode` | `undefined` | Custom content at the bottom. |
19
+ | `showRail` | `boolean` | `true` | Show the draggable sidebar rail. |
20
+ | `collapsible` | `"offcanvas" \| "icon" \| "none"` | `"offcanvas"` | Collapse behavior, forwarded to `Sidebar`. |
21
+ | `linkComponent` | `React.ComponentType<any>` | `undefined` | Custom link component for items. |
22
+ | `linkProps` | `Record<string, any>` | `{}` | Extra props passed to the link component. |
22
23
 
23
24
  `NavGroup` → `{ title: string; url?: string; items: NavItem[] }`
24
25
 
@@ -26,6 +27,10 @@ High-level app sidebar built on top of `Sidebar` primitives. Renders navigation
26
27
 
27
28
  `NavSubItem` → `{ title: string; url: string; isActive?: boolean; iconName?: IconName }`
28
29
 
30
+ `NavItem.url` is **ignored when the item has `subItems`**: that button toggles the
31
+ submenu (or opens the icon-mode dropdown) instead of navigating. Only the
32
+ sub-items' own `url`s are used.
33
+
29
34
  Inherits other props from `Sidebar` via `React.ComponentProps<typeof Sidebar>`.
30
35
 
31
36
  ---
@@ -33,9 +38,43 @@ Inherits other props from `Sidebar` via `React.ComponentProps<typeof Sidebar>`.
33
38
  ## Behavior
34
39
 
35
40
  - **Collapsible groups**: Clicking items with `subItems` toggles nested lists.
36
- - **Active state**: `isActive` highlights and expands relevant items/groups.
41
+ - **Active state**: `isActive` highlights the item. An item whose own `isActive`
42
+ or one of whose `subItems` is active starts already expanded at mount, in
43
+ `navigation` and `navigationFooter` alike. Auto-expansion applies once per
44
+ item: collapsing it by hand is remembered and never undone by a re-render.
45
+ - **Duplicate titles are safe**: expansion state is keyed by group + url + title,
46
+ so the same label in two groups keeps two independent states.
37
47
  - **Links**: Use `linkComponent` for framework routers (e.g., Next.js `Link`).
38
48
  - **Rail**: `showRail` displays a thin draggable handle to collapse/expand.
49
+ - **No interactive nesting**: the menu button _is_ the link (`asChild`), so there
50
+ is no `<a>` inside a `<button>`.
51
+
52
+ ---
53
+
54
+ ## Icon mode (`collapsible="icon"`)
55
+
56
+ The default stays `"offcanvas"` (the sidebar slides out of view when collapsed).
57
+ Pass `collapsible="icon"` to keep a 3rem icon-only rail instead:
58
+
59
+ ```tsx
60
+ <AppSidebar collapsible="icon" navigation={navigation} />
61
+ ```
62
+
63
+ Behavior when collapsed on desktop:
64
+
65
+ - **Labels hide**, they are never squashed or half-clipped: icon and label are
66
+ direct children of the menu button, which the `Sidebar` primitive shrinks to
67
+ `size-8` / `p-2`.
68
+ - **Tooltips**: every top-level item shows a tooltip with its title on the right.
69
+ Tooltips are suppressed while the sidebar is expanded and on mobile.
70
+ - **Items with `subItems`** open a dropdown on **click**, anchored to the right of
71
+ the icon, with one entry per sub-item (`url` preserved). Clicking outside
72
+ closes it. The inline vertical submenu is used only in expanded mode.
73
+ - **Items without `iconName`** fall back to the initial of their title, so they
74
+ are never a blank square. The full title stays in the accessibility tree and in
75
+ the tooltip.
76
+ - **Mobile** is unaffected: the sidebar renders in a full-screen `Sheet`, so items
77
+ keep labels and inline expansion.
39
78
 
40
79
  ---
41
80
 
@@ -11,7 +11,10 @@ Side sheet/dialog component with overlay, animated content, header/footer and cl
11
11
  - `Sheet`, `SheetTrigger`, `SheetClose`, `SheetContent`
12
12
  - `SheetHeader`, `SheetFooter`, `SheetTitle`, `SheetDescription`
13
13
 
14
- `SheetContent` prop `side` supports: `"top" | "right" | "bottom" | "left"` (default: `"right"`).
14
+ `SheetContent` prop `side` supports: `"top" | "right" | "bottom" | "left" | "full"` (default: `"right"`).
15
+
16
+ `"full"` covers the whole viewport (used by the mobile `Sidebar`). Having no edge to
17
+ slide in from, it fades and scales up (`zoom-in-95`) instead of sliding.
15
18
 
16
19
  ---
17
20
 
@@ -23,7 +23,8 @@ Low-level primitives to build responsive sidebars with desktop/offcanvas modes,
23
23
 
24
24
  ## Behavior
25
25
 
26
- - **Mobile**: Offcanvas via `Sheet` when on mobile; desktop uses fixed panel.
26
+ - **Mobile**: full-screen `Sheet` (`side="full"`) that fades and scales in, with its
27
+ close button visible — nothing of the page shows behind it; desktop uses a fixed panel.
27
28
  - **Collapsible**: `icon` mode shows only icons and tooltips; `offcanvas` moves panel off-screen.
28
29
  - **Keyboard**: Toggle with ⌘/Ctrl + B.
29
30
  - **Tooltips**: Menu buttons show tooltips only when collapsed on desktop.
@@ -47,7 +47,7 @@ This document provides a complete mapping of all components available in the lai
47
47
 
48
48
  - **Accordion** - Collapsible content panels for organizing information hierarchically
49
49
  - **AppCard** - Enhanced card component with variant styles, semantic states, size control, and loading skeleton support
50
- - **AppSidebar** - Application sidebar navigation component
50
+ - **AppSidebar** - Application sidebar navigation component, with optional icon-only collapse (`collapsible="icon"`: tooltips on top-level items, dropdown for sub-items)
51
51
  - **AppStepper** - Step-by-step progress indicator for multi-step processes
52
52
  - **AspectRatio** - Container that maintains a specific aspect ratio for responsive layouts
53
53
  - **Breadcrumb** - Breadcrumb navigation component for hierarchical navigation
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "schemaVersion": "1.1.0",
3
- "generatedAt": "2026-08-19T08:50:48.109Z",
3
+ "generatedAt": "2026-08-20T15:52:40.662Z",
4
4
  "package": {
5
5
  "name": "laif-ds",
6
- "version": "0.2.90"
6
+ "version": "0.2.92"
7
7
  },
8
8
  "stats": {
9
9
  "documentedComponentCount": 93,
@@ -930,6 +930,10 @@
930
930
  "title": "Behavior",
931
931
  "slug": "behavior"
932
932
  },
933
+ {
934
+ "title": "Icon mode (`collapsible=\"icon\"`)",
935
+ "slug": "icon-mode-collapsible-icon"
936
+ },
933
937
  {
934
938
  "title": "Examples",
935
939
  "slug": "examples"
@@ -952,10 +956,10 @@
952
956
  },
953
957
  "metadata": {
954
958
  "props": {
955
- "totalProps": 9,
959
+ "totalProps": 10,
956
960
  "requiredPropsCount": 1,
957
- "typedPropsCount": 9,
958
- "describedPropsCount": 9
961
+ "typedPropsCount": 10,
962
+ "describedPropsCount": 10
959
963
  },
960
964
  "accessibility": {
961
965
  "hasCoverage": true
@@ -6172,5 +6176,5 @@
6172
6176
  ]
6173
6177
  }
6174
6178
  ],
6175
- "checksum": "bd04a8acdf716cfa1271b8896b1f84d31c5b873787e57ff77578dfa88f346c43"
6179
+ "checksum": "45a413c2a13515169ecf8186102b81f4397185b855629c059394297c6c9c3303"
6176
6180
  }
@@ -1,106 +1,210 @@
1
1
  "use client";
2
- import { jsxs as c, jsx as t, Fragment as I } from "react/jsx-runtime";
3
- import * as v from "react";
2
+ import { jsxs as n, jsx as t, Fragment as R } from "react/jsx-runtime";
3
+ import * as s from "react";
4
+ import { designTokens as J } from "../design-tokens.js";
5
+ import { DropdownMenu as Q, DropdownMenuTrigger as U, DropdownMenuContent as V, DropdownMenuItem as W } from "./dropdown-menu.js";
4
6
  import { Icon as h } from "./icon.js";
5
- import { Sidebar as y, SidebarHeader as z, SidebarContent as B, SidebarGroup as x, SidebarGroupLabel as A, SidebarGroupContent as N, SidebarMenu as C, SidebarMenuItem as w, SidebarMenuSub as M, SidebarMenuSubItem as E, SidebarRail as F, SidebarMenuButton as j, SidebarMenuSubButton as D } from "./sidebar.js";
6
- function K({
7
- navigation: u,
8
- navigationFooter: G,
9
- headerContent: f,
10
- footerContent: R,
11
- showRail: g = !0,
12
- linkComponent: d,
13
- linkProps: m = {},
14
- ...k
7
+ import { useSidebar as X, Sidebar as Y, SidebarHeader as Z, SidebarContent as _, SidebarRail as k, SidebarGroup as P, SidebarGroupLabel as L, SidebarGroupContent as ee, SidebarMenu as re, SidebarMenuItem as x, SidebarMenuButton as M, SidebarMenuSub as te, SidebarMenuSubItem as ie, SidebarMenuSubButton as T } from "./sidebar.js";
8
+ import { Tooltip as ne, TooltipTrigger as ce, TooltipContent as se } from "./tooltip.js";
9
+ import { cn as le } from "../../lib/utils.js";
10
+ const $ = (c, l) => `${c.title} ${l.url} ${l.title}`, D = (c) => `${c.url} ${c.title}`;
11
+ function me({
12
+ navigation: c,
13
+ navigationFooter: l,
14
+ headerContent: w,
15
+ footerContent: j,
16
+ showRail: z = !0,
17
+ collapsible: f,
18
+ linkComponent: a,
19
+ linkProps: p = {},
20
+ ...G
15
21
  }) {
16
- const [b, o] = v.useState({});
17
- v.useEffect(() => {
18
- o((e) => {
19
- const n = { ...e };
20
- return u.forEach((l) => {
21
- l.items.some(
22
- (r) => r.isActive || r.subItems && r.subItems.some((s) => s.isActive)
23
- ) && (n[l.title] = !0);
24
- }), n;
22
+ const { state: K, isMobile: I } = X(), B = s.useId(), m = f === "icon" && K === "collapsed" && !I, [O, y] = s.useState({}), g = s.useMemo(
23
+ () => [...c, ...l ?? []].flatMap(
24
+ (e) => e.items.filter(
25
+ (r) => r.subItems?.length && (r.isActive || r.subItems.some((i) => i.isActive))
26
+ ).map((r) => $(e, r))
27
+ ).join("|"),
28
+ [c, l]
29
+ );
30
+ s.useEffect(() => {
31
+ g && y((e) => {
32
+ const r = g.split("|").filter((i) => e[i] === void 0);
33
+ return r.length ? { ...e, ...Object.fromEntries(r.map((i) => [i, !0])) } : e;
25
34
  });
26
- }, [u]);
27
- const S = (e, n, l) => {
28
- const i = e.subItems && e.subItems.length > 0, r = /* @__PURE__ */ c(I, { children: [
29
- /* @__PURE__ */ c("div", { className: "flex items-center gap-2", children: [
30
- e.iconName && /* @__PURE__ */ t(h, { name: e.iconName, size: "sm" }),
31
- /* @__PURE__ */ t("span", { children: e.title })
32
- ] }),
33
- i && /* @__PURE__ */ t("div", { className: "text-d-muted-foreground", children: n ? /* @__PURE__ */ t(h, { name: "ChevronDown", className: "h-4 w-4" }) : /* @__PURE__ */ t(h, { name: "ChevronRight", className: "h-4 w-4" }) })
35
+ }, [g]);
36
+ const v = s.useRef(/* @__PURE__ */ new Map()), A = s.useRef(null), N = (e) => (r) => {
37
+ r ? v.current.set(e, r) : v.current.delete(e);
38
+ };
39
+ s.useLayoutEffect(() => {
40
+ const e = A.current;
41
+ !e || document.activeElement !== document.body || v.current.get(e)?.focus();
42
+ }, [m]);
43
+ const o = (e) => e.iconName ? /* @__PURE__ */ t(h, { name: e.iconName, size: "sm" }) : f !== "icon" ? null : /* @__PURE__ */ t(
44
+ "span",
45
+ {
46
+ "aria-hidden": "true",
47
+ className: "flex size-4 shrink-0 items-center justify-center text-xs font-semibold uppercase opacity-0 transition-opacity group-data-[collapsible=icon]:opacity-100",
48
+ children: e.title.charAt(0)
49
+ }
50
+ ), F = (e) => {
51
+ const r = /* @__PURE__ */ n(R, { children: [
52
+ e.iconName && /* @__PURE__ */ t(h, { name: e.iconName, size: "xs" }),
53
+ /* @__PURE__ */ t("span", { children: e.title })
34
54
  ] });
35
- return d ? /* @__PURE__ */ t(j, { isActive: e.isActive, children: /* @__PURE__ */ t(
36
- d,
55
+ return a ? /* @__PURE__ */ t(T, { isActive: e.isActive, asChild: !0, children: /* @__PURE__ */ t(
56
+ a,
37
57
  {
38
- href: i ? "#" : e.url,
39
- className: "flex w-full items-center justify-between gap-2",
40
- onClick: i ? l : void 0,
41
- ...m,
58
+ href: e.url,
59
+ className: "flex w-full items-center gap-2",
60
+ "aria-current": e.isActive ? "page" : void 0,
61
+ ...p,
42
62
  children: r
43
63
  }
44
- ) }) : /* @__PURE__ */ t(j, { isActive: e.isActive, children: /* @__PURE__ */ t(
64
+ ) }) : /* @__PURE__ */ t(T, { isActive: e.isActive, asChild: !0, children: /* @__PURE__ */ t(
45
65
  "a",
46
66
  {
47
- href: i ? "#" : e.url,
48
- className: "flex w-full items-center justify-between gap-2",
49
- onClick: i ? l : void 0,
67
+ href: e.url,
68
+ className: "flex w-full items-center gap-2",
69
+ "aria-current": e.isActive ? "page" : void 0,
50
70
  children: r
51
71
  }
52
72
  ) });
53
- }, p = (e) => {
54
- const n = /* @__PURE__ */ c(I, { children: [
73
+ }, H = (e) => {
74
+ const r = /* @__PURE__ */ n(R, { children: [
55
75
  e.iconName && /* @__PURE__ */ t(h, { name: e.iconName, size: "xs" }),
56
76
  /* @__PURE__ */ t("span", { children: e.title })
57
- ] });
58
- return d ? /* @__PURE__ */ t(D, { isActive: e.isActive, asChild: !0, children: /* @__PURE__ */ t(
59
- d,
77
+ ] }), i = le(
78
+ "flex w-full items-center gap-2",
79
+ e.isActive && J.dropdownItem.selected
80
+ );
81
+ return /* @__PURE__ */ t(W, { asChild: !0, children: a ? /* @__PURE__ */ t(
82
+ a,
60
83
  {
61
84
  href: e.url,
62
- className: "flex w-full items-center gap-2",
63
- ...m,
64
- children: n
85
+ className: i,
86
+ "aria-current": e.isActive ? "page" : void 0,
87
+ ...p,
88
+ children: r
65
89
  }
66
- ) }) : /* @__PURE__ */ t(D, { isActive: e.isActive, asChild: !0, children: /* @__PURE__ */ t("a", { href: e.url, className: "flex w-full items-center gap-2", children: n }) });
67
- };
68
- return /* @__PURE__ */ c(y, { ...k, children: [
69
- f && /* @__PURE__ */ t(z, { children: f }),
70
- /* @__PURE__ */ t(B, { children: u.map((e) => /* @__PURE__ */ c(x, { children: [
71
- e.title && /* @__PURE__ */ t(A, { children: e.title }),
72
- /* @__PURE__ */ t(N, { children: /* @__PURE__ */ t(C, { children: e.items.map((n) => {
73
- const l = n.subItems && n.subItems.length > 0, i = b[n.title] || !1;
74
- return /* @__PURE__ */ c(w, { children: [
75
- S(n, i, (s) => {
76
- l && (s.preventDefault(), o((a) => ({
77
- ...a,
78
- [n.title]: !a[n.title]
79
- })));
80
- }),
81
- l && i && /* @__PURE__ */ t(M, { children: n.subItems.map((s) => /* @__PURE__ */ t(E, { children: p(s) }, s.title)) })
82
- ] }, n.title);
83
- }) }) })
84
- ] }, e.title)) }),
85
- G?.map((e) => /* @__PURE__ */ c(x, { children: [
86
- e.title && /* @__PURE__ */ t(A, { children: e.title }),
87
- /* @__PURE__ */ t(N, { children: /* @__PURE__ */ t(C, { children: e.items.map((n) => {
88
- const l = n.subItems && n.subItems.length > 0, i = b[n.title] || !1;
89
- return /* @__PURE__ */ c(w, { children: [
90
- S(n, i, (s) => {
91
- l && (s.preventDefault(), o((a) => ({
92
- ...a,
93
- [n.title]: !a[n.title]
94
- })));
95
- }),
96
- l && i && /* @__PURE__ */ t(M, { children: n.subItems.map((s) => /* @__PURE__ */ t(E, { children: p(s) }, s.title)) })
97
- ] }, n.title);
98
- }) }) })
99
- ] }, e.title)),
100
- R,
101
- g && /* @__PURE__ */ t(F, {})
90
+ ) : /* @__PURE__ */ t(
91
+ "a",
92
+ {
93
+ href: e.url,
94
+ className: i,
95
+ "aria-current": e.isActive ? "page" : void 0,
96
+ children: r
97
+ }
98
+ ) }, D(e));
99
+ }, q = (e, r) => {
100
+ const i = $(e, r), S = r.subItems ?? [], b = O[i] ?? !1, E = `${B}-${i.replace(/[^\w-]+/g, "-")}-submenu`, u = /* @__PURE__ */ t("span", { className: "truncate", children: r.title });
101
+ return S.length === 0 ? /* @__PURE__ */ t(x, { children: /* @__PURE__ */ t(
102
+ M,
103
+ {
104
+ asChild: !0,
105
+ isActive: r.isActive,
106
+ tooltip: r.title,
107
+ children: a ? /* @__PURE__ */ n(
108
+ a,
109
+ {
110
+ href: r.url,
111
+ "aria-current": r.isActive ? "page" : void 0,
112
+ ...p,
113
+ children: [
114
+ o(r),
115
+ u
116
+ ]
117
+ }
118
+ ) : /* @__PURE__ */ n(
119
+ "a",
120
+ {
121
+ href: r.url,
122
+ "aria-current": r.isActive ? "page" : void 0,
123
+ children: [
124
+ o(r),
125
+ u
126
+ ]
127
+ }
128
+ )
129
+ }
130
+ ) }, i) : m ? /* @__PURE__ */ t(x, { children: /* @__PURE__ */ n(ne, { children: [
131
+ /* @__PURE__ */ n(Q, { modal: !1, children: [
132
+ /* @__PURE__ */ t(U, { asChild: !0, children: /* @__PURE__ */ t(ce, { asChild: !0, children: /* @__PURE__ */ n(
133
+ M,
134
+ {
135
+ ref: N(i),
136
+ type: "button",
137
+ isActive: r.isActive,
138
+ onFocus: () => {
139
+ A.current = i;
140
+ },
141
+ children: [
142
+ o(r),
143
+ u
144
+ ]
145
+ }
146
+ ) }) }),
147
+ /* @__PURE__ */ t(
148
+ V,
149
+ {
150
+ side: "right",
151
+ align: "start",
152
+ sideOffset: 8,
153
+ className: "min-w-48",
154
+ children: S.map(H)
155
+ }
156
+ )
157
+ ] }),
158
+ /* @__PURE__ */ t(
159
+ se,
160
+ {
161
+ side: "right",
162
+ align: "center",
163
+ hidden: !m,
164
+ children: r.title
165
+ }
166
+ )
167
+ ] }) }, i) : /* @__PURE__ */ n(x, { children: [
168
+ /* @__PURE__ */ n(
169
+ M,
170
+ {
171
+ ref: N(i),
172
+ type: "button",
173
+ isActive: r.isActive,
174
+ tooltip: r.title,
175
+ "aria-expanded": b,
176
+ "aria-controls": E,
177
+ onFocus: () => {
178
+ A.current = i;
179
+ },
180
+ onClick: () => y((d) => ({ ...d, [i]: !d[i] })),
181
+ children: [
182
+ o(r),
183
+ u,
184
+ /* @__PURE__ */ t(
185
+ h,
186
+ {
187
+ name: b ? "ChevronDown" : "ChevronRight",
188
+ className: "text-d-muted-foreground ml-auto size-4 shrink-0 group-data-[collapsible=icon]:hidden"
189
+ }
190
+ )
191
+ ]
192
+ }
193
+ ),
194
+ b && /* @__PURE__ */ t(te, { id: E, children: S.map((d) => /* @__PURE__ */ t(ie, { children: F(d) }, D(d))) })
195
+ ] }, i);
196
+ }, C = (e) => /* @__PURE__ */ n(P, { children: [
197
+ e.title && /* @__PURE__ */ t(L, { children: e.title }),
198
+ /* @__PURE__ */ t(ee, { children: /* @__PURE__ */ t(re, { children: e.items.map((r) => q(e, r)) }) })
199
+ ] }, e.title);
200
+ return /* @__PURE__ */ n(Y, { collapsible: f, ...G, children: [
201
+ w && /* @__PURE__ */ t(Z, { children: w }),
202
+ /* @__PURE__ */ t(_, { children: c.map((e) => C(e)) }),
203
+ l?.map((e) => C(e)),
204
+ j,
205
+ z && /* @__PURE__ */ t(k, {})
102
206
  ] });
103
207
  }
104
208
  export {
105
- K as AppSidebar
209
+ me as AppSidebar
106
210
  };