1import type { FC, PropsWithChildren } from "react";
2import { useMemo } from "react";
3import { SidebarContext } from "./sidebar-provider";
4import type { SidebarItemGroup } from "./types";
5import { type VariantProps, cva } from "class-variance-authority";
6import { cn } from "@marzneshin/common/utils";
7import { SidebarHeader } from "./sidebar-header";
8import { SidebarFooter } from "./sidebar-footer";
9import { SidebarBody } from "./sidebar-body";
10import { SidebarItem } from "./sidebar-item";
11import { SidebarGroup } from "./sidebar-group";
12
13const sidebarVariants = cva("flex flex-col justify-between h-full w-full", {
14 variants: {
15 variant: {
16 default: "",
17 },
18 },
19});
20
21interface ContentComposition {
22 Header: typeof SidebarHeader;
23 Footer: typeof SidebarFooter;
24 Body: typeof SidebarBody;
25 Group: typeof SidebarGroup;
26 Item: typeof SidebarItem;
27}
28
29export interface SidebarProps
30 extends React.HTMLAttributes<HTMLDivElement>,
31 VariantProps<typeof sidebarVariants> {
32 sidebar: SidebarItemGroup;
33 collapsed: boolean;
34 setCollapsed: (state: boolean) => void;
35 open?: boolean;
36 setOpen?: (state: boolean) => void;
37}
38
39const Sidebar: FC<SidebarProps & PropsWithChildren> & ContentComposition = ({
40 collapsed,
41 setCollapsed,
42 sidebar,
43 variant,
44 className,
45 setOpen,
46 open,
47 children,
48 ...props
49}) => {
50 const contextValue = useMemo(
51 () => ({ sidebar, collapsed, setCollapsed, open, setOpen }),
52 [sidebar, collapsed, setCollapsed, open, setOpen],
53 );
54 return (
55 <SidebarContext.Provider value={contextValue}>
56 <div className={cn(sidebarVariants({ variant, className }))} {...props}>
57 {children}
58 </div>
59 </SidebarContext.Provider>
60 );
61};
62
63Sidebar.Header = SidebarHeader;
64Sidebar.Footer = SidebarFooter;
65Sidebar.Body = SidebarBody;
66Sidebar.Item = SidebarItem;
67Sidebar.Group = SidebarGroup;
68Sidebar.displayName = "Sidebar";
69
70export { Sidebar, sidebarVariants };