@kopexa/sidebar 17.1.74 → 17.2.1

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/index.js CHANGED
@@ -21,6 +21,12 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  // src/index.ts
22
22
  var index_exports = {};
23
23
  __export(index_exports, {
24
+ AppShell: () => AppShell,
25
+ AppShellAside: () => AppShellAside,
26
+ AppShellHeader: () => AppShellHeader,
27
+ AppShellMain: () => AppShellMain,
28
+ AppShellPanelContent: () => AppShellPanelContent,
29
+ AppShellRoot: () => AppShellRoot,
24
30
  Sidebar: () => Sidebar,
25
31
  SidebarContent: () => SidebarContent,
26
32
  SidebarFooter: () => SidebarFooter,
@@ -40,7 +46,23 @@ __export(index_exports, {
40
46
  SidebarRoot: () => SidebarRoot,
41
47
  SidebarSeparator: () => SidebarSeparator,
42
48
  SidebarTrigger: () => SidebarTrigger,
43
- useSidebar: () => useSidebar
49
+ SidebarV2: () => SidebarV2,
50
+ SidebarV2FromConfig: () => SidebarV2FromConfig,
51
+ SidebarV2Inset: () => SidebarV2Inset,
52
+ SidebarV2Panel: () => SidebarV2Panel,
53
+ SidebarV2PanelGroup: () => SidebarV2PanelGroup,
54
+ SidebarV2PanelItems: () => SidebarV2PanelItems,
55
+ SidebarV2PanelLabel: () => SidebarV2PanelLabel,
56
+ SidebarV2PanelLeaf: () => SidebarV2PanelLeaf,
57
+ SidebarV2Provider: () => SidebarV2Provider,
58
+ SidebarV2Rail: () => SidebarV2Rail,
59
+ SidebarV2RailItem: () => SidebarV2RailItem,
60
+ SidebarV2RailLink: () => SidebarV2RailLink,
61
+ SidebarV2RailSpacer: () => SidebarV2RailSpacer,
62
+ SidebarV2Trigger: () => SidebarV2Trigger,
63
+ SidebarV2Workspace: () => SidebarV2Workspace,
64
+ useSidebar: () => useSidebar,
65
+ useSidebarV2: () => useSidebarV2
44
66
  });
45
67
  module.exports = __toCommonJS(index_exports);
46
68
 
@@ -507,8 +529,819 @@ var Sidebar = Object.assign(SidebarRoot, {
507
529
  MenuButton: SidebarMenuButton,
508
530
  MenuAction: SidebarMenuAction
509
531
  });
532
+
533
+ // src/v2/app-shell.tsx
534
+ var import_react3 = require("react");
535
+ var import_react_dom = require("react-dom");
536
+
537
+ // src/v2/context.tsx
538
+ var import_react_utils2 = require("@kopexa/react-utils");
539
+ var import_theme2 = require("@kopexa/theme");
540
+ var import_tooltip2 = require("@kopexa/tooltip");
541
+ var import_use_is_mobile2 = require("@kopexa/use-is-mobile");
542
+ var import_react2 = require("react");
543
+ var import_jsx_runtime2 = require("react/jsx-runtime");
544
+ var PIN_COOKIE = "kpx_sidebar_v2_pinned";
545
+ var PIN_COOKIE_MAX_AGE = 60 * 60 * 24 * 7;
546
+ var [Provider2, useSidebarV2] = (0, import_react_utils2.createContext)({
547
+ name: "SidebarV2Context",
548
+ errorMessage: "useSidebarV2 must be used within <SidebarV2> (the provider component)."
549
+ });
550
+ var defaultRenderLink = (props) => {
551
+ const { href, className, children, ...rest } = props;
552
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("a", { href, className, ...rest, children });
553
+ };
554
+ function SidebarV2Provider({
555
+ children,
556
+ tone = "dark",
557
+ flyoutTrigger = "click",
558
+ activeHref,
559
+ renderLink = defaultRenderLink,
560
+ pinned: pinnedProp,
561
+ onPinnedChange,
562
+ defaultPinned = true
563
+ }) {
564
+ const isMobile = (0, import_use_is_mobile2.useIsMobile)();
565
+ const [drawerOpen, setDrawerOpen] = (0, import_react2.useState)(false);
566
+ const [flyoutValue, setFlyoutValue] = (0, import_react2.useState)(null);
567
+ const [selectedRail, setSelectedRail] = (0, import_react2.useState)(null);
568
+ const [openGroup, setOpenGroup] = (0, import_react2.useState)(null);
569
+ const [pinnedUncontrolled, setPinnedUncontrolled] = (0, import_react2.useState)(defaultPinned);
570
+ const pinned = pinnedProp != null ? pinnedProp : pinnedUncontrolled;
571
+ const [panelHost, setPanelHost] = (0, import_react2.useState)(null);
572
+ const [overrideCount, setOverrideCount] = (0, import_react2.useState)(0);
573
+ const registerPanelOverride = (0, import_react2.useCallback)(() => {
574
+ setOverrideCount((c) => c + 1);
575
+ return () => setOverrideCount((c) => c - 1);
576
+ }, []);
577
+ const panelOverrideActive = overrideCount > 0;
578
+ const navPreviewActive = pinned ? selectedRail !== null : flyoutValue !== null;
579
+ const styles = (0, import_react2.useMemo)(() => (0, import_theme2.sidebarV2)({ tone }), [tone]);
580
+ const setPinned = (0, import_react2.useCallback)(
581
+ (value2) => {
582
+ onPinnedChange == null ? void 0 : onPinnedChange(value2);
583
+ if (pinnedProp === void 0) {
584
+ setPinnedUncontrolled(value2);
585
+ }
586
+ document.cookie = `${PIN_COOKIE}=${value2}; path=/; max-age=${PIN_COOKIE_MAX_AGE}`;
587
+ },
588
+ [onPinnedChange, pinnedProp]
589
+ );
590
+ const togglePin = (0, import_react2.useCallback)(() => {
591
+ setPinned(!pinned);
592
+ setFlyoutValue(null);
593
+ }, [pinned, setPinned]);
594
+ const openFlyout = (0, import_react2.useCallback)((value2) => {
595
+ setFlyoutValue((curr) => curr === value2 ? null : value2);
596
+ }, []);
597
+ const setFlyout = (0, import_react2.useCallback)((value2) => {
598
+ setFlyoutValue(value2);
599
+ }, []);
600
+ const closeFlyout = (0, import_react2.useCallback)(() => setFlyoutValue(null), []);
601
+ const resetPanelSelection = (0, import_react2.useCallback)(() => {
602
+ setSelectedRail(null);
603
+ setFlyoutValue(null);
604
+ }, []);
605
+ const toggleGroup = (0, import_react2.useCallback)((key) => {
606
+ setOpenGroup((curr) => curr === key ? null : key);
607
+ }, []);
608
+ const isActive = (0, import_react2.useCallback)(
609
+ (href) => activeHref === href || href !== "/" && activeHref.startsWith(`${href}/`),
610
+ [activeHref]
611
+ );
612
+ const value = (0, import_react2.useMemo)(
613
+ () => ({
614
+ tone,
615
+ styles,
616
+ pinned,
617
+ togglePin,
618
+ setPinned,
619
+ selectedRail,
620
+ setSelectedRail,
621
+ flyoutTrigger,
622
+ flyoutValue,
623
+ openFlyout,
624
+ setFlyout,
625
+ closeFlyout,
626
+ resetPanelSelection,
627
+ openGroup,
628
+ toggleGroup,
629
+ setOpenGroup,
630
+ activeHref,
631
+ isActive,
632
+ renderLink,
633
+ isMobile,
634
+ drawerOpen,
635
+ setDrawerOpen,
636
+ panelHost,
637
+ setPanelHost,
638
+ panelOverrideActive,
639
+ registerPanelOverride,
640
+ navPreviewActive
641
+ }),
642
+ [
643
+ tone,
644
+ styles,
645
+ pinned,
646
+ togglePin,
647
+ setPinned,
648
+ selectedRail,
649
+ flyoutTrigger,
650
+ flyoutValue,
651
+ openFlyout,
652
+ setFlyout,
653
+ closeFlyout,
654
+ resetPanelSelection,
655
+ openGroup,
656
+ toggleGroup,
657
+ activeHref,
658
+ isActive,
659
+ renderLink,
660
+ isMobile,
661
+ drawerOpen,
662
+ panelHost,
663
+ panelOverrideActive,
664
+ registerPanelOverride,
665
+ navPreviewActive
666
+ ]
667
+ );
668
+ (0, import_react2.useEffect)(() => {
669
+ setDrawerOpen(false);
670
+ setFlyoutValue(null);
671
+ setSelectedRail(null);
672
+ setOpenGroup(null);
673
+ }, [activeHref]);
674
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Provider2, { value, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_tooltip2.TooltipProvider, { delayDuration: 0, children }) });
675
+ }
676
+
677
+ // src/v2/app-shell.tsx
678
+ var import_jsx_runtime3 = require("react/jsx-runtime");
679
+ var RAIL_WIDTH = "4rem";
680
+ var PANEL_WIDTH = "15rem";
681
+ function AppShellRoot({
682
+ className,
683
+ style,
684
+ children,
685
+ ...props
686
+ }) {
687
+ const { tone, styles } = useSidebarV2();
688
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
689
+ "div",
690
+ {
691
+ "data-slot": "app-shell",
692
+ "data-tone": tone,
693
+ className: styles.shell({ className }),
694
+ style: {
695
+ "--kpx-rail-width": RAIL_WIDTH,
696
+ "--kpx-panel-width": PANEL_WIDTH,
697
+ gridTemplateAreas: '"header header header header" "rail panel main aside"',
698
+ gridTemplateRows: "auto 1fr",
699
+ gridTemplateColumns: "auto auto 1fr auto",
700
+ ...style
701
+ },
702
+ ...props,
703
+ children
704
+ }
705
+ );
706
+ }
707
+ function AppShellHeader({
708
+ className,
709
+ style,
710
+ ...props
711
+ }) {
712
+ const { styles } = useSidebarV2();
713
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
714
+ "header",
715
+ {
716
+ "data-slot": "app-shell-header",
717
+ className: styles.header({ className }),
718
+ style: { gridArea: "header", ...style },
719
+ ...props
720
+ }
721
+ );
722
+ }
723
+ function AppShellMain({ className, style, ...props }) {
724
+ const { styles } = useSidebarV2();
725
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
726
+ "main",
727
+ {
728
+ "data-slot": "app-shell-main",
729
+ className: styles.main({ className }),
730
+ style: { gridArea: "main", ...style },
731
+ ...props
732
+ }
733
+ );
734
+ }
735
+ function AppShellAside({
736
+ className,
737
+ style,
738
+ ...props
739
+ }) {
740
+ const { styles } = useSidebarV2();
741
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
742
+ "aside",
743
+ {
744
+ "data-slot": "app-shell-aside",
745
+ className: styles.aside({ className }),
746
+ style: { gridArea: "aside", ...style },
747
+ ...props
748
+ }
749
+ );
750
+ }
751
+ function AppShellPanelContent({ children }) {
752
+ const { panelHost, registerPanelOverride, navPreviewActive } = useSidebarV2();
753
+ (0, import_react3.useEffect)(() => registerPanelOverride(), [registerPanelOverride]);
754
+ if (!panelHost || navPreviewActive) return null;
755
+ return (0, import_react_dom.createPortal)(children, panelHost);
756
+ }
757
+ var AppShell = AppShellRoot;
758
+ AppShell.Header = AppShellHeader;
759
+ AppShell.Main = AppShellMain;
760
+ AppShell.Aside = AppShellAside;
761
+ AppShell.PanelContent = AppShellPanelContent;
762
+
763
+ // src/v2/components.tsx
764
+ var import_button2 = require("@kopexa/button");
765
+ var import_icons2 = require("@kopexa/icons");
766
+ var import_shared_utils = require("@kopexa/shared-utils");
767
+ var import_theme3 = require("@kopexa/theme");
768
+ var import_tooltip3 = require("@kopexa/tooltip");
769
+ var import_react4 = require("react");
770
+
771
+ // src/v2/types.ts
772
+ function panelItemHasChildren(item) {
773
+ return "children" in item && Array.isArray(item.children);
774
+ }
775
+ function panelItemIsSection(item) {
776
+ return "section" in item;
777
+ }
778
+
779
+ // src/v2/components.tsx
780
+ var import_jsx_runtime4 = require("react/jsx-runtime");
781
+ function SidebarV2Inset({
782
+ className,
783
+ ...props
784
+ }) {
785
+ const { styles } = useSidebarV2();
786
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
787
+ "main",
788
+ {
789
+ "data-slot": "sidebar-v2-inset",
790
+ className: styles.inset({ className }),
791
+ ...props
792
+ }
793
+ );
794
+ }
795
+ function SidebarV2Rail({ className, ...props }) {
796
+ const { styles } = useSidebarV2();
797
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
798
+ "nav",
799
+ {
800
+ "data-slot": "sidebar-v2-rail",
801
+ className: styles.rail({ className }),
802
+ ...props
803
+ }
804
+ );
805
+ }
806
+ function SidebarV2RailSpacer() {
807
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { "aria-hidden": true, className: "flex-1" });
808
+ }
809
+ var SidebarV2Workspace = (0, import_react4.forwardRef)(({ name, role, logo, className, appearance = "rail", ...props }, ref) => {
810
+ const { styles } = useSidebarV2();
811
+ if (appearance === "bar") {
812
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
813
+ "button",
814
+ {
815
+ ref,
816
+ type: "button",
817
+ "data-slot": "sidebar-v2-workspace",
818
+ "aria-label": role ? `${name} \u2013 ${role}` : name,
819
+ className: styles.workspaceBar({ className }),
820
+ ...props,
821
+ children: [
822
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: styles.workspaceBarLogo(), children: logo != null ? logo : name.charAt(0).toUpperCase() }),
823
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: styles.workspaceBarText(), children: [
824
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: styles.workspaceBarName(), children: name }),
825
+ role && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: styles.workspaceBarRole(), children: role })
826
+ ] }),
827
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_icons2.ChevronDownIcon, { className: styles.workspaceBarChevron() })
828
+ ]
829
+ }
830
+ );
831
+ }
832
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
833
+ "button",
834
+ {
835
+ ref,
836
+ type: "button",
837
+ "data-slot": "sidebar-v2-workspace",
838
+ "aria-label": role ? `${name} \u2013 ${role}` : name,
839
+ className: styles.workspaceRail({ className }),
840
+ ...props,
841
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: styles.workspaceRailLogo(), children: [
842
+ logo != null ? logo : name.charAt(0).toUpperCase(),
843
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_icons2.ChevronDownIcon, { className: styles.workspaceRailChevron() })
844
+ ] })
845
+ }
846
+ );
847
+ });
848
+ SidebarV2Workspace.displayName = "SidebarV2Workspace";
849
+ function RailInner({
850
+ icon: Icon,
851
+ badge
852
+ }) {
853
+ const { styles } = useSidebarV2();
854
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
855
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { "aria-hidden": true, className: styles.railIndicator() }),
856
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Icon, { className: styles.railIcon() }),
857
+ badge != null && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: styles.railBadge(), children: badge })
858
+ ] });
859
+ }
860
+ function SidebarV2RailLink({
861
+ icon,
862
+ label,
863
+ href,
864
+ badge
865
+ }) {
866
+ const { renderLink, isActive, resetPanelSelection, styles } = useSidebarV2();
867
+ const active = isActive(href);
868
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_tooltip3.Tooltip, { content: label, side: "right", children: renderLink({
869
+ href,
870
+ className: styles.railButton(),
871
+ "data-active": active,
872
+ "aria-current": active ? "page" : void 0,
873
+ "aria-label": label,
874
+ // Navigating to a destination link clears any open panel preview,
875
+ // even when the route doesn't change (e.g. already on it).
876
+ onClick: resetPanelSelection,
877
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(RailInner, { icon, badge })
878
+ }) });
879
+ }
880
+ function SidebarV2RailItem({
881
+ icon,
882
+ label,
883
+ active,
884
+ hasPanel,
885
+ onClick,
886
+ onMouseEnter,
887
+ onMouseLeave,
888
+ badge
889
+ }) {
890
+ const { styles } = useSidebarV2();
891
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_tooltip3.Tooltip, { content: label, side: "right", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
892
+ "button",
893
+ {
894
+ type: "button",
895
+ "data-active": active,
896
+ "aria-label": label,
897
+ "aria-expanded": hasPanel ? active : void 0,
898
+ onClick,
899
+ onMouseEnter,
900
+ onMouseLeave,
901
+ className: styles.railButton(),
902
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(RailInner, { icon, badge })
903
+ }
904
+ ) });
905
+ }
906
+ function SidebarV2Panel({
907
+ title,
908
+ subtitle,
909
+ floating,
910
+ hidePin,
911
+ action,
912
+ children,
913
+ className
914
+ }) {
915
+ const { togglePin, pinned, styles } = useSidebarV2();
916
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
917
+ "div",
918
+ {
919
+ "data-slot": "sidebar-v2-panel",
920
+ "data-floating": floating ? "true" : "false",
921
+ className: styles.panel({ className }),
922
+ children: [
923
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: styles.panelHeader(), children: [
924
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "min-w-0 flex-1", children: [
925
+ title && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: styles.panelTitle(), children: title }),
926
+ subtitle && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: styles.panelSubtitle(), children: subtitle })
927
+ ] }),
928
+ action != null ? action : !hidePin && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
929
+ import_tooltip3.Tooltip,
930
+ {
931
+ content: pinned ? "Panel l\xF6sen" : "Panel anheften",
932
+ side: "bottom",
933
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
934
+ import_button2.IconButton,
935
+ {
936
+ variant: "ghost",
937
+ size: "sm",
938
+ "aria-label": pinned ? "Panel l\xF6sen" : "Panel anheften",
939
+ onClick: togglePin,
940
+ className: styles.panelPin(),
941
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_icons2.PanelLeftIcon, { className: "size-4" })
942
+ }
943
+ )
944
+ }
945
+ )
946
+ ] }),
947
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: styles.panelBody(), children })
948
+ ]
949
+ }
950
+ );
951
+ }
952
+ function SidebarV2PanelLabel({
953
+ className,
954
+ ...props
955
+ }) {
956
+ const { styles } = useSidebarV2();
957
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
958
+ "div",
959
+ {
960
+ "data-slot": "sidebar-v2-panel-label",
961
+ className: styles.panelLabel({ className }),
962
+ ...props
963
+ }
964
+ );
965
+ }
966
+ function SidebarV2PanelLeaf({
967
+ item,
968
+ active: activeProp
969
+ }) {
970
+ const { renderLink, isActive, tone, styles } = useSidebarV2();
971
+ const light = tone === "light";
972
+ const Icon = item.icon;
973
+ const active = activeProp != null ? activeProp : isActive(item.href);
974
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_jsx_runtime4.Fragment, { children: renderLink({
975
+ href: item.href,
976
+ "data-active": active,
977
+ "aria-current": active ? "page" : void 0,
978
+ // Light tone uses the recipe's leaf slot (group/leaf + data-active);
979
+ // dark tone reuses the existing sidebarMenuButton recipe.
980
+ className: light ? styles.panelLeaf() : (0, import_theme3.sidebarMenuButton)({ size: "md" }),
981
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
982
+ Icon && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Icon, { className: styles.panelLeafIcon() }),
983
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: styles.panelLeafLabel(), children: item.label }),
984
+ item.badge != null && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: styles.panelLeafBadge(), children: item.badge })
985
+ ] })
986
+ }) });
987
+ }
988
+ function SidebarV2PanelGroup({
989
+ item
990
+ }) {
991
+ var _a;
992
+ const { openGroup, toggleGroup, activeHref, renderLink, tone, styles } = useSidebarV2();
993
+ const light = tone === "light";
994
+ const Icon = item.icon;
995
+ const key = (_a = item.value) != null ? _a : item.label;
996
+ let bestChildHref = null;
997
+ let bestLen = -1;
998
+ for (const c of item.children) {
999
+ if (activeHref === c.href) {
1000
+ bestChildHref = c.href;
1001
+ break;
1002
+ }
1003
+ if (activeHref.startsWith(`${c.href}/`) && c.href.length > bestLen) {
1004
+ bestChildHref = c.href;
1005
+ bestLen = c.href.length;
1006
+ }
1007
+ }
1008
+ const containsActive = bestChildHref !== null;
1009
+ const open = openGroup === key || openGroup === null && containsActive;
1010
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { children: [
1011
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
1012
+ "button",
1013
+ {
1014
+ type: "button",
1015
+ "data-state": open ? "open" : "closed",
1016
+ "data-contains-active": containsActive,
1017
+ "aria-expanded": open,
1018
+ onClick: () => toggleGroup(key),
1019
+ className: (0, import_shared_utils.cn)(
1020
+ light ? styles.panelLeaf() : (0, import_theme3.sidebarMenuButton)({ size: "md" }),
1021
+ styles.panelGroupButton()
1022
+ ),
1023
+ children: [
1024
+ Icon && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Icon, { className: styles.panelGroupIcon() }),
1025
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: styles.panelGroupLabel(), children: item.label }),
1026
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_icons2.ChevronRightIcon, { className: styles.panelGroupChevron() })
1027
+ ]
1028
+ }
1029
+ ),
1030
+ open && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: styles.panelTree(), children: item.children.map((child) => {
1031
+ const active = child.href === bestChildHref;
1032
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: renderLink({
1033
+ href: child.href,
1034
+ "data-active": active,
1035
+ "aria-current": active ? "page" : void 0,
1036
+ className: styles.subItem(),
1037
+ children: child.label
1038
+ }) }, child.href);
1039
+ }) })
1040
+ ] });
1041
+ }
1042
+ function SidebarV2PanelItems({
1043
+ items
1044
+ }) {
1045
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_jsx_runtime4.Fragment, { children: items.map((item, idx) => {
1046
+ var _a;
1047
+ if (panelItemIsSection(item)) {
1048
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SidebarV2PanelLabel, { children: item.section }, `section-${item.section}-${idx}`);
1049
+ }
1050
+ if (panelItemHasChildren(item)) {
1051
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SidebarV2PanelGroup, { item }, (_a = item.value) != null ? _a : item.label);
1052
+ }
1053
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SidebarV2PanelLeaf, { item }, item.href);
1054
+ }) });
1055
+ }
1056
+ function SidebarV2Trigger({
1057
+ className,
1058
+ ...props
1059
+ }) {
1060
+ const { setDrawerOpen, drawerOpen } = useSidebarV2();
1061
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1062
+ import_button2.IconButton,
1063
+ {
1064
+ variant: "ghost",
1065
+ size: "md",
1066
+ "aria-label": "Navigation \xF6ffnen",
1067
+ onClick: () => setDrawerOpen(!drawerOpen),
1068
+ className,
1069
+ ...props,
1070
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_icons2.PanelLeftIcon, { className: "size-5" })
1071
+ }
1072
+ );
1073
+ }
1074
+
1075
+ // src/v2/from-config.tsx
1076
+ var import_drawer2 = require("@kopexa/drawer");
1077
+ var import_shared_utils2 = require("@kopexa/shared-utils");
1078
+ var import_react5 = require("motion/react");
1079
+ var import_react6 = require("react");
1080
+ var import_jsx_runtime5 = require("react/jsx-runtime");
1081
+ var RAIL_WIDTH2 = "4rem";
1082
+ var PANEL_WIDTH2 = "15rem";
1083
+ var railVars = {
1084
+ "--kpx-rail-width": RAIL_WIDTH2,
1085
+ "--kpx-panel-width": PANEL_WIDTH2
1086
+ };
1087
+ function entryValue(entry) {
1088
+ var _a;
1089
+ if (entry.type === "divider") return "divider";
1090
+ return entry.type === "panel" ? (_a = entry.value) != null ? _a : entry.label : entry.label;
1091
+ }
1092
+ function SidebarV2FromConfig({
1093
+ items,
1094
+ header
1095
+ }) {
1096
+ var _a, _b, _c;
1097
+ const {
1098
+ pinned,
1099
+ flyoutTrigger,
1100
+ flyoutValue,
1101
+ openFlyout,
1102
+ setFlyout,
1103
+ closeFlyout,
1104
+ selectedRail,
1105
+ setSelectedRail,
1106
+ isActive,
1107
+ isMobile,
1108
+ drawerOpen,
1109
+ setDrawerOpen,
1110
+ setPanelHost,
1111
+ panelOverrideActive,
1112
+ navPreviewActive,
1113
+ styles
1114
+ } = useSidebarV2();
1115
+ const hoverMode = flyoutTrigger === "hover" && !pinned && !isMobile;
1116
+ const closeTimer = (0, import_react6.useRef)(null);
1117
+ const cancelClose = (0, import_react6.useCallback)(() => {
1118
+ if (closeTimer.current) clearTimeout(closeTimer.current);
1119
+ closeTimer.current = null;
1120
+ }, []);
1121
+ const scheduleClose = (0, import_react6.useCallback)(() => {
1122
+ cancelClose();
1123
+ closeTimer.current = setTimeout(() => closeFlyout(), 160);
1124
+ }, [cancelClose, closeFlyout]);
1125
+ (0, import_react6.useEffect)(() => cancelClose, [cancelClose]);
1126
+ (0, import_react6.useEffect)(() => {
1127
+ if (pinned || isMobile || !flyoutValue) return;
1128
+ const onPointerDown = (event) => {
1129
+ const t = event.target;
1130
+ if (!t) return;
1131
+ if (t.closest('[data-slot="sidebar-v2-rail"]')) return;
1132
+ if (t.closest('[data-floating="true"]')) return;
1133
+ closeFlyout();
1134
+ };
1135
+ const onKeyDown = (event) => {
1136
+ if (event.key === "Escape") closeFlyout();
1137
+ };
1138
+ document.addEventListener("pointerdown", onPointerDown);
1139
+ document.addEventListener("keydown", onKeyDown);
1140
+ return () => {
1141
+ document.removeEventListener("pointerdown", onPointerDown);
1142
+ document.removeEventListener("keydown", onKeyDown);
1143
+ };
1144
+ }, [pinned, isMobile, flyoutValue, closeFlyout]);
1145
+ const panels = (0, import_react6.useMemo)(
1146
+ () => items.filter(
1147
+ (e) => e.type === "panel"
1148
+ ),
1149
+ [items]
1150
+ );
1151
+ const activeRailValue = (0, import_react6.useMemo)(() => {
1152
+ const match = panels.find(
1153
+ (p) => p.items.some((item) => {
1154
+ if (panelItemIsSection(item)) return false;
1155
+ return panelItemHasChildren(item) ? item.children.some((c) => isActive(c.href)) : isActive(item.href);
1156
+ })
1157
+ );
1158
+ return match ? entryValue(match) : null;
1159
+ }, [panels, isActive]);
1160
+ const shownValue = pinned ? selectedRail != null ? selectedRail : activeRailValue : flyoutValue;
1161
+ const shownPanel = (_a = panels.find((p) => entryValue(p) === shownValue)) != null ? _a : null;
1162
+ const topEntries = items.filter((e) => e.slot !== "bottom");
1163
+ const bottomEntries = items.filter((e) => e.slot === "bottom");
1164
+ function renderRailEntry(entry, index) {
1165
+ if (entry.type === "divider") {
1166
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1167
+ "div",
1168
+ {
1169
+ "aria-hidden": true,
1170
+ className: styles.railDivider()
1171
+ },
1172
+ `rail-divider-${index}`
1173
+ );
1174
+ }
1175
+ const value = entryValue(entry);
1176
+ if (entry.type === "link") {
1177
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1178
+ SidebarV2RailLink,
1179
+ {
1180
+ icon: entry.icon,
1181
+ label: entry.label,
1182
+ href: entry.href,
1183
+ badge: entry.badge
1184
+ },
1185
+ value
1186
+ );
1187
+ }
1188
+ if (entry.type === "action") {
1189
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1190
+ SidebarV2RailItem,
1191
+ {
1192
+ icon: entry.icon,
1193
+ label: entry.label,
1194
+ active: false,
1195
+ onClick: entry.onSelect
1196
+ },
1197
+ value
1198
+ );
1199
+ }
1200
+ const active = flyoutValue ? value === flyoutValue : value === (selectedRail != null ? selectedRail : activeRailValue);
1201
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1202
+ SidebarV2RailItem,
1203
+ {
1204
+ icon: entry.icon,
1205
+ label: entry.label,
1206
+ active,
1207
+ hasPanel: true,
1208
+ onClick: () => {
1209
+ if (pinned) setSelectedRail(value);
1210
+ else openFlyout(value);
1211
+ },
1212
+ onMouseEnter: hoverMode ? () => {
1213
+ cancelClose();
1214
+ setFlyout(value);
1215
+ } : void 0,
1216
+ onMouseLeave: hoverMode ? scheduleClose : void 0
1217
+ },
1218
+ value
1219
+ );
1220
+ }
1221
+ const railContent = /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
1222
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: styles.railScroll(), children: [
1223
+ header && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
1224
+ header,
1225
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: styles.railHeaderDivider() })
1226
+ ] }),
1227
+ topEntries.map(renderRailEntry)
1228
+ ] }),
1229
+ bottomEntries.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: styles.railBottom(), children: bottomEntries.map(renderRailEntry) })
1230
+ ] });
1231
+ const navData = pinned && shownPanel && (navPreviewActive || !panelOverrideActive) ? shownPanel : null;
1232
+ const [bufferedPanel, setBufferedPanel] = (0, import_react6.useState)(navData);
1233
+ (0, import_react6.useEffect)(() => {
1234
+ if (navData) {
1235
+ setBufferedPanel(navData);
1236
+ return;
1237
+ }
1238
+ const t = setTimeout(() => setBufferedPanel(null), 220);
1239
+ return () => clearTimeout(t);
1240
+ }, [navData]);
1241
+ const navToRender = navData != null ? navData : bufferedPanel;
1242
+ const renderNav = (!panelOverrideActive || navPreviewActive) && navToRender;
1243
+ const panelContent = navToRender && renderNav ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1244
+ SidebarV2Panel,
1245
+ {
1246
+ title: (_b = navToRender.title) != null ? _b : navToRender.label,
1247
+ subtitle: navToRender.subtitle,
1248
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SidebarV2PanelItems, { items: navToRender.items })
1249
+ },
1250
+ entryValue(navToRender)
1251
+ ) : null;
1252
+ const docked = Boolean(navData) || panelOverrideActive;
1253
+ const showFlyout = !pinned && Boolean(shownPanel);
1254
+ if (isMobile) {
1255
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1256
+ import_drawer2.Drawer.Root,
1257
+ {
1258
+ open: drawerOpen,
1259
+ onOpenChange: setDrawerOpen,
1260
+ placement: "left",
1261
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_drawer2.Drawer.Content, { className: styles.mobileDrawer(), children: [
1262
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_drawer2.Drawer.Header, { className: "sr-only", children: [
1263
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_drawer2.Drawer.Title, { children: "Navigation" }),
1264
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_drawer2.Drawer.Description, { children: "Hauptnavigation" })
1265
+ ] }),
1266
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex h-full", style: railVars, children: [
1267
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SidebarV2Rail, { children: railContent }),
1268
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1269
+ "div",
1270
+ {
1271
+ ref: setPanelHost,
1272
+ "data-slot": "sidebar-v2-panel-zone",
1273
+ className: "flex min-h-0",
1274
+ children: panelContent
1275
+ }
1276
+ )
1277
+ ] })
1278
+ ] })
1279
+ }
1280
+ );
1281
+ }
1282
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
1283
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SidebarV2Rail, { style: { gridArea: "rail" }, children: railContent }),
1284
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1285
+ "div",
1286
+ {
1287
+ ref: setPanelHost,
1288
+ "data-slot": "sidebar-v2-panel-zone",
1289
+ className: (0, import_shared_utils2.cn)(styles.panelZone(), pinned && "overflow-hidden"),
1290
+ style: { gridArea: "panel", width: docked ? PANEL_WIDTH2 : "0px" },
1291
+ children: [
1292
+ panelContent,
1293
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react5.AnimatePresence, { children: showFlyout && shownPanel && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1294
+ import_react5.motion.div,
1295
+ {
1296
+ "data-floating": "true",
1297
+ className: styles.flyout(),
1298
+ initial: { x: -14, opacity: 0 },
1299
+ animate: { x: 0, opacity: 1 },
1300
+ exit: { x: -14, opacity: 0 },
1301
+ transition: { duration: 0.16, ease: "easeOut" },
1302
+ onMouseEnter: hoverMode ? cancelClose : void 0,
1303
+ onMouseLeave: hoverMode ? scheduleClose : void 0,
1304
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1305
+ SidebarV2Panel,
1306
+ {
1307
+ floating: true,
1308
+ title: (_c = shownPanel.title) != null ? _c : shownPanel.label,
1309
+ subtitle: shownPanel.subtitle,
1310
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SidebarV2PanelItems, { items: shownPanel.items })
1311
+ }
1312
+ )
1313
+ },
1314
+ "sidebar-v2-flyout"
1315
+ ) })
1316
+ ]
1317
+ }
1318
+ )
1319
+ ] });
1320
+ }
1321
+
1322
+ // src/v2/index.tsx
1323
+ var SidebarV2 = SidebarV2Provider;
1324
+ SidebarV2.FromConfig = SidebarV2FromConfig;
1325
+ SidebarV2.Inset = SidebarV2Inset;
1326
+ SidebarV2.Trigger = SidebarV2Trigger;
1327
+ SidebarV2.Rail = SidebarV2Rail;
1328
+ SidebarV2.RailItem = SidebarV2RailItem;
1329
+ SidebarV2.RailLink = SidebarV2RailLink;
1330
+ SidebarV2.RailSpacer = SidebarV2RailSpacer;
1331
+ SidebarV2.Workspace = SidebarV2Workspace;
1332
+ SidebarV2.Panel = SidebarV2Panel;
1333
+ SidebarV2.PanelItems = SidebarV2PanelItems;
1334
+ SidebarV2.PanelLeaf = SidebarV2PanelLeaf;
1335
+ SidebarV2.PanelGroup = SidebarV2PanelGroup;
1336
+ SidebarV2.PanelLabel = SidebarV2PanelLabel;
510
1337
  // Annotate the CommonJS export names for ESM import in node:
