@umituz/web-dashboard 2.0.0 → 2.0.2
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/layouts/components/BrandLogo.js.map +1 -0
- package/dist/layouts/components/DashboardHeader.js.map +1 -0
- package/dist/layouts/components/DashboardLayout.js.map +1 -0
- package/dist/layouts/components/DashboardSidebar.js.map +1 -0
- package/dist/layouts/components/index.d.ts +10 -0
- package/dist/layouts/components/index.js +502 -0
- package/dist/layouts/components/index.js.map +1 -0
- package/dist/layouts/hooks/dashboard.js.map +1 -0
- package/dist/layouts/hooks/index.d.ts +3 -0
- package/dist/layouts/hooks/index.js +57 -0
- package/dist/layouts/hooks/index.js.map +1 -0
- package/dist/layouts/index.d.ts +17 -0
- package/dist/layouts/index.js +756 -0
- package/dist/layouts/index.js.map +1 -0
- package/dist/layouts/theme/default.js.map +1 -0
- package/dist/layouts/theme/index.d.ts +4 -0
- package/dist/layouts/theme/index.js +184 -0
- package/dist/layouts/theme/index.js.map +1 -0
- package/dist/layouts/theme/presets.js.map +1 -0
- package/dist/layouts/theme/utils.js.map +1 -0
- package/dist/layouts/types/index.d.ts +6 -0
- package/dist/layouts/types/index.js +2 -0
- package/dist/layouts/types/user.js.map +1 -0
- package/dist/layouts/utils/dashboard.js.map +1 -0
- package/dist/layouts/utils/index.d.ts +1 -0
- package/dist/layouts/utils/index.js +44 -0
- package/dist/layouts/utils/index.js.map +1 -0
- package/dist/settings/components/SettingsLayout.d.ts +19 -0
- package/dist/settings/components/SettingsLayout.js +170 -0
- package/dist/settings/components/SettingsLayout.js.map +1 -0
- package/dist/settings/components/SettingsSection.d.ts +24 -0
- package/dist/settings/components/SettingsSection.js +73 -0
- package/dist/settings/components/SettingsSection.js.map +1 -0
- package/dist/settings/components/index.d.ts +5 -0
- package/dist/settings/components/index.js +169 -0
- package/dist/settings/components/index.js.map +1 -0
- package/dist/settings/hooks/index.d.ts +3 -0
- package/dist/settings/hooks/index.js +59 -0
- package/dist/settings/hooks/index.js.map +1 -0
- package/dist/settings/hooks/useSettings.d.ts +25 -0
- package/dist/settings/hooks/useSettings.js +59 -0
- package/dist/settings/hooks/useSettings.js.map +1 -0
- package/dist/settings/index.d.ts +7 -0
- package/dist/settings/index.js +259 -0
- package/dist/settings/index.js.map +1 -0
- package/dist/settings/types/index.d.ts +2 -0
- package/dist/settings/types/index.js +2 -0
- package/dist/settings/types/index.js.map +1 -0
- package/dist/settings/types/settings.d.ts +79 -0
- package/dist/settings/types/settings.js +2 -0
- package/dist/settings/types/settings.js.map +1 -0
- package/dist/settings/utils/index.d.ts +3 -0
- package/dist/settings/utils/index.js +39 -0
- package/dist/settings/utils/index.js.map +1 -0
- package/dist/settings/utils/settings.d.ts +50 -0
- package/dist/settings/utils/settings.js +39 -0
- package/dist/settings/utils/settings.js.map +1 -0
- package/package.json +38 -48
- package/dist/components/BrandLogo.js.map +0 -1
- package/dist/components/DashboardHeader.js.map +0 -1
- package/dist/components/DashboardLayout.js.map +0 -1
- package/dist/components/DashboardSidebar.js.map +0 -1
- package/dist/hooks/dashboard.js.map +0 -1
- package/dist/theme/default.js.map +0 -1
- package/dist/theme/presets.js.map +0 -1
- package/dist/theme/utils.js.map +0 -1
- package/dist/utils/dashboard.js.map +0 -1
- /package/dist/{components → layouts/components}/BrandLogo.d.ts +0 -0
- /package/dist/{components → layouts/components}/BrandLogo.js +0 -0
- /package/dist/{components → layouts/components}/DashboardHeader.d.ts +0 -0
- /package/dist/{components → layouts/components}/DashboardHeader.js +0 -0
- /package/dist/{components → layouts/components}/DashboardLayout.d.ts +0 -0
- /package/dist/{components → layouts/components}/DashboardLayout.js +0 -0
- /package/dist/{components → layouts/components}/DashboardSidebar.d.ts +0 -0
- /package/dist/{components → layouts/components}/DashboardSidebar.js +0 -0
- /package/dist/{hooks → layouts/hooks}/dashboard.d.ts +0 -0
- /package/dist/{hooks → layouts/hooks}/dashboard.js +0 -0
- /package/dist/{theme → layouts/theme}/default.d.ts +0 -0
- /package/dist/{theme → layouts/theme}/default.js +0 -0
- /package/dist/{theme → layouts/theme}/presets.d.ts +0 -0
- /package/dist/{theme → layouts/theme}/presets.js +0 -0
- /package/dist/{theme → layouts/theme}/utils.d.ts +0 -0
- /package/dist/{theme → layouts/theme}/utils.js +0 -0
- /package/dist/{types/layout.js.map → layouts/types/index.js.map} +0 -0
- /package/dist/{types → layouts/types}/layout.d.ts +0 -0
- /package/dist/{types → layouts/types}/layout.js +0 -0
- /package/dist/{types/notification.js.map → layouts/types/layout.js.map} +0 -0
- /package/dist/{types → layouts/types}/notification.d.ts +0 -0
- /package/dist/{types → layouts/types}/notification.js +0 -0
- /package/dist/{types/sidebar.js.map → layouts/types/notification.js.map} +0 -0
- /package/dist/{types → layouts/types}/sidebar.d.ts +0 -0
- /package/dist/{types → layouts/types}/sidebar.js +0 -0
- /package/dist/{types/theme.js.map → layouts/types/sidebar.js.map} +0 -0
- /package/dist/{types → layouts/types}/theme.d.ts +0 -0
- /package/dist/{types → layouts/types}/theme.js +0 -0
- /package/dist/{types/user.js.map → layouts/types/theme.js.map} +0 -0
- /package/dist/{types → layouts/types}/user.d.ts +0 -0
- /package/dist/{types → layouts/types}/user.js +0 -0
- /package/dist/{utils → layouts/utils}/dashboard.d.ts +0 -0
- /package/dist/{utils → layouts/utils}/dashboard.js +0 -0
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/domains/settings/components/SettingsLayout.tsx
|
|
4
|
+
import { useState } from "react";
|
|
5
|
+
import { Outlet, useLocation, useNavigate } from "react-router-dom";
|
|
6
|
+
|
|
7
|
+
// src/domains/settings/components/SettingsSection.tsx
|
|
8
|
+
import { Link } from "react-router-dom";
|
|
9
|
+
import { ChevronRight } from "lucide-react";
|
|
10
|
+
import { cn } from "@umituz/web-design-system/utils";
|
|
11
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
12
|
+
var SettingsSection = ({
|
|
13
|
+
section,
|
|
14
|
+
currentPath,
|
|
15
|
+
onNavigate,
|
|
16
|
+
collapsed = false
|
|
17
|
+
}) => {
|
|
18
|
+
const filteredItems = section.items.filter((item) => item.enabled !== false);
|
|
19
|
+
if (filteredItems.length === 0) return null;
|
|
20
|
+
return /* @__PURE__ */ jsxs("div", { className: "mb-6 last:mb-0", children: [
|
|
21
|
+
!collapsed && /* @__PURE__ */ jsx("h3", { className: "px-2 mb-2 text-xs font-bold uppercase tracking-wider text-muted-foreground", children: section.title }),
|
|
22
|
+
/* @__PURE__ */ jsx("div", { className: "space-y-1", children: filteredItems.map((item) => {
|
|
23
|
+
const isActive = currentPath === item.path;
|
|
24
|
+
const itemContent = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
25
|
+
item.icon && /* @__PURE__ */ jsx(
|
|
26
|
+
item.icon,
|
|
27
|
+
{
|
|
28
|
+
className: cn(
|
|
29
|
+
"h-4 w-4 shrink-0",
|
|
30
|
+
isActive && "scale-110"
|
|
31
|
+
)
|
|
32
|
+
}
|
|
33
|
+
),
|
|
34
|
+
!collapsed && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
35
|
+
/* @__PURE__ */ jsx("span", { className: "flex-1 text-left", children: item.label }),
|
|
36
|
+
item.badge !== void 0 && item.badge > 0 && /* @__PURE__ */ jsx("span", { className: "ml-auto flex h-5 min-w-5 items-center justify-center rounded-full bg-destructive px-1.5 text-[10px] font-bold text-destructive-foreground", children: item.badge > 99 ? "99+" : item.badge }),
|
|
37
|
+
item.path && /* @__PURE__ */ jsx(ChevronRight, { className: "h-4 w-4 text-muted-foreground" })
|
|
38
|
+
] })
|
|
39
|
+
] });
|
|
40
|
+
const itemClassName = cn(
|
|
41
|
+
"flex items-center gap-3 rounded-lg px-3 py-2 text-sm font-medium transition-all duration-200 w-full",
|
|
42
|
+
"hover:bg-accent hover:text-accent-foreground",
|
|
43
|
+
isActive && "bg-accent text-accent-foreground",
|
|
44
|
+
collapsed ? "justify-center" : "justify-start"
|
|
45
|
+
);
|
|
46
|
+
if (item.path) {
|
|
47
|
+
return /* @__PURE__ */ jsx(
|
|
48
|
+
Link,
|
|
49
|
+
{
|
|
50
|
+
to: item.path,
|
|
51
|
+
onClick: () => onNavigate?.(item.path),
|
|
52
|
+
className: itemClassName,
|
|
53
|
+
title: collapsed ? item.label : void 0,
|
|
54
|
+
children: itemContent
|
|
55
|
+
},
|
|
56
|
+
item.key
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
return /* @__PURE__ */ jsx(
|
|
60
|
+
"button",
|
|
61
|
+
{
|
|
62
|
+
type: "button",
|
|
63
|
+
onClick: () => {
|
|
64
|
+
},
|
|
65
|
+
className: itemClassName,
|
|
66
|
+
title: collapsed ? item.label : void 0,
|
|
67
|
+
children: itemContent
|
|
68
|
+
},
|
|
69
|
+
item.key
|
|
70
|
+
);
|
|
71
|
+
}) })
|
|
72
|
+
] });
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
// src/domains/settings/components/SettingsLayout.tsx
|
|
76
|
+
import { Skeleton } from "@umituz/web-design-system/atoms";
|
|
77
|
+
import { ChevronLeft, Menu } from "lucide-react";
|
|
78
|
+
import { Button } from "@umituz/web-design-system/atoms";
|
|
79
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
80
|
+
var SettingsLayout = ({
|
|
81
|
+
config
|
|
82
|
+
}) => {
|
|
83
|
+
const location = useLocation();
|
|
84
|
+
const navigate = useNavigate();
|
|
85
|
+
const [collapsed, setCollapsed] = useState(false);
|
|
86
|
+
const [mobileOpen, setMobileOpen] = useState(false);
|
|
87
|
+
const [loading, setLoading] = useState(true);
|
|
88
|
+
useState(() => {
|
|
89
|
+
setLoading(true);
|
|
90
|
+
const timer = setTimeout(() => setLoading(false), 200);
|
|
91
|
+
return () => clearTimeout(timer);
|
|
92
|
+
});
|
|
93
|
+
const handleNavigate = (path) => {
|
|
94
|
+
navigate(path);
|
|
95
|
+
setMobileOpen(false);
|
|
96
|
+
};
|
|
97
|
+
return /* @__PURE__ */ jsxs2("div", { className: "flex h-screen w-full bg-background font-sans", children: [
|
|
98
|
+
/* @__PURE__ */ jsxs2(
|
|
99
|
+
"aside",
|
|
100
|
+
{
|
|
101
|
+
className: `hidden md:flex flex-col shrink-0 border-r border-border bg-card transition-all duration-300 ${collapsed ? "w-16" : "w-64"}`,
|
|
102
|
+
children: [
|
|
103
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex h-14 items-center justify-between border-b border-border px-4", children: [
|
|
104
|
+
!collapsed && /* @__PURE__ */ jsx2("h2", { className: "text-lg font-semibold text-foreground", children: config.brandName || "Settings" }),
|
|
105
|
+
/* @__PURE__ */ jsx2(
|
|
106
|
+
Button,
|
|
107
|
+
{
|
|
108
|
+
variant: "ghost",
|
|
109
|
+
size: "icon",
|
|
110
|
+
onClick: () => setCollapsed(!collapsed),
|
|
111
|
+
className: "ml-auto",
|
|
112
|
+
children: collapsed ? /* @__PURE__ */ jsx2(Menu, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx2(ChevronLeft, { className: "h-4 w-4" })
|
|
113
|
+
}
|
|
114
|
+
)
|
|
115
|
+
] }),
|
|
116
|
+
/* @__PURE__ */ jsx2("nav", { className: "flex-1 overflow-y-auto p-2", children: config.sections.map((section) => /* @__PURE__ */ jsx2(
|
|
117
|
+
SettingsSection,
|
|
118
|
+
{
|
|
119
|
+
section,
|
|
120
|
+
currentPath: location.pathname,
|
|
121
|
+
onNavigate: handleNavigate,
|
|
122
|
+
collapsed
|
|
123
|
+
},
|
|
124
|
+
section.key
|
|
125
|
+
)) })
|
|
126
|
+
]
|
|
127
|
+
}
|
|
128
|
+
),
|
|
129
|
+
mobileOpen && /* @__PURE__ */ jsxs2("div", { className: "fixed inset-0 z-50 md:hidden", children: [
|
|
130
|
+
/* @__PURE__ */ jsx2(
|
|
131
|
+
"div",
|
|
132
|
+
{
|
|
133
|
+
className: "absolute inset-0 bg-background/80 backdrop-blur-sm",
|
|
134
|
+
onClick: () => setMobileOpen(false)
|
|
135
|
+
}
|
|
136
|
+
),
|
|
137
|
+
/* @__PURE__ */ jsxs2("aside", { className: "absolute left-0 top-0 h-full w-64 border-r border-border bg-card shadow-xl", children: [
|
|
138
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex h-14 items-center justify-between border-b border-border px-4", children: [
|
|
139
|
+
/* @__PURE__ */ jsx2("h2", { className: "text-lg font-semibold text-foreground", children: config.brandName || "Settings" }),
|
|
140
|
+
/* @__PURE__ */ jsx2(Button, { variant: "ghost", size: "icon", onClick: () => setMobileOpen(false), children: /* @__PURE__ */ jsx2(Menu, { className: "h-4 w-4" }) })
|
|
141
|
+
] }),
|
|
142
|
+
/* @__PURE__ */ jsx2("nav", { className: "flex-1 overflow-y-auto p-2", children: config.sections.map((section) => /* @__PURE__ */ jsx2(
|
|
143
|
+
SettingsSection,
|
|
144
|
+
{
|
|
145
|
+
section,
|
|
146
|
+
currentPath: location.pathname,
|
|
147
|
+
onNavigate: handleNavigate
|
|
148
|
+
},
|
|
149
|
+
section.key
|
|
150
|
+
)) })
|
|
151
|
+
] })
|
|
152
|
+
] }),
|
|
153
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex flex-1 flex-col overflow-hidden min-w-0", children: [
|
|
154
|
+
/* @__PURE__ */ jsx2("header", { className: "flex h-14 items-center justify-between border-b border-border bg-card/50 backdrop-blur-md px-4 shrink-0 md:hidden", children: /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-3", children: [
|
|
155
|
+
/* @__PURE__ */ jsx2(Button, { variant: "ghost", size: "icon", onClick: () => setMobileOpen(true), children: /* @__PURE__ */ jsx2(Menu, { className: "h-5 w-5" }) }),
|
|
156
|
+
/* @__PURE__ */ jsx2("h2", { className: "text-sm font-semibold text-foreground", children: config.brandName || "Settings" })
|
|
157
|
+
] }) }),
|
|
158
|
+
/* @__PURE__ */ jsx2("main", { className: "flex-1 overflow-y-auto p-4 md:p-8", children: loading ? /* @__PURE__ */ jsxs2("div", { className: "mx-auto w-full max-w-4xl space-y-6", children: [
|
|
159
|
+
/* @__PURE__ */ jsx2(Skeleton, { className: "h-8 w-1/3 rounded-xl" }),
|
|
160
|
+
/* @__PURE__ */ jsx2("div", { className: "grid gap-4", children: Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ jsx2(Skeleton, { className: "h-24 rounded-xl" }, i)) })
|
|
161
|
+
] }) : /* @__PURE__ */ jsx2(Outlet, {}) })
|
|
162
|
+
] })
|
|
163
|
+
] });
|
|
164
|
+
};
|
|
165
|
+
var SettingsLayout_default = SettingsLayout;
|
|
166
|
+
export {
|
|
167
|
+
SettingsLayout,
|
|
168
|
+
SettingsLayout_default as default
|
|
169
|
+
};
|
|
170
|
+
//# sourceMappingURL=SettingsLayout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/domains/settings/components/SettingsLayout.tsx","../../../src/domains/settings/components/SettingsSection.tsx"],"sourcesContent":["import { useState } from \"react\";\nimport { Outlet, useLocation, useNavigate } from \"react-router-dom\";\nimport { SettingsSection } from \"./SettingsSection\";\nimport type { SettingsConfig } from \"../types/settings\";\nimport { Skeleton } from \"@umituz/web-design-system/atoms\";\nimport { ChevronLeft, Menu } from \"lucide-react\";\nimport { Button } from \"@umituz/web-design-system/atoms\";\n\ninterface SettingsLayoutProps {\n /** Settings configuration */\n config: SettingsConfig;\n}\n\n/**\n * Settings Layout Component\n *\n * Main layout wrapper for settings pages.\n * Provides sidebar navigation and content area.\n *\n * @param props - Settings layout props\n */\nexport const SettingsLayout = ({\n config,\n}: SettingsLayoutProps) => {\n const location = useLocation();\n const navigate = useNavigate();\n const [collapsed, setCollapsed] = useState(false);\n const [mobileOpen, setMobileOpen] = useState(false);\n const [loading, setLoading] = useState(true);\n\n // Simulate loading on route change\n useState(() => {\n setLoading(true);\n const timer = setTimeout(() => setLoading(false), 200);\n return () => clearTimeout(timer);\n });\n\n const handleNavigate = (path: string) => {\n navigate(path);\n setMobileOpen(false);\n };\n\n return (\n <div className=\"flex h-screen w-full bg-background font-sans\">\n {/* Desktop Sidebar */}\n <aside\n className={`hidden md:flex flex-col shrink-0 border-r border-border bg-card transition-all duration-300 ${\n collapsed ? \"w-16\" : \"w-64\"\n }`}\n >\n <div className=\"flex h-14 items-center justify-between border-b border-border px-4\">\n {!collapsed && (\n <h2 className=\"text-lg font-semibold text-foreground\">\n {config.brandName || \"Settings\"}\n </h2>\n )}\n <Button\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => setCollapsed(!collapsed)}\n className=\"ml-auto\"\n >\n {collapsed ? <Menu className=\"h-4 w-4\" /> : <ChevronLeft className=\"h-4 w-4\" />}\n </Button>\n </div>\n\n <nav className=\"flex-1 overflow-y-auto p-2\">\n {config.sections.map((section) => (\n <SettingsSection\n key={section.key}\n section={section}\n currentPath={location.pathname}\n onNavigate={handleNavigate}\n collapsed={collapsed}\n />\n ))}\n </nav>\n </aside>\n\n {/* Mobile Menu Overlay */}\n {mobileOpen && (\n <div className=\"fixed inset-0 z-50 md:hidden\">\n <div\n className=\"absolute inset-0 bg-background/80 backdrop-blur-sm\"\n onClick={() => setMobileOpen(false)}\n />\n <aside className=\"absolute left-0 top-0 h-full w-64 border-r border-border bg-card shadow-xl\">\n <div className=\"flex h-14 items-center justify-between border-b border-border px-4\">\n <h2 className=\"text-lg font-semibold text-foreground\">\n {config.brandName || \"Settings\"}\n </h2>\n <Button variant=\"ghost\" size=\"icon\" onClick={() => setMobileOpen(false)}>\n <Menu className=\"h-4 w-4\" />\n </Button>\n </div>\n\n <nav className=\"flex-1 overflow-y-auto p-2\">\n {config.sections.map((section) => (\n <SettingsSection\n key={section.key}\n section={section}\n currentPath={location.pathname}\n onNavigate={handleNavigate}\n />\n ))}\n </nav>\n </aside>\n </div>\n )}\n\n {/* Main Content Area */}\n <div className=\"flex flex-1 flex-col overflow-hidden min-w-0\">\n {/* Mobile Header */}\n <header className=\"flex h-14 items-center justify-between border-b border-border bg-card/50 backdrop-blur-md px-4 shrink-0 md:hidden\">\n <div className=\"flex items-center gap-3\">\n <Button variant=\"ghost\" size=\"icon\" onClick={() => setMobileOpen(true)}>\n <Menu className=\"h-5 w-5\" />\n </Button>\n <h2 className=\"text-sm font-semibold text-foreground\">\n {config.brandName || \"Settings\"}\n </h2>\n </div>\n </header>\n\n <main className=\"flex-1 overflow-y-auto p-4 md:p-8\">\n {loading ? (\n <div className=\"mx-auto w-full max-w-4xl space-y-6\">\n <Skeleton className=\"h-8 w-1/3 rounded-xl\" />\n <div className=\"grid gap-4\">\n {Array.from({ length: 3 }).map((_, i) => (\n <Skeleton key={i} className=\"h-24 rounded-xl\" />\n ))}\n </div>\n </div>\n ) : (\n <Outlet />\n )}\n </main>\n </div>\n </div>\n );\n};\n\nexport default SettingsLayout;\n","import { Link } from \"react-router-dom\";\nimport { ChevronRight } from \"lucide-react\";\nimport { cn } from \"@umituz/web-design-system/utils\";\nimport type { SettingsSection as SettingsSectionType } from \"../types/settings\";\n\ninterface SettingsSectionProps {\n /** Section configuration */\n section: SettingsSectionType;\n /** Current path */\n currentPath?: string;\n /** On navigate callback */\n onNavigate?: (path: string) => void;\n /** Collapsed state */\n collapsed?: boolean;\n}\n\n/**\n * Settings Section Component\n *\n * Displays a section of settings items.\n *\n * @param props - Settings section props\n */\nexport const SettingsSection = ({\n section,\n currentPath,\n onNavigate,\n collapsed = false,\n}: SettingsSectionProps) => {\n const filteredItems = section.items.filter((item) => item.enabled !== false);\n\n if (filteredItems.length === 0) return null;\n\n return (\n <div className=\"mb-6 last:mb-0\">\n {!collapsed && (\n <h3 className=\"px-2 mb-2 text-xs font-bold uppercase tracking-wider text-muted-foreground\">\n {section.title}\n </h3>\n )}\n\n <div className=\"space-y-1\">\n {filteredItems.map((item) => {\n const isActive = currentPath === item.path;\n\n const itemContent = (\n <>\n {item.icon && (\n <item.icon\n className={cn(\n \"h-4 w-4 shrink-0\",\n isActive && \"scale-110\"\n )}\n />\n )}\n {!collapsed && (\n <>\n <span className=\"flex-1 text-left\">{item.label}</span>\n {item.badge !== undefined && item.badge > 0 && (\n <span className=\"ml-auto flex h-5 min-w-5 items-center justify-center rounded-full bg-destructive px-1.5 text-[10px] font-bold text-destructive-foreground\">\n {item.badge > 99 ? \"99+\" : item.badge}\n </span>\n )}\n {item.path && <ChevronRight className=\"h-4 w-4 text-muted-foreground\" />}\n </>\n )}\n </>\n );\n\n const itemClassName = cn(\n \"flex items-center gap-3 rounded-lg px-3 py-2 text-sm font-medium transition-all duration-200 w-full\",\n \"hover:bg-accent hover:text-accent-foreground\",\n isActive && \"bg-accent text-accent-foreground\",\n collapsed ? \"justify-center\" : \"justify-start\"\n );\n\n if (item.path) {\n return (\n <Link\n key={item.key}\n to={item.path}\n onClick={() => onNavigate?.(item.path!)}\n className={itemClassName}\n title={collapsed ? item.label : undefined}\n >\n {itemContent}\n </Link>\n );\n }\n\n return (\n <button\n key={item.key}\n type=\"button\"\n onClick={() => {}}\n className={itemClassName}\n title={collapsed ? item.label : undefined}\n >\n {itemContent}\n </button>\n );\n })}\n </div>\n </div>\n );\n};\n"],"mappings":"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","names":["jsx","jsxs"]}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { SettingsSection as SettingsSection$1 } from '../types/settings.js';
|
|
3
|
+
import 'lucide-react';
|
|
4
|
+
|
|
5
|
+
interface SettingsSectionProps {
|
|
6
|
+
/** Section configuration */
|
|
7
|
+
section: SettingsSection$1;
|
|
8
|
+
/** Current path */
|
|
9
|
+
currentPath?: string;
|
|
10
|
+
/** On navigate callback */
|
|
11
|
+
onNavigate?: (path: string) => void;
|
|
12
|
+
/** Collapsed state */
|
|
13
|
+
collapsed?: boolean;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Settings Section Component
|
|
17
|
+
*
|
|
18
|
+
* Displays a section of settings items.
|
|
19
|
+
*
|
|
20
|
+
* @param props - Settings section props
|
|
21
|
+
*/
|
|
22
|
+
declare const SettingsSection: ({ section, currentPath, onNavigate, collapsed, }: SettingsSectionProps) => react_jsx_runtime.JSX.Element | null;
|
|
23
|
+
|
|
24
|
+
export { SettingsSection };
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/domains/settings/components/SettingsSection.tsx
|
|
4
|
+
import { Link } from "react-router-dom";
|
|
5
|
+
import { ChevronRight } from "lucide-react";
|
|
6
|
+
import { cn } from "@umituz/web-design-system/utils";
|
|
7
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
var SettingsSection = ({
|
|
9
|
+
section,
|
|
10
|
+
currentPath,
|
|
11
|
+
onNavigate,
|
|
12
|
+
collapsed = false
|
|
13
|
+
}) => {
|
|
14
|
+
const filteredItems = section.items.filter((item) => item.enabled !== false);
|
|
15
|
+
if (filteredItems.length === 0) return null;
|
|
16
|
+
return /* @__PURE__ */ jsxs("div", { className: "mb-6 last:mb-0", children: [
|
|
17
|
+
!collapsed && /* @__PURE__ */ jsx("h3", { className: "px-2 mb-2 text-xs font-bold uppercase tracking-wider text-muted-foreground", children: section.title }),
|
|
18
|
+
/* @__PURE__ */ jsx("div", { className: "space-y-1", children: filteredItems.map((item) => {
|
|
19
|
+
const isActive = currentPath === item.path;
|
|
20
|
+
const itemContent = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
21
|
+
item.icon && /* @__PURE__ */ jsx(
|
|
22
|
+
item.icon,
|
|
23
|
+
{
|
|
24
|
+
className: cn(
|
|
25
|
+
"h-4 w-4 shrink-0",
|
|
26
|
+
isActive && "scale-110"
|
|
27
|
+
)
|
|
28
|
+
}
|
|
29
|
+
),
|
|
30
|
+
!collapsed && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
31
|
+
/* @__PURE__ */ jsx("span", { className: "flex-1 text-left", children: item.label }),
|
|
32
|
+
item.badge !== void 0 && item.badge > 0 && /* @__PURE__ */ jsx("span", { className: "ml-auto flex h-5 min-w-5 items-center justify-center rounded-full bg-destructive px-1.5 text-[10px] font-bold text-destructive-foreground", children: item.badge > 99 ? "99+" : item.badge }),
|
|
33
|
+
item.path && /* @__PURE__ */ jsx(ChevronRight, { className: "h-4 w-4 text-muted-foreground" })
|
|
34
|
+
] })
|
|
35
|
+
] });
|
|
36
|
+
const itemClassName = cn(
|
|
37
|
+
"flex items-center gap-3 rounded-lg px-3 py-2 text-sm font-medium transition-all duration-200 w-full",
|
|
38
|
+
"hover:bg-accent hover:text-accent-foreground",
|
|
39
|
+
isActive && "bg-accent text-accent-foreground",
|
|
40
|
+
collapsed ? "justify-center" : "justify-start"
|
|
41
|
+
);
|
|
42
|
+
if (item.path) {
|
|
43
|
+
return /* @__PURE__ */ jsx(
|
|
44
|
+
Link,
|
|
45
|
+
{
|
|
46
|
+
to: item.path,
|
|
47
|
+
onClick: () => onNavigate?.(item.path),
|
|
48
|
+
className: itemClassName,
|
|
49
|
+
title: collapsed ? item.label : void 0,
|
|
50
|
+
children: itemContent
|
|
51
|
+
},
|
|
52
|
+
item.key
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
return /* @__PURE__ */ jsx(
|
|
56
|
+
"button",
|
|
57
|
+
{
|
|
58
|
+
type: "button",
|
|
59
|
+
onClick: () => {
|
|
60
|
+
},
|
|
61
|
+
className: itemClassName,
|
|
62
|
+
title: collapsed ? item.label : void 0,
|
|
63
|
+
children: itemContent
|
|
64
|
+
},
|
|
65
|
+
item.key
|
|
66
|
+
);
|
|
67
|
+
}) })
|
|
68
|
+
] });
|
|
69
|
+
};
|
|
70
|
+
export {
|
|
71
|
+
SettingsSection
|
|
72
|
+
};
|
|
73
|
+
//# sourceMappingURL=SettingsSection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/domains/settings/components/SettingsSection.tsx"],"sourcesContent":["import { Link } from \"react-router-dom\";\nimport { ChevronRight } from \"lucide-react\";\nimport { cn } from \"@umituz/web-design-system/utils\";\nimport type { SettingsSection as SettingsSectionType } from \"../types/settings\";\n\ninterface SettingsSectionProps {\n /** Section configuration */\n section: SettingsSectionType;\n /** Current path */\n currentPath?: string;\n /** On navigate callback */\n onNavigate?: (path: string) => void;\n /** Collapsed state */\n collapsed?: boolean;\n}\n\n/**\n * Settings Section Component\n *\n * Displays a section of settings items.\n *\n * @param props - Settings section props\n */\nexport const SettingsSection = ({\n section,\n currentPath,\n onNavigate,\n collapsed = false,\n}: SettingsSectionProps) => {\n const filteredItems = section.items.filter((item) => item.enabled !== false);\n\n if (filteredItems.length === 0) return null;\n\n return (\n <div className=\"mb-6 last:mb-0\">\n {!collapsed && (\n <h3 className=\"px-2 mb-2 text-xs font-bold uppercase tracking-wider text-muted-foreground\">\n {section.title}\n </h3>\n )}\n\n <div className=\"space-y-1\">\n {filteredItems.map((item) => {\n const isActive = currentPath === item.path;\n\n const itemContent = (\n <>\n {item.icon && (\n <item.icon\n className={cn(\n \"h-4 w-4 shrink-0\",\n isActive && \"scale-110\"\n )}\n />\n )}\n {!collapsed && (\n <>\n <span className=\"flex-1 text-left\">{item.label}</span>\n {item.badge !== undefined && item.badge > 0 && (\n <span className=\"ml-auto flex h-5 min-w-5 items-center justify-center rounded-full bg-destructive px-1.5 text-[10px] font-bold text-destructive-foreground\">\n {item.badge > 99 ? \"99+\" : item.badge}\n </span>\n )}\n {item.path && <ChevronRight className=\"h-4 w-4 text-muted-foreground\" />}\n </>\n )}\n </>\n );\n\n const itemClassName = cn(\n \"flex items-center gap-3 rounded-lg px-3 py-2 text-sm font-medium transition-all duration-200 w-full\",\n \"hover:bg-accent hover:text-accent-foreground\",\n isActive && \"bg-accent text-accent-foreground\",\n collapsed ? \"justify-center\" : \"justify-start\"\n );\n\n if (item.path) {\n return (\n <Link\n key={item.key}\n to={item.path}\n onClick={() => onNavigate?.(item.path!)}\n className={itemClassName}\n title={collapsed ? item.label : undefined}\n >\n {itemContent}\n </Link>\n );\n }\n\n return (\n <button\n key={item.key}\n type=\"button\"\n onClick={() => {}}\n className={itemClassName}\n title={collapsed ? item.label : undefined}\n >\n {itemContent}\n </button>\n );\n })}\n </div>\n </div>\n );\n};\n"],"mappings":";;;AAAA,SAAS,YAAY;AACrB,SAAS,oBAAoB;AAC7B,SAAS,UAAU;AAkCX,SAoBQ,UApBR,KAoBQ,YApBR;AAbD,IAAM,kBAAkB,CAAC;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY;AACd,MAA4B;AAC1B,QAAM,gBAAgB,QAAQ,MAAM,OAAO,CAAC,SAAS,KAAK,YAAY,KAAK;AAE3E,MAAI,cAAc,WAAW,EAAG,QAAO;AAEvC,SACE,qBAAC,SAAI,WAAU,kBACZ;AAAA,KAAC,aACA,oBAAC,QAAG,WAAU,8EACX,kBAAQ,OACX;AAAA,IAGF,oBAAC,SAAI,WAAU,aACZ,wBAAc,IAAI,CAAC,SAAS;AAC3B,YAAM,WAAW,gBAAgB,KAAK;AAEtC,YAAM,cACJ,iCACG;AAAA,aAAK,QACJ;AAAA,UAAC,KAAK;AAAA,UAAL;AAAA,YACC,WAAW;AAAA,cACT;AAAA,cACA,YAAY;AAAA,YACd;AAAA;AAAA,QACF;AAAA,QAED,CAAC,aACA,iCACE;AAAA,8BAAC,UAAK,WAAU,oBAAoB,eAAK,OAAM;AAAA,UAC9C,KAAK,UAAU,UAAa,KAAK,QAAQ,KACxC,oBAAC,UAAK,WAAU,6IACb,eAAK,QAAQ,KAAK,QAAQ,KAAK,OAClC;AAAA,UAED,KAAK,QAAQ,oBAAC,gBAAa,WAAU,iCAAgC;AAAA,WACxE;AAAA,SAEJ;AAGF,YAAM,gBAAgB;AAAA,QACpB;AAAA,QACA;AAAA,QACA,YAAY;AAAA,QACZ,YAAY,mBAAmB;AAAA,MACjC;AAEA,UAAI,KAAK,MAAM;AACb,eACE;AAAA,UAAC;AAAA;AAAA,YAEC,IAAI,KAAK;AAAA,YACT,SAAS,MAAM,aAAa,KAAK,IAAK;AAAA,YACtC,WAAW;AAAA,YACX,OAAO,YAAY,KAAK,QAAQ;AAAA,YAE/B;AAAA;AAAA,UANI,KAAK;AAAA,QAOZ;AAAA,MAEJ;AAEA,aACE;AAAA,QAAC;AAAA;AAAA,UAEC,MAAK;AAAA,UACL,SAAS,MAAM;AAAA,UAAC;AAAA,UAChB,WAAW;AAAA,UACX,OAAO,YAAY,KAAK,QAAQ;AAAA,UAE/B;AAAA;AAAA,QANI,KAAK;AAAA,MAOZ;AAAA,IAEJ,CAAC,GACH;AAAA,KACF;AAEJ;","names":[]}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/domains/settings/components/SettingsLayout.tsx
|
|
4
|
+
import { useState } from "react";
|
|
5
|
+
import { Outlet, useLocation, useNavigate } from "react-router-dom";
|
|
6
|
+
|
|
7
|
+
// src/domains/settings/components/SettingsSection.tsx
|
|
8
|
+
import { Link } from "react-router-dom";
|
|
9
|
+
import { ChevronRight } from "lucide-react";
|
|
10
|
+
import { cn } from "@umituz/web-design-system/utils";
|
|
11
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
12
|
+
var SettingsSection = ({
|
|
13
|
+
section,
|
|
14
|
+
currentPath,
|
|
15
|
+
onNavigate,
|
|
16
|
+
collapsed = false
|
|
17
|
+
}) => {
|
|
18
|
+
const filteredItems = section.items.filter((item) => item.enabled !== false);
|
|
19
|
+
if (filteredItems.length === 0) return null;
|
|
20
|
+
return /* @__PURE__ */ jsxs("div", { className: "mb-6 last:mb-0", children: [
|
|
21
|
+
!collapsed && /* @__PURE__ */ jsx("h3", { className: "px-2 mb-2 text-xs font-bold uppercase tracking-wider text-muted-foreground", children: section.title }),
|
|
22
|
+
/* @__PURE__ */ jsx("div", { className: "space-y-1", children: filteredItems.map((item) => {
|
|
23
|
+
const isActive = currentPath === item.path;
|
|
24
|
+
const itemContent = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
25
|
+
item.icon && /* @__PURE__ */ jsx(
|
|
26
|
+
item.icon,
|
|
27
|
+
{
|
|
28
|
+
className: cn(
|
|
29
|
+
"h-4 w-4 shrink-0",
|
|
30
|
+
isActive && "scale-110"
|
|
31
|
+
)
|
|
32
|
+
}
|
|
33
|
+
),
|
|
34
|
+
!collapsed && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
35
|
+
/* @__PURE__ */ jsx("span", { className: "flex-1 text-left", children: item.label }),
|
|
36
|
+
item.badge !== void 0 && item.badge > 0 && /* @__PURE__ */ jsx("span", { className: "ml-auto flex h-5 min-w-5 items-center justify-center rounded-full bg-destructive px-1.5 text-[10px] font-bold text-destructive-foreground", children: item.badge > 99 ? "99+" : item.badge }),
|
|
37
|
+
item.path && /* @__PURE__ */ jsx(ChevronRight, { className: "h-4 w-4 text-muted-foreground" })
|
|
38
|
+
] })
|
|
39
|
+
] });
|
|
40
|
+
const itemClassName = cn(
|
|
41
|
+
"flex items-center gap-3 rounded-lg px-3 py-2 text-sm font-medium transition-all duration-200 w-full",
|
|
42
|
+
"hover:bg-accent hover:text-accent-foreground",
|
|
43
|
+
isActive && "bg-accent text-accent-foreground",
|
|
44
|
+
collapsed ? "justify-center" : "justify-start"
|
|
45
|
+
);
|
|
46
|
+
if (item.path) {
|
|
47
|
+
return /* @__PURE__ */ jsx(
|
|
48
|
+
Link,
|
|
49
|
+
{
|
|
50
|
+
to: item.path,
|
|
51
|
+
onClick: () => onNavigate?.(item.path),
|
|
52
|
+
className: itemClassName,
|
|
53
|
+
title: collapsed ? item.label : void 0,
|
|
54
|
+
children: itemContent
|
|
55
|
+
},
|
|
56
|
+
item.key
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
return /* @__PURE__ */ jsx(
|
|
60
|
+
"button",
|
|
61
|
+
{
|
|
62
|
+
type: "button",
|
|
63
|
+
onClick: () => {
|
|
64
|
+
},
|
|
65
|
+
className: itemClassName,
|
|
66
|
+
title: collapsed ? item.label : void 0,
|
|
67
|
+
children: itemContent
|
|
68
|
+
},
|
|
69
|
+
item.key
|
|
70
|
+
);
|
|
71
|
+
}) })
|
|
72
|
+
] });
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
// src/domains/settings/components/SettingsLayout.tsx
|
|
76
|
+
import { Skeleton } from "@umituz/web-design-system/atoms";
|
|
77
|
+
import { ChevronLeft, Menu } from "lucide-react";
|
|
78
|
+
import { Button } from "@umituz/web-design-system/atoms";
|
|
79
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
80
|
+
var SettingsLayout = ({
|
|
81
|
+
config
|
|
82
|
+
}) => {
|
|
83
|
+
const location = useLocation();
|
|
84
|
+
const navigate = useNavigate();
|
|
85
|
+
const [collapsed, setCollapsed] = useState(false);
|
|
86
|
+
const [mobileOpen, setMobileOpen] = useState(false);
|
|
87
|
+
const [loading, setLoading] = useState(true);
|
|
88
|
+
useState(() => {
|
|
89
|
+
setLoading(true);
|
|
90
|
+
const timer = setTimeout(() => setLoading(false), 200);
|
|
91
|
+
return () => clearTimeout(timer);
|
|
92
|
+
});
|
|
93
|
+
const handleNavigate = (path) => {
|
|
94
|
+
navigate(path);
|
|
95
|
+
setMobileOpen(false);
|
|
96
|
+
};
|
|
97
|
+
return /* @__PURE__ */ jsxs2("div", { className: "flex h-screen w-full bg-background font-sans", children: [
|
|
98
|
+
/* @__PURE__ */ jsxs2(
|
|
99
|
+
"aside",
|
|
100
|
+
{
|
|
101
|
+
className: `hidden md:flex flex-col shrink-0 border-r border-border bg-card transition-all duration-300 ${collapsed ? "w-16" : "w-64"}`,
|
|
102
|
+
children: [
|
|
103
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex h-14 items-center justify-between border-b border-border px-4", children: [
|
|
104
|
+
!collapsed && /* @__PURE__ */ jsx2("h2", { className: "text-lg font-semibold text-foreground", children: config.brandName || "Settings" }),
|
|
105
|
+
/* @__PURE__ */ jsx2(
|
|
106
|
+
Button,
|
|
107
|
+
{
|
|
108
|
+
variant: "ghost",
|
|
109
|
+
size: "icon",
|
|
110
|
+
onClick: () => setCollapsed(!collapsed),
|
|
111
|
+
className: "ml-auto",
|
|
112
|
+
children: collapsed ? /* @__PURE__ */ jsx2(Menu, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx2(ChevronLeft, { className: "h-4 w-4" })
|
|
113
|
+
}
|
|
114
|
+
)
|
|
115
|
+
] }),
|
|
116
|
+
/* @__PURE__ */ jsx2("nav", { className: "flex-1 overflow-y-auto p-2", children: config.sections.map((section) => /* @__PURE__ */ jsx2(
|
|
117
|
+
SettingsSection,
|
|
118
|
+
{
|
|
119
|
+
section,
|
|
120
|
+
currentPath: location.pathname,
|
|
121
|
+
onNavigate: handleNavigate,
|
|
122
|
+
collapsed
|
|
123
|
+
},
|
|
124
|
+
section.key
|
|
125
|
+
)) })
|
|
126
|
+
]
|
|
127
|
+
}
|
|
128
|
+
),
|
|
129
|
+
mobileOpen && /* @__PURE__ */ jsxs2("div", { className: "fixed inset-0 z-50 md:hidden", children: [
|
|
130
|
+
/* @__PURE__ */ jsx2(
|
|
131
|
+
"div",
|
|
132
|
+
{
|
|
133
|
+
className: "absolute inset-0 bg-background/80 backdrop-blur-sm",
|
|
134
|
+
onClick: () => setMobileOpen(false)
|
|
135
|
+
}
|
|
136
|
+
),
|
|
137
|
+
/* @__PURE__ */ jsxs2("aside", { className: "absolute left-0 top-0 h-full w-64 border-r border-border bg-card shadow-xl", children: [
|
|
138
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex h-14 items-center justify-between border-b border-border px-4", children: [
|
|
139
|
+
/* @__PURE__ */ jsx2("h2", { className: "text-lg font-semibold text-foreground", children: config.brandName || "Settings" }),
|
|
140
|
+
/* @__PURE__ */ jsx2(Button, { variant: "ghost", size: "icon", onClick: () => setMobileOpen(false), children: /* @__PURE__ */ jsx2(Menu, { className: "h-4 w-4" }) })
|
|
141
|
+
] }),
|
|
142
|
+
/* @__PURE__ */ jsx2("nav", { className: "flex-1 overflow-y-auto p-2", children: config.sections.map((section) => /* @__PURE__ */ jsx2(
|
|
143
|
+
SettingsSection,
|
|
144
|
+
{
|
|
145
|
+
section,
|
|
146
|
+
currentPath: location.pathname,
|
|
147
|
+
onNavigate: handleNavigate
|
|
148
|
+
},
|
|
149
|
+
section.key
|
|
150
|
+
)) })
|
|
151
|
+
] })
|
|
152
|
+
] }),
|
|
153
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex flex-1 flex-col overflow-hidden min-w-0", children: [
|
|
154
|
+
/* @__PURE__ */ jsx2("header", { className: "flex h-14 items-center justify-between border-b border-border bg-card/50 backdrop-blur-md px-4 shrink-0 md:hidden", children: /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-3", children: [
|
|
155
|
+
/* @__PURE__ */ jsx2(Button, { variant: "ghost", size: "icon", onClick: () => setMobileOpen(true), children: /* @__PURE__ */ jsx2(Menu, { className: "h-5 w-5" }) }),
|
|
156
|
+
/* @__PURE__ */ jsx2("h2", { className: "text-sm font-semibold text-foreground", children: config.brandName || "Settings" })
|
|
157
|
+
] }) }),
|
|
158
|
+
/* @__PURE__ */ jsx2("main", { className: "flex-1 overflow-y-auto p-4 md:p-8", children: loading ? /* @__PURE__ */ jsxs2("div", { className: "mx-auto w-full max-w-4xl space-y-6", children: [
|
|
159
|
+
/* @__PURE__ */ jsx2(Skeleton, { className: "h-8 w-1/3 rounded-xl" }),
|
|
160
|
+
/* @__PURE__ */ jsx2("div", { className: "grid gap-4", children: Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ jsx2(Skeleton, { className: "h-24 rounded-xl" }, i)) })
|
|
161
|
+
] }) : /* @__PURE__ */ jsx2(Outlet, {}) })
|
|
162
|
+
] })
|
|
163
|
+
] });
|
|
164
|
+
};
|
|
165
|
+
export {
|
|
166
|
+
SettingsLayout,
|
|
167
|
+
SettingsSection
|
|
168
|
+
};
|
|
169
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/domains/settings/components/SettingsLayout.tsx","../../../src/domains/settings/components/SettingsSection.tsx"],"sourcesContent":["import { useState } from \"react\";\nimport { Outlet, useLocation, useNavigate } from \"react-router-dom\";\nimport { SettingsSection } from \"./SettingsSection\";\nimport type { SettingsConfig } from \"../types/settings\";\nimport { Skeleton } from \"@umituz/web-design-system/atoms\";\nimport { ChevronLeft, Menu } from \"lucide-react\";\nimport { Button } from \"@umituz/web-design-system/atoms\";\n\ninterface SettingsLayoutProps {\n /** Settings configuration */\n config: SettingsConfig;\n}\n\n/**\n * Settings Layout Component\n *\n * Main layout wrapper for settings pages.\n * Provides sidebar navigation and content area.\n *\n * @param props - Settings layout props\n */\nexport const SettingsLayout = ({\n config,\n}: SettingsLayoutProps) => {\n const location = useLocation();\n const navigate = useNavigate();\n const [collapsed, setCollapsed] = useState(false);\n const [mobileOpen, setMobileOpen] = useState(false);\n const [loading, setLoading] = useState(true);\n\n // Simulate loading on route change\n useState(() => {\n setLoading(true);\n const timer = setTimeout(() => setLoading(false), 200);\n return () => clearTimeout(timer);\n });\n\n const handleNavigate = (path: string) => {\n navigate(path);\n setMobileOpen(false);\n };\n\n return (\n <div className=\"flex h-screen w-full bg-background font-sans\">\n {/* Desktop Sidebar */}\n <aside\n className={`hidden md:flex flex-col shrink-0 border-r border-border bg-card transition-all duration-300 ${\n collapsed ? \"w-16\" : \"w-64\"\n }`}\n >\n <div className=\"flex h-14 items-center justify-between border-b border-border px-4\">\n {!collapsed && (\n <h2 className=\"text-lg font-semibold text-foreground\">\n {config.brandName || \"Settings\"}\n </h2>\n )}\n <Button\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => setCollapsed(!collapsed)}\n className=\"ml-auto\"\n >\n {collapsed ? <Menu className=\"h-4 w-4\" /> : <ChevronLeft className=\"h-4 w-4\" />}\n </Button>\n </div>\n\n <nav className=\"flex-1 overflow-y-auto p-2\">\n {config.sections.map((section) => (\n <SettingsSection\n key={section.key}\n section={section}\n currentPath={location.pathname}\n onNavigate={handleNavigate}\n collapsed={collapsed}\n />\n ))}\n </nav>\n </aside>\n\n {/* Mobile Menu Overlay */}\n {mobileOpen && (\n <div className=\"fixed inset-0 z-50 md:hidden\">\n <div\n className=\"absolute inset-0 bg-background/80 backdrop-blur-sm\"\n onClick={() => setMobileOpen(false)}\n />\n <aside className=\"absolute left-0 top-0 h-full w-64 border-r border-border bg-card shadow-xl\">\n <div className=\"flex h-14 items-center justify-between border-b border-border px-4\">\n <h2 className=\"text-lg font-semibold text-foreground\">\n {config.brandName || \"Settings\"}\n </h2>\n <Button variant=\"ghost\" size=\"icon\" onClick={() => setMobileOpen(false)}>\n <Menu className=\"h-4 w-4\" />\n </Button>\n </div>\n\n <nav className=\"flex-1 overflow-y-auto p-2\">\n {config.sections.map((section) => (\n <SettingsSection\n key={section.key}\n section={section}\n currentPath={location.pathname}\n onNavigate={handleNavigate}\n />\n ))}\n </nav>\n </aside>\n </div>\n )}\n\n {/* Main Content Area */}\n <div className=\"flex flex-1 flex-col overflow-hidden min-w-0\">\n {/* Mobile Header */}\n <header className=\"flex h-14 items-center justify-between border-b border-border bg-card/50 backdrop-blur-md px-4 shrink-0 md:hidden\">\n <div className=\"flex items-center gap-3\">\n <Button variant=\"ghost\" size=\"icon\" onClick={() => setMobileOpen(true)}>\n <Menu className=\"h-5 w-5\" />\n </Button>\n <h2 className=\"text-sm font-semibold text-foreground\">\n {config.brandName || \"Settings\"}\n </h2>\n </div>\n </header>\n\n <main className=\"flex-1 overflow-y-auto p-4 md:p-8\">\n {loading ? (\n <div className=\"mx-auto w-full max-w-4xl space-y-6\">\n <Skeleton className=\"h-8 w-1/3 rounded-xl\" />\n <div className=\"grid gap-4\">\n {Array.from({ length: 3 }).map((_, i) => (\n <Skeleton key={i} className=\"h-24 rounded-xl\" />\n ))}\n </div>\n </div>\n ) : (\n <Outlet />\n )}\n </main>\n </div>\n </div>\n );\n};\n\nexport default SettingsLayout;\n","import { Link } from \"react-router-dom\";\nimport { ChevronRight } from \"lucide-react\";\nimport { cn } from \"@umituz/web-design-system/utils\";\nimport type { SettingsSection as SettingsSectionType } from \"../types/settings\";\n\ninterface SettingsSectionProps {\n /** Section configuration */\n section: SettingsSectionType;\n /** Current path */\n currentPath?: string;\n /** On navigate callback */\n onNavigate?: (path: string) => void;\n /** Collapsed state */\n collapsed?: boolean;\n}\n\n/**\n * Settings Section Component\n *\n * Displays a section of settings items.\n *\n * @param props - Settings section props\n */\nexport const SettingsSection = ({\n section,\n currentPath,\n onNavigate,\n collapsed = false,\n}: SettingsSectionProps) => {\n const filteredItems = section.items.filter((item) => item.enabled !== false);\n\n if (filteredItems.length === 0) return null;\n\n return (\n <div className=\"mb-6 last:mb-0\">\n {!collapsed && (\n <h3 className=\"px-2 mb-2 text-xs font-bold uppercase tracking-wider text-muted-foreground\">\n {section.title}\n </h3>\n )}\n\n <div className=\"space-y-1\">\n {filteredItems.map((item) => {\n const isActive = currentPath === item.path;\n\n const itemContent = (\n <>\n {item.icon && (\n <item.icon\n className={cn(\n \"h-4 w-4 shrink-0\",\n isActive && \"scale-110\"\n )}\n />\n )}\n {!collapsed && (\n <>\n <span className=\"flex-1 text-left\">{item.label}</span>\n {item.badge !== undefined && item.badge > 0 && (\n <span className=\"ml-auto flex h-5 min-w-5 items-center justify-center rounded-full bg-destructive px-1.5 text-[10px] font-bold text-destructive-foreground\">\n {item.badge > 99 ? \"99+\" : item.badge}\n </span>\n )}\n {item.path && <ChevronRight className=\"h-4 w-4 text-muted-foreground\" />}\n </>\n )}\n </>\n );\n\n const itemClassName = cn(\n \"flex items-center gap-3 rounded-lg px-3 py-2 text-sm font-medium transition-all duration-200 w-full\",\n \"hover:bg-accent hover:text-accent-foreground\",\n isActive && \"bg-accent text-accent-foreground\",\n collapsed ? \"justify-center\" : \"justify-start\"\n );\n\n if (item.path) {\n return (\n <Link\n key={item.key}\n to={item.path}\n onClick={() => onNavigate?.(item.path!)}\n className={itemClassName}\n title={collapsed ? item.label : undefined}\n >\n {itemContent}\n </Link>\n );\n }\n\n return (\n <button\n key={item.key}\n type=\"button\"\n onClick={() => {}}\n className={itemClassName}\n title={collapsed ? item.label : undefined}\n >\n {itemContent}\n </button>\n );\n })}\n </div>\n </div>\n );\n};\n"],"mappings":"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","names":["jsx","jsxs"]}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/domains/settings/hooks/useSettings.ts
|
|
4
|
+
import { useState, useCallback } from "react";
|
|
5
|
+
function useSettings(initialConfig) {
|
|
6
|
+
const [config, setConfig] = useState(initialConfig);
|
|
7
|
+
const updateItem = useCallback(
|
|
8
|
+
(sectionKey, itemKey, updates) => {
|
|
9
|
+
setConfig((prev) => ({
|
|
10
|
+
...prev,
|
|
11
|
+
sections: prev.sections.map(
|
|
12
|
+
(section) => section.key === sectionKey ? {
|
|
13
|
+
...section,
|
|
14
|
+
items: section.items.map(
|
|
15
|
+
(item) => item.key === itemKey ? { ...item, ...updates } : item
|
|
16
|
+
)
|
|
17
|
+
} : section
|
|
18
|
+
)
|
|
19
|
+
}));
|
|
20
|
+
},
|
|
21
|
+
[]
|
|
22
|
+
);
|
|
23
|
+
const toggleItem = useCallback((sectionKey, itemKey) => {
|
|
24
|
+
setConfig((prev) => ({
|
|
25
|
+
...prev,
|
|
26
|
+
sections: prev.sections.map(
|
|
27
|
+
(section) => section.key === sectionKey ? {
|
|
28
|
+
...section,
|
|
29
|
+
items: section.items.map(
|
|
30
|
+
(item) => item.key === itemKey ? { ...item, enabled: item.enabled === void 0 ? true : !item.enabled } : item
|
|
31
|
+
)
|
|
32
|
+
} : section
|
|
33
|
+
)
|
|
34
|
+
}));
|
|
35
|
+
}, []);
|
|
36
|
+
const setItemBadge = useCallback((sectionKey, itemKey, badge) => {
|
|
37
|
+
setConfig((prev) => ({
|
|
38
|
+
...prev,
|
|
39
|
+
sections: prev.sections.map(
|
|
40
|
+
(section) => section.key === sectionKey ? {
|
|
41
|
+
...section,
|
|
42
|
+
items: section.items.map(
|
|
43
|
+
(item) => item.key === itemKey ? { ...item, badge } : item
|
|
44
|
+
)
|
|
45
|
+
} : section
|
|
46
|
+
)
|
|
47
|
+
}));
|
|
48
|
+
}, []);
|
|
49
|
+
return {
|
|
50
|
+
config,
|
|
51
|
+
updateItem,
|
|
52
|
+
toggleItem,
|
|
53
|
+
setItemBadge
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
export {
|
|
57
|
+
useSettings
|
|
58
|
+
};
|
|
59
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/domains/settings/hooks/useSettings.ts"],"sourcesContent":["/**\n * Settings Hooks\n *\n * Custom React hooks for settings functionality\n */\n\nimport { useState, useCallback } from \"react\";\nimport type { SettingsConfig, SettingsItem } from \"../types/settings\";\n\n/**\n * Use Settings Hook\n *\n * Manages settings state and actions\n *\n * @param initialConfig - Initial settings configuration\n * @returns Settings state and actions\n */\nexport function useSettings(initialConfig: SettingsConfig) {\n const [config, setConfig] = useState<SettingsConfig>(initialConfig);\n\n const updateItem = useCallback(\n (sectionKey: string, itemKey: string, updates: Partial<SettingsItem>) => {\n setConfig((prev) => ({\n ...prev,\n sections: prev.sections.map((section) =>\n section.key === sectionKey\n ? {\n ...section,\n items: section.items.map((item) =>\n item.key === itemKey ? { ...item, ...updates } : item\n ),\n }\n : section\n ),\n }));\n },\n []\n );\n\n const toggleItem = useCallback((sectionKey: string, itemKey: string) => {\n setConfig((prev) => ({\n ...prev,\n sections: prev.sections.map((section) =>\n section.key === sectionKey\n ? {\n ...section,\n items: section.items.map((item) =>\n item.key === itemKey\n ? { ...item, enabled: item.enabled === undefined ? true : !item.enabled }\n : item\n ),\n }\n : section\n ),\n }));\n }, []);\n\n const setItemBadge = useCallback((sectionKey: string, itemKey: string, badge: number | undefined) => {\n setConfig((prev) => ({\n ...prev,\n sections: prev.sections.map((section) =>\n section.key === sectionKey\n ? {\n ...section,\n items: section.items.map((item) =>\n item.key === itemKey ? { ...item, badge } : item\n ),\n }\n : section\n ),\n }));\n }, []);\n\n return {\n config,\n updateItem,\n toggleItem,\n setItemBadge,\n };\n}\n"],"mappings":";;;AAMA,SAAS,UAAU,mBAAmB;AAW/B,SAAS,YAAY,eAA+B;AACzD,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAyB,aAAa;AAElE,QAAM,aAAa;AAAA,IACjB,CAAC,YAAoB,SAAiB,YAAmC;AACvE,gBAAU,CAAC,UAAU;AAAA,QACnB,GAAG;AAAA,QACH,UAAU,KAAK,SAAS;AAAA,UAAI,CAAC,YAC3B,QAAQ,QAAQ,aACZ;AAAA,YACE,GAAG;AAAA,YACH,OAAO,QAAQ,MAAM;AAAA,cAAI,CAAC,SACxB,KAAK,QAAQ,UAAU,EAAE,GAAG,MAAM,GAAG,QAAQ,IAAI;AAAA,YACnD;AAAA,UACF,IACA;AAAA,QACN;AAAA,MACF,EAAE;AAAA,IACJ;AAAA,IACA,CAAC;AAAA,EACH;AAEA,QAAM,aAAa,YAAY,CAAC,YAAoB,YAAoB;AACtE,cAAU,CAAC,UAAU;AAAA,MACnB,GAAG;AAAA,MACH,UAAU,KAAK,SAAS;AAAA,QAAI,CAAC,YAC3B,QAAQ,QAAQ,aACZ;AAAA,UACE,GAAG;AAAA,UACH,OAAO,QAAQ,MAAM;AAAA,YAAI,CAAC,SACxB,KAAK,QAAQ,UACT,EAAE,GAAG,MAAM,SAAS,KAAK,YAAY,SAAY,OAAO,CAAC,KAAK,QAAQ,IACtE;AAAA,UACN;AAAA,QACF,IACA;AAAA,MACN;AAAA,IACF,EAAE;AAAA,EACJ,GAAG,CAAC,CAAC;AAEL,QAAM,eAAe,YAAY,CAAC,YAAoB,SAAiB,UAA8B;AACnG,cAAU,CAAC,UAAU;AAAA,MACnB,GAAG;AAAA,MACH,UAAU,KAAK,SAAS;AAAA,QAAI,CAAC,YAC3B,QAAQ,QAAQ,aACZ;AAAA,UACE,GAAG;AAAA,UACH,OAAO,QAAQ,MAAM;AAAA,YAAI,CAAC,SACxB,KAAK,QAAQ,UAAU,EAAE,GAAG,MAAM,MAAM,IAAI;AAAA,UAC9C;AAAA,QACF,IACA;AAAA,MACN;AAAA,IACF,EAAE;AAAA,EACJ,GAAG,CAAC,CAAC;AAEL,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;","names":[]}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { SettingsConfig, SettingsItem } from '../types/settings.js';
|
|
2
|
+
import 'lucide-react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Settings Hooks
|
|
6
|
+
*
|
|
7
|
+
* Custom React hooks for settings functionality
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Use Settings Hook
|
|
12
|
+
*
|
|
13
|
+
* Manages settings state and actions
|
|
14
|
+
*
|
|
15
|
+
* @param initialConfig - Initial settings configuration
|
|
16
|
+
* @returns Settings state and actions
|
|
17
|
+
*/
|
|
18
|
+
declare function useSettings(initialConfig: SettingsConfig): {
|
|
19
|
+
config: SettingsConfig;
|
|
20
|
+
updateItem: (sectionKey: string, itemKey: string, updates: Partial<SettingsItem>) => void;
|
|
21
|
+
toggleItem: (sectionKey: string, itemKey: string) => void;
|
|
22
|
+
setItemBadge: (sectionKey: string, itemKey: string, badge: number | undefined) => void;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export { useSettings };
|