react-shadcn-kit 0.0.8 → 0.1.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.
@@ -1,78 +1,114 @@
1
- import { jsx as o, jsxs as d } from "react/jsx-runtime";
2
- import { SidebarProvider as x, SidebarInset as I } from "./atoms/sidebar.js";
3
- import { AppSidebar as N } from "./organisms/app-sidebar.js";
4
- import { AppNavbar as T } from "./organisms/app-navbar.js";
5
- import * as u from "lucide-react";
6
- const a = (n) => u[n] ?? u.Circle;
7
- function A({
8
- children: n,
9
- layoutConfig: r
10
- }) {
11
- const { navbar: e = {}, sidebar: i = {} } = r.components || {}, h = e.items?.map((s) => ({
12
- ...s,
13
- icon: a(s.icon || "")
14
- })), b = e.userMenuItems?.map((s) => ({
15
- ...s,
16
- icon: s.icon ? a(s.icon) : void 0
17
- })), m = i.groups?.map((s) => ({
18
- ...s,
19
- items: s.items.map((l) => ({
20
- ...l,
21
- icon: a(l.icon || "")
22
- }))
23
- })), p = i.userMenuItems?.map((s) => ({
24
- ...s,
25
- icon: s.icon ? a(s.icon) : void 0
26
- })), f = {
27
- "--sidebar-width": i.width || "250px"
28
- }, t = r.layoutRules || {
29
- public: { navbar: !0, sidebar: !0 }
30
- }, c = t.public?.sidebar ?? !0, g = t.public?.navbar ?? !0, v = e.notifications?.enabled && e.notifications.count ? Array.from({ length: e.notifications.count }).map(() => ({
31
- title: "New Notification",
32
- description: "You have a new notification.",
33
- date: "Just now",
34
- read: !e.notifications?.isNewNotification
35
- })) : [], w = i.scrollable ?? !0;
36
- return /* @__PURE__ */ o("div", { style: { "--header-height": "calc(var(--spacing, 14))" }, children: /* @__PURE__ */ d(x, { defaultOpen: !0, className: "flex flex-col", style: f, children: [
37
- g && /* @__PURE__ */ o(
38
- T,
39
- {
40
- items: h,
41
- searchPlaceholder: e.search?.placeholder,
42
- showSearch: e.search?.enabled ?? !1,
43
- showThemeToggle: e.showThemeToggle,
44
- showUserMenu: e.showUserMenu,
45
- showNotifications: e.notifications?.enabled,
46
- notifications: v,
47
- user: r.user,
48
- userMenuItems: b,
49
- branding: e.branding,
50
- labels: void 0,
51
- style: { height: e.height },
52
- showSidebarTrigger: c && (e.showSidebarTrigger ?? !0)
53
- }
54
- ),
55
- /* @__PURE__ */ d("div", { className: "flex flex-1", children: [
56
- c && /* @__PURE__ */ o(
57
- N,
58
- {
59
- side: i.placement === "right" ? "right" : "left",
60
- scrollable: w,
61
- fixed: !0,
62
- groups: m,
63
- showThemeToggle: i.showThemeToggle,
64
- user: r.user,
65
- userMenuItems: p,
66
- branding: i.branding,
67
- labels: void 0,
68
- hideBranding: !1
69
- }
70
- ),
71
- /* @__PURE__ */ o(I, { children: /* @__PURE__ */ o("div", { className: "p-4 mx-auto w-full", style: void 0, children: n }) })
1
+ import { jsx as n, jsxs as d } from "react/jsx-runtime";
2
+ import { useState as O, useRef as N, useEffect as W } from "react";
3
+ import { SidebarProvider as T, SidebarInset as I } from "./atoms/sidebar.js";
4
+ import { AppSidebar as M } from "./organisms/app-sidebar.js";
5
+ import { AppNavbar as U } from "./organisms/app-navbar.js";
6
+ import * as E from "lucide-react";
7
+ const A = (o) => E[o] ?? E.Circle, p = (o) => o?.map((r) => ({
8
+ ...r,
9
+ icon: r.icon ? A(r.icon) : void 0,
10
+ items: r.items ? p(r.items) : void 0
11
+ })), L = (o) => o?.map((r) => ({
12
+ ...r,
13
+ icon: r.icon ? A(r.icon) : void 0
14
+ })), Y = (o) => o?.map((r) => ({
15
+ ...r,
16
+ items: p(r.items) || []
17
+ })), P = "250px", R = "calc(var(--spacing, 14))";
18
+ function k({ children: o, config: r }) {
19
+ const {
20
+ showNavbar: g = !0,
21
+ showSidebar: u = !0,
22
+ user: t,
23
+ navbar: e = {},
24
+ sidebar: s = {},
25
+ content: v = {},
26
+ sidebarDefaultOpen: b = !0
27
+ } = r, a = s.fullHeight ?? !1, [D, h] = O(!0), m = N(0), w = N(null);
28
+ W(() => {
29
+ if (e.scrollBehavior !== "hide-on-scroll") {
30
+ h(!0);
31
+ return;
32
+ }
33
+ const l = a ? w.current : window;
34
+ if (!l) return;
35
+ const c = () => {
36
+ const i = l === window ? window.scrollY : l.scrollTop;
37
+ i < m.current || i < 50 ? e.showOnScrollUp !== !1 && h(!0) : i > m.current && i > 50 && h(!1), m.current = i;
38
+ };
39
+ return l === window ? (window.addEventListener("scroll", c, { passive: !0 }), () => window.removeEventListener("scroll", c)) : (l.addEventListener("scroll", c, { passive: !0 }), () => l.removeEventListener("scroll", c));
40
+ }, [e.scrollBehavior, e.showOnScrollUp, a]);
41
+ const x = {
42
+ placement: "top",
43
+ sticky: e.scrollBehavior === "sticky" || e.scrollBehavior === "hide-on-scroll",
44
+ branding: e.branding,
45
+ items: p(e.items),
46
+ search: e.search,
47
+ notifications: e.notifications,
48
+ showThemeToggle: e.showThemeToggle ?? !1,
49
+ showSidebarTrigger: u && !a && (e.showSidebarTrigger ?? !0),
50
+ showUserMenu: e.showUserMenu ?? !1,
51
+ user: t,
52
+ userMenuItems: L(e.userMenuItems),
53
+ loginButton: e.loginButton,
54
+ style: {
55
+ ...e.height ? { height: e.height } : {},
56
+ ...e.scrollBehavior === "hide-on-scroll" ? {
57
+ transform: D ? "translateY(0)" : "translateY(-100%)",
58
+ transition: "transform 0.3s ease-in-out"
59
+ } : {}
60
+ },
61
+ className: e.blendWithBody ? "border-0 bg-transparent" : void 0
62
+ }, H = t ? {
63
+ name: t.name,
64
+ email: t.email,
65
+ image: t.image,
66
+ username: t.username,
67
+ roles: t.roles
68
+ } : void 0, f = {
69
+ side: s.placement ?? "left",
70
+ fixed: s.fixed ?? !0,
71
+ scrollable: s.scrollable ?? !0,
72
+ groups: Y(s.groups),
73
+ showThemeToggle: s.showThemeToggle ?? !1,
74
+ showUserMenu: s.showUserMenu ?? !1,
75
+ user: H,
76
+ userMenuItems: L(s.userMenuItems),
77
+ branding: s.branding,
78
+ hideBranding: s.hideBranding ?? !1,
79
+ loginButton: s.loginButton,
80
+ className: s.blendWithBody ? "border-0 bg-transparent" : void 0
81
+ }, S = {
82
+ "--sidebar-width": s.width || P
83
+ }, y = {
84
+ padding: v.padding,
85
+ maxWidth: v.maxWidth
86
+ }, B = {
87
+ "--header-height": e.height || R
88
+ };
89
+ return a && u ? /* @__PURE__ */ n("div", { style: B, className: "flex h-screen", children: /* @__PURE__ */ d(T, { defaultOpen: b, style: S, children: [
90
+ /* @__PURE__ */ n(M, { ...f, className: `h-screen ${f.className || ""}` }),
91
+ /* @__PURE__ */ d("div", { className: "flex flex-col flex-1 overflow-hidden", children: [
92
+ g && /* @__PURE__ */ n(U, { ...x }),
93
+ /* @__PURE__ */ n(I, { ref: w, className: "flex-1 overflow-auto", children: /* @__PURE__ */ n("div", { className: "p-4 mx-auto w-full", style: y, children: o }) })
72
94
  ] })
73
- ] }) });
95
+ ] }) }) : /* @__PURE__ */ n("div", { style: B, children: /* @__PURE__ */ d(
96
+ T,
97
+ {
98
+ defaultOpen: b,
99
+ className: "flex flex-col",
100
+ style: S,
101
+ children: [
102
+ g && /* @__PURE__ */ n(U, { ...x }),
103
+ /* @__PURE__ */ d("div", { className: "flex flex-1", children: [
104
+ u && /* @__PURE__ */ n(M, { ...f }),
105
+ /* @__PURE__ */ n(I, { children: /* @__PURE__ */ n("div", { className: "p-4 mx-auto w-full", style: y, children: o }) })
106
+ ] })
107
+ ]
108
+ }
109
+ ) });
74
110
  }
75
111
  export {
76
- A as default
112
+ k as default
77
113
  };
78
114
  //# sourceMappingURL=default-layout.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"default-layout.js","sources":["../src/default-layout.tsx"],"sourcesContent":["import React from \"react\";\nimport { SidebarProvider, SidebarInset } from \"@/atoms/sidebar\";\nimport { AppSidebar } from \"@/organisms/app-sidebar\";\nimport { AppNavbar } from \"@/organisms/app-navbar\";\nimport * as LucideIcons from \"lucide-react\";\n\nexport type Placement = \"left\" | \"right\" | \"top\" | \"bottom\";\nexport type NavbarHeight = \"sm\" | \"md\" | \"lg\" | string;\nexport type RouteType = \"public\" | \"auth\" | \"private\";\nexport type HttpMethod = \"GET\" | \"POST\";\n\nexport type LayoutRules = {\n [key in RouteType]?: { navbar?: boolean; sidebar?: boolean };\n};\n\nexport type UserConfig = {\n name?: string;\n image?: string;\n username?: string;\n email?: string;\n roles?: string[];\n};\n\nexport type SearchConfig = {\n enabled?: boolean;\n placeholder?: string;\n action?: string;\n method?: HttpMethod;\n debounceTimeMs?: number;\n suggestionsApi?: string;\n};\n\nexport type NotificationsList = {\n title: string;\n image?: string;\n description: string;\n date: string;\n read: boolean;\n};\n\nexport type NotificationConfig = {\n enabled?: boolean;\n isNewNotification?: boolean;\n count?: number;\n showBadge?: boolean;\n notifications?: NotificationsList[];\n};\n\nexport type MenuItem = {\n label: string;\n href: string;\n icon?: string;\n disabled?: boolean;\n};\n\nexport type BrandingConfig = {\n logoUrl?: string;\n logoAlt?: string;\n title?: string;\n subtitle?: string;\n};\n\nexport type BaseComponentConfig = {\n showThemeToggle?: boolean;\n showUserMenu?: boolean;\n search?: SearchConfig;\n scrollable?: boolean;\n branding?: BrandingConfig;\n showSidebarTrigger?: boolean;\n customContent?: React.ReactNode;\n notifications?: NotificationConfig;\n};\n\nexport type NavbarConfig = BaseComponentConfig & {\n height?: NavbarHeight;\n items?: MenuItem[];\n userMenuItems?: { label: string; href?: string; icon?: string; onClick?: () => void }[];\n};\n\nexport type SidebarGroup = {\n label: string;\n items: MenuItem[];\n collapsible?: boolean;\n};\n\nexport type SidebarConfig = BaseComponentConfig & {\n width?: string;\n placement?: Placement;\n groups?: SidebarGroup[];\n userMenuItems?: { label: string; href?: string; icon?: string; onClick?: () => void }[];\n};\n\nexport type ComponentConfig = {\n navbar?: NavbarConfig;\n sidebar?: SidebarConfig;\n};\n\nexport type LayoutConfig = {\n layoutRules?: LayoutRules;\n user?: UserConfig;\n search?: SearchConfig;\n components?: ComponentConfig;\n appName?: string;\n theme?: \"light\" | \"dark\" | \"system\";\n};\n\nconst getIcon = (name: string) => {\n // @ts-ignore – dynamic access to lucide icons\n return (LucideIcons as any)[name] ?? (LucideIcons as any)[\"Circle\"];\n};\n\nexport default function DefaultLayout({\n children,\n layoutConfig,\n}: {\n children: React.ReactNode;\n layoutConfig: LayoutConfig;\n}) {\n const { navbar = {}, sidebar = {} } = layoutConfig.components || {};\n\n const navbarItems = navbar.items?.map((item) => ({\n ...item,\n icon: getIcon(item.icon || \"\"),\n }));\n\n const navbarUserMenuItems = navbar.userMenuItems?.map((item) => ({\n ...item,\n icon: item.icon ? getIcon(item.icon) : undefined,\n }));\n\n const sidebarGroups = sidebar.groups?.map((group) => ({\n ...group,\n items: group.items.map((item) => ({\n ...item,\n icon: getIcon(item.icon || \"\"),\n })),\n }));\n\n const sidebarUserMenuItems = sidebar.userMenuItems?.map((item) => ({\n ...item,\n icon: item.icon ? getIcon(item.icon) : undefined,\n }));\n\n const sidebarProviderStyle: React.CSSProperties = {\n \"--sidebar-width\": sidebar.width || \"250px\",\n } as React.CSSProperties;\n\n const layoutRules = layoutConfig.layoutRules || {\n public: { navbar: true, sidebar: true },\n auth: { navbar: true, sidebar: true },\n private: { navbar: true, sidebar: true },\n };\n\n const showSidebar = layoutRules.public?.sidebar ?? true;\n const showNavbar = layoutRules.public?.navbar ?? true;\n\n const notifications =\n navbar.notifications?.enabled && navbar.notifications.count\n ? Array.from({ length: navbar.notifications.count }).map(() => ({\n title: \"New Notification\",\n description: \"You have a new notification.\",\n date: \"Just now\",\n read: !navbar.notifications?.isNewNotification,\n }))\n : [];\n\n const scrollable = sidebar.scrollable ?? true;\n const maxWidth = undefined;\n\n return (\n <div style={{ \"--header-height\": \"calc(var(--spacing, 14))\" } as React.CSSProperties}>\n <SidebarProvider defaultOpen={true} className=\"flex flex-col\" style={sidebarProviderStyle}>\n {showNavbar && (\n <AppNavbar\n items={navbarItems}\n searchPlaceholder={navbar.search?.placeholder}\n showSearch={navbar.search?.enabled ?? false}\n showThemeToggle={navbar.showThemeToggle}\n showUserMenu={navbar.showUserMenu}\n showNotifications={navbar.notifications?.enabled}\n notifications={notifications}\n user={layoutConfig.user}\n userMenuItems={navbarUserMenuItems}\n branding={navbar.branding}\n labels={undefined}\n style={{ height: navbar.height }}\n showSidebarTrigger={showSidebar && (navbar.showSidebarTrigger ?? true)}\n />\n )}\n <div className=\"flex flex-1\">\n {showSidebar && (\n <AppSidebar\n side={sidebar.placement === \"right\" ? \"right\" : \"left\"}\n scrollable={scrollable}\n fixed={true}\n groups={sidebarGroups}\n showThemeToggle={sidebar.showThemeToggle}\n user={layoutConfig.user}\n userMenuItems={sidebarUserMenuItems}\n branding={sidebar.branding}\n labels={undefined}\n hideBranding={false}\n />\n )}\n <SidebarInset>\n <div className=\"p-4 mx-auto w-full\" style={maxWidth ? { maxWidth } : undefined}>\n {children}\n </div>\n </SidebarInset>\n </div>\n </SidebarProvider>\n </div>\n );\n}\n"],"names":["jsx","jsxs","SidebarProvider","SidebarInset","AppSidebar","AppNavbar","LucideIcons","getIcon","name","DefaultLayout","children","layoutConfig","navbar","sidebar","navbarItems","item","navbarUserMenuItems","sidebarGroups","group","sidebarUserMenuItems","sidebarProviderStyle","layoutRules","showSidebar","showNavbar","notifications","scrollable"],"mappings":"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"}
1
+ {"version":3,"file":"default-layout.js","sources":["../src/default-layout.tsx"],"sourcesContent":["\"use client\";\n\nimport React, { useState, useEffect, useRef } from \"react\";\nimport { SidebarProvider, SidebarInset } from \"@/atoms/sidebar\";\nimport { AppSidebar, type AppSidebarProps } from \"@/organisms/app-sidebar\";\nimport { AppNavbar, type AppNavbarProps } from \"@/organisms/app-navbar\";\nimport * as LucideIcons from \"lucide-react\";\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\nexport type User = {\n name: string;\n email: string;\n image?: string;\n username?: string;\n roles?: string[];\n};\n\ntype MenuItem = {\n label: string;\n href: string;\n icon?: React.ComponentType<{ className?: string }>;\n disabled?: boolean;\n items?: MenuItem[];\n};\n\ntype MenuGroup = {\n label?: string;\n items: MenuItem[];\n collapsible?: boolean;\n};\n\ntype UserMenuItem = {\n label: string;\n href?: string;\n icon?: React.ComponentType<{ className?: string }>;\n onClick?: () => void;\n};\n\nexport type Branding = {\n logoUrl?: string;\n logoAlt?: string;\n title?: string;\n subtitle?: string;\n href?: string;\n};\n\nexport type LoginButton = {\n label?: string;\n href?: string;\n variant?: \"default\" | \"destructive\" | \"outline\" | \"secondary\" | \"ghost\" | \"link\";\n onClick?: () => void;\n};\n\nexport type SearchConfig = {\n enabled?: boolean;\n placeholder?: string;\n onSearch?: (value: string) => void;\n};\n\nexport type NotificationItem = {\n title: string;\n description: string;\n date: string;\n read: boolean;\n image?: string;\n};\n\nexport type NotificationsConfig = {\n enabled?: boolean;\n items?: NotificationItem[];\n onNotificationClick?: (notification: NotificationItem, index: number) => void;\n};\n\nexport type NavbarConfig = {\n height?: string;\n items?: MenuItemInput[];\n search?: SearchConfig;\n notifications?: NotificationsConfig;\n showThemeToggle?: boolean;\n showUserMenu?: boolean;\n showSidebarTrigger?: boolean;\n branding?: Branding;\n userMenuItems?: UserMenuItemInput[];\n loginButton?: LoginButton;\n // Removed fullWidth option\n blendWithBody?: boolean;\n // New scroll behavior options\n scrollBehavior?: \"sticky\" | \"hide-on-scroll\" | \"static\";\n showOnScrollUp?: boolean;\n};\n\nexport type SidebarConfig = {\n width?: string;\n placement?: \"left\" | \"right\";\n groups?: MenuGroupInput[];\n showThemeToggle?: boolean;\n showUserMenu?: boolean;\n branding?: Branding;\n hideBranding?: boolean;\n userMenuItems?: UserMenuItemInput[];\n loginButton?: LoginButton;\n scrollable?: boolean;\n fixed?: boolean;\n fullHeight?: boolean;\n blendWithBody?: boolean;\n};\n\nexport type ContentConfig = {\n maxWidth?: string;\n padding?: string;\n};\n\n// Input types (with string icons)\nexport type MenuItemInput = {\n label: string;\n href: string;\n icon?: string;\n disabled?: boolean;\n items?: MenuItemInput[];\n};\n\nexport type MenuGroupInput = {\n label?: string;\n items: MenuItemInput[];\n collapsible?: boolean;\n};\n\nexport type UserMenuItemInput = {\n label: string;\n href?: string;\n icon?: string;\n onClick?: () => void;\n};\n\nexport type LayoutConfig = {\n showNavbar?: boolean;\n showSidebar?: boolean;\n user?: User;\n navbar?: NavbarConfig;\n sidebar?: SidebarConfig;\n content?: ContentConfig;\n sidebarDefaultOpen?: boolean;\n};\n\nexport type DefaultLayoutProps = {\n children: React.ReactNode;\n config: LayoutConfig;\n};\n\n// ============================================================================\n// UTILITIES\n// ============================================================================\n\nconst getIcon = (name: string): React.ComponentType<{ className?: string }> => {\n return (LucideIcons as any)[name] ?? (LucideIcons as any)[\"Circle\"];\n};\n\nconst mapMenuItems = (items?: MenuItemInput[]): MenuItem[] | undefined => {\n return items?.map((item) => ({\n ...item,\n icon: item.icon ? getIcon(item.icon) : undefined,\n items: item.items ? mapMenuItems(item.items) : undefined,\n }));\n};\n\nconst mapUserMenuItems = (items?: UserMenuItemInput[]): UserMenuItem[] | undefined => {\n return items?.map((item) => ({\n ...item,\n icon: item.icon ? getIcon(item.icon) : undefined,\n }));\n};\n\nconst mapSidebarGroups = (groups?: MenuGroupInput[]): MenuGroup[] | undefined => {\n return groups?.map((group) => ({\n ...group,\n items: mapMenuItems(group.items) || [],\n }));\n};\n\n// ============================================================================\n// DEFAULTS\n// ============================================================================\n\nconst DEFAULT_SIDEBAR_WIDTH = \"250px\";\nconst DEFAULT_NAVBAR_HEIGHT = \"calc(var(--spacing, 14))\";\n\n// ============================================================================\n// MAIN COMPONENT\n// ============================================================================\n\nexport default function DefaultLayout({ children, config }: DefaultLayoutProps) {\n const {\n showNavbar = true,\n showSidebar = true,\n user,\n navbar = {},\n sidebar = {},\n content = {},\n sidebarDefaultOpen = true,\n } = config;\n\n // Layout mode calculations\n const sidebarFullHeight = sidebar.fullHeight ?? false;\n\n // Scroll behavior logic\n const [navbarVisible, setNavbarVisible] = useState(true);\n const lastScrollY = useRef(0);\n const scrollContainerRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (navbar.scrollBehavior !== \"hide-on-scroll\") {\n setNavbarVisible(true);\n return;\n }\n\n // Determine the scroll container based on layout variant\n const scrollContainer = sidebarFullHeight ? scrollContainerRef.current : window;\n\n if (!scrollContainer) return;\n\n const handleScroll = () => {\n const currentScrollY =\n scrollContainer === window ? window.scrollY : (scrollContainer as HTMLDivElement).scrollTop;\n\n // Show if scrolling up or at top, hide if scrolling down\n if (currentScrollY < lastScrollY.current || currentScrollY < 50) {\n if (navbar.showOnScrollUp !== false) {\n setNavbarVisible(true);\n }\n } else if (currentScrollY > lastScrollY.current && currentScrollY > 50) {\n setNavbarVisible(false);\n }\n lastScrollY.current = currentScrollY;\n };\n\n if (scrollContainer === window) {\n window.addEventListener(\"scroll\", handleScroll, { passive: true });\n return () => window.removeEventListener(\"scroll\", handleScroll);\n } else {\n scrollContainer.addEventListener(\"scroll\", handleScroll, { passive: true });\n return () => scrollContainer.removeEventListener(\"scroll\", handleScroll);\n }\n }, [navbar.scrollBehavior, navbar.showOnScrollUp, sidebarFullHeight]);\n\n // Prepare navbar props\n const navbarProps: AppNavbarProps = {\n placement: \"top\",\n sticky: navbar.scrollBehavior === \"sticky\" || navbar.scrollBehavior === \"hide-on-scroll\",\n branding: navbar.branding,\n items: mapMenuItems(navbar.items),\n search: navbar.search,\n notifications: navbar.notifications,\n showThemeToggle: navbar.showThemeToggle ?? false,\n showSidebarTrigger: showSidebar && !sidebarFullHeight && (navbar.showSidebarTrigger ?? true),\n showUserMenu: navbar.showUserMenu ?? false,\n user: user,\n userMenuItems: mapUserMenuItems(navbar.userMenuItems),\n loginButton: navbar.loginButton,\n style: {\n ...(navbar.height ? { height: navbar.height } : {}),\n ...(navbar.scrollBehavior === \"hide-on-scroll\"\n ? {\n transform: navbarVisible ? \"translateY(0)\" : \"translateY(-100%)\",\n transition: \"transform 0.3s ease-in-out\",\n }\n : {}),\n },\n className: navbar.blendWithBody ? \"border-0 bg-transparent\" : undefined,\n };\n\n // Prepare sidebar props - convert User to match sidebar's optional fields\n const sidebarUser = user\n ? {\n name: user.name,\n email: user.email,\n image: user.image,\n username: user.username,\n roles: user.roles,\n }\n : undefined;\n\n const sidebarProps: AppSidebarProps = {\n side: sidebar.placement ?? \"left\",\n fixed: sidebar.fixed ?? true,\n scrollable: sidebar.scrollable ?? true,\n groups: mapSidebarGroups(sidebar.groups),\n showThemeToggle: sidebar.showThemeToggle ?? false,\n showUserMenu: sidebar.showUserMenu ?? false,\n user: sidebarUser,\n userMenuItems: mapUserMenuItems(sidebar.userMenuItems),\n branding: sidebar.branding,\n hideBranding: sidebar.hideBranding ?? false,\n loginButton: sidebar.loginButton,\n className: sidebar.blendWithBody ? \"border-0 bg-transparent\" : undefined,\n };\n\n // Sidebar provider styles\n const sidebarProviderStyle: React.CSSProperties = {\n \"--sidebar-width\": sidebar.width || DEFAULT_SIDEBAR_WIDTH,\n } as React.CSSProperties;\n\n // Content styles\n const contentStyle: React.CSSProperties = {\n padding: content.padding,\n maxWidth: content.maxWidth,\n };\n\n const containerStyle: React.CSSProperties = {\n \"--header-height\": navbar.height || DEFAULT_NAVBAR_HEIGHT,\n } as React.CSSProperties;\n\n // ============================================================================\n // LAYOUT VARIANTS\n // ============================================================================\n\n // Variant 1: Full-height sidebar (sidebar spans entire viewport, navbar is indented)\n if (sidebarFullHeight && showSidebar) {\n return (\n <div style={containerStyle} className=\"flex h-screen\">\n <SidebarProvider defaultOpen={sidebarDefaultOpen} style={sidebarProviderStyle}>\n <AppSidebar {...sidebarProps} className={`h-screen ${sidebarProps.className || \"\"}`} />\n\n <div className=\"flex flex-col flex-1 overflow-hidden\">\n {showNavbar && <AppNavbar {...navbarProps} />}\n\n <SidebarInset ref={scrollContainerRef} className=\"flex-1 overflow-auto\">\n <div className=\"p-4 mx-auto w-full\" style={contentStyle}>\n {children}\n </div>\n </SidebarInset>\n </div>\n </SidebarProvider>\n </div>\n );\n }\n\n // Variant 3: Default (navbar and sidebar share space)\n return (\n <div style={containerStyle}>\n <SidebarProvider\n defaultOpen={sidebarDefaultOpen}\n className=\"flex flex-col\"\n style={sidebarProviderStyle}\n >\n {showNavbar && <AppNavbar {...navbarProps} />}\n\n <div className=\"flex flex-1\">\n {showSidebar && <AppSidebar {...sidebarProps} />}\n\n <SidebarInset>\n <div className=\"p-4 mx-auto w-full\" style={contentStyle}>\n {children}\n </div>\n </SidebarInset>\n </div>\n </SidebarProvider>\n </div>\n );\n}\n"],"names":["jsx","jsxs","useState","useRef","useEffect","SidebarProvider","SidebarInset","AppSidebar","AppNavbar","LucideIcons","getIcon","name","mapMenuItems","items","item","mapUserMenuItems","mapSidebarGroups","groups","group","DEFAULT_SIDEBAR_WIDTH","DEFAULT_NAVBAR_HEIGHT","DefaultLayout","children","config","showNavbar","showSidebar","user","navbar","sidebar","content","sidebarDefaultOpen","sidebarFullHeight","navbarVisible","setNavbarVisible","lastScrollY","scrollContainerRef","scrollContainer","handleScroll","currentScrollY","navbarProps","sidebarUser","sidebarProps","sidebarProviderStyle","contentStyle","containerStyle"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  export * from './organisms/app-sidebar';
2
2
  export * from './organisms/app-navbar';
3
3
  export { default as DefaultLayout } from './default-layout';
4
- export type { LayoutConfig, UserConfig, SearchConfig, NotificationsList, NotificationConfig, MenuItem, BrandingConfig, BaseComponentConfig, NavbarConfig, SidebarConfig, ComponentConfig, LayoutRules, RouteType, HttpMethod, NavbarHeight, Placement, } from './default-layout';
4
+ export type * from './default-layout';
5
5
  export * from './atoms/accordion';
6
6
  export * from './atoms/alert-dialog';
7
7
  export * from './atoms/alert';
@@ -1,26 +1,25 @@
1
1
  import { jsxs as a, jsx as e } from "react/jsx-runtime";
2
- import * as d from "react";
3
- import { Avatar as t, AvatarImage as m, AvatarFallback as h } from "../atoms/avatar.js";
2
+ import * as i from "react";
3
+ import { Avatar as t, AvatarImage as d, AvatarFallback as m } from "../atoms/avatar.js";
4
4
  import { Button as s } from "../atoms/button.js";
5
- import { DropdownMenu as p, DropdownMenuTrigger as f, DropdownMenuContent as u, DropdownMenuLabel as g, DropdownMenuSeparator as x, DropdownMenuItem as o } from "../atoms/dropdown-menu.js";
5
+ import { DropdownMenu as h, DropdownMenuTrigger as p, DropdownMenuContent as f, DropdownMenuLabel as u, DropdownMenuSeparator as x, DropdownMenuItem as g } from "../atoms/dropdown-menu.js";
6
6
  import { cn as w } from "../lib/utils.js";
7
- function b({ user: n, items: l, className: i }) {
8
- return /* @__PURE__ */ a(p, { children: [
9
- /* @__PURE__ */ e(f, { asChild: !0, children: /* @__PURE__ */ e(s, { variant: "ghost", size: "icon", className: w("rounded-full", i), children: /* @__PURE__ */ a(t, { className: "h-8 w-8", children: [
10
- /* @__PURE__ */ e(m, { src: n.avatar, alt: n.name }),
11
- /* @__PURE__ */ e(h, { children: n.name?.[0] ?? "U" })
7
+ function b({ user: n, items: o, className: l }) {
8
+ return /* @__PURE__ */ a(h, { children: [
9
+ /* @__PURE__ */ e(p, { asChild: !0, children: /* @__PURE__ */ e(s, { variant: "ghost", size: "icon", className: w("rounded-full", l), children: /* @__PURE__ */ a(t, { className: "h-8 w-8", children: [
10
+ /* @__PURE__ */ e(d, { src: n.avatar, alt: n.name }),
11
+ /* @__PURE__ */ e(m, { children: n.name?.[0] ?? "U" })
12
12
  ] }) }) }),
13
- /* @__PURE__ */ a(u, { align: "end", children: [
14
- /* @__PURE__ */ e(g, { className: "p-0 font-normal", children: /* @__PURE__ */ a("div", { className: "flex flex-col space-y-1", children: [
13
+ /* @__PURE__ */ a(f, { align: "end", children: [
14
+ /* @__PURE__ */ e(u, { className: "p-0 font-normal", children: /* @__PURE__ */ a("div", { className: "flex flex-col space-y-1", children: [
15
15
  /* @__PURE__ */ e("p", { className: "text-sm font-medium leading-none", children: n.name }),
16
16
  /* @__PURE__ */ e("p", { className: "text-xs leading-none text-muted-foreground", children: n.email })
17
17
  ] }) }),
18
18
  /* @__PURE__ */ e(x, {}),
19
- l?.map((r, c) => /* @__PURE__ */ e(o, { asChild: !0, children: /* @__PURE__ */ a("a", { href: r.href ?? "#", onClick: r.onClick, children: [
20
- r.icon && d.createElement(r.icon, { className: "mr-2 h-4 w-4" }),
19
+ o?.map((r, c) => /* @__PURE__ */ e(g, { asChild: !0, children: /* @__PURE__ */ a("a", { href: r.href ?? "#", onClick: r.onClick, children: [
20
+ r.icon && i.createElement(r.icon, { className: "mr-2 h-4 w-4" }),
21
21
  /* @__PURE__ */ e("span", { children: r.label })
22
- ] }) }, c)),
23
- !l?.length && /* @__PURE__ */ e(o, { asChild: !0, children: /* @__PURE__ */ e("a", { href: "#profile", children: "Profile" }) })
22
+ ] }) }, c))
24
23
  ] })
25
24
  ] });
26
25
  }
@@ -1 +1 @@
1
- {"version":3,"file":"user-menu.js","sources":["../../src/molecules/user-menu.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { Avatar, AvatarFallback, AvatarImage } from \"@/atoms/avatar\";\nimport { Button } from \"@/atoms/button\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"@/atoms/dropdown-menu\";\nimport { cn } from \"@/lib/utils\";\n\nexport interface UserMenuProps {\n user: {\n name: string;\n email: string;\n avatar?: string;\n };\n items?: Array<{\n label: string;\n href?: string;\n onClick?: () => void;\n icon?: React.ComponentType<{ className?: string }>;\n }>;\n className?: string;\n}\n\nexport function UserMenu({ user, items, className }: UserMenuProps) {\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button variant=\"ghost\" size=\"icon\" className={cn(\"rounded-full\", className)}>\n <Avatar className=\"h-8 w-8\">\n <AvatarImage src={user.avatar} alt={user.name} />\n <AvatarFallback>{user.name?.[0] ?? \"U\"}</AvatarFallback>\n </Avatar>\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n <DropdownMenuLabel className=\"p-0 font-normal\">\n <div className=\"flex flex-col space-y-1\">\n <p className=\"text-sm font-medium leading-none\">{user.name}</p>\n <p className=\"text-xs leading-none text-muted-foreground\">{user.email}</p>\n </div>\n </DropdownMenuLabel>\n <DropdownMenuSeparator />\n {items?.map((item, i) => (\n <DropdownMenuItem key={i} asChild>\n <a href={item.href ?? \"#\"} onClick={item.onClick}>\n {item.icon && React.createElement(item.icon, { className: \"mr-2 h-4 w-4\" })}\n <span>{item.label}</span>\n </a>\n </DropdownMenuItem>\n ))}\n {!items?.length && (\n <DropdownMenuItem asChild>\n <a href=\"#profile\">Profile</a>\n </DropdownMenuItem>\n )}\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n"],"names":["UserMenu","user","items","className","DropdownMenu","jsx","DropdownMenuTrigger","Button","cn","jsxs","Avatar","AvatarImage","AvatarFallback","DropdownMenuContent","DropdownMenuLabel","DropdownMenuSeparator","item","i","DropdownMenuItem","React"],"mappings":";;;;;;AA8BO,SAASA,EAAS,EAAE,MAAAC,GAAM,OAAAC,GAAO,WAAAC,KAA4B;AAClE,2BACGC,GAAA,EACC,UAAA;AAAA,IAAA,gBAAAC,EAACC,KAAoB,SAAO,IAC1B,UAAA,gBAAAD,EAACE,GAAA,EAAO,SAAQ,SAAQ,MAAK,QAAO,WAAWC,EAAG,gBAAgBL,CAAS,GACzE,UAAA,gBAAAM,EAACC,GAAA,EAAO,WAAU,WAChB,UAAA;AAAA,MAAA,gBAAAL,EAACM,KAAY,KAAKV,EAAK,QAAQ,KAAKA,EAAK,MAAM;AAAA,wBAC9CW,GAAA,EAAgB,UAAAX,EAAK,OAAO,CAAC,KAAK,IAAA,CAAI;AAAA,IAAA,EAAA,CACzC,GACF,GACF;AAAA,IACA,gBAAAQ,EAACI,GAAA,EAAoB,OAAM,OACzB,UAAA;AAAA,MAAA,gBAAAR,EAACS,KAAkB,WAAU,mBAC3B,UAAA,gBAAAL,EAAC,OAAA,EAAI,WAAU,2BACb,UAAA;AAAA,QAAA,gBAAAJ,EAAC,KAAA,EAAE,WAAU,oCAAoC,UAAAJ,EAAK,MAAK;AAAA,QAC3D,gBAAAI,EAAC,KAAA,EAAE,WAAU,8CAA8C,YAAK,MAAA,CAAM;AAAA,MAAA,EAAA,CACxE,EAAA,CACF;AAAA,wBACCU,GAAA,EAAsB;AAAA,MACtBb,GAAO,IAAI,CAACc,GAAMC,wBAChBC,GAAA,EAAyB,SAAO,IAC/B,UAAA,gBAAAT,EAAC,OAAE,MAAMO,EAAK,QAAQ,KAAK,SAASA,EAAK,SACtC,UAAA;AAAA,QAAAA,EAAK,QAAQG,EAAM,cAAcH,EAAK,MAAM,EAAE,WAAW,gBAAgB;AAAA,QAC1E,gBAAAX,EAAC,QAAA,EAAM,UAAAW,EAAK,MAAA,CAAM;AAAA,MAAA,GACpB,EAAA,GAJqBC,CAKvB,CACD;AAAA,MACA,CAACf,GAAO,UACP,gBAAAG,EAACa,GAAA,EAAiB,SAAO,IACvB,UAAA,gBAAAb,EAAC,KAAA,EAAE,MAAK,YAAW,UAAA,UAAA,CAAO,EAAA,CAC5B;AAAA,IAAA,EAAA,CAEJ;AAAA,EAAA,GACF;AAEJ;"}
1
+ {"version":3,"file":"user-menu.js","sources":["../../src/molecules/user-menu.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { Avatar, AvatarFallback, AvatarImage } from \"@/atoms/avatar\";\nimport { Button } from \"@/atoms/button\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"@/atoms/dropdown-menu\";\nimport { cn } from \"@/lib/utils\";\n\nexport interface UserMenuProps {\n user: {\n name: string;\n email: string;\n avatar?: string;\n };\n items?: Array<{\n label: string;\n href?: string;\n onClick?: () => void;\n icon?: React.ComponentType<{ className?: string }>;\n }>;\n className?: string;\n}\n\nexport function UserMenu({ user, items, className }: UserMenuProps) {\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button variant=\"ghost\" size=\"icon\" className={cn(\"rounded-full\", className)}>\n <Avatar className=\"h-8 w-8\">\n <AvatarImage src={user.avatar} alt={user.name} />\n <AvatarFallback>{user.name?.[0] ?? \"U\"}</AvatarFallback>\n </Avatar>\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n <DropdownMenuLabel className=\"p-0 font-normal\">\n <div className=\"flex flex-col space-y-1\">\n <p className=\"text-sm font-medium leading-none\">{user.name}</p>\n <p className=\"text-xs leading-none text-muted-foreground\">{user.email}</p>\n </div>\n </DropdownMenuLabel>\n <DropdownMenuSeparator />\n {items?.map((item, i) => (\n <DropdownMenuItem key={i} asChild>\n <a href={item.href ?? \"#\"} onClick={item.onClick}>\n {item.icon && React.createElement(item.icon, { className: \"mr-2 h-4 w-4\" })}\n <span>{item.label}</span>\n </a>\n </DropdownMenuItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n"],"names":["UserMenu","user","items","className","DropdownMenu","jsx","DropdownMenuTrigger","Button","cn","jsxs","Avatar","AvatarImage","AvatarFallback","DropdownMenuContent","DropdownMenuLabel","DropdownMenuSeparator","item","i","DropdownMenuItem","React"],"mappings":";;;;;;AA8BO,SAASA,EAAS,EAAE,MAAAC,GAAM,OAAAC,GAAO,WAAAC,KAA4B;AAClE,2BACGC,GAAA,EACC,UAAA;AAAA,IAAA,gBAAAC,EAACC,KAAoB,SAAO,IAC1B,UAAA,gBAAAD,EAACE,GAAA,EAAO,SAAQ,SAAQ,MAAK,QAAO,WAAWC,EAAG,gBAAgBL,CAAS,GACzE,UAAA,gBAAAM,EAACC,GAAA,EAAO,WAAU,WAChB,UAAA;AAAA,MAAA,gBAAAL,EAACM,KAAY,KAAKV,EAAK,QAAQ,KAAKA,EAAK,MAAM;AAAA,wBAC9CW,GAAA,EAAgB,UAAAX,EAAK,OAAO,CAAC,KAAK,IAAA,CAAI;AAAA,IAAA,EAAA,CACzC,GACF,GACF;AAAA,IACA,gBAAAQ,EAACI,GAAA,EAAoB,OAAM,OACzB,UAAA;AAAA,MAAA,gBAAAR,EAACS,KAAkB,WAAU,mBAC3B,UAAA,gBAAAL,EAAC,OAAA,EAAI,WAAU,2BACb,UAAA;AAAA,QAAA,gBAAAJ,EAAC,KAAA,EAAE,WAAU,oCAAoC,UAAAJ,EAAK,MAAK;AAAA,QAC3D,gBAAAI,EAAC,KAAA,EAAE,WAAU,8CAA8C,YAAK,MAAA,CAAM;AAAA,MAAA,EAAA,CACxE,EAAA,CACF;AAAA,wBACCU,GAAA,EAAsB;AAAA,MACtBb,GAAO,IAAI,CAACc,GAAMC,wBAChBC,GAAA,EAAyB,SAAO,IAC/B,UAAA,gBAAAT,EAAC,OAAE,MAAMO,EAAK,QAAQ,KAAK,SAASA,EAAK,SACtC,UAAA;AAAA,QAAAA,EAAK,QAAQG,EAAM,cAAcH,EAAK,MAAM,EAAE,WAAW,gBAAgB;AAAA,QAC1E,gBAAAX,EAAC,QAAA,EAAM,UAAAW,EAAK,MAAA,CAAM;AAAA,MAAA,EAAA,CACpB,EAAA,GAJqBC,CAKvB,CACD;AAAA,IAAA,EAAA,CACH;AAAA,EAAA,GACF;AAEJ;"}
@@ -1,36 +1,73 @@
1
- import { UserConfig, BrandingConfig, MenuItem, NotificationsList } from '../default-layout';
2
- interface NavbarLabels {
3
- profile?: string;
4
- notifications?: string;
5
- noNotifications?: string;
6
- }
7
- interface UserMenuItem {
1
+ type Placement = "top" | "bottom";
2
+ type NavItem = {
3
+ label: string;
4
+ href: string;
5
+ icon?: React.ComponentType<{
6
+ className?: string;
7
+ }>;
8
+ disabled?: boolean;
9
+ };
10
+ type User = {
11
+ name: string;
12
+ email: string;
13
+ image?: string;
14
+ };
15
+ type UserMenuItem = {
8
16
  label: string;
9
17
  href?: string;
10
18
  icon?: React.ComponentType<{
11
19
  className?: string;
12
20
  }>;
13
21
  onClick?: () => void;
14
- }
15
- interface AppNavbarProps {
16
- items?: (MenuItem & {
17
- icon?: React.ComponentType<{
18
- className?: string;
19
- }>;
20
- })[];
21
- searchPlaceholder?: string;
22
- user?: UserConfig;
23
- userMenuItems?: UserMenuItem[];
24
- notifications?: NotificationsList[];
25
- branding?: BrandingConfig;
26
- labels?: NavbarLabels;
27
- showSearch?: boolean;
28
- showSidebarTrigger?: boolean;
29
- showUserMenu?: boolean;
30
- showThemeToggle?: boolean;
31
- showNotifications?: boolean;
22
+ };
23
+ type Notification = {
24
+ title: string;
25
+ description: string;
26
+ date: string;
27
+ read: boolean;
28
+ };
29
+ type Branding = {
30
+ logoUrl?: string;
31
+ logoAlt?: string;
32
+ title?: string;
33
+ href?: string;
34
+ };
35
+ type LoginButton = {
36
+ label?: string;
37
+ href?: string;
38
+ variant?: "default" | "destructive" | "outline" | "secondary" | "ghost" | "link";
39
+ onClick?: () => void;
40
+ };
41
+ type SearchConfig = {
42
+ enabled?: boolean;
43
+ placeholder?: string;
44
+ onSearch?: (value: string) => void;
45
+ };
46
+ type NotificationsConfig = {
47
+ enabled?: boolean;
48
+ items?: Notification[];
49
+ onNotificationClick?: (notification: Notification, index: number) => void;
50
+ };
51
+ type Labels = {
52
+ notifications?: string;
53
+ noNotifications?: string;
54
+ };
55
+ export type AppNavbarProps = {
56
+ placement?: Placement;
57
+ sticky?: boolean;
32
58
  className?: string;
33
59
  style?: React.CSSProperties;
34
- }
35
- export declare function AppNavbar({ items, searchPlaceholder, user, userMenuItems, notifications, branding, labels, showSearch, showSidebarTrigger, showUserMenu, showThemeToggle, showNotifications, className, style, }: AppNavbarProps): import("react/jsx-runtime").JSX.Element;
60
+ branding?: Branding;
61
+ items?: NavItem[];
62
+ search?: SearchConfig;
63
+ notifications?: NotificationsConfig;
64
+ showThemeToggle?: boolean;
65
+ showSidebarTrigger?: boolean;
66
+ user?: User;
67
+ userMenuItems?: UserMenuItem[];
68
+ loginButton?: LoginButton;
69
+ showUserMenu?: boolean;
70
+ labels?: Labels;
71
+ };
72
+ export declare function AppNavbar({ placement, sticky, className, style, branding, items, search, notifications, showThemeToggle, showSidebarTrigger, user, userMenuItems, loginButton, labels, showUserMenu, }: AppNavbarProps): import("react/jsx-runtime").JSX.Element;
36
73
  export {};