nexstruct 1.0.0

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 (229) hide show
  1. package/AGENTS.md +122 -0
  2. package/LICENSE +21 -0
  3. package/README.md +103 -0
  4. package/package.json +99 -0
  5. package/scaffold/generator.js +409 -0
  6. package/scaffold/index.js +20 -0
  7. package/scaffold/prompts.js +108 -0
  8. package/templates/api/axios/src/api/axios/client.api.ts +30 -0
  9. package/templates/api/axios/src/api/axios/users.api.ts +15 -0
  10. package/templates/api/fetch/src/api/fetch/client.api.ts +68 -0
  11. package/templates/api/fetch/src/api/fetch/users.api.ts +15 -0
  12. package/templates/api/trpc/src/api/trpc/client.api.ts +4 -0
  13. package/templates/api/trpc/src/api/trpc/router.api.ts +15 -0
  14. package/templates/api/trpc/src/api/trpc/server.client.api.ts +4 -0
  15. package/templates/api/trpc/src/providers/trpc.provider.tsx +24 -0
  16. package/templates/auth/clerk/src/auth/clerk/auth.service.ts +4 -0
  17. package/templates/auth/clerk/src/hooks/use-auth.hook.ts +13 -0
  18. package/templates/auth/clerk/src/middleware.ts +7 -0
  19. package/templates/auth/clerk/src/providers/auth.provider.tsx +6 -0
  20. package/templates/auth/next-auth/src/app/api/auth/[...nextauth]/route.ts +5 -0
  21. package/templates/auth/next-auth/src/auth/next-auth/auth.service.ts +45 -0
  22. package/templates/auth/next-auth/src/hooks/use-session.hook.ts +13 -0
  23. package/templates/auth/next-auth/src/providers/session.provider.tsx +6 -0
  24. package/templates/forms/formik/src/components/forms/login-form.component.tsx +30 -0
  25. package/templates/forms/formik/src/forms/formik/hooks/use-form-config.hook.ts +7 -0
  26. package/templates/forms/formik/src/forms/formik/schemas/example.schema.ts +8 -0
  27. package/templates/forms/react-hook-form/src/components/forms/login-form.component.tsx +27 -0
  28. package/templates/forms/react-hook-form/src/forms/react-hook-form/hooks/use-form.hook.ts +13 -0
  29. package/templates/forms/react-hook-form/src/forms/react-hook-form/schemas/example.schema.ts +15 -0
  30. package/templates/nextjs-base/next.config.ts +5 -0
  31. package/templates/nextjs-base/postcss.config.mjs +9 -0
  32. package/templates/nextjs-base/src/app/_components/navbar.tsx +88 -0
  33. package/templates/nextjs-base/src/app/_components/sidebar.tsx +223 -0
  34. package/templates/nextjs-base/src/app/error.tsx +39 -0
  35. package/templates/nextjs-base/src/app/globals.css +71 -0
  36. package/templates/nextjs-base/src/app/layout.tsx +21 -0
  37. package/templates/nextjs-base/src/app/loading.tsx +13 -0
  38. package/templates/nextjs-base/src/app/not-found.tsx +22 -0
  39. package/templates/nextjs-base/src/app/page.tsx +10 -0
  40. package/templates/nextjs-base/tailwind.config.ts +69 -0
  41. package/templates/shared/src/components/common/theme-toggle.component.tsx +31 -0
  42. package/templates/shared/src/components/common/toast/custom-message.component.tsx +18 -0
  43. package/templates/shared/src/components/common/toast/index.ts +8 -0
  44. package/templates/shared/src/components/common/toast/toast-message.component.tsx +112 -0
  45. package/templates/shared/src/hooks/use-debounce.hook.ts +12 -0
  46. package/templates/shared/src/hooks/use-fetch.hook.ts +42 -0
  47. package/templates/shared/src/hooks/use-intersection-observer.hook.ts +39 -0
  48. package/templates/shared/src/hooks/use-local-storage.hook.ts +30 -0
  49. package/templates/shared/src/hooks/use-media-query.hook.ts +26 -0
  50. package/templates/shared/src/hooks/use-toggle.hook.ts +12 -0
  51. package/templates/shared/src/lib/utils.util.ts +361 -0
  52. package/templates/shared/src/providers/theme.provider.tsx +17 -0
  53. package/templates/shared/src/providers/toast.provider.tsx +32 -0
  54. package/templates/shared/src/types/common.type.ts +34 -0
  55. package/templates/state/context/src/store/context/auth.context.tsx +47 -0
  56. package/templates/state/context/src/store/context/counter.context.tsx +41 -0
  57. package/templates/state/context/src/store/context/index.ts +2 -0
  58. package/templates/state/redux/src/providers/redux.provider.tsx +7 -0
  59. package/templates/state/redux/src/store/redux/hooks.store.ts +5 -0
  60. package/templates/state/redux/src/store/redux/index.ts +4 -0
  61. package/templates/state/redux/src/store/redux/slices/api.slice.ts +8 -0
  62. package/templates/state/redux/src/store/redux/slices/counter.slice.ts +24 -0
  63. package/templates/state/redux/src/store/redux/store.store.ts +13 -0
  64. package/templates/state/zustand/src/store/zustand/counter.store.ts +15 -0
  65. package/templates/state/zustand/src/store/zustand/index.ts +2 -0
  66. package/templates/state/zustand/src/store/zustand/user.store.ts +32 -0
  67. package/templates/ui/antd/COMPONENT_GUIDE.md +326 -0
  68. package/templates/ui/antd/src/app/examples/dialog/page.tsx +205 -0
  69. package/templates/ui/antd/src/app/examples/form/page.tsx +160 -0
  70. package/templates/ui/antd/src/app/examples/layout.tsx +125 -0
  71. package/templates/ui/antd/src/app/examples/page.tsx +64 -0
  72. package/templates/ui/antd/src/app/examples/table/page.tsx +118 -0
  73. package/templates/ui/antd/src/app/page.tsx +283 -0
  74. package/templates/ui/antd/src/components/common/DynamicTable/dynamic-table.component.tsx +79 -0
  75. package/templates/ui/antd/src/components/common/button/action-button.component.tsx +63 -0
  76. package/templates/ui/antd/src/components/common/dialog/dialog-wrapper.component.tsx +63 -0
  77. package/templates/ui/antd/src/components/common/fields/assets/components/check-field.component.tsx +55 -0
  78. package/templates/ui/antd/src/components/common/fields/assets/components/date-picker-field.component.tsx +80 -0
  79. package/templates/ui/antd/src/components/common/fields/assets/components/limit-field.component.tsx +26 -0
  80. package/templates/ui/antd/src/components/common/fields/assets/components/multi-check-field.component.tsx +56 -0
  81. package/templates/ui/antd/src/components/common/fields/assets/components/number-field.component.tsx +100 -0
  82. package/templates/ui/antd/src/components/common/fields/assets/components/otp-field.component.tsx +63 -0
  83. package/templates/ui/antd/src/components/common/fields/assets/components/password-field.component.tsx +106 -0
  84. package/templates/ui/antd/src/components/common/fields/assets/components/phone-number-field.component.tsx +78 -0
  85. package/templates/ui/antd/src/components/common/fields/assets/components/radio-field.component.tsx +55 -0
  86. package/templates/ui/antd/src/components/common/fields/assets/components/range-date-picker.component.tsx +66 -0
  87. package/templates/ui/antd/src/components/common/fields/assets/components/search-field.component.tsx +24 -0
  88. package/templates/ui/antd/src/components/common/fields/assets/components/select-field.component.tsx +82 -0
  89. package/templates/ui/antd/src/components/common/fields/assets/components/single-check-field.component.tsx +50 -0
  90. package/templates/ui/antd/src/components/common/fields/assets/components/single-select-field.component.tsx +86 -0
  91. package/templates/ui/antd/src/components/common/fields/assets/components/string-number-field.component.tsx +80 -0
  92. package/templates/ui/antd/src/components/common/fields/assets/components/switch-field.component.tsx +62 -0
  93. package/templates/ui/antd/src/components/common/fields/assets/components/text-area-field.component.tsx +85 -0
  94. package/templates/ui/antd/src/components/common/fields/assets/components/text-field.component.tsx +88 -0
  95. package/templates/ui/antd/src/components/common/fields/assets/interface/input-props.type.ts +233 -0
  96. package/templates/ui/antd/src/components/common/fields/cusInputField.component.tsx +40 -0
  97. package/templates/ui/antd/src/components/common/pagination/pagination.component.tsx +27 -0
  98. package/templates/ui/antd/src/components/ui/avatar.component.tsx +8 -0
  99. package/templates/ui/antd/src/components/ui/badge.component.tsx +8 -0
  100. package/templates/ui/antd/src/components/ui/button.component.tsx +8 -0
  101. package/templates/ui/antd/src/components/ui/card.component.tsx +8 -0
  102. package/templates/ui/antd/src/components/ui/checkbox.component.tsx +8 -0
  103. package/templates/ui/antd/src/components/ui/dialog.component.tsx +9 -0
  104. package/templates/ui/antd/src/components/ui/dropdown-menu.component.tsx +10 -0
  105. package/templates/ui/antd/src/components/ui/form.component.tsx +12 -0
  106. package/templates/ui/antd/src/components/ui/input.component.tsx +13 -0
  107. package/templates/ui/antd/src/components/ui/label.component.tsx +18 -0
  108. package/templates/ui/antd/src/components/ui/popover.component.tsx +8 -0
  109. package/templates/ui/antd/src/components/ui/progress.component.tsx +8 -0
  110. package/templates/ui/antd/src/components/ui/radio-group.component.tsx +10 -0
  111. package/templates/ui/antd/src/components/ui/scroll-area.component.tsx +25 -0
  112. package/templates/ui/antd/src/components/ui/select.component.tsx +8 -0
  113. package/templates/ui/antd/src/components/ui/separator.component.tsx +8 -0
  114. package/templates/ui/antd/src/components/ui/sheet.component.tsx +8 -0
  115. package/templates/ui/antd/src/components/ui/switch.component.tsx +8 -0
  116. package/templates/ui/antd/src/components/ui/table.component.tsx +8 -0
  117. package/templates/ui/antd/src/components/ui/tabs.component.tsx +8 -0
  118. package/templates/ui/antd/src/components/ui/textarea.component.tsx +9 -0
  119. package/templates/ui/antd/src/components/ui/tooltip.component.tsx +8 -0
  120. package/templates/ui/antd/src/lib/theme.util.ts +40 -0
  121. package/templates/ui/antd/src/providers/antd.provider.tsx +13 -0
  122. package/templates/ui/mui/src/app/examples/layout.tsx +113 -0
  123. package/templates/ui/mui/src/app/examples/page.tsx +716 -0
  124. package/templates/ui/mui/src/app/page.tsx +298 -0
  125. package/templates/ui/mui/src/components/common/DynamicTable/dynamic-table.component.tsx +131 -0
  126. package/templates/ui/mui/src/components/common/button/action-button.component.tsx +57 -0
  127. package/templates/ui/mui/src/components/common/dialog/dialog-wrapper.component.tsx +55 -0
  128. package/templates/ui/mui/src/components/common/fields/assets/components/check-field.component.tsx +51 -0
  129. package/templates/ui/mui/src/components/common/fields/assets/components/date-picker-field.component.tsx +50 -0
  130. package/templates/ui/mui/src/components/common/fields/assets/components/multi-check-field.component.tsx +14 -0
  131. package/templates/ui/mui/src/components/common/fields/assets/components/number-field.component.tsx +59 -0
  132. package/templates/ui/mui/src/components/common/fields/assets/components/password-field.component.tsx +87 -0
  133. package/templates/ui/mui/src/components/common/fields/assets/components/phone-number-field.component.tsx +48 -0
  134. package/templates/ui/mui/src/components/common/fields/assets/components/radio-field.component.tsx +37 -0
  135. package/templates/ui/mui/src/components/common/fields/assets/components/search-field.component.tsx +41 -0
  136. package/templates/ui/mui/src/components/common/fields/assets/components/select-field.component.tsx +77 -0
  137. package/templates/ui/mui/src/components/common/fields/assets/components/single-check-field.component.tsx +39 -0
  138. package/templates/ui/mui/src/components/common/fields/assets/components/single-select-field.component.tsx +56 -0
  139. package/templates/ui/mui/src/components/common/fields/assets/components/string-number-field.component.tsx +52 -0
  140. package/templates/ui/mui/src/components/common/fields/assets/components/switch-field.component.tsx +35 -0
  141. package/templates/ui/mui/src/components/common/fields/assets/components/text-area-field.component.tsx +46 -0
  142. package/templates/ui/mui/src/components/common/fields/assets/components/text-field.component.tsx +51 -0
  143. package/templates/ui/mui/src/components/common/fields/assets/interface/input-props.type.ts +193 -0
  144. package/templates/ui/mui/src/components/common/fields/cusInputField.component.tsx +34 -0
  145. package/templates/ui/mui/src/components/common/pagination/pagination.component.tsx +59 -0
  146. package/templates/ui/mui/src/components/ui/avatar.component.tsx +19 -0
  147. package/templates/ui/mui/src/components/ui/badge.component.tsx +18 -0
  148. package/templates/ui/mui/src/components/ui/button.component.tsx +22 -0
  149. package/templates/ui/mui/src/components/ui/card.component.tsx +39 -0
  150. package/templates/ui/mui/src/components/ui/checkbox.component.tsx +21 -0
  151. package/templates/ui/mui/src/components/ui/dialog.component.tsx +38 -0
  152. package/templates/ui/mui/src/components/ui/dropdown-menu.component.tsx +43 -0
  153. package/templates/ui/mui/src/components/ui/form.component.tsx +98 -0
  154. package/templates/ui/mui/src/components/ui/input.component.tsx +15 -0
  155. package/templates/ui/mui/src/components/ui/label.component.tsx +15 -0
  156. package/templates/ui/mui/src/components/ui/popover.component.tsx +20 -0
  157. package/templates/ui/mui/src/components/ui/progress.component.tsx +19 -0
  158. package/templates/ui/mui/src/components/ui/radio-group.component.tsx +25 -0
  159. package/templates/ui/mui/src/components/ui/scroll-area.component.tsx +27 -0
  160. package/templates/ui/mui/src/components/ui/select.component.tsx +26 -0
  161. package/templates/ui/mui/src/components/ui/separator.component.tsx +11 -0
  162. package/templates/ui/mui/src/components/ui/sheet.component.tsx +44 -0
  163. package/templates/ui/mui/src/components/ui/switch.component.tsx +23 -0
  164. package/templates/ui/mui/src/components/ui/table.component.tsx +34 -0
  165. package/templates/ui/mui/src/components/ui/tabs.component.tsx +38 -0
  166. package/templates/ui/mui/src/components/ui/textarea.component.tsx +18 -0
  167. package/templates/ui/mui/src/components/ui/tooltip.component.tsx +24 -0
  168. package/templates/ui/mui/src/lib/theme.util.ts +73 -0
  169. package/templates/ui/mui/src/providers/mui.provider.tsx +13 -0
  170. package/templates/ui/shadcn/COMPONENT_GUIDE.md +306 -0
  171. package/templates/ui/shadcn/src/app/examples/dialog/page.tsx +122 -0
  172. package/templates/ui/shadcn/src/app/examples/form/page.tsx +107 -0
  173. package/templates/ui/shadcn/src/app/examples/layout.tsx +24 -0
  174. package/templates/ui/shadcn/src/app/examples/page.tsx +30 -0
  175. package/templates/ui/shadcn/src/app/examples/table/page.tsx +77 -0
  176. package/templates/ui/shadcn/src/app/page.tsx +20 -0
  177. package/templates/ui/shadcn/src/components/common/DynamicTable/dynamic-table.component.tsx +136 -0
  178. package/templates/ui/shadcn/src/components/common/button/action-button.component.tsx +68 -0
  179. package/templates/ui/shadcn/src/components/common/dialog/dialog-wrapper.component.tsx +58 -0
  180. package/templates/ui/shadcn/src/components/common/fields/assets/components/check-field.component.tsx +52 -0
  181. package/templates/ui/shadcn/src/components/common/fields/assets/components/date-picker-field.component.tsx +62 -0
  182. package/templates/ui/shadcn/src/components/common/fields/assets/components/dynamic-file-upload-field.component.tsx +152 -0
  183. package/templates/ui/shadcn/src/components/common/fields/assets/components/limit-field.component.tsx +73 -0
  184. package/templates/ui/shadcn/src/components/common/fields/assets/components/multi-check-field.component.tsx +46 -0
  185. package/templates/ui/shadcn/src/components/common/fields/assets/components/number-field.component.tsx +124 -0
  186. package/templates/ui/shadcn/src/components/common/fields/assets/components/otp-field.component.tsx +61 -0
  187. package/templates/ui/shadcn/src/components/common/fields/assets/components/password-field.component.tsx +110 -0
  188. package/templates/ui/shadcn/src/components/common/fields/assets/components/phone-number-field.component.tsx +90 -0
  189. package/templates/ui/shadcn/src/components/common/fields/assets/components/radio-field.component.tsx +41 -0
  190. package/templates/ui/shadcn/src/components/common/fields/assets/components/range-date-picker.component.tsx +71 -0
  191. package/templates/ui/shadcn/src/components/common/fields/assets/components/rich-text-editor.component.tsx +91 -0
  192. package/templates/ui/shadcn/src/components/common/fields/assets/components/search-field.component.tsx +34 -0
  193. package/templates/ui/shadcn/src/components/common/fields/assets/components/select-field.component.tsx +231 -0
  194. package/templates/ui/shadcn/src/components/common/fields/assets/components/single-check-field.component.tsx +42 -0
  195. package/templates/ui/shadcn/src/components/common/fields/assets/components/single-select-field.component.tsx +82 -0
  196. package/templates/ui/shadcn/src/components/common/fields/assets/components/string-number-field.component.tsx +68 -0
  197. package/templates/ui/shadcn/src/components/common/fields/assets/components/switch-field.component.tsx +61 -0
  198. package/templates/ui/shadcn/src/components/common/fields/assets/components/text-area-field.component.tsx +62 -0
  199. package/templates/ui/shadcn/src/components/common/fields/assets/components/text-area-with-file.component.tsx +142 -0
  200. package/templates/ui/shadcn/src/components/common/fields/assets/components/text-field.component.tsx +80 -0
  201. package/templates/ui/shadcn/src/components/common/fields/assets/components/tiny-editor.component.tsx +51 -0
  202. package/templates/ui/shadcn/src/components/common/fields/assets/components/upload-profile-picture.component.tsx +103 -0
  203. package/templates/ui/shadcn/src/components/common/fields/assets/components/upload-video-file.component.tsx +86 -0
  204. package/templates/ui/shadcn/src/components/common/fields/assets/interface/input-props.type.ts +198 -0
  205. package/templates/ui/shadcn/src/components/common/fields/cusInputField.component.tsx +52 -0
  206. package/templates/ui/shadcn/src/components/common/pagination/pagination.component.tsx +68 -0
  207. package/templates/ui/shadcn/src/components/ui/avatar.component.tsx +37 -0
  208. package/templates/ui/shadcn/src/components/ui/badge.component.tsx +28 -0
  209. package/templates/ui/shadcn/src/components/ui/button.component.tsx +52 -0
  210. package/templates/ui/shadcn/src/components/ui/card.component.tsx +46 -0
  211. package/templates/ui/shadcn/src/components/ui/checkbox.component.tsx +25 -0
  212. package/templates/ui/shadcn/src/components/ui/dialog.component.tsx +98 -0
  213. package/templates/ui/shadcn/src/components/ui/dropdown-menu.component.tsx +163 -0
  214. package/templates/ui/shadcn/src/components/ui/form.component.tsx +110 -0
  215. package/templates/ui/shadcn/src/components/ui/input-otp.component.tsx +64 -0
  216. package/templates/ui/shadcn/src/components/ui/input.component.tsx +23 -0
  217. package/templates/ui/shadcn/src/components/ui/label.component.tsx +23 -0
  218. package/templates/ui/shadcn/src/components/ui/popover.component.tsx +27 -0
  219. package/templates/ui/shadcn/src/components/ui/progress.component.tsx +22 -0
  220. package/templates/ui/shadcn/src/components/ui/radio-group.component.tsx +33 -0
  221. package/templates/ui/shadcn/src/components/ui/scroll-area.component.tsx +37 -0
  222. package/templates/ui/shadcn/src/components/ui/select.component.tsx +139 -0
  223. package/templates/ui/shadcn/src/components/ui/separator.component.tsx +23 -0
  224. package/templates/ui/shadcn/src/components/ui/sheet.component.tsx +89 -0
  225. package/templates/ui/shadcn/src/components/ui/switch.component.tsx +26 -0
  226. package/templates/ui/shadcn/src/components/ui/table.component.tsx +71 -0
  227. package/templates/ui/shadcn/src/components/ui/tabs.component.tsx +52 -0
  228. package/templates/ui/shadcn/src/components/ui/textarea.component.tsx +20 -0
  229. package/templates/ui/shadcn/src/components/ui/tooltip.component.tsx +25 -0