511
1338
  0 && (module.exports = {
1339
+ AppShell,
1340
+ AppShellAside,
1341
+ AppShellHeader,
1342
+ AppShellMain,
1343
+ AppShellPanelContent,
1344
+ AppShellRoot,
512
1345
  Sidebar,
513
1346
  SidebarContent,
514
1347
  SidebarFooter,
@@ -528,5 +1361,21 @@ var Sidebar = Object.assign(SidebarRoot, {
528
1361
  SidebarRoot,
529
1362
  SidebarSeparator,
530
1363
  SidebarTrigger,
531
- useSidebar
1364
+ SidebarV2,
1365
+ SidebarV2FromConfig,
1366
+ SidebarV2Inset,
1367
+ SidebarV2Panel,
1368
+ SidebarV2PanelGroup,
1369
+ SidebarV2PanelItems,
1370
+ SidebarV2PanelLabel,
1371
+ SidebarV2PanelLeaf,
1372
+ SidebarV2Provider,
1373
+ SidebarV2Rail,
1374
+ SidebarV2RailItem,
1375
+ SidebarV2RailLink,
1376
+ SidebarV2RailSpacer,
1377
+ SidebarV2Trigger,
1378
+ SidebarV2Workspace,
1379
+ useSidebar,
1380
+ useSidebarV2
532
1381
  });