@kopexa/sidebar 17.2.0 → 17.3.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.
package/dist/v2/index.mjs CHANGED
@@ -2,7 +2,7 @@
2
2
  "use client";
3
3
  import {
4
4
  SidebarV2
5
- } from "../chunk-WA2NSEYE.mjs";
5
+ } from "../chunk-6H2EH7LL.mjs";
6
6
  import {
7
7
  AppShell,
8
8
  AppShellAside,
@@ -10,10 +10,10 @@ import {
10
10
  AppShellMain,
11
11
  AppShellPanelContent,
12
12
  AppShellRoot
13
- } from "../chunk-PZFEB2PM.mjs";
13
+ } from "../chunk-WIP5GNGJ.mjs";
14
14
  import {
15
15
  SidebarV2FromConfig
16
- } from "../chunk-CMYTESJM.mjs";
16
+ } from "../chunk-G2J7EJQ6.mjs";
17
17
  import {
18
18
  SidebarV2Inset,
19
19
  SidebarV2Panel,
@@ -27,12 +27,12 @@ import {
27
27
  SidebarV2RailSpacer,
28
28
  SidebarV2Trigger,
29
29
  SidebarV2Workspace
30
- } from "../chunk-EIXUCY5M.mjs";
31
- import "../chunk-SDMGFB6V.mjs";
30
+ } from "../chunk-5VE25P3M.mjs";
32
31
  import {
33
32
  SidebarV2Provider,
34
33
  useSidebarV2
35
- } from "../chunk-3L2F566G.mjs";
34
+ } from "../chunk-XBTONQ3L.mjs";
35
+ import "../chunk-BFZFZSUC.mjs";
36
36
  export {
37
37
  AppShell,
38
38
  AppShellAside,
@@ -32,7 +32,10 @@ type SidebarV2PanelItem = {
32
32
  label: string;
33
33
  href: string;
34
34
  icon?: SidebarV2Icon;
35
+ /** Count pill after the label (e.g. number of open items). */
35
36
  badge?: number | string;
37
+ /** Status chip after the label, e.g. "Preview", "Beta", "Neu". */
38
+ tag?: string;
36
39
  /** Stable key; defaults to href. */
37
40
  value?: string;
38
41
  } | {
@@ -72,9 +75,25 @@ type SidebarV2RailEntry = {
72
75
  slot?: "top" | "bottom";
73
76
  };
74
77
  type SidebarV2Nav = SidebarV2RailEntry[];
78
+ /**
79
+ * A route's identity is its pathname — query (`?`) and hash (`#`) are transient
80
+ * (filters, tabs-by-query, scroll anchors) and never part of nav identity. Strip
81
+ * them (and any trailing slash) before comparing, so a nav href that carries an
82
+ * incidental `?param` still matches the bare route. `/` is preserved.
83
+ */
84
+ declare function normalizePath(href: string): string;
85
+ /**
86
+ * Length of the match between an already-normalized `currentPath` and a target
87
+ * `href`, or `-1` when it doesn't match. Exact and ancestor-prefix matches both
88
+ * return the target's length; callers keep the longest (most specific) one so the
89
+ * panel/item that owns the deepest matching route wins — never a shorter prefix
90
+ * from an unrelated entry. The boundary is `/`, so `/risks` never matches
91
+ * `/risks-archive`.
92
+ */
93
+ declare function pathMatchLength(currentPath: string, href: string): number;
75
94
  declare function panelItemHasChildren(item: SidebarV2PanelItem): item is Extract<SidebarV2PanelItem, {
76
95
  children: SidebarV2SubItem[];
77
96
  }>;
78
97
  declare function panelItemIsSection(item: SidebarV2PanelItem): item is SidebarV2PanelSection;
79
98
 
80
- export { type SidebarV2Icon, type SidebarV2LinkProps, type SidebarV2Nav, type SidebarV2PanelItem, type SidebarV2PanelSection, type SidebarV2RailEntry, type SidebarV2SubItem, panelItemHasChildren, panelItemIsSection };
99
+ export { type SidebarV2Icon, type SidebarV2LinkProps, type SidebarV2Nav, type SidebarV2PanelItem, type SidebarV2PanelSection, type SidebarV2RailEntry, type SidebarV2SubItem, normalizePath, panelItemHasChildren, panelItemIsSection, pathMatchLength };
@@ -32,7 +32,10 @@ type SidebarV2PanelItem = {
32
32
  label: string;
33
33
  href: string;
34
34
  icon?: SidebarV2Icon;
35
+ /** Count pill after the label (e.g. number of open items). */
35
36
  badge?: number | string;
37
+ /** Status chip after the label, e.g. "Preview", "Beta", "Neu". */
38
+ tag?: string;
36
39
  /** Stable key; defaults to href. */
37
40
  value?: string;
38
41
  } | {
@@ -72,9 +75,25 @@ type SidebarV2RailEntry = {
72
75
  slot?: "top" | "bottom";
73
76
  };
74
77
  type SidebarV2Nav = SidebarV2RailEntry[];
78
+ /**
79
+ * A route's identity is its pathname — query (`?`) and hash (`#`) are transient
80
+ * (filters, tabs-by-query, scroll anchors) and never part of nav identity. Strip
81
+ * them (and any trailing slash) before comparing, so a nav href that carries an
82
+ * incidental `?param` still matches the bare route. `/` is preserved.
83
+ */
84
+ declare function normalizePath(href: string): string;
85
+ /**
86
+ * Length of the match between an already-normalized `currentPath` and a target
87
+ * `href`, or `-1` when it doesn't match. Exact and ancestor-prefix matches both
88
+ * return the target's length; callers keep the longest (most specific) one so the
89
+ * panel/item that owns the deepest matching route wins — never a shorter prefix
90
+ * from an unrelated entry. The boundary is `/`, so `/risks` never matches
91
+ * `/risks-archive`.
92
+ */
93
+ declare function pathMatchLength(currentPath: string, href: string): number;
75
94
  declare function panelItemHasChildren(item: SidebarV2PanelItem): item is Extract<SidebarV2PanelItem, {
76
95
  children: SidebarV2SubItem[];
77
96
  }>;
78
97
  declare function panelItemIsSection(item: SidebarV2PanelItem): item is SidebarV2PanelSection;
79
98
 
80
- export { type SidebarV2Icon, type SidebarV2LinkProps, type SidebarV2Nav, type SidebarV2PanelItem, type SidebarV2PanelSection, type SidebarV2RailEntry, type SidebarV2SubItem, panelItemHasChildren, panelItemIsSection };
99
+ export { type SidebarV2Icon, type SidebarV2LinkProps, type SidebarV2Nav, type SidebarV2PanelItem, type SidebarV2PanelSection, type SidebarV2RailEntry, type SidebarV2SubItem, normalizePath, panelItemHasChildren, panelItemIsSection, pathMatchLength };
package/dist/v2/types.js CHANGED
@@ -21,10 +21,23 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  // src/v2/types.ts
22
22
  var types_exports = {};
23
23
  __export(types_exports, {
24
+ normalizePath: () => normalizePath,
24
25
  panelItemHasChildren: () => panelItemHasChildren,
25
- panelItemIsSection: () => panelItemIsSection
26
+ panelItemIsSection: () => panelItemIsSection,
27
+ pathMatchLength: () => pathMatchLength
26
28
  });
27
29
  module.exports = __toCommonJS(types_exports);
30
+ function normalizePath(href) {
31
+ const path = href.split("#")[0].split("?")[0].replace(/\/+$/, "");
32
+ return path === "" ? "/" : path;
33
+ }
34
+ function pathMatchLength(currentPath, href) {
35
+ const target = normalizePath(href);
36
+ if (currentPath === target) return target.length;
37
+ if (target !== "/" && currentPath.startsWith(`${target}/`))
38
+ return target.length;
39
+ return -1;
40
+ }
28
41
  function panelItemHasChildren(item) {
29
42
  return "children" in item && Array.isArray(item.children);
30
43
  }
@@ -33,6 +46,8 @@ function panelItemIsSection(item) {
33
46
  }
34
47
  // Annotate the CommonJS export names for ESM import in node:
35
48
  0 && (module.exports = {
49
+ normalizePath,
36
50
  panelItemHasChildren,
37
- panelItemIsSection
51
+ panelItemIsSection,
52
+ pathMatchLength
38
53
  });
package/dist/v2/types.mjs CHANGED
@@ -1,9 +1,13 @@
1
1
  "use client";
2
2
  import {
3
+ normalizePath,
3
4
  panelItemHasChildren,
4
- panelItemIsSection
5
- } from "../chunk-SDMGFB6V.mjs";
5
+ panelItemIsSection,
6
+ pathMatchLength
7
+ } from "../chunk-BFZFZSUC.mjs";
6
8
  export {
9
+ normalizePath,
7
10
  panelItemHasChildren,
8
- panelItemIsSection
11
+ panelItemIsSection,
12
+ pathMatchLength
9
13
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kopexa/sidebar",
3
- "version": "17.2.0",
3
+ "version": "17.3.0",
4
4
  "description": "",
5
5
  "keywords": [
6
6
  "sidebar"
@@ -28,19 +28,19 @@
28
28
  "motion": ">=12.23.6",
29
29
  "react": ">=19.0.0-rc.0",
30
30
  "react-dom": ">=19.0.0-rc.0",
31
- "@kopexa/theme": "17.33.0"
31
+ "@kopexa/theme": "17.34.0"
32
32
  },
33
33
  "dependencies": {
34
34
  "@radix-ui/react-slot": "^1.2.4",
35
- "@kopexa/button": "17.0.91",
36
- "@kopexa/icons": "17.10.20",
37
- "@kopexa/drawer": "17.2.56",
38
- "@kopexa/input": "17.0.91",
39
- "@kopexa/react-utils": "17.1.33",
40
- "@kopexa/separator": "17.0.91",
41
- "@kopexa/shared-utils": "17.0.91",
42
- "@kopexa/tooltip": "17.2.56",
43
- "@kopexa/use-is-mobile": "17.0.91"
35
+ "@kopexa/drawer": "17.2.58",
36
+ "@kopexa/icons": "17.10.22",
37
+ "@kopexa/input": "17.0.93",
38
+ "@kopexa/use-is-mobile": "17.0.93",
39
+ "@kopexa/react-utils": "17.1.35",
40
+ "@kopexa/tooltip": "17.2.58",
41
+ "@kopexa/button": "17.0.93",
42
+ "@kopexa/shared-utils": "17.0.93",
43
+ "@kopexa/separator": "17.0.93"
44
44
  },
45
45
  "clean-package": "../../../clean-package.config.json",
46
46
  "module": "dist/index.mjs",
@@ -1,458 +0,0 @@
1
- "use client";
2
- import {
3
- panelItemHasChildren,
4
- panelItemIsSection
5
- } from "./chunk-SDMGFB6V.mjs";
6
- import {
7
- useSidebarV2
8
- } from "./chunk-3L2F566G.mjs";
9
-
10
- // src/v2/components.tsx
11
- import { IconButton } from "@kopexa/button";
12
- import {
13
- ChevronDownIcon,
14
- ChevronRightIcon,
15
- PanelLeftIcon
16
- } from "@kopexa/icons";
17
- import { cn } from "@kopexa/shared-utils";
18
- import { sidebarMenuButton } from "@kopexa/theme";
19
- import { Tooltip } from "@kopexa/tooltip";
20
- import { forwardRef } from "react";
21
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
22
- function SidebarV2Inset({
23
- className,
24
- ...props
25
- }) {
26
- const { tone } = useSidebarV2();
27
- return /* @__PURE__ */ jsx(
28
- "main",
29
- {
30
- "data-slot": "sidebar-v2-inset",
31
- className: cn(
32
- "relative flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden bg-background",
33
- "md:m-2 md:rounded-xl md:shadow-sm",
34
- // On a light surround the white card needs a hairline to define its
35
- // edge; on the dark surround a border would read as a seam.
36
- tone === "light" && "md:border md:border-border/70",
37
- className
38
- ),
39
- ...props
40
- }
41
- );
42
- }
43
- function SidebarV2Rail({ className, ...props }) {
44
- const { tone } = useSidebarV2();
45
- const light = tone === "light";
46
- return /* @__PURE__ */ jsx(
47
- "nav",
48
- {
49
- "data-slot": "sidebar-v2-rail",
50
- className: cn(
51
- "flex w-(--kpx-rail-width) shrink-0 flex-col overflow-hidden bg-sidebar py-2 text-sidebar-foreground",
52
- // Light tone: the dark rail floats as a rounded card on the light
53
- // surround. Dark tone: full-height, flush to the edge.
54
- light ? "m-2 rounded-2xl shadow-sm" : "h-full",
55
- className
56
- ),
57
- ...props
58
- }
59
- );
60
- }
61
- function SidebarV2RailSpacer() {
62
- return /* @__PURE__ */ jsx("div", { "aria-hidden": true, className: "flex-1" });
63
- }
64
- var SidebarV2Workspace = forwardRef(({ name, role, logo, className, appearance = "rail", ...props }, ref) => {
65
- if (appearance === "bar") {
66
- return /* @__PURE__ */ jsxs(
67
- "button",
68
- {
69
- ref,
70
- type: "button",
71
- "data-slot": "sidebar-v2-workspace",
72
- "aria-label": role ? `${name} \u2013 ${role}` : name,
73
- className: cn(
74
- "group/ws flex cursor-pointer items-center gap-2 rounded-lg py-1 pr-2 pl-1",
75
- "outline-hidden ring-ring transition-colors hover:bg-foreground/5 focus-visible:ring-2",
76
- className
77
- ),
78
- ...props,
79
- children: [
80
- /* @__PURE__ */ jsx("span", { className: "flex size-7 shrink-0 items-center justify-center rounded-md bg-primary text-xs font-semibold text-primary-foreground", children: logo != null ? logo : name.charAt(0).toUpperCase() }),
81
- /* @__PURE__ */ jsxs("span", { className: "flex min-w-0 flex-col text-left leading-tight", children: [
82
- /* @__PURE__ */ jsx("span", { className: "truncate text-sm font-semibold text-foreground", children: name }),
83
- role && /* @__PURE__ */ jsx("span", { className: "truncate text-xs text-muted-foreground", children: role })
84
- ] }),
85
- /* @__PURE__ */ jsx(ChevronDownIcon, { className: "size-4 shrink-0 text-muted-foreground" })
86
- ]
87
- }
88
- );
89
- }
90
- return /* @__PURE__ */ jsx(
91
- "button",
92
- {
93
- ref,
94
- type: "button",
95
- "data-slot": "sidebar-v2-workspace",
96
- "aria-label": role ? `${name} \u2013 ${role}` : name,
97
- className: cn(
98
- "group/ws relative mx-auto mt-1 flex cursor-pointer items-center justify-center rounded-lg p-1",
99
- "outline-hidden ring-sidebar-ring transition-colors",
100
- "hover:bg-sidebar-accent focus-visible:ring-2",
101
- className
102
- ),
103
- ...props,
104
- children: /* @__PURE__ */ jsxs("span", { className: "relative flex size-9 shrink-0 items-center justify-center rounded-lg bg-primary text-sm font-semibold text-primary-foreground", children: [
105
- logo != null ? logo : name.charAt(0).toUpperCase(),
106
- /* @__PURE__ */ jsx(ChevronDownIcon, { className: "absolute -right-1 -bottom-1 size-3.5 rounded-full bg-sidebar p-px text-sidebar-foreground/60" })
107
- ] })
108
- }
109
- );
110
- });
111
- SidebarV2Workspace.displayName = "SidebarV2Workspace";
112
- function railButtonClasses(active) {
113
- return cn(
114
- "group/rail relative mx-auto flex size-11 shrink-0 cursor-pointer items-center justify-center rounded-xl",
115
- "outline-hidden ring-sidebar-ring transition-colors",
116
- "text-sidebar-foreground/85 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground",
117
- "focus-visible:ring-2",
118
- active && "bg-sidebar-accent text-sidebar-accent-foreground"
119
- );
120
- }
121
- function RailInner({
122
- icon: Icon,
123
- active,
124
- badge
125
- }) {
126
- return /* @__PURE__ */ jsxs(Fragment, { children: [
127
- /* @__PURE__ */ jsx(
128
- "span",
129
- {
130
- "aria-hidden": true,
131
- className: cn(
132
- "absolute top-1/2 left-0 h-5 w-0.5 -translate-x-[0.6rem] -translate-y-1/2 rounded-r bg-primary transition-opacity",
133
- active ? "opacity-100" : "opacity-0"
134
- )
135
- }
136
- ),
137
- /* @__PURE__ */ jsx(Icon, { className: "size-5 shrink-0" }),
138
- badge != null && /* @__PURE__ */ jsx("span", { className: "absolute -top-0.5 -right-0.5 flex h-4 min-w-4 items-center justify-center rounded-full bg-primary px-1 text-[0.5625rem] font-semibold text-primary-foreground", children: badge })
139
- ] });
140
- }
141
- function SidebarV2RailLink({
142
- icon,
143
- label,
144
- href,
145
- badge
146
- }) {
147
- const { renderLink, isActive, resetPanelSelection } = useSidebarV2();
148
- const active = isActive(href);
149
- return /* @__PURE__ */ jsx(Tooltip, { content: label, side: "right", children: renderLink({
150
- href,
151
- className: railButtonClasses(active),
152
- "data-active": active,
153
- "aria-current": active ? "page" : void 0,
154
- "aria-label": label,
155
- // Navigating to a destination link clears any open panel preview,
156
- // even when the route doesn't change (e.g. already on it).
157
- onClick: resetPanelSelection,
158
- children: /* @__PURE__ */ jsx(RailInner, { icon, label, active, badge })
159
- }) });
160
- }
161
- function SidebarV2RailItem({
162
- icon,
163
- label,
164
- active,
165
- hasPanel,
166
- onClick,
167
- onMouseEnter,
168
- onMouseLeave,
169
- badge
170
- }) {
171
- return /* @__PURE__ */ jsx(Tooltip, { content: label, side: "right", children: /* @__PURE__ */ jsx(
172
- "button",
173
- {
174
- type: "button",
175
- "data-active": active,
176
- "aria-label": label,
177
- "aria-expanded": hasPanel ? active : void 0,
178
- onClick,
179
- onMouseEnter,
180
- onMouseLeave,
181
- className: railButtonClasses(active),
182
- children: /* @__PURE__ */ jsx(RailInner, { icon, label, active, badge })
183
- }
184
- ) });
185
- }
186
- function SidebarV2Panel({
187
- title,
188
- subtitle,
189
- floating,
190
- hidePin,
191
- action,
192
- children,
193
- className
194
- }) {
195
- const { togglePin, pinned, tone } = useSidebarV2();
196
- const light = tone === "light";
197
- return /* @__PURE__ */ jsxs(
198
- "div",
199
- {
200
- "data-slot": "sidebar-v2-panel",
201
- "data-floating": floating,
202
- className: cn(
203
- "flex h-full w-(--kpx-panel-width) shrink-0 flex-col",
204
- // Surface. The flyout is a distinct floating card (white on light),
205
- // so it reads as an overlay rather than a flat full-height slab.
206
- floating ? light ? "bg-background text-foreground" : "bg-sidebar text-sidebar-foreground" : light ? "bg-muted text-foreground" : "bg-sidebar text-sidebar-foreground",
207
- floating ? (
208
- // Floating card: rounded, soft layered shadow, hairline ring.
209
- cn(
210
- "overflow-hidden rounded-2xl shadow-2xl shadow-black/20 ring-1",
211
- light ? "ring-black/5" : "ring-white/10"
212
- )
213
- ) : (
214
- // Pinned: light blends into the surround (no border); dark keeps a
215
- // hairline against the rail.
216
- light ? "" : "border-l border-sidebar-border/40"
217
- ),
218
- className
219
- ),
220
- children: [
221
- /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-2 px-3 pt-3 pb-1.5", children: [
222
- /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
223
- title && /* @__PURE__ */ jsx(
224
- "div",
225
- {
226
- className: cn(
227
- "truncate text-sm font-semibold",
228
- light ? "text-foreground" : "text-sidebar-foreground"
229
- ),
230
- children: title
231
- }
232
- ),
233
- subtitle && /* @__PURE__ */ jsx(
234
- "div",
235
- {
236
- className: cn(
237
- "truncate text-xs",
238
- light ? "text-muted-foreground" : "text-sidebar-foreground/70"
239
- ),
240
- children: subtitle
241
- }
242
- )
243
- ] }),
244
- action != null ? action : !hidePin && /* @__PURE__ */ jsx(
245
- Tooltip,
246
- {
247
- content: pinned ? "Panel l\xF6sen" : "Panel anheften",
248
- side: "bottom",
249
- children: /* @__PURE__ */ jsx(
250
- IconButton,
251
- {
252
- variant: "ghost",
253
- size: "sm",
254
- "aria-label": pinned ? "Panel l\xF6sen" : "Panel anheften",
255
- onClick: togglePin,
256
- className: cn(
257
- "-mr-1 shrink-0",
258
- light ? "text-muted-foreground hover:bg-foreground/5 hover:text-foreground" : "text-sidebar-foreground/60 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground"
259
- ),
260
- children: /* @__PURE__ */ jsx(PanelLeftIcon, { className: "size-4" })
261
- }
262
- )
263
- }
264
- )
265
- ] }),
266
- /* @__PURE__ */ jsx("div", { className: "flex min-h-0 flex-1 flex-col gap-0.5 overflow-auto p-2", children })
267
- ]
268
- }
269
- );
270
- }
271
- function panelRowLight(active) {
272
- return cn(
273
- "flex h-8 w-full items-center gap-2.5 rounded-md px-2 text-sm outline-hidden ring-ring transition-colors focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",
274
- active ? "bg-primary/10 font-medium text-primary" : "text-foreground/80 hover:bg-foreground/5"
275
- );
276
- }
277
- function SidebarV2PanelLabel({
278
- className,
279
- ...props
280
- }) {
281
- const { tone } = useSidebarV2();
282
- return /* @__PURE__ */ jsx(
283
- "div",
284
- {
285
- "data-slot": "sidebar-v2-panel-label",
286
- className: cn(
287
- "px-2 pt-3 pb-1 text-[0.6875rem] font-medium uppercase tracking-wide",
288
- tone === "light" ? "text-muted-foreground" : "text-sidebar-foreground/50",
289
- className
290
- ),
291
- ...props
292
- }
293
- );
294
- }
295
- function SidebarV2PanelLeaf({
296
- item,
297
- active: activeProp
298
- }) {
299
- const { renderLink, isActive, tone } = useSidebarV2();
300
- const light = tone === "light";
301
- const Icon = item.icon;
302
- const active = activeProp != null ? activeProp : isActive(item.href);
303
- return /* @__PURE__ */ jsx(Fragment, { children: renderLink({
304
- href: item.href,
305
- "data-active": active,
306
- "aria-current": active ? "page" : void 0,
307
- className: light ? panelRowLight(active) : sidebarMenuButton({ size: "md" }),
308
- children: /* @__PURE__ */ jsxs(Fragment, { children: [
309
- Icon && /* @__PURE__ */ jsx(
310
- Icon,
311
- {
312
- className: cn(
313
- light ? active ? void 0 : "text-muted-foreground" : "text-sidebar-foreground/75"
314
- )
315
- }
316
- ),
317
- /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate", children: item.label }),
318
- item.badge != null && /* @__PURE__ */ jsx(
319
- "span",
320
- {
321
- className: cn(
322
- "ml-auto rounded-full px-1.5 text-[0.625rem] font-medium",
323
- light ? "bg-foreground/10 text-foreground/70" : "bg-sidebar-accent text-sidebar-accent-foreground"
324
- ),
325
- children: item.badge
326
- }
327
- )
328
- ] })
329
- }) });
330
- }
331
- function SidebarV2PanelGroup({
332
- item
333
- }) {
334
- var _a;
335
- const { openGroup, toggleGroup, activeHref, renderLink, tone } = useSidebarV2();
336
- const light = tone === "light";
337
- const Icon = item.icon;
338
- const key = (_a = item.value) != null ? _a : item.label;
339
- let bestChildHref = null;
340
- let bestLen = -1;
341
- for (const c of item.children) {
342
- if (activeHref === c.href) {
343
- bestChildHref = c.href;
344
- break;
345
- }
346
- if (activeHref.startsWith(`${c.href}/`) && c.href.length > bestLen) {
347
- bestChildHref = c.href;
348
- bestLen = c.href.length;
349
- }
350
- }
351
- const containsActive = bestChildHref !== null;
352
- const open = openGroup === key || openGroup === null && containsActive;
353
- return /* @__PURE__ */ jsxs("div", { children: [
354
- /* @__PURE__ */ jsxs(
355
- "button",
356
- {
357
- type: "button",
358
- "data-state": open ? "open" : "closed",
359
- "aria-expanded": open,
360
- onClick: () => toggleGroup(key),
361
- className: cn(
362
- light ? panelRowLight(false) : sidebarMenuButton({ size: "md" }),
363
- "cursor-pointer",
364
- containsActive && (light ? "font-medium text-foreground" : "font-medium")
365
- ),
366
- children: [
367
- Icon && /* @__PURE__ */ jsx(
368
- Icon,
369
- {
370
- className: light ? "text-muted-foreground" : "text-sidebar-foreground/75"
371
- }
372
- ),
373
- /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate text-left", children: item.label }),
374
- /* @__PURE__ */ jsx(
375
- ChevronRightIcon,
376
- {
377
- className: cn(
378
- "size-3.5! shrink-0 transition-transform",
379
- light ? "text-muted-foreground" : "text-sidebar-foreground/60",
380
- open && "rotate-90"
381
- )
382
- }
383
- )
384
- ]
385
- }
386
- ),
387
- open && /* @__PURE__ */ jsx(
388
- "div",
389
- {
390
- className: cn(
391
- "my-0.5 ml-[1.05rem] flex flex-col border-l pl-3",
392
- light ? "border-border" : "border-sidebar-border"
393
- ),
394
- children: item.children.map((child) => {
395
- const active = child.href === bestChildHref;
396
- return /* @__PURE__ */ jsx("span", { children: renderLink({
397
- href: child.href,
398
- "data-active": active,
399
- "aria-current": active ? "page" : void 0,
400
- className: cn(
401
- "relative block rounded-md px-2 py-1.5 text-[0.8125rem] outline-hidden transition-colors focus-visible:ring-2",
402
- "before:absolute before:top-1/2 before:-left-3 before:h-px before:w-2.5",
403
- light ? active ? "bg-primary/10 font-medium text-primary ring-ring before:bg-primary" : "text-muted-foreground ring-ring hover:bg-foreground/5 hover:text-foreground before:bg-border" : active ? "bg-sidebar-accent font-medium text-sidebar-accent-foreground ring-sidebar-ring before:bg-primary" : "text-sidebar-foreground/80 ring-sidebar-ring hover:bg-sidebar-accent/60 hover:text-sidebar-accent-foreground before:bg-sidebar-foreground/30"
404
- ),
405
- children: child.label
406
- }) }, child.href);
407
- })
408
- }
409
- )
410
- ] });
411
- }
412
- function SidebarV2PanelItems({
413
- items
414
- }) {
415
- return /* @__PURE__ */ jsx(Fragment, { children: items.map((item, idx) => {
416
- var _a;
417
- if (panelItemIsSection(item)) {
418
- return /* @__PURE__ */ jsx(SidebarV2PanelLabel, { children: item.section }, `section-${item.section}-${idx}`);
419
- }
420
- if (panelItemHasChildren(item)) {
421
- return /* @__PURE__ */ jsx(SidebarV2PanelGroup, { item }, (_a = item.value) != null ? _a : item.label);
422
- }
423
- return /* @__PURE__ */ jsx(SidebarV2PanelLeaf, { item }, item.href);
424
- }) });
425
- }
426
- function SidebarV2Trigger({
427
- className,
428
- ...props
429
- }) {
430
- const { setDrawerOpen, drawerOpen } = useSidebarV2();
431
- return /* @__PURE__ */ jsx(
432
- IconButton,
433
- {
434
- variant: "ghost",
435
- size: "md",
436
- "aria-label": "Navigation \xF6ffnen",
437
- onClick: () => setDrawerOpen(!drawerOpen),
438
- className,
439
- ...props,
440
- children: /* @__PURE__ */ jsx(PanelLeftIcon, { className: "size-5" })
441
- }
442
- );
443
- }
444
-
445
- export {
446
- SidebarV2Inset,
447
- SidebarV2Rail,
448
- SidebarV2RailSpacer,
449
- SidebarV2Workspace,
450
- SidebarV2RailLink,
451
- SidebarV2RailItem,
452
- SidebarV2Panel,
453
- SidebarV2PanelLabel,
454
- SidebarV2PanelLeaf,
455
- SidebarV2PanelGroup,
456
- SidebarV2PanelItems,
457
- SidebarV2Trigger
458
- };
@@ -1,14 +0,0 @@
1
- "use client";
2
-
3
- // src/v2/types.ts
4
- function panelItemHasChildren(item) {
5
- return "children" in item && Array.isArray(item.children);
6
- }
7
- function panelItemIsSection(item) {
8
- return "section" in item;
9
- }
10
-
11
- export {
12
- panelItemHasChildren,
13
- panelItemIsSection
14
- };