@@ -0,0 +1,25 @@
1
+ 'use client';
2
+ import MuiRadioGroup, { RadioGroupProps as MuiRadioGroupProps } from '@mui/material/RadioGroup';
3
+ import MuiRadio from '@mui/material/Radio';
4
+ import FormControlLabel from '@mui/material/FormControlLabel';
5
+ import FormControl from '@mui/material/FormControl';
6
+ import { styled } from '@mui/material/styles';
7
+
8
+ const StyledRadio = styled(MuiRadio)(({ theme }) => ({
9
+ color: theme.palette.text.secondary,
10
+ '&.Mui-checked': {
11
+ color: theme.palette.primary.main,
12
+ },
13
+ }));
14
+
15
+ export type RadioGroupProps = MuiRadioGroupProps;
16
+
17
+ export function RadioGroup(props: RadioGroupProps) {
18
+ return <MuiRadioGroup {...props} />;
19
+ }
20
+
21
+ export const RadioGroupItem = StyledRadio;
22
+
23
+ export function RadioItem({ label, ...props }: { label?: React.ReactNode; value: string }) {
24
+ return <FormControlLabel control={<StyledRadio {...props} />} label={label} />;
25
+ }
@@ -0,0 +1,27 @@
1
+ 'use client';
2
+ import Box from '@mui/material/Box';
3
+ import { styled } from '@mui/material/styles';
4
+
5
+ const ScrollAreaRoot = styled(Box)({
6
+ overflow: 'auto',
7
+ position: 'relative',
8
+ '&::-webkit-scrollbar': {
9
+ width: 8,
10
+ height: 8,
11
+ },
12
+ '&::-webkit-scrollbar-track': {
13
+ backgroundColor: 'transparent',
14
+ },
15
+ '&::-webkit-scrollbar-thumb': {
16
+ backgroundColor: 'rgba(0,0,0,0.2)',
17
+ borderRadius: 4,
18
+ },
19
+ });
20
+
21
+ export type ScrollAreaProps = { children: React.ReactNode; className?: string };
22
+
23
+ export function ScrollArea({ children, ...props }: ScrollAreaProps) {
24
+ return <ScrollAreaRoot {...props}>{children}</ScrollAreaRoot>;
25
+ }
26
+
27
+ export const ScrollBar = Box;
@@ -0,0 +1,26 @@
1
+ 'use client';
2
+ import MuiSelect, { SelectProps as MuiSelectProps } from '@mui/material/Select';
3
+ import MenuItem from '@mui/material/MenuItem';
4
+ import FormControl from '@mui/material/FormControl';
5
+ import InputLabel from '@mui/material/InputLabel';
6
+ import { styled } from '@mui/material/styles';
7
+
8
+ const StyledSelect = styled(MuiSelect)(({ theme }) => ({
9
+ borderRadius: theme.shape.borderRadius,
10
+ '& .MuiOutlinedInput-notchedOutline': {
11
+ borderRadius: theme.shape.borderRadius,
12
+ },
13
+ }));
14
+
15
+ export type SelectProps = MuiSelectProps;
16
+
17
+ export function Select(props: SelectProps) {
18
+ return <StyledSelect {...props} />;
19
+ }
20
+
21
+ export const SelectItem = MenuItem;
22
+ export const SelectGroup = FormControl;
23
+ export const SelectLabel = InputLabel;
24
+ export const SelectValue = MuiSelect;
25
+ export const SelectTrigger = StyledSelect;
26
+ export const SelectContent = ({ children, ...props }: { children: React.ReactNode } & Record<string, any>) => <>{children}</>;
@@ -0,0 +1,11 @@
1
+ 'use client';
2
+ import Divider from '@mui/material/Divider';
3
+
4
+ export type SeparatorProps = {
5
+ orientation?: 'horizontal' | 'vertical';
6
+ className?: string;
7
+ };
8
+
9
+ export function Separator({ orientation = 'horizontal', ...props }: SeparatorProps) {
10
+ return <Divider orientation={orientation === 'vertical' ? 'vertical' : 'horizontal'} {...props} />;
11
+ }
@@ -0,0 +1,44 @@
1
+ 'use client';
2
+ import MuiDrawer, { DrawerProps as MuiDrawerProps } from '@mui/material/Drawer';
3
+ import Box from '@mui/material/Box';
4
+ import IconButton from '@mui/material/IconButton';
5
+ import CloseIcon from '@mui/icons-material/Close';
6
+ import Typography from '@mui/material/Typography';
7
+ import { styled } from '@mui/material/styles';
8
+
9
+ const StyledSheet = styled(MuiDrawer)(({ theme }) => ({
10
+ '& .MuiDrawer-paper': {
11
+ borderRadius: 0,
12
+ },
13
+ }));
14
+
15
+ export type SheetProps = MuiDrawerProps;
16
+
17
+ export function Sheet(props: SheetProps) {
18
+ return <StyledSheet {...props} />;
19
+ }
20
+
21
+ export const SheetTrigger = ({ children, onClick }: { children: React.ReactNode; onClick?: () => void }) => <>{children}</>;
22
+ export const SheetClose = CloseIcon;
23
+ export const SheetPortal = Box;
24
+
25
+ export function SheetContent({ children, onClose, title, ...props }: SheetProps & { title?: string }) {
26
+ return (
27
+ <StyledSheet {...props} onClose={onClose}>
28
+ <Box sx={{ p: 2, display: 'flex', alignItems: 'center', justifyContent: 'space-between', borderBottom: 1, borderColor: 'divider' }}>
29
+ {title && <Typography variant="h6">{title}</Typography>}
30
+ {onClose && (
31
+ <IconButton onClick={() => onClose({}, 'escapeKeyDown')}>
32
+ <CloseIcon />
33
+ </IconButton>
34
+ )}
35
+ </Box>
36
+ <Box sx={{ p: 2 }}>{children}</Box>
37
+ </StyledSheet>
38
+ );
39
+ }
40
+
41
+ export const SheetHeader = Box;
42
+ export const SheetFooter = Box;
43
+ export const SheetTitle = Typography;
44
+ export const SheetDescription = Typography;
@@ -0,0 +1,23 @@
1
+ 'use client';
2
+ import MuiSwitch, { SwitchProps as MuiSwitchProps } from '@mui/material/Switch';
3
+ import FormControlLabel from '@mui/material/FormControlLabel';
4
+ import { styled } from '@mui/material/styles';
5
+
6
+ const StyledSwitch = styled(MuiSwitch)(({ theme }) => ({
7
+ '& .MuiSwitch-switchBase.Mui-checked': {
8
+ color: theme.palette.primary.main,
9
+ },
10
+ '& .MuiSwitch-switchBase.Mui-checked + .MuiSwitch-track': {
11
+ backgroundColor: theme.palette.primary.main,
12
+ },
13
+ }));
14
+
15
+ export type SwitchProps = MuiSwitchProps;
16
+
17
+ export function Switch(props: SwitchProps) {
18
+ return <StyledSwitch {...props} />;
19
+ }
20
+
21
+ export function SwitchLabel({ label, ...props }: SwitchProps & { label?: React.ReactNode }) {
22
+ return <FormControlLabel control={<Switch {...props} />} label={label} />;
23
+ }
@@ -0,0 +1,34 @@
1
+ 'use client';
2
+ import MuiTable, { TableProps as MuiTableProps } from '@mui/material/Table';
3
+ import MuiTableBody from '@mui/material/TableBody';
4
+ import MuiTableCell from '@mui/material/TableCell';
5
+ import MuiTableContainer from '@mui/material/TableContainer';
6
+ import MuiTableHead from '@mui/material/TableHead';
7
+ import MuiTableRow from '@mui/material/TableRow';
8
+ import MuiTableFooter from '@mui/material/TableFooter';
9
+ import MuiTablePagination from '@mui/material/TablePagination';
10
+ import Paper from '@mui/material/Paper';
11
+ import { styled } from '@mui/material/styles';
12
+
13
+ const StyledTableContainer = styled(MuiTableContainer)(({ theme }) => ({
14
+ borderRadius: theme.shape.borderRadius,
15
+ border: `1px solid ${theme.palette.divider}`,
16
+ }));
17
+
18
+ export type TableProps = MuiTableProps;
19
+
20
+ export function Table({ children, ...props }: TableProps) {
21
+ return (
22
+ <StyledTableContainer component={Paper}>
23
+ <MuiTable {...props}>{children}</MuiTable>
24
+ </StyledTableContainer>
25
+ );
26
+ }
27
+
28
+ export const TableHeader = MuiTableHead;
29
+ export const TableBody = MuiTableBody;
30
+ export const TableFooter = MuiTableFooter;
31
+ export const TableRow = MuiTableRow;
32
+ export const TableHead = MuiTableCell;
33
+ export const TableCell = MuiTableCell;
34
+ export const TableCaption = MuiTablePagination;
@@ -0,0 +1,38 @@
1
+ 'use client';
2
+ import MuiTabs, { TabsProps as MuiTabsProps } from '@mui/material/Tabs';
3
+ import MuiTab, { TabProps as MuiTabProps } from '@mui/material/Tab';
4
+ import Box from '@mui/material/Box';
5
+ import { styled } from '@mui/material/styles';
6
+
7
+ const StyledTabs = styled(MuiTabs)(({ theme }) => ({
8
+ '& .MuiTabs-indicator': {
9
+ backgroundColor: theme.palette.primary.main,
10
+ },
11
+ }));
12
+
13
+ const StyledTab = styled(MuiTab)(({ theme }) => ({
14
+ textTransform: 'none',
15
+ fontWeight: 500,
16
+ borderRadius: theme.shape.borderRadius,
17
+ '&.Mui-selected': {
18
+ color: theme.palette.primary.main,
19
+ },
20
+ }));
21
+
22
+ export type TabsProps = MuiTabsProps;
23
+ export type TabProps = MuiTabProps;
24
+
25
+ export function Tabs(props: TabsProps) {
26
+ return <StyledTabs {...props} />;
27
+ }
28
+
29
+ export const TabsList = StyledTabs;
30
+ export const TabsTrigger = StyledTab;
31
+
32
+ export function TabsContent({ children, value, ...props }: { children: React.ReactNode; value: any } & Record<string, any>) {
33
+ return (
34
+ <Box role="tabpanel" {...props}>
35
+ {children}
36
+ </Box>
37
+ );
38
+ }
@@ -0,0 +1,18 @@
1
+ 'use client';
2
+ import MuiTextField, { TextFieldProps as MuiTextFieldProps } from '@mui/material/TextField';
3
+ import { styled } from '@mui/material/styles';
4
+
5
+ const StyledTextarea = styled(MuiTextField)(({ theme }) => ({
6
+ '& .MuiOutlinedInput-root': {
7
+ borderRadius: theme.shape.borderRadius,
8
+ },
9
+ '& textarea': {
10
+ minHeight: 80,
11
+ },
12
+ }));
13
+
14
+ export type TextareaProps = MuiTextFieldProps;
15
+
16
+ export function Textarea(props: TextareaProps) {
17
+ return <StyledTextarea variant="outlined" fullWidth multiline {...props} />;
18
+ }
@@ -0,0 +1,24 @@
1
+ 'use client';
2
+ import MuiTooltip, { TooltipProps as MuiTooltipProps } from '@mui/material/Tooltip';
3
+ import { styled } from '@mui/material/styles';
4
+
5
+ const StyledTooltip = styled(MuiTooltip)({
6
+ '& .MuiTooltip-tooltip': {
7
+ fontSize: '0.75rem',
8
+ padding: '6px 12px',
9
+ },
10
+ });
11
+
12
+ export type TooltipProps = MuiTooltipProps;
13
+ export type TooltipProviderProps = { children: React.ReactNode };
14
+
15
+ export function TooltipProvider({ children }: TooltipProviderProps) {
16
+ return <>{children}</>;
17
+ }
18
+
19
+ export function Tooltip(props: TooltipProps) {
20
+ return <StyledTooltip {...props} />;
21
+ }
22
+
23
+ export const TooltipTrigger = ({ children, ...props }: { children: React.ReactElement } & Record<string, any>) => children;
24
+ export const TooltipContent = MuiTooltip;
@@ -0,0 +1,73 @@
1
+ 'use client';
2
+ import { createTheme } from '@mui/material/styles';
3
+
4
+ export const theme = createTheme({
5
+ colorSchemes: {
6
+ light: {
7
+ palette: {
8
+ primary: { main: '#2563eb' },
9
+ secondary: { main: '#64748b' },
10
+ error: { main: '#dc2626' },
11
+ warning: { main: '#f59e0b' },
12
+ success: { main: '#16a34a' },
13
+ info: { main: '#0ea5e9' },
14
+ },
15
+ },
16
+ dark: {
17
+ palette: {
18
+ primary: { main: '#60a5fa' },
19
+ secondary: { main: '#94a3b8' },
20
+ error: { main: '#f87171' },
21
+ warning: { main: '#fbbf24' },
22
+ success: { main: '#4ade80' },
23
+ info: { main: '#38bdf8' },
24
+ },
25
+ },
26
+ },
27
+ shape: { borderRadius: 8 },
28
+ typography: {
29
+ fontFamily: '"Inter", "Roboto", "Helvetica", "Arial", sans-serif',
30
+ },
31
+ components: {
32
+ MuiButton: {
33
+ styleOverrides: {
34
+ root: {
35
+ textTransform: 'none',
36
+ borderRadius: 8,
37
+ fontWeight: 500,
38
+ },
39
+ },
40
+ },
41
+ MuiTextField: {
42
+ styleOverrides: {
43
+ root: {
44
+ '& .MuiOutlinedInput-root': {
45
+ borderRadius: 8,
46
+ },
47
+ },
48
+ },
49
+ },
50
+ MuiCard: {
51
+ styleOverrides: {
52
+ root: {
53
+ borderRadius: 8,
54
+ },
55
+ },
56
+ },
57
+ MuiDialog: {
58
+ styleOverrides: {
59
+ paper: {
60
+ borderRadius: 8,
61
+ },
62
+ },
63
+ },
64
+ MuiChip: {
65
+ styleOverrides: {
66
+ root: {
67
+ fontWeight: 600,
68
+ fontSize: '0.75rem',
69
+ },
70
+ },
71
+ },
72
+ },
73
+ });
@@ -0,0 +1,13 @@
1
+ 'use client';
2
+ import { ThemeProvider } from '@mui/material/styles';
3
+ import CssBaseline from '@mui/material/CssBaseline';
4
+ import { theme } from '@/lib/theme.util';
5
+
6
+ export function MuiProvider({ children }: { children: React.ReactNode }) {
7
+ return (
8
+ <ThemeProvider theme={theme}>
9
+ <CssBaseline />
10
+ {children}
11
+ </ThemeProvider>
12
+ );
13
+ }
@@ -0,0 +1,306 @@
1
+ # Custom Component System — Usage Guide
2
+
3
+ This project includes a reusable, dynamic component system built on shadcn/ui + react-hook-form + zod. Every component follows a **dual-mode** pattern: works with or without react-hook-form.
4
+
5
+ ---
6
+
7
+ ## 1. CustomField — Dynamic Form Fields
8
+
9
+ A compound object (`CustomField.*`) that registers all field types. Each field auto-wraps in shadcn `<FormField>` when given a `form` prop, or renders standalone with `value`/`setValue`.
10
+
11
+ ### Available Fields
12
+
13
+ | Component | Usage |
14
+ |-----------|-------|
15
+ | `CustomField.Text` | Single-line text with optional left/right icons, array input |
16
+ | `CustomField.TextArea` | Multi-line text with configurable rows |
17
+ | `CustomField.Number` | Number input (integer/float) |
18
+ | `CustomField.StringNumber` | Numeric string (digits only, e.g. roll number, PIN) |
19
+ | `CustomField.Password` | Password with show/hide toggle |
20
+ | `CustomField.SingleSelectField` | Single-select dropdown (wraps shadcn Select) |
21
+ | `CustomField.SelectField` | Advanced select with search, single/multiple, images, flags |
22
+ | `CustomField.Switch` | Toggle switch with optional border/label/description |
23
+ | `CustomField.RadioField` | Radio group from options array |
24
+ | `CustomField.CheckField` | Multi-checkbox group from options array |
25
+ | `CustomField.MultiCheckField` | Alternative multi-checkbox (same as CheckField) |
26
+ | `CustomField.SingleCheckField` | Single checkbox with optional description |
27
+ | `CustomField.SearchField` | Search input with clear button |
28
+ | `CustomField.DatePickerField` | Native date picker input |
29
+ | `CustomField.PhoneNumber` | Telephone input (`type="tel"`) |
30
+
31
+ ### Shared Props (all fields)
32
+
33
+ | Prop | Type | Default | Description |
34
+ |------|------|---------|-------------|
35
+ | `form` | `UseFormReturn` | — | react-hook-form instance (omit for standalone) |
36
+ | `name` | `string` | — | Field name in form schema |
37
+ | `labelName` | `string` | — | Visible label text |
38
+ | `required` | `boolean` | `false` | Shows red asterisk |
39
+ | `disabled` | `boolean` | `false` | Disables input |
40
+ | `viewOnly` | `boolean` | `false` | Renders plain text instead of input |
41
+ | `disableLabelFormatting` | `boolean` | `false` | Skip auto-formatting of label text |
42
+ | `customMessage` | `string\|ReactNode` | — | Custom message below field |
43
+ | `placeholder` | `string` | — | Placeholder text |
44
+
45
+ ### With react-hook-form (controlled)
46
+
47
+ ```tsx
48
+ import { useForm } from 'react-hook-form';
49
+ import { zodResolver } from '@hookform/resolvers/zod';
50
+ import { z } from 'zod';
51
+ import { Form } from '@/components/ui/form.component';
52
+ import { CustomField } from '@/components/common/fields/cusInputField.component';
53
+
54
+ const schema = z.object({
55
+ name: z.string().min(1, 'Required'),
56
+ email: z.string().email('Invalid email'),
57
+ role: z.string().min(1),
58
+ });
59
+
60
+ export function UserForm() {
61
+ const form = useForm({ resolver: zodResolver(schema) });
62
+
63
+ return (
64
+ <Form {...form}>
65
+ <form onSubmit={form.handleSubmit(console.log)} className="space-y-4">
66
+ <CustomField.Text form={form} name="name" labelName="Full Name" required />
67
+ <CustomField.Text
68
+ form={form}
69
+ name="email"
70
+ labelName="Email"
71
+ placeholder="Enter email"
72
+ leftIcon={<MailIcon />}
73
+ />
74
+ <CustomField.SingleSelectField
75
+ form={form}
76
+ name="role"
77
+ labelName="Role"
78
+ options={['admin', 'user', 'editor']}
79
+ />
80
+ <Button type="submit">Submit</Button>
81
+ </form>
82
+ </Form>
83
+ );
84
+ }
85
+ ```
86
+
87
+ ### Standalone (uncontrolled)
88
+
89
+ ```tsx
90
+ const [email, setEmail] = useState('');
91
+
92
+ <CustomField.Text
93
+ name="email"
94
+ labelName="Email"
95
+ value={email}
96
+ setValue={setEmail}
97
+ placeholder="Enter email"
98
+ />
99
+ ```
100
+
101
+ ---
102
+
103
+ ## 2. DynamicTable — Config-Driven Table
104
+
105
+ Renders a table from a `columns` config array, with loading/empty states, optional checkboxes, and expandable rows.
106
+
107
+ ```tsx
108
+ import { DynamicTable } from '@/components/common/DynamicTable/dynamic-table.component';
109
+
110
+ const columns = [
111
+ { key: 'name', header: 'Name' },
112
+ { key: 'email', header: 'Email' },
113
+ {
114
+ key: 'status',
115
+ header: 'Status',
116
+ render: (row) => (
117
+ <Badge variant={row.active ? 'default' : 'secondary'}>
118
+ {row.active ? 'Active' : 'Inactive'}
119
+ </Badge>
120
+ ),
121
+ },
122
+ {
123
+ key: 'actions',
124
+ header: '',
125
+ render: (row) => (
126
+ <ActionButton
127
+ variant="outline"
128
+ buttonContent="Edit"
129
+ handleOpen={() => handleEdit(row)}
130
+ />
131
+ ),
132
+ },
133
+ ];
134
+
135
+ <DynamicTable
136
+ data={users}
137
+ isLoading={loading}
138
+ currentPage={page}
139
+ setCurrentPage={setPage}
140
+ config={{ columns, emptyMessage: 'No users found' }}
141
+ />
142
+ ```
143
+
144
+ ### With checkbox selection
145
+
146
+ ```tsx
147
+ const [selected, setSelected] = useState<string[]>([]);
148
+
149
+ <DynamicTable
150
+ data={users}
151
+ isLoading={loading}
152
+ currentPage={page}
153
+ setCurrentPage={setPage}
154
+ config={{ columns }}
155
+ isCheckBox
156
+ selectedIds={selected}
157
+ setSelectedIds={setSelected}
158
+ />
159
+ ```
160
+
161
+ ---
162
+
163
+ ## 3. DialogWrapper — Reusable Modal
164
+
165
+ A scrollable dialog with sticky header, optional close button, and optional footer.
166
+
167
+ ```tsx
168
+ import { DialogWrapper } from '@/components/common/dialog/dialog-wrapper.component';
169
+
170
+ const [open, setOpen] = useState(false);
171
+
172
+ <DialogWrapper
173
+ open={open}
174
+ setOpen={setOpen}
175
+ title="Edit User"
176
+ description="Update user details"
177
+ triggerContent={<Button>Open Dialog</Button>}
178
+ footer={<Button type="submit">Save</Button>}
179
+ >
180
+ <Form {...form}>
181
+ <form onSubmit={form.handleSubmit(onSubmit)}>
182
+ <CustomField.Text form={form} name="name" labelName="Name" required />
183
+ </form>
184
+ </Form>
185
+ </DialogWrapper>
186
+ ```
187
+
188
+ ### Controlled from parent
189
+
190
+ ```tsx
191
+ // Parent passes open/setOpen
192
+ <DialogWrapper open={modalOpen} setOpen={setModalOpen}>
193
+ <UserForm ... />
194
+ </DialogWrapper>
195
+ ```
196
+
197
+ ### Without trigger content
198
+
199
+ ```tsx
200
+ // Dialog opened programmatically
201
+ const [open, setOpen] = useState(true); // starts open
202
+
203
+ <DialogWrapper open={open} setOpen={setOpen}>
204
+ <p>This dialog has no trigger button.</p>
205
+ </DialogWrapper>
206
+ ```
207
+
208
+ ---
209
+
210
+ ## 4. ActionButton — Extended Button
211
+
212
+ A button with variant, icon positions, loading spinner, and optional tooltip.
213
+
214
+ ```tsx
215
+ import { ActionButton } from '@/components/common/button/action-button.component';
216
+
217
+ // Simple
218
+ <ActionButton buttonContent="Save" handleOpen={handleSave} />
219
+
220
+ // With tooltip
221
+ <ActionButton
222
+ variant="outline"
223
+ icon={<EditIcon />}
224
+ buttonContent="Edit"
225
+ tooltipContent="Edit this item"
226
+ handleOpen={() => setEditOpen(true)}
227
+ />
228
+
229
+ // Loading state
230
+ <ActionButton
231
+ buttonContent="Submit"
232
+ isPending={isSubmitting}
233
+ loadingContent="Saving..."
234
+ type="submit"
235
+ />
236
+
237
+ // With left icon only
238
+ <ActionButton icon={<PlusIcon />} buttonContent="Add User" variant="default" />
239
+
240
+ // Destructive
241
+ <ActionButton buttonContent="Delete" variant="destructive" handleOpen={handleDelete} />
242
+ ```
243
+
244
+ ---
245
+
246
+ ## 5. Pagination — Page Navigation
247
+
248
+ ```tsx
249
+ import { Pagination } from '@/components/common/pagination/pagination.component';
250
+
251
+ <Pagination
252
+ currentPage={page}
253
+ totalPages={totalPages}
254
+ setCurrentPage={setPage}
255
+ />
256
+ ```
257
+
258
+ ---
259
+
260
+ ## 6. Form Pattern (recommended)
261
+
262
+ ```tsx
263
+ import { useForm } from 'react-hook-form';
264
+ import { zodResolver } from '@hookform/resolvers/zod';
265
+ import { z } from 'zod';
266
+ import { Form } from '@/components/ui/form';
267
+ import { Button } from '@/components/ui/button';
268
+ import { CustomField } from '@/components/common/fields/cusInputField';
269
+
270
+ // 1. Define schema
271
+ const formSchema = z.object({
272
+ title: z.string().min(1, 'Title is required'),
273
+ description: z.string().optional(),
274
+ category: z.string().min(1, 'Select a category'),
275
+ published: z.boolean().default(false),
276
+ });
277
+
278
+ type FormData = z.infer<typeof formSchema>;
279
+
280
+ // 2. Create form
281
+ const form = useForm<FormData>({
282
+ resolver: zodResolver(formSchema),
283
+ defaultValues: { title: '', published: false },
284
+ });
285
+
286
+ // 3. Render
287
+ <Form {...form}>
288
+ <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6">
289
+ <CustomField.Text form={form} name="title" labelName="Title" required />
290
+ <CustomField.TextArea form={form} name="description" labelName="Description" rows={5} />
291
+ <CustomField.SingleSelectField
292
+ form={form}
293
+ name="category"
294
+ labelName="Category"
295
+ options={['tech', 'design', 'business']}
296
+ />
297
+ <CustomField.Switch
298
+ form={form}
299
+ name="published"
300
+ labelName="Publish"
301
+ description="Make this visible to everyone"
302
+ />
303
+ <Button type="submit" disabled={isPending}>Save</Button>
304
+ </form>
305
+ </Form>
306
+ ```