@imksh/create 1.0.30 → 1.0.31
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/package.json +1 -1
- package/src/utils/askTemplate.js +2 -1
- package/templates/layers/electron/base/electron/main.js +262 -0
- package/templates/layers/electron/base/electron/preload.js +37 -0
- package/templates/layers/electron/base/electron-builder.json5 +68 -0
- package/templates/layers/electron/javascript/_gitignore +38 -0
- package/templates/layers/electron/javascript/package.json +49 -0
- package/templates/layers/electron/javascript/src/components/layout/SidebarLayout.jsx +43 -0
- package/templates/layers/electron/javascript/src/components/ui/TitleBar.jsx +130 -0
- package/templates/layers/electron/javascript/src/config/appConfig.js +51 -0
- package/templates/layers/electron/javascript/src/hooks/useElectron.js +68 -0
- package/templates/layers/electron/javascript/src/main.jsx +17 -0
- package/templates/layers/electron/javascript/src/store/useUiStore.js +59 -0
- package/templates/layers/electron/javascript/vite.config.js +29 -0
- package/templates/layers/electron/typescript/_gitignore +38 -0
- package/templates/layers/electron/typescript/electron/main.ts +213 -0
- package/templates/layers/electron/typescript/electron/preload.ts +52 -0
- package/templates/layers/electron/typescript/package.json +52 -0
- package/templates/layers/electron/typescript/src/components/layout/SidebarLayout.tsx +42 -0
- package/templates/layers/electron/typescript/src/components/ui/TitleBar.tsx +120 -0
- package/templates/layers/electron/typescript/src/config/appConfig.ts +52 -0
- package/templates/layers/electron/typescript/src/hooks/useElectron.ts +68 -0
- package/templates/layers/electron/typescript/src/main.tsx +17 -0
- package/templates/layers/electron/typescript/src/store/useUiStore.ts +97 -0
- package/templates/layers/electron/typescript/src/vite-env.d.ts +13 -0
- package/templates/layers/electron/typescript/tsconfig.json +25 -0
- package/templates/layers/electron/typescript/tsconfig.node.json +11 -0
- package/templates/layers/electron/typescript/vite.config.ts +29 -0
- package/templates/layers/next/javascript/src/components/common/Breadcrumbs.jsx +44 -6
- package/templates/layers/next/javascript/src/components/common/Loading.jsx +1 -0
- package/templates/layers/next/javascript/src/components/common/LottieIcon.jsx +1 -0
- package/templates/layers/next/javascript/src/components/common/Pagination.jsx +170 -0
- package/templates/layers/next/javascript/src/components/common/SidebarModal.jsx +180 -0
- package/templates/layers/next/javascript/src/components/common/StatsCard.jsx +168 -0
- package/templates/layers/next/javascript/src/components/common/Table.jsx +191 -41
- package/templates/layers/next/javascript/src/components/common/Tabs.jsx +187 -0
- package/templates/layers/next/javascript/src/components/common/ToggleSwitch.jsx +4 -3
- package/templates/layers/next/javascript/src/components/layout/ProtectedRoute.jsx +2 -1
- package/templates/layers/next/javascript/src/components/layout/PublicLayout.jsx +3 -6
- package/templates/layers/next/javascript/src/components/layout/SidebarLayout.jsx +4 -17
- package/templates/layers/next/javascript/src/components/modals/ConfirmModal.jsx +4 -12
- package/templates/layers/next/javascript/src/components/modals/Modal.jsx +50 -19
- package/templates/layers/next/javascript/src/components/ui/Input.jsx +50 -0
- package/templates/layers/next/{typescript/src/components/ui/sidebar.tsx → javascript/src/components/ui/Sidebar.jsx} +65 -53
- package/templates/layers/next/javascript/src/components/ui/SidebarHeader.jsx +11 -6
- package/templates/layers/next/javascript/src/config/appConfig.js +4 -4
- package/templates/layers/next/javascript/src/hooks/useWindowSize.js +2 -3
- package/templates/layers/next/javascript/src/store/useUiStore.js +9 -4
- package/templates/layers/next/typescript/src/components/common/Breadcrumbs.tsx +57 -8
- package/templates/layers/next/typescript/src/components/common/Loading.tsx +1 -0
- package/templates/layers/next/typescript/src/components/common/Pagination.tsx +186 -0
- package/templates/layers/next/typescript/src/components/common/SidebarModal.tsx +200 -0
- package/templates/layers/next/typescript/src/components/common/StatsCard.tsx +232 -0
- package/templates/layers/next/typescript/src/components/common/Table.tsx +201 -35
- package/templates/layers/next/typescript/src/components/common/Tabs.tsx +190 -0
- package/templates/layers/next/typescript/src/components/common/ToggleSwitch.tsx +12 -8
- package/templates/layers/next/typescript/src/components/layout/PublicLayout.tsx +8 -6
- package/templates/layers/next/typescript/src/components/layout/SidebarLayout.tsx +8 -17
- package/templates/layers/next/typescript/src/components/modals/ConfirmModal.tsx +1 -0
- package/templates/layers/next/typescript/src/components/modals/Modal.tsx +67 -21
- package/templates/layers/next/typescript/src/components/ui/Button.tsx +1 -0
- package/templates/layers/next/typescript/src/components/ui/Input.tsx +40 -60
- package/templates/layers/next/{javascript/src/components/ui/sidebar.jsx → typescript/src/components/ui/Sidebar.tsx} +77 -44
- package/templates/layers/next/typescript/src/components/ui/SidebarHeader.tsx +16 -10
- package/templates/layers/next/typescript/src/config/appConfig.ts +4 -4
- package/templates/layers/next/typescript/src/hooks/useWindowSize.ts +2 -3
- package/templates/layers/next/typescript/src/store/useUiStore.ts +14 -4
- package/templates/layers/node/typescript/package-lock.json +2 -2
- package/templates/layers/node/typescript/package.json +1 -1
- package/templates/layers/prisma/typescript/prisma/schema.prisma +35 -10
- package/templates/layers/react/javascript/src/components/common/Breadcrumbs.jsx +62 -58
- package/templates/layers/react/javascript/src/components/common/Pagination.jsx +164 -76
- package/templates/layers/react/javascript/src/components/common/SidebarModal.jsx +179 -0
- package/templates/layers/react/javascript/src/components/common/StatsCard.jsx +167 -0
- package/templates/layers/react/javascript/src/components/common/Table.jsx +248 -132
- package/templates/layers/react/javascript/src/components/common/Tabs.jsx +164 -112
- package/templates/layers/react/javascript/src/components/common/ToggleSwitch.jsx +3 -3
- package/templates/layers/react/javascript/src/components/layout/SidebarLayout.jsx +4 -12
- package/templates/layers/react/javascript/src/components/modals/Modal.jsx +53 -18
- package/templates/layers/react/javascript/src/components/ui/Input.jsx +49 -0
- package/templates/layers/react/javascript/src/components/ui/Sidebar.jsx +215 -0
- package/templates/layers/react/javascript/src/components/ui/SidebarHeader.jsx +25 -30
- package/templates/layers/react/javascript/src/config/appConfig.js +3 -3
- package/templates/layers/react/javascript/src/hooks/useWindowSize.js +2 -2
- package/templates/layers/react/typescript/src/components/common/Breadcrumbs.tsx +32 -6
- package/templates/layers/react/typescript/src/components/common/Pagination.tsx +151 -57
- package/templates/layers/react/typescript/src/components/common/SidebarModal.tsx +199 -0
- package/templates/layers/react/typescript/src/components/common/StatsCard.tsx +231 -0
- package/templates/layers/react/typescript/src/components/common/Table.tsx +197 -34
- package/templates/layers/react/typescript/src/components/common/Tabs.tsx +56 -12
- package/templates/layers/react/typescript/src/components/common/ToggleSwitch.tsx +15 -3
- package/templates/layers/react/typescript/src/components/layout/SidebarLayout.tsx +3 -6
- package/templates/layers/react/typescript/src/components/modals/Modal.tsx +151 -0
- package/templates/layers/react/typescript/src/components/ui/Input.tsx +58 -0
- package/templates/layers/react/typescript/src/components/ui/Sidebar.tsx +116 -53
- package/templates/layers/react/typescript/src/components/ui/SidebarHeader.tsx +5 -4
- package/templates/layers/react/typescript/src/config/appConfig.ts +3 -3
- package/templates/layers/react/typescript/src/hooks/useWindowSize.ts +2 -3
- package/templates/layers/react-native/base/src/config/appConfig.ts +1 -1
- package/templates/presets/electron/preset.json +9 -0
- package/templates/presets/electron-ts/preset.json +9 -0
- package/templates/layers/react/javascript/src/components/ui/sidebar.jsx +0 -169
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import React, { InputHTMLAttributes, ReactNode } from "react";
|
|
2
|
+
import { X } from "lucide-react";
|
|
3
|
+
|
|
4
|
+
export interface InputProps extends Omit<
|
|
5
|
+
InputHTMLAttributes<HTMLInputElement>,
|
|
6
|
+
"size"
|
|
7
|
+
> {
|
|
8
|
+
icon?: ReactNode;
|
|
9
|
+
wrapperClassName?: string;
|
|
10
|
+
onClear?: () => void;
|
|
11
|
+
size?: "xs" | "sm" | "md" | "lg";
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
|
15
|
+
(
|
|
16
|
+
{
|
|
17
|
+
icon,
|
|
18
|
+
wrapperClassName = "",
|
|
19
|
+
onClear,
|
|
20
|
+
className = "",
|
|
21
|
+
value,
|
|
22
|
+
size,
|
|
23
|
+
...props
|
|
24
|
+
},
|
|
25
|
+
ref,
|
|
26
|
+
) => {
|
|
27
|
+
const sizeClass = size ? `input-${size}` : "";
|
|
28
|
+
return (
|
|
29
|
+
<div className={`relative ${wrapperClassName}`}>
|
|
30
|
+
{icon && (
|
|
31
|
+
<div className="absolute left-3 top-1/2 -translate-y-1/2 text-base-content/50 pointer-events-none flex items-center justify-center z-10">
|
|
32
|
+
{icon}
|
|
33
|
+
</div>
|
|
34
|
+
)}
|
|
35
|
+
<input
|
|
36
|
+
ref={ref}
|
|
37
|
+
value={value}
|
|
38
|
+
className={`input input-bordered w-full ${sizeClass} ${icon ? "pl-10" : ""} ${
|
|
39
|
+
onClear && value ? "pr-10" : ""
|
|
40
|
+
} ${className}`}
|
|
41
|
+
{...props}
|
|
42
|
+
/>
|
|
43
|
+
{onClear && value && (
|
|
44
|
+
<button
|
|
45
|
+
type="button"
|
|
46
|
+
onClick={onClear}
|
|
47
|
+
className="absolute right-3 top-1/2 -translate-y-1/2 text-base-content/40 hover:text-base-content transition-colors flex items-center justify-center"
|
|
48
|
+
aria-label="Clear input"
|
|
49
|
+
>
|
|
50
|
+
<X size={16} />
|
|
51
|
+
</button>
|
|
52
|
+
)}
|
|
53
|
+
</div>
|
|
54
|
+
);
|
|
55
|
+
},
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
Input.displayName = "Input";
|
|
@@ -2,14 +2,18 @@ import { NavLink } from "react-router-dom";
|
|
|
2
2
|
import { IoClose } from "react-icons/io5";
|
|
3
3
|
import { useUiStore } from "../../store/useUiStore";
|
|
4
4
|
import { navigation } from "../../config/navigation";
|
|
5
|
-
import {
|
|
5
|
+
import { Moon, Sun } from "lucide-react";
|
|
6
6
|
import appConfig from "../../config/appConfig";
|
|
7
7
|
import { motion, AnimatePresence } from "framer-motion";
|
|
8
8
|
import useWindowSize from "../../hooks/useWindowSize";
|
|
9
|
+
import { useAuthStore } from "../../store/useAuthStore";
|
|
10
|
+
import { GoSidebarCollapse, GoSidebarExpand } from "react-icons/go";
|
|
11
|
+
import { CiLogout } from "react-icons/ci";
|
|
9
12
|
|
|
10
13
|
const Sidebar = () => {
|
|
11
|
-
const { open, close, collapsed, toggleCollapsed } =
|
|
12
|
-
|
|
14
|
+
const { open, close, collapsed, toggleCollapsed, theme, toggleTheme } =
|
|
15
|
+
useUiStore();
|
|
16
|
+
const { logout, user } = useAuthStore();
|
|
13
17
|
const { width } = useWindowSize();
|
|
14
18
|
const isMobile = width < 1024; // lg breakpoint
|
|
15
19
|
|
|
@@ -44,7 +48,7 @@ const Sidebar = () => {
|
|
|
44
48
|
h-screen bg-base-200 border-r border-base-300
|
|
45
49
|
flex flex-col overflow-hidden
|
|
46
50
|
transition-[width] duration-300
|
|
47
|
-
${collapsed ? "w-
|
|
51
|
+
${collapsed ? "w-18" : "w-[75%] md:w-[16%] md:max-w-60"}
|
|
48
52
|
`}
|
|
49
53
|
>
|
|
50
54
|
{/* Header */}
|
|
@@ -79,68 +83,127 @@ const Sidebar = () => {
|
|
|
79
83
|
</div>
|
|
80
84
|
|
|
81
85
|
{/* Navigation */}
|
|
82
|
-
<nav
|
|
83
|
-
|
|
84
|
-
|
|
86
|
+
<nav
|
|
87
|
+
className="flex-1 overflow-y-auto p-2.5 space-y-1"
|
|
88
|
+
data-lenis-prevent
|
|
89
|
+
>
|
|
90
|
+
{navigation
|
|
91
|
+
.filter((item) => {
|
|
92
|
+
const orgRole = (user as any)?.orgRole;
|
|
93
|
+
const isUserAdmin =
|
|
94
|
+
user?.role === "ADMIN" ||
|
|
95
|
+
orgRole === "OWNER" ||
|
|
96
|
+
orgRole === "ADMIN";
|
|
97
|
+
|
|
98
|
+
// Check if item is hidden for this role
|
|
99
|
+
if (item.hiddenForRoles) {
|
|
100
|
+
if (
|
|
101
|
+
isUserAdmin &&
|
|
102
|
+
(item.hiddenForRoles.includes("OWNER") ||
|
|
103
|
+
item.hiddenForRoles.includes("ADMIN"))
|
|
104
|
+
) {
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
if (orgRole && item.hiddenForRoles.includes(orgRole)) {
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (!item.allowedRoles) return true; // visible to all
|
|
113
|
+
// System-level ADMIN always gets full access
|
|
114
|
+
if (user?.role === "ADMIN") return true;
|
|
115
|
+
// If orgRole not yet resolved, show all items (fail open for admins)
|
|
116
|
+
if (!orgRole) return true;
|
|
117
|
+
return item.allowedRoles.includes(orgRole);
|
|
118
|
+
})
|
|
119
|
+
.map((item) => {
|
|
120
|
+
const Icon = item.icon;
|
|
85
121
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
122
|
+
return (
|
|
123
|
+
<NavLink
|
|
124
|
+
key={item.path}
|
|
125
|
+
to={item.path}
|
|
126
|
+
onClick={isMobile ? close : undefined}
|
|
127
|
+
className={({ isActive }) =>
|
|
128
|
+
`flex items-center gap-3 rounded-box px-4 py-3 duration-0 h-12
|
|
93
129
|
${
|
|
94
130
|
isActive
|
|
95
131
|
? "bg-primary text-primary-content"
|
|
96
132
|
: "hover:bg-base-300"
|
|
97
133
|
} ${collapsed ? "justify-center px-0" : ""}`
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
134
|
+
}
|
|
135
|
+
title={collapsed ? item.title : ""}
|
|
136
|
+
>
|
|
137
|
+
<Icon
|
|
138
|
+
size={18}
|
|
139
|
+
className={`shrink-0 ${collapsed && "mr-auto"}`}
|
|
140
|
+
/>
|
|
105
141
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
142
|
+
{!collapsed && (
|
|
143
|
+
<span className="font-medium transition-all duration-0 whitespace-nowrap">
|
|
144
|
+
{item.title}
|
|
145
|
+
</span>
|
|
146
|
+
)}
|
|
147
|
+
</NavLink>
|
|
148
|
+
);
|
|
149
|
+
})}
|
|
114
150
|
</nav>
|
|
115
151
|
|
|
116
|
-
{/* Footer with
|
|
117
|
-
<
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
152
|
+
{/* Footer with Actions */}
|
|
153
|
+
<div
|
|
154
|
+
className={`p-3 border-t border-base-300/50 shrink-0 flex gap-2 ${
|
|
155
|
+
collapsed
|
|
156
|
+
? "flex-col items-center justify-center"
|
|
157
|
+
: "flex-row items-center justify-between"
|
|
158
|
+
}`}
|
|
121
159
|
>
|
|
122
|
-
{!collapsed && <span>{theme === "dark" ? "Dark" : "Light"}</span>}
|
|
123
|
-
<span className="btn btn-xs btn-ghost btn-circle ">
|
|
124
|
-
{theme === "dark" ? (
|
|
125
|
-
<Sun size={16} className="shrink-0 " />
|
|
126
|
-
) : (
|
|
127
|
-
<Moon size={16} className="shrink-0" />
|
|
128
|
-
)}
|
|
129
|
-
</span>
|
|
130
|
-
</button>
|
|
131
|
-
<div className="p-3 border-t border-base-300/50 shrink-0 flex flex-col gap-2">
|
|
132
160
|
<button
|
|
133
|
-
onClick={
|
|
134
|
-
|
|
135
|
-
|
|
161
|
+
onClick={() => {
|
|
162
|
+
logout();
|
|
163
|
+
close();
|
|
164
|
+
}}
|
|
165
|
+
className={`btn btn-sm btn-circle btn-soft btn-error ${collapsed ? "hidden" : "flex"}`}
|
|
166
|
+
title="Logout"
|
|
136
167
|
>
|
|
137
|
-
{
|
|
138
|
-
<ChevronRight size={18} className="shrink-0 mr-auto" />
|
|
139
|
-
) : (
|
|
140
|
-
<ChevronLeft size={18} className="shrink-0" />
|
|
141
|
-
)}
|
|
142
|
-
{!collapsed && <span className="truncate">Collapse</span>}
|
|
168
|
+
<CiLogout size={18} />
|
|
143
169
|
</button>
|
|
170
|
+
|
|
171
|
+
<div
|
|
172
|
+
className={`flex items-center gap-2 ${collapsed ? "flex-col" : ""}`}
|
|
173
|
+
>
|
|
174
|
+
<button
|
|
175
|
+
onClick={toggleTheme}
|
|
176
|
+
className="flex items-center gap-3 hover:opacity-80 transition-opacity"
|
|
177
|
+
title="Toggle Theme"
|
|
178
|
+
>
|
|
179
|
+
<div
|
|
180
|
+
className={`btn btn-sm btn-circle btn-primary btn-soft pointer-events-none ${collapsed ? "hidden" : "flex"}`}
|
|
181
|
+
>
|
|
182
|
+
{theme === "dark" ? (
|
|
183
|
+
<Sun size={16} className="shrink-0" />
|
|
184
|
+
) : (
|
|
185
|
+
<Moon size={16} className="shrink-0" />
|
|
186
|
+
)}
|
|
187
|
+
</div>
|
|
188
|
+
{!collapsed && (
|
|
189
|
+
<span className="md:hidden font-medium text-sm text-base-content/80">
|
|
190
|
+
{theme === "dark" ? "Dark Mode" : "Light Mode"}
|
|
191
|
+
</span>
|
|
192
|
+
)}
|
|
193
|
+
</button>
|
|
194
|
+
|
|
195
|
+
<button
|
|
196
|
+
onClick={toggleCollapsed}
|
|
197
|
+
className="btn btn-sm btn-circle btn-outline border-none text-base-content/70 hover:text-base-content hover:bg-base-300/60 hidden md:flex"
|
|
198
|
+
title={collapsed ? "Expand Sidebar" : "Collapse Sidebar"}
|
|
199
|
+
>
|
|
200
|
+
{collapsed ? (
|
|
201
|
+
<GoSidebarExpand size={18} />
|
|
202
|
+
) : (
|
|
203
|
+
<GoSidebarCollapse size={18} />
|
|
204
|
+
)}
|
|
205
|
+
</button>
|
|
206
|
+
</div>
|
|
144
207
|
</div>
|
|
145
208
|
</motion.aside>
|
|
146
209
|
)}
|
|
@@ -8,7 +8,10 @@ interface SidebarHeaderProps {
|
|
|
8
8
|
actions?: React.ReactNode;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
const SidebarHeader = ({
|
|
11
|
+
const SidebarHeader = ({
|
|
12
|
+
title = "Dashboard",
|
|
13
|
+
actions = null,
|
|
14
|
+
}: SidebarHeaderProps) => {
|
|
12
15
|
const { toggleSidebar, breadcrumbs } = useUiStore();
|
|
13
16
|
|
|
14
17
|
return (
|
|
@@ -28,9 +31,7 @@ const SidebarHeader = ({ title = "Dashboard", actions = null }: SidebarHeaderPro
|
|
|
28
31
|
)}
|
|
29
32
|
</div>
|
|
30
33
|
|
|
31
|
-
<div className="flex items-center gap-2">
|
|
32
|
-
{actions}
|
|
33
|
-
</div>
|
|
34
|
+
<div className="flex items-center gap-2">{actions}</div>
|
|
34
35
|
</header>
|
|
35
36
|
);
|
|
36
37
|
};
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
const appConfig = {
|
|
2
2
|
app: {
|
|
3
|
-
name: "
|
|
3
|
+
name: "My App",
|
|
4
4
|
logo: "./logo.png",
|
|
5
|
-
shortName: "
|
|
5
|
+
shortName: "App",
|
|
6
6
|
description: "A React application built with @imksh/create",
|
|
7
7
|
version: "1.0.0",
|
|
8
|
-
author: "
|
|
8
|
+
author: "",
|
|
9
9
|
},
|
|
10
10
|
|
|
11
11
|
api: {
|
|
@@ -2,11 +2,10 @@ import { useState, useEffect } from "react";
|
|
|
2
2
|
|
|
3
3
|
const useWindowSize = () => {
|
|
4
4
|
const [size, setSize] = useState({
|
|
5
|
-
width: window.innerWidth,
|
|
6
|
-
height: window.innerHeight,
|
|
5
|
+
width: typeof window !== "undefined" ? window.innerWidth : 1024,
|
|
6
|
+
height: typeof window !== "undefined" ? window.innerHeight : 768,
|
|
7
7
|
});
|
|
8
8
|
|
|
9
|
-
|
|
10
9
|
useEffect(() => {
|
|
11
10
|
const handleResize = () => {
|
|
12
11
|
setSize({
|
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { NavLink } from "react-router-dom";
|
|
3
|
-
import { IoClose } from "react-icons/io5";
|
|
4
|
-
import { useUiStore } from "../../store/useUiStore";
|
|
5
|
-
import { navigation } from "../../config/navigation";
|
|
6
|
-
import { ChevronLeft, ChevronRight, Moon, Sun } from "lucide-react";
|
|
7
|
-
import appConfig from "../../config/appConfig";
|
|
8
|
-
import { motion, AnimatePresence } from "framer-motion";
|
|
9
|
-
import useWindowSize from "../../hooks/useWindowSize";
|
|
10
|
-
const Sidebar = () => {
|
|
11
|
-
const { open, close, collapsed, toggleCollapsed } = useUiStore();
|
|
12
|
-
const { theme, toggleTheme } = useUiStore();
|
|
13
|
-
const { width } = useWindowSize();
|
|
14
|
-
const isMobile = width < 1024;
|
|
15
|
-
const showSidebar = !isMobile || open;
|
|
16
|
-
return /* @__PURE__ */ jsxs(Fragment, {
|
|
17
|
-
children: [
|
|
18
|
-
/* @__PURE__ */ jsx(AnimatePresence, {
|
|
19
|
-
children:
|
|
20
|
-
isMobile &&
|
|
21
|
-
open &&
|
|
22
|
-
/* @__PURE__ */ jsx(motion.div, {
|
|
23
|
-
initial: { opacity: 0 },
|
|
24
|
-
animate: { opacity: 1 },
|
|
25
|
-
exit: { opacity: 0 },
|
|
26
|
-
transition: { duration: 0.2 },
|
|
27
|
-
className: "fixed inset-0 bg-base-100/40 z-40 lg:hidden",
|
|
28
|
-
onClick: close,
|
|
29
|
-
}),
|
|
30
|
-
}),
|
|
31
|
-
/* @__PURE__ */ jsx(AnimatePresence, {
|
|
32
|
-
children:
|
|
33
|
-
showSidebar &&
|
|
34
|
-
/* @__PURE__ */ jsxs(motion.aside, {
|
|
35
|
-
initial: isMobile ? { x: "-100%" } : false,
|
|
36
|
-
animate: { x: 0 },
|
|
37
|
-
exit: isMobile ? { x: "-100%" } : void 0,
|
|
38
|
-
transition: { type: "tween", duration: 0.25, ease: "easeInOut" },
|
|
39
|
-
className: `
|
|
40
|
-
fixed lg:static top-0 left-0 z-50
|
|
41
|
-
h-screen bg-base-200 border-r border-base-300
|
|
42
|
-
flex flex-col overflow-hidden
|
|
43
|
-
transition-[width] duration-300
|
|
44
|
-
${collapsed ? "w-20" : "w-[75%] md:w-[16%] md:max-w-60"}
|
|
45
|
-
`,
|
|
46
|
-
children: [
|
|
47
|
-
/* @__PURE__ */ jsxs("div", {
|
|
48
|
-
className:
|
|
49
|
-
"h-16 border-b border-base-300 flex items-center justify-between px-5",
|
|
50
|
-
children: [
|
|
51
|
-
/* @__PURE__ */ jsxs("div", {
|
|
52
|
-
className: "flex items-center gap-3",
|
|
53
|
-
children: [
|
|
54
|
-
appConfig.app.logo
|
|
55
|
-
? /* @__PURE__ */ jsx("img", {
|
|
56
|
-
src: appConfig.app.logo,
|
|
57
|
-
alt: "",
|
|
58
|
-
className: "w-8 h-8 rounded-lg",
|
|
59
|
-
})
|
|
60
|
-
: /* @__PURE__ */ jsx("div", {
|
|
61
|
-
className: "flex items-center",
|
|
62
|
-
children: /* @__PURE__ */ jsx("div", {
|
|
63
|
-
className:
|
|
64
|
-
"bg-primary w-8 h-8 rounded-lg flex items-center justify-center text-primary-content font-bold",
|
|
65
|
-
children: appConfig.app.name.charAt(0),
|
|
66
|
-
}),
|
|
67
|
-
}),
|
|
68
|
-
/* @__PURE__ */ jsx("h1", {
|
|
69
|
-
className: `text-xl font-black text-primary whitespace-nowrap overflow-hidden ${collapsed ? "hidden" : ""}`,
|
|
70
|
-
children: appConfig.app.name,
|
|
71
|
-
}),
|
|
72
|
-
],
|
|
73
|
-
}),
|
|
74
|
-
/* @__PURE__ */ jsx("button", {
|
|
75
|
-
className: `btn btn-sm btn-circle btn-ghost md:hidden ${collapsed ? "hidden" : ""}`,
|
|
76
|
-
onClick: close,
|
|
77
|
-
children: /* @__PURE__ */ jsx(IoClose, { size: 20 }),
|
|
78
|
-
}),
|
|
79
|
-
],
|
|
80
|
-
}),
|
|
81
|
-
/* @__PURE__ */ jsx("nav", {
|
|
82
|
-
className: "flex-1 overflow-y-auto p-2.5 space-y-1",
|
|
83
|
-
"data-lenis-prevent": true,
|
|
84
|
-
children: navigation.map((item) => {
|
|
85
|
-
const Icon = item.icon;
|
|
86
|
-
return /* @__PURE__ */ jsxs(
|
|
87
|
-
NavLink,
|
|
88
|
-
{
|
|
89
|
-
to: item.path,
|
|
90
|
-
onClick: isMobile ? close : void 0,
|
|
91
|
-
className: ({
|
|
92
|
-
isActive,
|
|
93
|
-
}) => `flex items-center gap-3 rounded-box px-4 py-3 duration-0 h-12
|
|
94
|
-
${isActive ? "bg-primary text-primary-content" : "hover:bg-base-300"} ${collapsed ? "justify-center px-0" : ""}`,
|
|
95
|
-
title: collapsed ? item.title : "",
|
|
96
|
-
children: [
|
|
97
|
-
/* @__PURE__ */ jsx(Icon, {
|
|
98
|
-
size: 18,
|
|
99
|
-
className: `shrink-0 ${collapsed && "mr-auto"}`,
|
|
100
|
-
}),
|
|
101
|
-
!collapsed &&
|
|
102
|
-
/* @__PURE__ */ jsx("span", {
|
|
103
|
-
className:
|
|
104
|
-
"font-medium transition-all duration-0 whitespace-nowrap",
|
|
105
|
-
children: item.title,
|
|
106
|
-
}),
|
|
107
|
-
],
|
|
108
|
-
},
|
|
109
|
-
item.path,
|
|
110
|
-
);
|
|
111
|
-
}),
|
|
112
|
-
}),
|
|
113
|
-
/* @__PURE__ */ jsxs("button", {
|
|
114
|
-
onClick: toggleTheme,
|
|
115
|
-
className: `w-full flex items-center gap-3 px-3 py-2.5 md:px-4 text-sm font-semibold transition-all duration-150 text-base-content/60 hover:text-base-content hover:bg-base-300/60 justify-between rounded-none ${collapsed ? "justify-center" : ""}`,
|
|
116
|
-
title: "Toggle Theme",
|
|
117
|
-
children: [
|
|
118
|
-
!collapsed &&
|
|
119
|
-
/* @__PURE__ */ jsx("span", {
|
|
120
|
-
children: theme === "dark" ? "Dark" : "Light",
|
|
121
|
-
}),
|
|
122
|
-
/* @__PURE__ */ jsx("span", {
|
|
123
|
-
className: "btn btn-xs btn-ghost btn-circle ",
|
|
124
|
-
children:
|
|
125
|
-
theme === "dark"
|
|
126
|
-
? /* @__PURE__ */ jsx(Sun, {
|
|
127
|
-
size: 16,
|
|
128
|
-
className: "shrink-0 ",
|
|
129
|
-
})
|
|
130
|
-
: /* @__PURE__ */ jsx(Moon, {
|
|
131
|
-
size: 16,
|
|
132
|
-
className: "shrink-0",
|
|
133
|
-
}),
|
|
134
|
-
}),
|
|
135
|
-
],
|
|
136
|
-
}),
|
|
137
|
-
/* @__PURE__ */ jsx("div", {
|
|
138
|
-
className:
|
|
139
|
-
"p-3 border-t border-base-300/50 shrink-0 flex flex-col gap-2",
|
|
140
|
-
children: /* @__PURE__ */ jsxs("button", {
|
|
141
|
-
onClick: toggleCollapsed,
|
|
142
|
-
className: `w-full flex items-center gap-3 px-3 py-2.5 rounded-xl text-sm font-semibold transition-all duration-150 text-base-content/60 hover:text-base-content hover:bg-base-300/60 ${collapsed ? "justify-center" : ""}`,
|
|
143
|
-
title: collapsed ? "Expand Sidebar" : "Collapse Sidebar",
|
|
144
|
-
children: [
|
|
145
|
-
collapsed
|
|
146
|
-
? /* @__PURE__ */ jsx(ChevronRight, {
|
|
147
|
-
size: 18,
|
|
148
|
-
className: "shrink-0 mr-auto",
|
|
149
|
-
})
|
|
150
|
-
: /* @__PURE__ */ jsx(ChevronLeft, {
|
|
151
|
-
size: 18,
|
|
152
|
-
className: "shrink-0",
|
|
153
|
-
}),
|
|
154
|
-
!collapsed &&
|
|
155
|
-
/* @__PURE__ */ jsx("span", {
|
|
156
|
-
className: "truncate",
|
|
157
|
-
children: "Collapse",
|
|
158
|
-
}),
|
|
159
|
-
],
|
|
160
|
-
}),
|
|
161
|
-
}),
|
|
162
|
-
],
|
|
163
|
-
}),
|
|
164
|
-
}),
|
|
165
|
-
],
|
|
166
|
-
});
|
|
167
|
-
};
|
|
168
|
-
var sidebar_default = Sidebar;
|
|
169
|
-
export { sidebar_default as default };
|