@imksh/create 1.0.30 → 1.0.32

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.
Files changed (247) hide show
  1. package/README.md +2 -0
  2. package/package.json +1 -1
  3. package/src/commands/create.js +2 -0
  4. package/src/index.js +1 -1
  5. package/src/utils/askTemplate.js +2 -1
  6. package/templates/layers/electron/base/electron/main.js +262 -0
  7. package/templates/layers/electron/base/electron/preload.js +37 -0
  8. package/templates/layers/electron/base/electron-builder.json5 +68 -0
  9. package/templates/layers/electron/javascript/_gitignore +38 -0
  10. package/templates/layers/electron/javascript/package.json +49 -0
  11. package/templates/layers/electron/javascript/src/components/layout/SidebarLayout.jsx +43 -0
  12. package/templates/layers/electron/javascript/src/components/ui/TitleBar.jsx +130 -0
  13. package/templates/layers/electron/javascript/src/config/appConfig.js +51 -0
  14. package/templates/layers/electron/javascript/src/hooks/useElectron.js +68 -0
  15. package/templates/layers/electron/javascript/src/main.jsx +17 -0
  16. package/templates/layers/electron/javascript/src/store/useUiStore.js +59 -0
  17. package/templates/layers/electron/javascript/vite.config.js +29 -0
  18. package/templates/layers/electron/typescript/_gitignore +38 -0
  19. package/templates/layers/electron/typescript/electron/main.ts +213 -0
  20. package/templates/layers/electron/typescript/electron/preload.ts +52 -0
  21. package/templates/layers/electron/typescript/package.json +52 -0
  22. package/templates/layers/electron/typescript/src/components/layout/SidebarLayout.tsx +42 -0
  23. package/templates/layers/electron/typescript/src/components/ui/TitleBar.tsx +120 -0
  24. package/templates/layers/electron/typescript/src/config/appConfig.ts +52 -0
  25. package/templates/layers/electron/typescript/src/hooks/useElectron.ts +68 -0
  26. package/templates/layers/electron/typescript/src/main.tsx +17 -0
  27. package/templates/layers/electron/typescript/src/store/useUiStore.ts +97 -0
  28. package/templates/layers/electron/typescript/src/vite-env.d.ts +13 -0
  29. package/templates/layers/electron/typescript/tsconfig.json +25 -0
  30. package/templates/layers/electron/typescript/tsconfig.node.json +11 -0
  31. package/templates/layers/electron/typescript/vite.config.ts +29 -0
  32. package/templates/layers/next/javascript/package.json +8 -2
  33. package/templates/layers/next/javascript/src/components/common/Breadcrumbs.jsx +44 -6
  34. package/templates/layers/next/javascript/src/components/common/Loading.jsx +1 -0
  35. package/templates/layers/next/javascript/src/components/common/LottieIcon.jsx +1 -0
  36. package/templates/layers/next/javascript/src/components/common/Pagination.jsx +170 -0
  37. package/templates/layers/next/javascript/src/components/common/SidebarModal.jsx +180 -0
  38. package/templates/layers/next/javascript/src/components/common/StatsCard.jsx +168 -0
  39. package/templates/layers/next/javascript/src/components/common/Table.jsx +191 -41
  40. package/templates/layers/next/javascript/src/components/common/Tabs.jsx +187 -0
  41. package/templates/layers/next/javascript/src/components/common/ToggleSwitch.jsx +4 -3
  42. package/templates/layers/next/javascript/src/components/layout/ProtectedRoute.jsx +2 -1
  43. package/templates/layers/next/javascript/src/components/layout/PublicLayout.jsx +3 -6
  44. package/templates/layers/next/javascript/src/components/layout/SidebarLayout.jsx +4 -17
  45. package/templates/layers/next/javascript/src/components/modals/ConfirmModal.jsx +4 -12
  46. package/templates/layers/next/javascript/src/components/modals/Modal.jsx +50 -19
  47. package/templates/layers/next/javascript/src/components/ui/Input.jsx +50 -0
  48. package/templates/layers/next/{typescript/src/components/ui/sidebar.tsx → javascript/src/components/ui/Sidebar.jsx} +65 -53
  49. package/templates/layers/next/javascript/src/components/ui/SidebarHeader.jsx +11 -6
  50. package/templates/layers/next/javascript/src/config/appConfig.js +4 -4
  51. package/templates/layers/next/javascript/src/hooks/useWindowSize.js +2 -3
  52. package/templates/layers/next/javascript/src/store/useUiStore.js +9 -4
  53. package/templates/layers/next/typescript/.eslintrc.json +12 -0
  54. package/templates/layers/next/typescript/package.json +14 -3
  55. package/templates/layers/next/typescript/src/components/common/Breadcrumbs.tsx +57 -8
  56. package/templates/layers/next/typescript/src/components/common/Loading.tsx +2 -1
  57. package/templates/layers/next/typescript/src/components/common/LottieIcon.tsx +2 -2
  58. package/templates/layers/next/typescript/src/components/common/Pagination.tsx +186 -0
  59. package/templates/layers/next/typescript/src/components/common/SidebarModal.tsx +200 -0
  60. package/templates/layers/next/typescript/src/components/common/StatsCard.tsx +232 -0
  61. package/templates/layers/next/typescript/src/components/common/Table.tsx +205 -39
  62. package/templates/layers/next/typescript/src/components/common/Tabs.tsx +190 -0
  63. package/templates/layers/next/typescript/src/components/common/ToggleSwitch.tsx +12 -8
  64. package/templates/layers/next/typescript/src/components/layout/PublicLayout.tsx +8 -6
  65. package/templates/layers/next/typescript/src/components/layout/SidebarLayout.tsx +8 -17
  66. package/templates/layers/next/typescript/src/components/modals/ConfirmModal.tsx +3 -1
  67. package/templates/layers/next/typescript/src/components/modals/Modal.tsx +67 -21
  68. package/templates/layers/next/typescript/src/components/ui/Button.tsx +1 -0
  69. package/templates/layers/next/typescript/src/components/ui/Header.tsx +2 -2
  70. package/templates/layers/next/typescript/src/components/ui/Input.tsx +40 -60
  71. package/templates/layers/next/{javascript/src/components/ui/sidebar.jsx → typescript/src/components/ui/Sidebar.tsx} +77 -44
  72. package/templates/layers/next/typescript/src/components/ui/SidebarHeader.tsx +16 -10
  73. package/templates/layers/next/typescript/src/config/appConfig.ts +4 -4
  74. package/templates/layers/next/typescript/src/hooks/usePwaInstall.ts +10 -4
  75. package/templates/layers/next/typescript/src/hooks/useWindowSize.ts +2 -3
  76. package/templates/layers/next/typescript/src/services/authService.ts +1 -1
  77. package/templates/layers/next/typescript/src/store/useAuthStore.ts +24 -9
  78. package/templates/layers/next/typescript/src/store/useUiStore.ts +14 -4
  79. package/templates/layers/node/javascript/.env.example +3 -1
  80. package/templates/layers/node/javascript/package.json +12 -3
  81. package/templates/layers/node/javascript/src/app.js +2 -1
  82. package/templates/layers/node/javascript/src/controllers/auth.controller.js +106 -168
  83. package/templates/layers/node/javascript/src/controllers/push.controller.js +51 -58
  84. package/templates/layers/node/javascript/src/controllers/upload.controller.js +12 -19
  85. package/templates/layers/node/javascript/src/middleware/auth.middleware.js +5 -11
  86. package/templates/layers/node/javascript/src/middleware/errorHandler.js +6 -4
  87. package/templates/layers/node/javascript/src/routes/auth.route.js +2 -0
  88. package/templates/layers/node/javascript/src/services/auth.service.js +159 -164
  89. package/templates/layers/node/javascript/src/utils/ApiError.js +20 -0
  90. package/templates/layers/node/javascript/src/utils/SuccessResponse.js +15 -0
  91. package/templates/layers/node/javascript/src/utils/apiResponse.js +4 -0
  92. package/templates/layers/node/javascript/src/utils/asyncHandler.js +5 -0
  93. package/templates/layers/node/typescript/.env.example +3 -1
  94. package/templates/layers/node/typescript/.eslintrc.cjs +28 -0
  95. package/templates/layers/node/typescript/package-lock.json +2 -2
  96. package/templates/layers/node/typescript/package.json +17 -3
  97. package/templates/layers/node/typescript/src/app.ts +3 -2
  98. package/templates/layers/node/typescript/src/config/db.ts +3 -2
  99. package/templates/layers/node/typescript/src/config/socket.ts +5 -4
  100. package/templates/layers/node/typescript/src/controllers/auth.controller.ts +104 -132
  101. package/templates/layers/node/typescript/src/controllers/push.controller.ts +52 -59
  102. package/templates/layers/node/typescript/src/controllers/upload.controller.ts +12 -19
  103. package/templates/layers/node/typescript/src/middleware/auth.middleware.ts +13 -7
  104. package/templates/layers/node/typescript/src/middleware/errorHandler.ts +18 -5
  105. package/templates/layers/node/typescript/src/middleware/rateLimiter.ts +2 -2
  106. package/templates/layers/node/typescript/src/routes/auth.route.ts +2 -0
  107. package/templates/layers/node/typescript/src/services/auth.service.ts +86 -43
  108. package/templates/layers/node/typescript/src/types/express.d.ts +5 -3
  109. package/templates/layers/node/typescript/src/utils/ApiError.ts +25 -0
  110. package/templates/layers/node/typescript/src/utils/SuccessResponse.ts +17 -0
  111. package/templates/layers/node/typescript/src/utils/apiResponse.ts +4 -0
  112. package/templates/layers/node/typescript/src/utils/asyncHandler.ts +13 -0
  113. package/templates/layers/node/typescript/src/utils/cloudinaryUpload.ts +18 -7
  114. package/templates/layers/node/typescript/src/utils/expoNotification.ts +1 -1
  115. package/templates/layers/node/typescript/src/utils/genOtpToken.ts +7 -1
  116. package/templates/layers/node/typescript/src/utils/jwt.ts +8 -2
  117. package/templates/layers/node/typescript/src/utils/logger.ts +2 -1
  118. package/templates/layers/node/typescript/src/utils/pushHelper.ts +13 -9
  119. package/templates/layers/node-prisma/javascript/.env.example +3 -1
  120. package/templates/layers/node-prisma/javascript/package.json +11 -2
  121. package/templates/layers/node-prisma/javascript/src/app.js +2 -1
  122. package/templates/layers/node-prisma/javascript/src/controllers/auth.controller.js +90 -135
  123. package/templates/layers/node-prisma/javascript/src/controllers/push.controller.js +64 -76
  124. package/templates/layers/node-prisma/javascript/src/controllers/upload.controller.js +12 -19
  125. package/templates/layers/node-prisma/javascript/src/middleware/auth.middleware.js +5 -4
  126. package/templates/layers/node-prisma/javascript/src/middleware/errorHandler.js +6 -4
  127. package/templates/layers/node-prisma/javascript/src/routes/auth.route.js +2 -0
  128. package/templates/layers/node-prisma/javascript/src/services/auth.service.js +145 -122
  129. package/templates/layers/node-prisma/javascript/src/utils/ApiError.js +20 -0
  130. package/templates/layers/node-prisma/javascript/src/utils/SuccessResponse.js +15 -0
  131. package/templates/layers/node-prisma/javascript/src/utils/apiResponse.js +4 -0
  132. package/templates/layers/node-prisma/javascript/src/utils/asyncHandler.js +5 -0
  133. package/templates/layers/node-prisma/typescript/.env.example +3 -1
  134. package/templates/layers/node-prisma/typescript/.eslintrc.cjs +28 -0
  135. package/templates/layers/node-prisma/typescript/package.json +19 -5
  136. package/templates/layers/node-prisma/typescript/src/app.ts +3 -2
  137. package/templates/layers/node-prisma/typescript/src/config/prisma.ts +3 -2
  138. package/templates/layers/node-prisma/typescript/src/config/socket.ts +5 -4
  139. package/templates/layers/node-prisma/typescript/src/controllers/auth.controller.ts +89 -105
  140. package/templates/layers/node-prisma/typescript/src/controllers/push.controller.ts +67 -83
  141. package/templates/layers/node-prisma/typescript/src/controllers/upload.controller.ts +12 -19
  142. package/templates/layers/node-prisma/typescript/src/middleware/auth.middleware.ts +9 -13
  143. package/templates/layers/node-prisma/typescript/src/middleware/errorHandler.ts +18 -5
  144. package/templates/layers/node-prisma/typescript/src/middleware/rateLimiter.ts +2 -2
  145. package/templates/layers/node-prisma/typescript/src/routes/auth.route.ts +2 -0
  146. package/templates/layers/node-prisma/typescript/src/services/auth.service.ts +83 -31
  147. package/templates/layers/node-prisma/typescript/src/types/express.d.ts +5 -3
  148. package/templates/layers/node-prisma/typescript/src/utils/ApiError.ts +25 -0
  149. package/templates/layers/node-prisma/typescript/src/utils/SuccessResponse.ts +17 -0
  150. package/templates/layers/node-prisma/typescript/src/utils/apiResponse.ts +4 -0
  151. package/templates/layers/node-prisma/typescript/src/utils/asyncHandler.ts +13 -0
  152. package/templates/layers/node-prisma/typescript/src/utils/cloudinaryUpload.ts +18 -7
  153. package/templates/layers/node-prisma/typescript/src/utils/genOtpToken.ts +7 -1
  154. package/templates/layers/node-prisma/typescript/src/utils/jwt.ts +8 -2
  155. package/templates/layers/node-prisma/typescript/src/utils/logger.ts +2 -1
  156. package/templates/layers/node-prisma/typescript/src/utils/pushHelper.ts +10 -6
  157. package/templates/layers/prisma/javascript/package.json +8 -0
  158. package/templates/layers/prisma/typescript/package.json +14 -1
  159. package/templates/layers/prisma/typescript/prisma/schema.prisma +35 -10
  160. package/templates/layers/prisma/typescript/src/config/db.ts +3 -2
  161. package/templates/layers/react/javascript/package.json +6 -0
  162. package/templates/layers/react/javascript/src/components/common/Breadcrumbs.jsx +62 -58
  163. package/templates/layers/react/javascript/src/components/common/Pagination.jsx +164 -76
  164. package/templates/layers/react/javascript/src/components/common/SidebarModal.jsx +179 -0
  165. package/templates/layers/react/javascript/src/components/common/StatsCard.jsx +167 -0
  166. package/templates/layers/react/javascript/src/components/common/Table.jsx +248 -132
  167. package/templates/layers/react/javascript/src/components/common/Tabs.jsx +164 -112
  168. package/templates/layers/react/javascript/src/components/common/ToggleSwitch.jsx +3 -3
  169. package/templates/layers/react/javascript/src/components/layout/SidebarLayout.jsx +4 -12
  170. package/templates/layers/react/javascript/src/components/modals/Modal.jsx +53 -18
  171. package/templates/layers/react/javascript/src/components/ui/Input.jsx +49 -0
  172. package/templates/layers/react/javascript/src/components/ui/Sidebar.jsx +215 -0
  173. package/templates/layers/react/javascript/src/components/ui/SidebarHeader.jsx +25 -30
  174. package/templates/layers/react/javascript/src/config/appConfig.js +3 -3
  175. package/templates/layers/react/javascript/src/hooks/useWindowSize.js +2 -2
  176. package/templates/layers/react/typescript/.eslintrc.cjs +20 -0
  177. package/templates/layers/react/typescript/package.json +11 -2
  178. package/templates/layers/react/typescript/src/components/common/Breadcrumbs.tsx +32 -6
  179. package/templates/layers/react/typescript/src/components/common/Pagination.tsx +151 -57
  180. package/templates/layers/react/typescript/src/components/common/SidebarModal.tsx +199 -0
  181. package/templates/layers/react/typescript/src/components/common/StatsCard.tsx +231 -0
  182. package/templates/layers/react/typescript/src/components/common/Table.tsx +201 -38
  183. package/templates/layers/react/typescript/src/components/common/Tabs.tsx +56 -12
  184. package/templates/layers/react/typescript/src/components/common/ToggleSwitch.tsx +15 -3
  185. package/templates/layers/react/typescript/src/components/layout/SidebarLayout.tsx +3 -6
  186. package/templates/layers/react/typescript/src/components/modals/Modal.tsx +151 -0
  187. package/templates/layers/react/typescript/src/components/ui/Input.tsx +58 -0
  188. package/templates/layers/react/typescript/src/components/ui/Sidebar.tsx +116 -53
  189. package/templates/layers/react/typescript/src/components/ui/SidebarHeader.tsx +5 -4
  190. package/templates/layers/react/typescript/src/config/appConfig.ts +3 -3
  191. package/templates/layers/react/typescript/src/hooks/useWindowSize.ts +2 -3
  192. package/templates/layers/react/typescript/src/main.tsx +11 -11
  193. package/templates/layers/react/typescript/src/services/authService.ts +1 -1
  194. package/templates/layers/react/typescript/src/store/useAuthStore.ts +24 -9
  195. package/templates/layers/react-native/base/app.json +9 -22
  196. package/templates/layers/react-native/base/eslint.config.js +5 -1
  197. package/templates/layers/react-native/base/package.json +11 -1
  198. package/templates/layers/react-native/base/src/app/(auth)/edit-profile.tsx +7 -7
  199. package/templates/layers/react-native/base/src/app/(auth)/login.tsx +31 -7
  200. package/templates/layers/react-native/base/src/app/(tabs)/_layout.tsx +3 -3
  201. package/templates/layers/react-native/base/src/app/(tabs)/index.tsx +6 -5
  202. package/templates/layers/react-native/base/src/app/_layout.tsx +3 -3
  203. package/templates/layers/react-native/base/src/app/doc-viewer.tsx +3 -3
  204. package/templates/layers/react-native/base/src/components/common/ConfirmationToast.tsx +58 -40
  205. package/templates/layers/react-native/base/src/components/common/GoogleAuthButton.tsx +144 -0
  206. package/templates/layers/react-native/base/src/components/common/LocationLoader.tsx +64 -9
  207. package/templates/layers/react-native/base/src/components/common/Typography.tsx +54 -19
  208. package/templates/layers/react-native/base/src/components/ui/ClassicTabBar.tsx +15 -12
  209. package/templates/layers/react-native/base/src/components/ui/CustomTabBar.tsx +84 -90
  210. package/templates/layers/react-native/base/src/components/ui/Drawer.tsx +344 -0
  211. package/templates/layers/react-native/base/src/components/ui/Sidebar.tsx +4 -4
  212. package/templates/layers/react-native/base/src/components/ui/buttons/Button.tsx +29 -6
  213. package/templates/layers/react-native/base/src/components/ui/data-display/Accordion.tsx +2 -2
  214. package/templates/layers/react-native/base/src/components/ui/data-display/Badge.tsx +1 -2
  215. package/templates/layers/react-native/base/src/components/ui/data-display/Image.tsx +3 -3
  216. package/templates/layers/react-native/base/src/components/ui/data-display/SwipeableRow.tsx +28 -7
  217. package/templates/layers/react-native/base/src/components/ui/feedback/GestureWrapper.tsx +11 -4
  218. package/templates/layers/react-native/base/src/components/ui/inputs/DatePicker.tsx +3 -3
  219. package/templates/layers/react-native/base/src/components/ui/inputs/ImagePickerModal.tsx +45 -19
  220. package/templates/layers/react-native/base/src/components/ui/inputs/Input.tsx +28 -9
  221. package/templates/layers/react-native/base/src/components/ui/inputs/SearchablePicker.tsx +199 -0
  222. package/templates/layers/react-native/base/src/components/ui/inputs/Switch.tsx +7 -7
  223. package/templates/layers/react-native/base/src/components/ui/inputs/WebLocationPicker.tsx +146 -72
  224. package/templates/layers/react-native/base/src/config/api.ts +5 -5
  225. package/templates/layers/react-native/base/src/config/appConfig.ts +1 -1
  226. package/templates/layers/react-native/base/src/services/auth.service.ts +3 -1
  227. package/templates/layers/react-native/base/src/services/permission.service.ts +0 -2
  228. package/templates/layers/react-native/base/src/services/socket.service.ts +0 -7
  229. package/templates/layers/react-native/base/src/store/useAuthStore.ts +61 -16
  230. package/templates/layers/react-native/base/src/store/useNotificationStore.ts +36 -42
  231. package/templates/layers/react-native/base/src/types/images.d.ts +7 -5
  232. package/templates/layers/react-native/base/src/utils/fileDownload.ts +206 -0
  233. package/templates/layers/react-native/base/src/utils/storage.ts +1 -1
  234. package/templates/presets/electron/preset.json +9 -0
  235. package/templates/presets/electron-ts/preset.json +9 -0
  236. package/templates/presets/production-fullstack/overrides/client/package.json +9 -0
  237. package/templates/presets/production-fullstack/overrides/mobile/app.json +2 -15
  238. package/templates/presets/production-fullstack/overrides/mobile/package.json +11 -1
  239. package/templates/presets/production-fullstack/overrides/mobile/src/app/_layout.tsx +3 -3
  240. package/templates/presets/production-fullstack/overrides/mobile/src/components/ui/Drawer.tsx +344 -0
  241. package/templates/presets/production-fullstack/overrides/mobile/src/components/ui/inputs/DatePicker.tsx +3 -3
  242. package/templates/presets/production-fullstack/overrides/mobile/src/components/ui/inputs/ImagePickerModal.tsx +3 -3
  243. package/templates/presets/production-fullstack/overrides/server/package.json +11 -2
  244. package/templates/layers/react/javascript/src/components/ui/sidebar.jsx +0 -169
  245. package/templates/layers/react-native/base/src/components/ui/BottomModal.tsx +0 -176
  246. package/templates/presets/production-fullstack/overrides/mobile/src/components/ui/BottomModal.tsx +0 -159
  247. /package/templates/layers/react-native/base/assets/images/logo/{logoWithBg.png → icon.png} +0 -0
