@kopexa/sidebar 17.1.74 → 17.2.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,1011 @@
1
+ "use client";
2
+ "use strict";
3
+ "use client";
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
21
+
22
+ // src/v2/index.tsx
23
+ var v2_exports = {};
24
+ __export(v2_exports, {
25
+ AppShell: () => AppShell,
26
+ AppShellAside: () => AppShellAside,
27
+ AppShellHeader: () => AppShellHeader,
28
+ AppShellMain: () => AppShellMain,
29
+ AppShellPanelContent: () => AppShellPanelContent,
30
+ AppShellRoot: () => AppShellRoot,
31
+ SidebarV2: () => SidebarV2,
32
+ SidebarV2FromConfig: () => SidebarV2FromConfig,
33
+ SidebarV2Inset: () => SidebarV2Inset,
34
+ SidebarV2Panel: () => SidebarV2Panel,
35
+ SidebarV2PanelGroup: () => SidebarV2PanelGroup,
36
+ SidebarV2PanelItems: () => SidebarV2PanelItems,
37
+ SidebarV2PanelLabel: () => SidebarV2PanelLabel,
38
+ SidebarV2PanelLeaf: () => SidebarV2PanelLeaf,
39
+ SidebarV2Provider: () => SidebarV2Provider,
40
+ SidebarV2Rail: () => SidebarV2Rail,
41
+ SidebarV2RailItem: () => SidebarV2RailItem,
42
+ SidebarV2RailLink: () => SidebarV2RailLink,
43
+ SidebarV2RailSpacer: () => SidebarV2RailSpacer,
44
+ SidebarV2Trigger: () => SidebarV2Trigger,
45
+ SidebarV2Workspace: () => SidebarV2Workspace,
46
+ useSidebarV2: () => useSidebarV2
47
+ });
48
+ module.exports = __toCommonJS(v2_exports);
49
+
50
+ // src/v2/app-shell.tsx
51
+ var import_shared_utils = require("@kopexa/shared-utils");
52
+ var import_react2 = require("react");
53
+ var import_react_dom = require("react-dom");
54
+
55
+ // src/v2/context.tsx
56
+ var import_react_utils = require("@kopexa/react-utils");
57
+ var import_tooltip = require("@kopexa/tooltip");
58
+ var import_use_is_mobile = require("@kopexa/use-is-mobile");
59
+ var import_react = require("react");
60
+ var import_jsx_runtime = require("react/jsx-runtime");
61
+ var PIN_COOKIE = "kpx_sidebar_v2_pinned";
62
+ var PIN_COOKIE_MAX_AGE = 60 * 60 * 24 * 7;
63
+ var [Provider, useSidebarV2] = (0, import_react_utils.createContext)({
64
+ name: "SidebarV2Context",
65
+ errorMessage: "useSidebarV2 must be used within <SidebarV2> (the provider component)."
66
+ });
67
+ var defaultRenderLink = (props) => {
68
+ const { href, className, children, ...rest } = props;
69
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { href, className, ...rest, children });
70
+ };
71
+ function SidebarV2Provider({
72
+ children,
73
+ tone = "dark",
74
+ flyoutTrigger = "click",
75
+ activeHref,
76
+ renderLink = defaultRenderLink,
77
+ pinned: pinnedProp,
78
+ onPinnedChange,
79
+ defaultPinned = true
80
+ }) {
81
+ const isMobile = (0, import_use_is_mobile.useIsMobile)();
82
+ const [drawerOpen, setDrawerOpen] = (0, import_react.useState)(false);
83
+ const [flyoutValue, setFlyoutValue] = (0, import_react.useState)(null);
84
+ const [selectedRail, setSelectedRail] = (0, import_react.useState)(null);
85
+ const [openGroup, setOpenGroup] = (0, import_react.useState)(null);
86
+ const [pinnedUncontrolled, setPinnedUncontrolled] = (0, import_react.useState)(defaultPinned);
87
+ const pinned = pinnedProp != null ? pinnedProp : pinnedUncontrolled;
88
+ const [panelHost, setPanelHost] = (0, import_react.useState)(null);
89
+ const [overrideCount, setOverrideCount] = (0, import_react.useState)(0);
90
+ const registerPanelOverride = (0, import_react.useCallback)(() => {
91
+ setOverrideCount((c) => c + 1);
92
+ return () => setOverrideCount((c) => c - 1);
93
+ }, []);
94
+ const panelOverrideActive = overrideCount > 0;
95
+ const navPreviewActive = pinned ? selectedRail !== null : flyoutValue !== null;
96
+ const setPinned = (0, import_react.useCallback)(
97
+ (value2) => {
98
+ onPinnedChange == null ? void 0 : onPinnedChange(value2);
99
+ if (pinnedProp === void 0) {
100
+ setPinnedUncontrolled(value2);
101
+ }
102
+ document.cookie = `${PIN_COOKIE}=${value2}; path=/; max-age=${PIN_COOKIE_MAX_AGE}`;
103
+ },
104
+ [onPinnedChange, pinnedProp]
105
+ );
106
+ const togglePin = (0, import_react.useCallback)(() => {
107
+ setPinned(!pinned);
108
+ setFlyoutValue(null);
109
+ }, [pinned, setPinned]);
110
+ const openFlyout = (0, import_react.useCallback)((value2) => {
111
+ setFlyoutValue((curr) => curr === value2 ? null : value2);
112
+ }, []);
113
+ const setFlyout = (0, import_react.useCallback)((value2) => {
114
+ setFlyoutValue(value2);
115
+ }, []);
116
+ const closeFlyout = (0, import_react.useCallback)(() => setFlyoutValue(null), []);
117
+ const resetPanelSelection = (0, import_react.useCallback)(() => {
118
+ setSelectedRail(null);
119
+ setFlyoutValue(null);
120
+ }, []);
121
+ const toggleGroup = (0, import_react.useCallback)((key) => {
122
+ setOpenGroup((curr) => curr === key ? null : key);
123
+ }, []);
124
+ const isActive = (0, import_react.useCallback)(
125
+ (href) => activeHref === href || href !== "/" && activeHref.startsWith(`${href}/`),
126
+ [activeHref]
127
+ );
128
+ const value = (0, import_react.useMemo)(
129
+ () => ({
130
+ tone,
131
+ pinned,
132
+ togglePin,
133
+ setPinned,
134
+ selectedRail,
135
+ setSelectedRail,
136
+ flyoutTrigger,
137
+ flyoutValue,
138
+ openFlyout,
139
+ setFlyout,
140
+ closeFlyout,
141
+ resetPanelSelection,
142
+ openGroup,
143
+ toggleGroup,
144
+ setOpenGroup,
145
+ activeHref,
146
+ isActive,
147
+ renderLink,
148
+ isMobile,
149
+ drawerOpen,
150
+ setDrawerOpen,
151
+ panelHost,
152
+ setPanelHost,
153
+ panelOverrideActive,
154
+ registerPanelOverride,
155
+ navPreviewActive
156
+ }),
157
+ [
158
+ tone,
159
+ pinned,
160
+ togglePin,
161
+ setPinned,
162
+ selectedRail,
163
+ flyoutTrigger,
164
+ flyoutValue,
165
+ openFlyout,
166
+ setFlyout,
167
+ closeFlyout,
168
+ resetPanelSelection,
169
+ openGroup,
170
+ toggleGroup,
171
+ activeHref,
172
+ isActive,
173
+ renderLink,
174
+ isMobile,
175
+ drawerOpen,
176
+ panelHost,
177
+ panelOverrideActive,
178
+ registerPanelOverride,
179
+ navPreviewActive
180
+ ]
181
+ );
182
+ (0, import_react.useEffect)(() => {
183
+ setDrawerOpen(false);
184
+ setFlyoutValue(null);
185
+ setSelectedRail(null);
186
+ setOpenGroup(null);
187
+ }, [activeHref]);
188
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Provider, { value, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_tooltip.TooltipProvider, { delayDuration: 0, children }) });
189
+ }
190
+
191
+ // src/v2/app-shell.tsx
192
+ var import_jsx_runtime2 = require("react/jsx-runtime");
193
+ var RAIL_WIDTH = "4rem";
194
+ var PANEL_WIDTH = "15rem";
195
+ function AppShellRoot({
196
+ className,
197
+ style,
198
+ children,
199
+ ...props
200
+ }) {
201
+ const { tone } = useSidebarV2();
202
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
203
+ "div",
204
+ {
205
+ "data-slot": "app-shell",
206
+ "data-tone": tone,
207
+ className: (0, import_shared_utils.cn)(
208
+ "relative isolate grid h-svh w-full overflow-hidden antialiased",
209
+ tone === "light" ? "bg-muted text-foreground" : "bg-sidebar text-sidebar-foreground",
210
+ className
211
+ ),
212
+ style: {
213
+ "--kpx-rail-width": RAIL_WIDTH,
214
+ "--kpx-panel-width": PANEL_WIDTH,
215
+ gridTemplateAreas: '"header header header header" "rail panel main aside"',
216
+ gridTemplateRows: "auto 1fr",
217
+ gridTemplateColumns: "auto auto 1fr auto",
218
+ ...style
219
+ },
220
+ ...props,
221
+ children
222
+ }
223
+ );
224
+ }
225
+ function AppShellHeader({
226
+ className,
227
+ style,
228
+ ...props
229
+ }) {
230
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
231
+ "header",
232
+ {
233
+ "data-slot": "app-shell-header",
234
+ className: (0, import_shared_utils.cn)("z-20 flex h-14 items-center gap-3 px-2", className),
235
+ style: { gridArea: "header", ...style },
236
+ ...props
237
+ }
238
+ );
239
+ }
240
+ function AppShellMain({ className, style, ...props }) {
241
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
242
+ "main",
243
+ {
244
+ "data-slot": "app-shell-main",
245
+ className: (0, import_shared_utils.cn)(
246
+ "relative flex min-h-0 min-w-0 flex-col overflow-hidden bg-background",
247
+ "m-2 rounded-xl shadow-sm",
248
+ className
249
+ ),
250
+ style: { gridArea: "main", ...style },
251
+ ...props
252
+ }
253
+ );
254
+ }
255
+ function AppShellAside({
256
+ className,
257
+ style,
258
+ ...props
259
+ }) {
260
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
261
+ "aside",
262
+ {
263
+ "data-slot": "app-shell-aside",
264
+ className: (0, import_shared_utils.cn)("min-h-0 min-w-0 overflow-hidden", className),
265
+ style: { gridArea: "aside", ...style },
266
+ ...props
267
+ }
268
+ );
269
+ }
270
+ function AppShellPanelContent({ children }) {
271
+ const { panelHost, registerPanelOverride, navPreviewActive } = useSidebarV2();
272
+ (0, import_react2.useEffect)(() => registerPanelOverride(), [registerPanelOverride]);
273
+ if (!panelHost || navPreviewActive) return null;
274
+ return (0, import_react_dom.createPortal)(children, panelHost);
275
+ }
276
+ var AppShell = AppShellRoot;
277
+ AppShell.Header = AppShellHeader;
278
+ AppShell.Main = AppShellMain;
279
+ AppShell.Aside = AppShellAside;
280
+ AppShell.PanelContent = AppShellPanelContent;
281
+
282
+ // src/v2/components.tsx
283
+ var import_button = require("@kopexa/button");
284
+ var import_icons = require("@kopexa/icons");
285
+ var import_shared_utils2 = require("@kopexa/shared-utils");
286
+ var import_theme = require("@kopexa/theme");
287
+ var import_tooltip2 = require("@kopexa/tooltip");
288
+ var import_react3 = require("react");
289
+
290
+ // src/v2/types.ts
291
+ function panelItemHasChildren(item) {
292
+ return "children" in item && Array.isArray(item.children);
293
+ }
294
+ function panelItemIsSection(item) {
295
+ return "section" in item;
296
+ }
297
+
298
+ // src/v2/components.tsx
299
+ var import_jsx_runtime3 = require("react/jsx-runtime");
300
+ function SidebarV2Inset({
301
+ className,
302
+ ...props
303
+ }) {
304
+ const { tone } = useSidebarV2();
305
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
306
+ "main",
307
+ {
308
+ "data-slot": "sidebar-v2-inset",
309
+ className: (0, import_shared_utils2.cn)(
310
+ "relative flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden bg-background",
311
+ "md:m-2 md:rounded-xl md:shadow-sm",
312
+ // On a light surround the white card needs a hairline to define its
313
+ // edge; on the dark surround a border would read as a seam.
314
+ tone === "light" && "md:border md:border-border/70",
315
+ className
316
+ ),
317
+ ...props
318
+ }
319
+ );
320
+ }
321
+ function SidebarV2Rail({ className, ...props }) {
322
+ const { tone } = useSidebarV2();
323
+ const light = tone === "light";
324
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
325
+ "nav",
326
+ {
327
+ "data-slot": "sidebar-v2-rail",
328
+ className: (0, import_shared_utils2.cn)(
329
+ "flex w-(--kpx-rail-width) shrink-0 flex-col overflow-hidden bg-sidebar py-2 text-sidebar-foreground",
330
+ // Light tone: the dark rail floats as a rounded card on the light
331
+ // surround. Dark tone: full-height, flush to the edge.
332
+ light ? "m-2 rounded-2xl shadow-sm" : "h-full",
333
+ className
334
+ ),
335
+ ...props
336
+ }
337
+ );
338
+ }
339
+ function SidebarV2RailSpacer() {
340
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { "aria-hidden": true, className: "flex-1" });
341
+ }
342
+ var SidebarV2Workspace = (0, import_react3.forwardRef)(({ name, role, logo, className, appearance = "rail", ...props }, ref) => {
343
+ if (appearance === "bar") {
344
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
345
+ "button",
346
+ {
347
+ ref,
348
+ type: "button",
349
+ "data-slot": "sidebar-v2-workspace",
350
+ "aria-label": role ? `${name} \u2013 ${role}` : name,
351
+ className: (0, import_shared_utils2.cn)(
352
+ "group/ws flex cursor-pointer items-center gap-2 rounded-lg py-1 pr-2 pl-1",
353
+ "outline-hidden ring-ring transition-colors hover:bg-foreground/5 focus-visible:ring-2",
354
+ className
355
+ ),
356
+ ...props,
357
+ children: [
358
+ /* @__PURE__ */ (0, import_jsx_runtime3.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() }),
359
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "flex min-w-0 flex-col text-left leading-tight", children: [
360
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "truncate text-sm font-semibold text-foreground", children: name }),
361
+ role && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "truncate text-xs text-muted-foreground", children: role })
362
+ ] }),
363
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_icons.ChevronDownIcon, { className: "size-4 shrink-0 text-muted-foreground" })
364
+ ]
365
+ }
366
+ );
367
+ }
368
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
369
+ "button",
370
+ {
371
+ ref,
372
+ type: "button",
373
+ "data-slot": "sidebar-v2-workspace",
374
+ "aria-label": role ? `${name} \u2013 ${role}` : name,
375
+ className: (0, import_shared_utils2.cn)(
376
+ "group/ws relative mx-auto mt-1 flex cursor-pointer items-center justify-center rounded-lg p-1",
377
+ "outline-hidden ring-sidebar-ring transition-colors",
378
+ "hover:bg-sidebar-accent focus-visible:ring-2",
379
+ className
380
+ ),
381
+ ...props,
382
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.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: [
383
+ logo != null ? logo : name.charAt(0).toUpperCase(),
384
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_icons.ChevronDownIcon, { className: "absolute -right-1 -bottom-1 size-3.5 rounded-full bg-sidebar p-px text-sidebar-foreground/60" })
385
+ ] })
386
+ }
387
+ );
388
+ });
389
+ SidebarV2Workspace.displayName = "SidebarV2Workspace";
390
+ function railButtonClasses(active) {
391
+ return (0, import_shared_utils2.cn)(
392
+ "group/rail relative mx-auto flex size-11 shrink-0 cursor-pointer items-center justify-center rounded-xl",
393
+ "outline-hidden ring-sidebar-ring transition-colors",
394
+ "text-sidebar-foreground/85 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground",
395
+ "focus-visible:ring-2",
396
+ active && "bg-sidebar-accent text-sidebar-accent-foreground"
397
+ );
398
+ }
399
+ function RailInner({
400
+ icon: Icon,
401
+ active,
402
+ badge
403
+ }) {
404
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
405
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
406
+ "span",
407
+ {
408
+ "aria-hidden": true,
409
+ className: (0, import_shared_utils2.cn)(
410
+ "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",
411
+ active ? "opacity-100" : "opacity-0"
412
+ )
413
+ }
414
+ ),
415
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Icon, { className: "size-5 shrink-0" }),
416
+ badge != null && /* @__PURE__ */ (0, import_jsx_runtime3.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 })
417
+ ] });
418
+ }
419
+ function SidebarV2RailLink({
420
+ icon,
421
+ label,
422
+ href,
423
+ badge
424
+ }) {
425
+ const { renderLink, isActive, resetPanelSelection } = useSidebarV2();
426
+ const active = isActive(href);
427
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_tooltip2.Tooltip, { content: label, side: "right", children: renderLink({
428
+ href,
429
+ className: railButtonClasses(active),
430
+ "data-active": active,
431
+ "aria-current": active ? "page" : void 0,
432
+ "aria-label": label,
433
+ // Navigating to a destination link clears any open panel preview,
434
+ // even when the route doesn't change (e.g. already on it).
435
+ onClick: resetPanelSelection,
436
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(RailInner, { icon, label, active, badge })
437
+ }) });
438
+ }
439
+ function SidebarV2RailItem({
440
+ icon,
441
+ label,
442
+ active,
443
+ hasPanel,
444
+ onClick,
445
+ onMouseEnter,
446
+ onMouseLeave,
447
+ badge
448
+ }) {
449
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_tooltip2.Tooltip, { content: label, side: "right", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
450
+ "button",
451
+ {
452
+ type: "button",
453
+ "data-active": active,
454
+ "aria-label": label,
455
+ "aria-expanded": hasPanel ? active : void 0,
456
+ onClick,
457
+ onMouseEnter,
458
+ onMouseLeave,
459
+ className: railButtonClasses(active),
460
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(RailInner, { icon, label, active, badge })
461
+ }
462
+ ) });
463
+ }
464
+ function SidebarV2Panel({
465
+ title,
466
+ subtitle,
467
+ floating,
468
+ hidePin,
469
+ action,
470
+ children,
471
+ className
472
+ }) {
473
+ const { togglePin, pinned, tone } = useSidebarV2();
474
+ const light = tone === "light";
475
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
476
+ "div",
477
+ {
478
+ "data-slot": "sidebar-v2-panel",
479
+ "data-floating": floating,
480
+ className: (0, import_shared_utils2.cn)(
481
+ "flex h-full w-(--kpx-panel-width) shrink-0 flex-col",
482
+ // Surface. The flyout is a distinct floating card (white on light),
483
+ // so it reads as an overlay rather than a flat full-height slab.
484
+ floating ? light ? "bg-background text-foreground" : "bg-sidebar text-sidebar-foreground" : light ? "bg-muted text-foreground" : "bg-sidebar text-sidebar-foreground",
485
+ floating ? (
486
+ // Floating card: rounded, soft layered shadow, hairline ring.
487
+ (0, import_shared_utils2.cn)(
488
+ "overflow-hidden rounded-2xl shadow-2xl shadow-black/20 ring-1",
489
+ light ? "ring-black/5" : "ring-white/10"
490
+ )
491
+ ) : (
492
+ // Pinned: light blends into the surround (no border); dark keeps a
493
+ // hairline against the rail.
494
+ light ? "" : "border-l border-sidebar-border/40"
495
+ ),
496
+ className
497
+ ),
498
+ children: [
499
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "flex items-start gap-2 px-3 pt-3 pb-1.5", children: [
500
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "min-w-0 flex-1", children: [
501
+ title && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
502
+ "div",
503
+ {
504
+ className: (0, import_shared_utils2.cn)(
505
+ "truncate text-sm font-semibold",
506
+ light ? "text-foreground" : "text-sidebar-foreground"
507
+ ),
508
+ children: title
509
+ }
510
+ ),
511
+ subtitle && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
512
+ "div",
513
+ {
514
+ className: (0, import_shared_utils2.cn)(
515
+ "truncate text-xs",
516
+ light ? "text-muted-foreground" : "text-sidebar-foreground/70"
517
+ ),
518
+ children: subtitle
519
+ }
520
+ )
521
+ ] }),
522
+ action != null ? action : !hidePin && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
523
+ import_tooltip2.Tooltip,
524
+ {
525
+ content: pinned ? "Panel l\xF6sen" : "Panel anheften",
526
+ side: "bottom",
527
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
528
+ import_button.IconButton,
529
+ {
530
+ variant: "ghost",
531
+ size: "sm",
532
+ "aria-label": pinned ? "Panel l\xF6sen" : "Panel anheften",
533
+ onClick: togglePin,
534
+ className: (0, import_shared_utils2.cn)(
535
+ "-mr-1 shrink-0",
536
+ light ? "text-muted-foreground hover:bg-foreground/5 hover:text-foreground" : "text-sidebar-foreground/60 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground"
537
+ ),
538
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_icons.PanelLeftIcon, { className: "size-4" })
539
+ }
540
+ )
541
+ }
542
+ )
543
+ ] }),
544
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "flex min-h-0 flex-1 flex-col gap-0.5 overflow-auto p-2", children })
545
+ ]
546
+ }
547
+ );
548
+ }
549
+ function panelRowLight(active) {
550
+ return (0, import_shared_utils2.cn)(
551
+ "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",
552
+ active ? "bg-primary/10 font-medium text-primary" : "text-foreground/80 hover:bg-foreground/5"
553
+ );
554
+ }
555
+ function SidebarV2PanelLabel({
556
+ className,
557
+ ...props
558
+ }) {
559
+ const { tone } = useSidebarV2();
560
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
561
+ "div",
562
+ {
563
+ "data-slot": "sidebar-v2-panel-label",
564
+ className: (0, import_shared_utils2.cn)(
565
+ "px-2 pt-3 pb-1 text-[0.6875rem] font-medium uppercase tracking-wide",
566
+ tone === "light" ? "text-muted-foreground" : "text-sidebar-foreground/50",
567
+ className
568
+ ),
569
+ ...props
570
+ }
571
+ );
572
+ }
573
+ function SidebarV2PanelLeaf({
574
+ item,
575
+ active: activeProp
576
+ }) {
577
+ const { renderLink, isActive, tone } = useSidebarV2();
578
+ const light = tone === "light";
579
+ const Icon = item.icon;
580
+ const active = activeProp != null ? activeProp : isActive(item.href);
581
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children: renderLink({
582
+ href: item.href,
583
+ "data-active": active,
584
+ "aria-current": active ? "page" : void 0,
585
+ className: light ? panelRowLight(active) : (0, import_theme.sidebarMenuButton)({ size: "md" }),
586
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
587
+ Icon && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
588
+ Icon,
589
+ {
590
+ className: (0, import_shared_utils2.cn)(
591
+ light ? active ? void 0 : "text-muted-foreground" : "text-sidebar-foreground/75"
592
+ )
593
+ }
594
+ ),
595
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "min-w-0 flex-1 truncate", children: item.label }),
596
+ item.badge != null && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
597
+ "span",
598
+ {
599
+ className: (0, import_shared_utils2.cn)(
600
+ "ml-auto rounded-full px-1.5 text-[0.625rem] font-medium",
601
+ light ? "bg-foreground/10 text-foreground/70" : "bg-sidebar-accent text-sidebar-accent-foreground"
602
+ ),
603
+ children: item.badge
604
+ }
605
+ )
606
+ ] })
607
+ }) });
608
+ }
609
+ function SidebarV2PanelGroup({
610
+ item
611
+ }) {
612
+ var _a;
613
+ const { openGroup, toggleGroup, activeHref, renderLink, tone } = useSidebarV2();
614
+ const light = tone === "light";
615
+ const Icon = item.icon;
616
+ const key = (_a = item.value) != null ? _a : item.label;
617
+ let bestChildHref = null;
618
+ let bestLen = -1;
619
+ for (const c of item.children) {
620
+ if (activeHref === c.href) {
621
+ bestChildHref = c.href;
622
+ break;
623
+ }
624
+ if (activeHref.startsWith(`${c.href}/`) && c.href.length > bestLen) {
625
+ bestChildHref = c.href;
626
+ bestLen = c.href.length;
627
+ }
628
+ }
629
+ const containsActive = bestChildHref !== null;
630
+ const open = openGroup === key || openGroup === null && containsActive;
631
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { children: [
632
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
633
+ "button",
634
+ {
635
+ type: "button",
636
+ "data-state": open ? "open" : "closed",
637
+ "aria-expanded": open,
638
+ onClick: () => toggleGroup(key),
639
+ className: (0, import_shared_utils2.cn)(
640
+ light ? panelRowLight(false) : (0, import_theme.sidebarMenuButton)({ size: "md" }),
641
+ "cursor-pointer",
642
+ containsActive && (light ? "font-medium text-foreground" : "font-medium")
643
+ ),
644
+ children: [
645
+ Icon && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
646
+ Icon,
647
+ {
648
+ className: light ? "text-muted-foreground" : "text-sidebar-foreground/75"
649
+ }
650
+ ),
651
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "min-w-0 flex-1 truncate text-left", children: item.label }),
652
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
653
+ import_icons.ChevronRightIcon,
654
+ {
655
+ className: (0, import_shared_utils2.cn)(
656
+ "size-3.5! shrink-0 transition-transform",
657
+ light ? "text-muted-foreground" : "text-sidebar-foreground/60",
658
+ open && "rotate-90"
659
+ )
660
+ }
661
+ )
662
+ ]
663
+ }
664
+ ),
665
+ open && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
666
+ "div",
667
+ {
668
+ className: (0, import_shared_utils2.cn)(
669
+ "my-0.5 ml-[1.05rem] flex flex-col border-l pl-3",
670
+ light ? "border-border" : "border-sidebar-border"
671
+ ),
672
+ children: item.children.map((child) => {
673
+ const active = child.href === bestChildHref;
674
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: renderLink({
675
+ href: child.href,
676
+ "data-active": active,
677
+ "aria-current": active ? "page" : void 0,
678
+ className: (0, import_shared_utils2.cn)(
679
+ "relative block rounded-md px-2 py-1.5 text-[0.8125rem] outline-hidden transition-colors focus-visible:ring-2",
680
+ "before:absolute before:top-1/2 before:-left-3 before:h-px before:w-2.5",
681
+ 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"
682
+ ),
683
+ children: child.label
684
+ }) }, child.href);
685
+ })
686
+ }
687
+ )
688
+ ] });
689
+ }
690
+ function SidebarV2PanelItems({
691
+ items
692
+ }) {
693
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children: items.map((item, idx) => {
694
+ var _a;
695
+ if (panelItemIsSection(item)) {
696
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(SidebarV2PanelLabel, { children: item.section }, `section-${item.section}-${idx}`);
697
+ }
698
+ if (panelItemHasChildren(item)) {
699
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(SidebarV2PanelGroup, { item }, (_a = item.value) != null ? _a : item.label);
700
+ }
701
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(SidebarV2PanelLeaf, { item }, item.href);
702
+ }) });
703
+ }
704
+ function SidebarV2Trigger({
705
+ className,
706
+ ...props
707
+ }) {
708
+ const { setDrawerOpen, drawerOpen } = useSidebarV2();
709
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
710
+ import_button.IconButton,
711
+ {
712
+ variant: "ghost",
713
+ size: "md",
714
+ "aria-label": "Navigation \xF6ffnen",
715
+ onClick: () => setDrawerOpen(!drawerOpen),
716
+ className,
717
+ ...props,
718
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_icons.PanelLeftIcon, { className: "size-5" })
719
+ }
720
+ );
721
+ }
722
+
723
+ // src/v2/from-config.tsx
724
+ var import_drawer = require("@kopexa/drawer");
725
+ var import_shared_utils3 = require("@kopexa/shared-utils");
726
+ var import_react4 = require("motion/react");
727
+ var import_react5 = require("react");
728
+ var import_jsx_runtime4 = require("react/jsx-runtime");
729
+ var RAIL_WIDTH2 = "4rem";
730
+ var PANEL_WIDTH2 = "15rem";
731
+ var railVars = {
732
+ "--kpx-rail-width": RAIL_WIDTH2,
733
+ "--kpx-panel-width": PANEL_WIDTH2
734
+ };
735
+ function entryValue(entry) {
736
+ var _a;
737
+ if (entry.type === "divider") return "divider";
738
+ return entry.type === "panel" ? (_a = entry.value) != null ? _a : entry.label : entry.label;
739
+ }
740
+ function SidebarV2FromConfig({
741
+ items,
742
+ header
743
+ }) {
744
+ var _a, _b, _c;
745
+ const {
746
+ pinned,
747
+ flyoutTrigger,
748
+ flyoutValue,
749
+ openFlyout,
750
+ setFlyout,
751
+ closeFlyout,
752
+ selectedRail,
753
+ setSelectedRail,
754
+ isActive,
755
+ isMobile,
756
+ drawerOpen,
757
+ setDrawerOpen,
758
+ setPanelHost,
759
+ panelOverrideActive,
760
+ navPreviewActive
761
+ } = useSidebarV2();
762
+ const hoverMode = flyoutTrigger === "hover" && !pinned && !isMobile;
763
+ const closeTimer = (0, import_react5.useRef)(null);
764
+ const cancelClose = (0, import_react5.useCallback)(() => {
765
+ if (closeTimer.current) clearTimeout(closeTimer.current);
766
+ closeTimer.current = null;
767
+ }, []);
768
+ const scheduleClose = (0, import_react5.useCallback)(() => {
769
+ cancelClose();
770
+ closeTimer.current = setTimeout(() => closeFlyout(), 160);
771
+ }, [cancelClose, closeFlyout]);
772
+ (0, import_react5.useEffect)(() => cancelClose, [cancelClose]);
773
+ (0, import_react5.useEffect)(() => {
774
+ if (pinned || isMobile || !flyoutValue) return;
775
+ const onPointerDown = (event) => {
776
+ const t = event.target;
777
+ if (!t) return;
778
+ if (t.closest('[data-slot="sidebar-v2-rail"]')) return;
779
+ if (t.closest('[data-floating="true"]')) return;
780
+ closeFlyout();
781
+ };
782
+ const onKeyDown = (event) => {
783
+ if (event.key === "Escape") closeFlyout();
784
+ };
785
+ document.addEventListener("pointerdown", onPointerDown);
786
+ document.addEventListener("keydown", onKeyDown);
787
+ return () => {
788
+ document.removeEventListener("pointerdown", onPointerDown);
789
+ document.removeEventListener("keydown", onKeyDown);
790
+ };
791
+ }, [pinned, isMobile, flyoutValue, closeFlyout]);
792
+ const panels = (0, import_react5.useMemo)(
793
+ () => items.filter(
794
+ (e) => e.type === "panel"
795
+ ),
796
+ [items]
797
+ );
798
+ const activeRailValue = (0, import_react5.useMemo)(() => {
799
+ const match = panels.find(
800
+ (p) => p.items.some((item) => {
801
+ if (panelItemIsSection(item)) return false;
802
+ return panelItemHasChildren(item) ? item.children.some((c) => isActive(c.href)) : isActive(item.href);
803
+ })
804
+ );
805
+ return match ? entryValue(match) : null;
806
+ }, [panels, isActive]);
807
+ const shownValue = pinned ? selectedRail != null ? selectedRail : activeRailValue : flyoutValue;
808
+ const shownPanel = (_a = panels.find((p) => entryValue(p) === shownValue)) != null ? _a : null;
809
+ const topEntries = items.filter((e) => e.slot !== "bottom");
810
+ const bottomEntries = items.filter((e) => e.slot === "bottom");
811
+ function renderRailEntry(entry, index) {
812
+ if (entry.type === "divider") {
813
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
814
+ "div",
815
+ {
816
+ "aria-hidden": true,
817
+ className: "mx-3 my-1.5 h-px shrink-0 bg-sidebar-border/70"
818
+ },
819
+ `rail-divider-${index}`
820
+ );
821
+ }
822
+ const value = entryValue(entry);
823
+ if (entry.type === "link") {
824
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
825
+ SidebarV2RailLink,
826
+ {
827
+ icon: entry.icon,
828
+ label: entry.label,
829
+ href: entry.href,
830
+ badge: entry.badge
831
+ },
832
+ value
833
+ );
834
+ }
835
+ if (entry.type === "action") {
836
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
837
+ SidebarV2RailItem,
838
+ {
839
+ icon: entry.icon,
840
+ label: entry.label,
841
+ active: false,
842
+ onClick: entry.onSelect
843
+ },
844
+ value
845
+ );
846
+ }
847
+ const active = flyoutValue ? value === flyoutValue : value === (selectedRail != null ? selectedRail : activeRailValue);
848
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
849
+ SidebarV2RailItem,
850
+ {
851
+ icon: entry.icon,
852
+ label: entry.label,
853
+ active,
854
+ hasPanel: true,
855
+ onClick: () => {
856
+ if (pinned) setSelectedRail(value);
857
+ else openFlyout(value);
858
+ },
859
+ onMouseEnter: hoverMode ? () => {
860
+ cancelClose();
861
+ setFlyout(value);
862
+ } : void 0,
863
+ onMouseLeave: hoverMode ? scheduleClose : void 0
864
+ },
865
+ value
866
+ );
867
+ }
868
+ const railContent = /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
869
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex min-h-0 flex-1 flex-col gap-1 overflow-y-auto [scrollbar-width:none] [&::-webkit-scrollbar]:hidden", children: [
870
+ header && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
871
+ header,
872
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mx-3 my-1 h-px shrink-0 bg-sidebar-border/60" })
873
+ ] }),
874
+ topEntries.map(renderRailEntry)
875
+ ] }),
876
+ bottomEntries.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "flex shrink-0 flex-col gap-1 pt-1", children: bottomEntries.map(renderRailEntry) })
877
+ ] });
878
+ const navData = pinned && shownPanel && (navPreviewActive || !panelOverrideActive) ? shownPanel : null;
879
+ const [bufferedPanel, setBufferedPanel] = (0, import_react5.useState)(navData);
880
+ (0, import_react5.useEffect)(() => {
881
+ if (navData) {
882
+ setBufferedPanel(navData);
883
+ return;
884
+ }
885
+ const t = setTimeout(() => setBufferedPanel(null), 220);
886
+ return () => clearTimeout(t);
887
+ }, [navData]);
888
+ const navToRender = navData != null ? navData : bufferedPanel;
889
+ const renderNav = (!panelOverrideActive || navPreviewActive) && navToRender;
890
+ const panelContent = navToRender && renderNav ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
891
+ SidebarV2Panel,
892
+ {
893
+ title: (_b = navToRender.title) != null ? _b : navToRender.label,
894
+ subtitle: navToRender.subtitle,
895
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SidebarV2PanelItems, { items: navToRender.items })
896
+ },
897
+ entryValue(navToRender)
898
+ ) : null;
899
+ const docked = Boolean(navData) || panelOverrideActive;
900
+ const showFlyout = !pinned && Boolean(shownPanel);
901
+ if (isMobile) {
902
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
903
+ import_drawer.Drawer.Root,
904
+ {
905
+ open: drawerOpen,
906
+ onOpenChange: setDrawerOpen,
907
+ placement: "left",
908
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_drawer.Drawer.Content, { className: "w-auto max-w-[85vw] border-0 bg-sidebar p-0 [&>button]:hidden", children: [
909
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_drawer.Drawer.Header, { className: "sr-only", children: [
910
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_drawer.Drawer.Title, { children: "Navigation" }),
911
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_drawer.Drawer.Description, { children: "Hauptnavigation" })
912
+ ] }),
913
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex h-full", style: railVars, children: [
914
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SidebarV2Rail, { children: railContent }),
915
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
916
+ "div",
917
+ {
918
+ ref: setPanelHost,
919
+ "data-slot": "sidebar-v2-panel-zone",
920
+ className: "flex min-h-0",
921
+ children: panelContent
922
+ }
923
+ )
924
+ ] })
925
+ ] })
926
+ }
927
+ );
928
+ }
929
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
930
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SidebarV2Rail, { style: { gridArea: "rail" }, children: railContent }),
931
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
932
+ "div",
933
+ {
934
+ ref: setPanelHost,
935
+ "data-slot": "sidebar-v2-panel-zone",
936
+ className: (0, import_shared_utils3.cn)(
937
+ "relative shrink-0 transition-[width] duration-200 ease-out motion-reduce:transition-none",
938
+ pinned && "overflow-hidden"
939
+ ),
940
+ style: { gridArea: "panel", width: docked ? PANEL_WIDTH2 : "0px" },
941
+ children: [
942
+ panelContent,
943
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react4.AnimatePresence, { children: showFlyout && shownPanel && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
944
+ import_react4.motion.div,
945
+ {
946
+ "data-floating": "true",
947
+ className: "absolute inset-y-2 left-1 z-30",
948
+ initial: { x: -14, opacity: 0 },
949
+ animate: { x: 0, opacity: 1 },
950
+ exit: { x: -14, opacity: 0 },
951
+ transition: { duration: 0.16, ease: "easeOut" },
952
+ onMouseEnter: hoverMode ? cancelClose : void 0,
953
+ onMouseLeave: hoverMode ? scheduleClose : void 0,
954
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
955
+ SidebarV2Panel,
956
+ {
957
+ floating: true,
958
+ title: (_c = shownPanel.title) != null ? _c : shownPanel.label,
959
+ subtitle: shownPanel.subtitle,
960
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SidebarV2PanelItems, { items: shownPanel.items })
961
+ }
962
+ )
963
+ },
964
+ "sidebar-v2-flyout"
965
+ ) })
966
+ ]
967
+ }
968
+ )
969
+ ] });
970
+ }
971
+
972
+ // src/v2/index.tsx
973
+ var SidebarV2 = SidebarV2Provider;
974
+ SidebarV2.FromConfig = SidebarV2FromConfig;
975
+ SidebarV2.Inset = SidebarV2Inset;
976
+ SidebarV2.Trigger = SidebarV2Trigger;
977
+ SidebarV2.Rail = SidebarV2Rail;
978
+ SidebarV2.RailItem = SidebarV2RailItem;
979
+ SidebarV2.RailLink = SidebarV2RailLink;
980
+ SidebarV2.RailSpacer = SidebarV2RailSpacer;
981
+ SidebarV2.Workspace = SidebarV2Workspace;
982
+ SidebarV2.Panel = SidebarV2Panel;
983
+ SidebarV2.PanelItems = SidebarV2PanelItems;
984
+ SidebarV2.PanelLeaf = SidebarV2PanelLeaf;
985
+ SidebarV2.PanelGroup = SidebarV2PanelGroup;
986
+ SidebarV2.PanelLabel = SidebarV2PanelLabel;
987
+ // Annotate the CommonJS export names for ESM import in node:
988
+ 0 && (module.exports = {
989
+ AppShell,
990
+ AppShellAside,
991
+ AppShellHeader,
992
+ AppShellMain,
993
+ AppShellPanelContent,
994
+ AppShellRoot,
995
+ SidebarV2,
996
+ SidebarV2FromConfig,
997
+ SidebarV2Inset,
998
+ SidebarV2Panel,
999
+ SidebarV2PanelGroup,
1000
+ SidebarV2PanelItems,
1001
+ SidebarV2PanelLabel,
1002
+ SidebarV2PanelLeaf,
1003
+ SidebarV2Provider,
1004
+ SidebarV2Rail,
1005
+ SidebarV2RailItem,
1006
+ SidebarV2RailLink,
1007
+ SidebarV2RailSpacer,
1008
+ SidebarV2Trigger,
1009
+ SidebarV2Workspace,
1010
+ useSidebarV2
1011
+ });