@@ -1,134 +1,186 @@
1
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
1
  import React from "react";
3
2
  import { ChevronDown } from "lucide-react";
4
3
  import { motion } from "framer-motion";
5
- const Tabs = ({
4
+
5
+ export const Tabs = ({
6
6
  tabs,
7
7
  activeTab,
8
8
  onChange,
9
- variant = "underline",
10
- className = "",
9
+ variant = "box",
10
+ className = "bg-base-200 w-fit",
11
11
  dropdown = false,
12
+ disabled = false,
13
+ size = "base",
12
14
  }) => {
13
15
  const [isOpen, setIsOpen] = React.useState(false);
16
+
17
+ const getTabSizeClass = () => {
18
+ switch (size) {
19
+ case "xs":
20
+ return "text-xs px-2.5 h-7 min-h-7";
21
+ case "sm":
22
+ return "text-sm px-3 h-8 min-h-8";
23
+ case "base":
24
+ return "text-base px-4 h-10 min-h-10";
25
+ case "lg":
26
+ return "text-lg px-6 h-12 min-h-12";
27
+ case "xl":
28
+ return "text-xl px-6 h-14 min-h-14";
29
+ case "2xl":
30
+ return "text-2xl px-8 h-16 min-h-16";
31
+ default:
32
+ return "text-base px-4 h-10 min-h-10";
33
+ }
34
+ };
35
+
36
+ const getBtnSizeClass = () => {
37
+ switch (size) {
38
+ case "xs":
39
+ return "btn-xs text-xs";
40
+ case "sm":
41
+ return "btn-sm text-sm";
42
+ case "base":
43
+ return "text-base";
44
+ case "lg":
45
+ return "btn-lg text-lg";
46
+ case "xl":
47
+ return "btn-lg text-xl";
48
+ case "2xl":
49
+ return "btn-lg text-2xl";
50
+ default:
51
+ return "text-base";
52
+ }
53
+ };
54
+
55
+ const tabSizeClass = getTabSizeClass();
56
+ const btnSizeClass = getBtnSizeClass();
57
+
58
+ // Close dropdown if user clicks outside
14
59
  React.useEffect(() => {
15
60
  if (!dropdown || !isOpen) return;
16
61
  const closeMenu = () => setIsOpen(false);
17
62
  document.addEventListener("click", closeMenu);
18
63
  return () => document.removeEventListener("click", closeMenu);
19
64
  }, [dropdown, isOpen]);
65
+
20
66
  const renderDropdown = () => {
21
67
  if (!dropdown) return null;
22
68
  const activeItem = tabs.find((t) => t.id === activeTab);
23
- return /* @__PURE__ */ jsxs("div", {
24
- className: "relative md:hidden w-full max-w-xs z-[50]",
25
- onClick: (e) => e.stopPropagation(),
26
- children: [
27
- /* @__PURE__ */ jsxs("button", {
28
- onClick: () => setIsOpen(!isOpen),
29
- className:
30
- "btn btn-sm bg-base-200 border-base-300 border flex w-full items-center justify-between px-3 text-base-content ",
31
- children: [
32
- /* @__PURE__ */ jsxs("div", {
33
- className: "flex items-center gap-1.5",
34
- children: [
35
- activeItem?.icon,
36
- /* @__PURE__ */ jsx("span", {
37
- className: "font-semibold",
38
- children: activeItem?.label,
39
- }),
40
- ],
41
- }),
42
- /* @__PURE__ */ jsx(ChevronDown, {
43
- size: 14,
44
- className: `opacity-50 transition-transform ${isOpen ? "rotate-180" : ""}`,
45
- }),
46
- ],
47
- }),
48
- isOpen &&
49
- /* @__PURE__ */ jsx("div", {
50
- className:
51
- "absolute top-full left-0 right-0 mt-1 bg-base-100 border border-base-200 shadow rounded-lg py-1 animate-in fade-in slide-in-from-top-2",
52
- children: tabs.map((tab) =>
53
- /* @__PURE__ */ jsxs(
54
- "button",
55
- {
56
- onClick: () => {
57
- onChange(tab.id);
58
- setIsOpen(false);
59
- },
60
- className: `w-full flex items-center gap-2 px-3 py-2 text-sm transition-colors ${activeTab === tab.id ? "bg-primary/10 text-primary font-semibold" : "hover:bg-base-200 text-base-content/80"}`,
61
- children: [tab.icon, tab.label],
62
- },
63
- tab.id,
64
- ),
65
- ),
66
- }),
67
- ],
68
- });
69
+ return (
70
+ <div
71
+ className="relative md:hidden w-full max-w-xs z-[50]"
72
+ onClick={(e) => e.stopPropagation()}
73
+ >
74
+ {/* Trigger Button */}
75
+ <button
76
+ type="button"
77
+ onClick={() => setIsOpen(!isOpen)}
78
+ disabled={disabled}
79
+ className={`btn ${btnSizeClass} bg-base-200 border-base-300 border flex w-full items-center justify-between px-3 text-base-content ${disabled ? "opacity-50 cursor-not-allowed" : ""}`}
80
+ >
81
+ <div className="flex items-center gap-1.5">
82
+ {activeItem?.icon}
83
+ <span className="font-semibold">{activeItem?.label}</span>
84
+ </div>
85
+ <ChevronDown
86
+ size={14}
87
+ className={`opacity-50 transition-transform ${isOpen ? "rotate-180" : ""}`}
88
+ />
89
+ </button>
90
+
91
+ {/* Dropdown Menu */}
92
+ {isOpen && (
93
+ <div className="absolute top-full left-0 right-0 mt-1 bg-base-100 border border-base-200 shadow rounded-lg py-1 animate-in fade-in slide-in-from-top-2">
94
+ {tabs.map((tab) => (
95
+ <button
96
+ key={tab.id}
97
+ onClick={() => {
98
+ onChange(tab.id);
99
+ setIsOpen(false);
100
+ }}
101
+ type="button"
102
+ className={`w-full flex items-center gap-2 px-3 py-2 transition-colors ${size === "base" ? "text-sm" : `text-${size}`} ${
103
+ activeTab === tab.id
104
+ ? "bg-primary/10 text-primary font-semibold"
105
+ : "hover:bg-base-200 text-base-content/80"
106
+ }`}
107
+ >
108
+ {tab.icon}
109
+ {tab.label}
110
+ </button>
111
+ ))}
112
+ </div>
113
+ )}
114
+ </div>
115
+ );
69
116
  };
117
+
70
118
  if (variant === "box") {
71
- return /* @__PURE__ */ jsxs(Fragment, {
72
- children: [
73
- renderDropdown(),
74
- /* @__PURE__ */ jsx("div", {
75
- className: `tabs tabs-boxed bg-base-200 p-1 flex-nowrap overflow-x-auto hide-scrollbar shrink-0 rounded-lg ${dropdown ? "hidden md:flex" : "flex"} ${className}`,
76
- children: tabs.map((tab) =>
77
- /* @__PURE__ */ jsxs(
78
- "button",
79
- {
80
- onClick: () => onChange(tab.id),
81
- className: `tab whitespace-nowrap flex items-center rounded-lg gap-2 relative z-0 ${activeTab === tab.id ? "text-primary-content" : "text-base-content/70 hover:text-base-content"}`,
82
- children: [
83
- activeTab === tab.id &&
84
- /* @__PURE__ */ jsx(motion.div, {
85
- layoutId: "activeTabBox",
86
- className: "absolute inset-0 bg-primary rounded-lg -z-10",
87
- transition: { type: "spring", duration: 0, bounce: 0.2 },
88
- }),
89
- tab.icon,
90
- tab.label,
91
- ],
92
- },
93
- tab.id,
94
- ),
95
- ),
96
- }),
97
- ],
98
- });
119
+ return (
120
+ <>
121
+ {renderDropdown()}
122
+ <div
123
+ className={`tabs tabs-boxed p-1 flex-nowrap overflow-x-auto hide-scrollbar shrink-0 rounded-lg ${dropdown ? "hidden md:flex" : "flex"} ${className}`}
124
+ >
125
+ {tabs.map((tab) => (
126
+ <button
127
+ type="button"
128
+ key={tab.id}
129
+ onClick={() => onChange(tab.id)}
130
+ disabled={disabled}
131
+ className={`tab ${tabSizeClass} whitespace-nowrap flex items-center rounded-lg gap-2 relative z-0 ${
132
+ activeTab === tab.id
133
+ ? "text-primary-content"
134
+ : "text-base-content/70 hover:text-base-content "
135
+ } ${disabled ? "opacity-50 cursor-not-allowed" : ""}`}
136
+ >
137
+ {activeTab === tab.id && (
138
+ <motion.div
139
+ layoutId="activeTabBox"
140
+ className="absolute inset-0 bg-primary rounded-lg -z-10"
141
+ transition={{ type: "spring", duration: 0, bounce: 0.2 }}
142
+ />
143
+ )}
144
+ {tab.icon}
145
+ {tab.label}
146
+ </button>
147
+ ))}
148
+ </div>
149
+ </>
150
+ );
99
151
  }
100
- return /* @__PURE__ */ jsxs(Fragment, {
101
- children: [
102
- renderDropdown(),
103
- /* @__PURE__ */ jsx("div", {
104
- className: `tabs tabs-bordered ${dropdown ? "hidden md:flex" : "flex"} ${className}`,
105
- children: tabs.map((tab) =>
106
- /* @__PURE__ */ jsxs(
107
- "button",
108
- {
109
- onClick: () => onChange(tab.id),
110
- className: `tab whitespace-nowrap relative !border-transparent ${activeTab === tab.id ? "font-semibold text-primary" : "text-base-content/70 hover:text-base-content"}`,
111
- children: [
112
- activeTab === tab.id &&
113
- /* @__PURE__ */ jsx(motion.div, {
114
- layoutId: "activeTabUnderline",
115
- className:
116
- "absolute bottom-0 left-0 right-0 h-0.5 bg-primary",
117
- transition: { type: "spring", duration: 0.5, bounce: 0.2 },
118
- }),
119
- tab.icon &&
120
- /* @__PURE__ */ jsx("span", {
121
- className: "mr-2",
122
- children: tab.icon,
123
- }),
124
- tab.label,
125
- ],
126
- },
127
- tab.id,
128
- ),
129
- ),
130
- }),
131
- ],
132
- });
152
+
153
+ // default: underline
154
+ return (
155
+ <>
156
+ {renderDropdown()}
157
+ <div
158
+ className={`tabs tabs-bordered ${dropdown ? "hidden md:flex" : "flex"} ${className}`}
159
+ >
160
+ {tabs.map((tab) => (
161
+ <button
162
+ type="button"
163
+ key={tab.id}
164
+ onClick={() => onChange(tab.id)}
165
+ disabled={disabled}
166
+ className={`tab ${tabSizeClass} whitespace-nowrap relative !border-transparent ${
167
+ activeTab === tab.id
168
+ ? "font-semibold text-primary"
169
+ : "text-base-content/70 hover:text-base-content"
170
+ } ${disabled ? "opacity-50 cursor-not-allowed" : ""}`}
171
+ >
172
+ {activeTab === tab.id && (
173
+ <motion.div
174
+ layoutId="activeTabUnderline"
175
+ className="absolute bottom-0 left-0 right-0 h-0.5 bg-primary"
176
+ transition={{ type: "spring", duration: 0.5, bounce: 0.2 }}
177
+ />
178
+ )}
179
+ {tab.icon && <span className="mr-2">{tab.icon}</span>}
180
+ {tab.label}
181
+ </button>
182
+ ))}
183
+ </div>
184
+ </>
185
+ );
133
186
  };
134
- export { Tabs };
@@ -1,10 +1,10 @@
1
1
  import React from "react";
2
2
  import { motion } from "motion/react";
3
3
 
4
- const ToggleSwitch = ({ checked, onChange, label }) => {
4
+ const ToggleSwitch = ({ checked, onChange, label, className }) => {
5
5
  return (
6
6
  <div
7
- className="flex items-center gap-3 cursor-pointer select-none w-fit group"
7
+ className={`flex items-center gap-3 cursor-pointer select-none w-fit group ${className}`}
8
8
  onClick={() => onChange(!checked)}
9
9
  >
10
10
  <span className="text-sm font-bold">{label}</span>
@@ -16,7 +16,7 @@ const ToggleSwitch = ({ checked, onChange, label }) => {
16
16
  }`}
17
17
  >
18
18
  <motion.div
19
- className={`w-4 h-4 rounded-full shadow-sm ${
19
+ className={`w-4 h-4 rounded-full shadow ${
20
20
  checked ? "bg-white" : "bg-base-content/40"
21
21
  }`}
22
22
  layout
@@ -1,20 +1,15 @@
1
- import { useEffect } from "react";
2
1
  import { Outlet, useLocation } from "react-router-dom";
3
2
  import SidebarHeader from "../ui/SidebarHeader";
4
- import Sidebar from "../ui/sidebar";
3
+ import Sidebar from "../ui/Sidebar";
5
4
  import { useUiStore } from "../../store/useUiStore";
6
- import appConfig from "../../config/appConfig";
7
5
 
8
6
  const SidebarLayout = () => {
9
7
  const { headerTitle, headerActions, setHeaderTitle, setHeaderActions } =
10
8
  useUiStore();
11
9
  const { pathname } = useLocation();
12
10
 
13
- // Reset header title and actions whenever the route shifts
14
- useEffect(() => {
15
- setHeaderTitle(appConfig.app.name);
16
- setHeaderActions(null);
17
- }, [pathname, setHeaderTitle, setHeaderActions]);
11
+ // Layout no longer resets title on every route change.
12
+ // Individual pages are responsible for setting their own title via useUiStore.
18
13
 
19
14
  return (
20
15
  <div className="flex h-screen overflow-hidden">
@@ -23,10 +18,7 @@ const SidebarLayout = () => {
23
18
  <div className="flex flex-1 flex-col overflow-hidden">
24
19
  <SidebarHeader title={headerTitle} actions={headerActions} />
25
20
 
26
- <main
27
- className="flex-1 h-full overflow-y-auto px-2 py-6 md:p-6 max-w-7xl"
28
- data-lenis-prevent
29
- >
21
+ <main className="flex-1 h-full overflow-y-auto " data-lenis-prevent>
30
22
  <Outlet />
31
23
  </main>
32
24
  </div>
@@ -1,13 +1,19 @@
1
1
  import { useEffect } from "react";
2
2
  import { createPortal } from "react-dom";
3
3
  import { IoClose } from "react-icons/io5";
4
+ import { useUiStore } from "../../store/useUiStore";
4
5
 
5
6
  const sizes = {
6
7
  sm: "max-w-sm",
7
8
  md: "max-w-md",
8
9
  lg: "max-w-lg",
9
- xl: "max-w-2xl",
10
- "2xl": "max-w-4xl",
10
+ xl: "max-w-xl",
11
+ "2xl": "max-w-2xl",
12
+ "3xl": "max-w-3xl",
13
+ "4xl": "max-w-4xl",
14
+ "5xl": "max-w-5xl",
15
+ "6xl": "max-w-6xl",
16
+ "7xl": "max-w-7xl",
11
17
  full: "max-w-7xl",
12
18
  };
13
19
 
@@ -16,12 +22,27 @@ const Modal = ({
16
22
  onClose,
17
23
  title,
18
24
  children,
19
- size = "md",
25
+ size = "4xl",
20
26
  closeOnBackdrop = true,
21
27
  closeOnEsc = true,
22
28
  showCloseButton = true,
29
+ hideHeader = false,
30
+ className = "",
31
+ bodyClass = "p-2 sm:p-4",
23
32
  footer,
33
+ height,
24
34
  }) => {
35
+ const setModalOpen = useUiStore((state) => state.setModalOpen);
36
+
37
+ useEffect(() => {
38
+ if (open) {
39
+ setModalOpen(true);
40
+ return () => {
41
+ setModalOpen(false);
42
+ };
43
+ }
44
+ }, [open, setModalOpen]);
45
+
25
46
  useEffect(() => {
26
47
  if (!open || !closeOnEsc) return;
27
48
 
@@ -33,7 +54,9 @@ const Modal = ({
33
54
 
34
55
  document.addEventListener("keydown", handleKeyDown);
35
56
 
36
- return () => document.removeEventListener("keydown", handleKeyDown);
57
+ return () => {
58
+ document.removeEventListener("keydown", handleKeyDown);
59
+ };
37
60
  }, [open, closeOnEsc, onClose]);
38
61
 
39
62
  if (!open) return null;
@@ -50,35 +73,47 @@ const Modal = ({
50
73
  <div
51
74
  className={`
52
75
  relative
76
+ flex flex-col overflow-hidden max-h-[90vh]
53
77
  w-full
54
78
  ${sizes[size]}
55
79
  rounded-2xl
56
80
  bg-base-100
57
- shadow-2xl
81
+ shadow-md
58
82
  border border-base-300
59
83
  animate-in zoom-in-95 fade-in duration-200
84
+ ${className}
60
85
  `}
86
+ style={height ? { height } : undefined}
61
87
  >
62
88
  {/* Header */}
63
- <div className="flex items-center justify-between border-b border-base-300 px-6 py-4">
64
- <h2 className="text-lg font-bold">{title}</h2>
89
+ {!hideHeader && (title || showCloseButton) && (
90
+ <div className="flex items-center justify-between border-b border-base-300 px-6 py-4 shrink-0">
91
+ {title && <h2 className="text-lg font-bold">{title}</h2>}
65
92
 
66
- {showCloseButton && (
67
- <button
68
- className="btn btn-circle btn-sm btn-ghost"
69
- onClick={onClose}
70
- >
71
- <IoClose size={20} />
72
- </button>
73
- )}
74
- </div>
93
+ {showCloseButton && (
94
+ <button
95
+ className="btn btn-circle btn-sm btn-error btn-soft text-error/70 hover:text-error hover:bg-error/20 hover:shadow-sm hover:rotate-180 transition-transform duration-200"
96
+ onClick={onClose}
97
+ >
98
+ <IoClose size={20} className="" />
99
+ </button>
100
+ )}
101
+ </div>
102
+ )}
75
103
 
76
104
  {/* Body */}
77
- <div className="max-h-[70vh] overflow-y-auto p-6">{children}</div>
105
+ <div
106
+ className={`flex-1 min-h-0 overflow-y-auto ${bodyClass}`}
107
+ data-lenis-prevent="true"
108
+ >
109
+ {children}
110
+ </div>
78
111
 
79
112
  {/* Footer */}
80
113
  {footer && (
81
- <div className="border-t border-base-300 px-6 py-4">{footer}</div>
114
+ <div className="border-t border-base-300 px-6 py-4 shrink-0">
115
+ {footer}
116
+ </div>
82
117
  )}
83
118
  </div>
84
119
  </div>,
@@ -0,0 +1,49 @@
1
+ import React from "react";
2
+ import { X } from "lucide-react";
3
+
4
+ export const Input = React.forwardRef(
5
+ (
6
+ {
7
+ icon,
8
+ wrapperClassName = "",
9
+ onClear,
10
+ className = "",
11
+ value,
12
+ size,
13
+ ...props
14
+ },
15
+ ref,
16
+ ) => {
17
+ const sizeClass = size ? `input-${size}` : "";
18
+ return (
19
+ <div className={`relative ${wrapperClassName}`}>
20
+ {icon && (
21
+ <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">
22
+ {icon}
23
+ </div>
24
+ )}
25
+ <input
26
+ ref={ref}
27
+ value={value}
28
+ className={`input input-bordered w-full ${sizeClass} ${icon ? "pl-10" : ""} ${
29
+ onClear && value ? "pr-10" : ""
30
+ } ${className}`}
31
+ {...props}
32
+ />
33
+
34
+ {onClear && value && (
35
+ <button
36
+ type="button"
37
+ onClick={onClear}
38
+ 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"
39
+ aria-label="Clear input"
40
+ >
41
+ <X size={16} />
42
+ </button>
43
+ )}
44
+ </div>
45
+ );
46
+ },
47
+ );
48
+
49
+ Input.displayName = "Input";