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,125 @@
1
+ 'use client';
2
+
3
+ import { useState } from 'react';
4
+ import Link from 'next/link';
5
+ import {
6
+ Layout, Typography, Button, Space, Drawer, List, Divider, Grid, theme,
7
+ } from 'antd';
8
+ import {
9
+ MenuOutlined, CloseOutlined, HomeOutlined, GithubOutlined, AppstoreOutlined,
10
+ } from '@ant-design/icons';
11
+
12
+ const { Header, Content, Footer } = Layout;
13
+ const { Text } = Typography;
14
+ const { useBreakpoint } = Grid;
15
+
16
+ export default function ExamplesLayout({ children }: { children: React.ReactNode }) {
17
+ const [mobileOpen, setMobileOpen] = useState(false);
18
+ const screens = useBreakpoint();
19
+ const { token } = theme.useToken();
20
+
21
+ return (
22
+ <Layout style={{ minHeight: '100vh', background: token.colorBgContainer }}>
23
+ {/* Navbar */}
24
+ <Header style={{
25
+ position: 'sticky', top: 0, zIndex: 100,
26
+ background: 'rgba(255,255,255,0.9)', backdropFilter: 'blur(16px)',
27
+ borderBottom: `1px solid ${token.colorBorderSecondary}`,
28
+ display: 'flex', alignItems: 'center', justifyContent: 'space-between',
29
+ padding: '0 24px', height: 64,
30
+ }}>
31
+ <Space>
32
+ <Link href="/" passHref legacyBehavior>
33
+ <div style={{ display: 'flex', alignItems: 'center', gap: 8, cursor: 'pointer' }}>
34
+ <div style={{
35
+ width: 28, height: 28, borderRadius: 6,
36
+ background: token.colorPrimary, display: 'flex',
37
+ alignItems: 'center', justifyContent: 'center',
38
+ }}>
39
+ <Text strong style={{ color: '#fff', fontSize: 14 }}>F</Text>
40
+ </div>
41
+ <Text strong style={{ display: screens.sm ? 'block' : 'none' }}>Nexstruct</Text>
42
+ </div>
43
+ </Link>
44
+ <Divider type="vertical" />
45
+ <Space size={4}>
46
+ <AppstoreOutlined style={{ color: token.colorPrimary, fontSize: 14 }} />
47
+ <Text style={{ color: token.colorPrimary, fontWeight: 500 }}>Components</Text>
48
+ </Space>
49
+ </Space>
50
+
51
+ {screens.md && (
52
+ <Space>
53
+ <Link href="/" passHref legacyBehavior>
54
+ <Button type="text" size="small" icon={<HomeOutlined />}>Home</Button>
55
+ </Link>
56
+ <Button type="text" size="small" icon={<GithubOutlined />} href="https://github.com" target="_blank" />
57
+ </Space>
58
+ )}
59
+
60
+ {!screens.md && (
61
+ <Button type="text" icon={<MenuOutlined />} onClick={() => setMobileOpen(true)} />
62
+ )}
63
+ </Header>
64
+
65
+ {/* Mobile Drawer */}
66
+ <Drawer
67
+ title="Navigate"
68
+ placement="right"
69
+ onClose={() => setMobileOpen(false)}
70
+ open={mobileOpen}
71
+ closeIcon={<CloseOutlined />}
72
+ width={280}
73
+ >
74
+ <List
75
+ dataSource={[
76
+ { label: 'Home', href: '/' },
77
+ { label: 'Components', href: '/examples' },
78
+ ]}
79
+ renderItem={(item) => (
80
+ <List.Item>
81
+ <Link href={item.href} passHref legacyBehavior>
82
+ <Button type="link" onClick={() => setMobileOpen(false)}>
83
+ {item.label}
84
+ </Button>
85
+ </Link>
86
+ </List.Item>
87
+ )}
88
+ />
89
+ </Drawer>
90
+
91
+ {/* Content */}
92
+ <Content style={{ minHeight: 'calc(100vh - 128px)' }}>
93
+ {children}
94
+ </Content>
95
+
96
+ {/* Footer */}
97
+ <Footer style={{
98
+ background: token.colorBgElevated,
99
+ borderTop: `1px solid ${token.colorBorderSecondary}`,
100
+ padding: '16px 24px',
101
+ }}>
102
+ <div style={{
103
+ display: 'flex', justifyContent: 'space-between',
104
+ alignItems: 'center', flexWrap: 'wrap', gap: 8,
105
+ maxWidth: 1200, margin: '0 auto',
106
+ }}>
107
+ <Text type="secondary" style={{ fontSize: 12, opacity: 0.6 }}>
108
+ Ant Design Component System — Scaffolded with Nexstruct
109
+ </Text>
110
+ <Space size="middle">
111
+ <Link href="/" passHref legacyBehavior>
112
+ <Text style={{ fontSize: 12, opacity: 0.6, cursor: 'pointer' }}>Home</Text>
113
+ </Link>
114
+ <Text
115
+ style={{ fontSize: 12, opacity: 0.6, cursor: 'pointer' }}
116
+ onClick={() => window.scrollTo({ top: 0, behavior: 'smooth' })}
117
+ >
118
+ Back to Top
119
+ </Text>
120
+ </Space>
121
+ </div>
122
+ </Footer>
123
+ </Layout>
124
+ );
125
+ }
@@ -0,0 +1,64 @@
1
+ 'use client';
2
+
3
+ import Link from 'next/link';
4
+ import { Card, Row, Col, Typography, Space, theme } from 'antd';
5
+ import {
6
+ FormOutlined, TableOutlined, AppstoreOutlined,
7
+ } from '@ant-design/icons';
8
+
9
+ const { Title, Text, Paragraph } = Typography;
10
+
11
+ const examples = [
12
+ {
13
+ href: '/examples/form',
14
+ title: 'Form Components',
15
+ desc: 'All CustomField field types with react-hook-form validation and Zod schemas.',
16
+ icon: <FormOutlined style={{ fontSize: 40, color: '#1677ff' }} />,
17
+ },
18
+ {
19
+ href: '/examples/table',
20
+ title: 'DynamicTable',
21
+ desc: 'Config-driven table with loading, empty, and checkbox selection states using Ant Design Table.',
22
+ icon: <TableOutlined style={{ fontSize: 40, color: '#13c2c2' }} />,
23
+ },
24
+ {
25
+ href: '/examples/dialog',
26
+ title: 'Dialog, ActionButton & Pagination',
27
+ desc: 'Reusable DialogWrapper, action button variants with tooltips, and Ant Design pagination.',
28
+ icon: <AppstoreOutlined style={{ fontSize: 40, color: '#722ed1' }} />,
29
+ },
30
+ ];
31
+
32
+ export default function ExamplesPage() {
33
+ const { token } = theme.useToken();
34
+
35
+ return (
36
+ <div style={{ padding: 48, maxWidth: 960, margin: '0 auto' }}>
37
+ <div style={{ marginBottom: 32 }}>
38
+ <Title level={2} style={{ fontWeight: 800, margin: 0 }}>Component Examples</Title>
39
+ <Text type="secondary" style={{ fontSize: 16, display: 'block', marginTop: 4 }}>
40
+ Interactive demos of the Ant Design custom component system.
41
+ </Text>
42
+ </div>
43
+ <Row gutter={[24, 24]}>
44
+ {examples.map((ex) => (
45
+ <Col xs={24} sm={12} lg={8} key={ex.href}>
46
+ <Link href={ex.href} passHref legacyBehavior>
47
+ <Card
48
+ hoverable
49
+ style={{ height: '100%', borderRadius: 12, cursor: 'pointer' }}
50
+ styles={{ body: { padding: 24 } }}
51
+ >
52
+ <div style={{ marginBottom: 16 }}>{ex.icon}</div>
53
+ <Title level={4} style={{ fontWeight: 700, margin: 0 }}>{ex.title}</Title>
54
+ <Paragraph type="secondary" style={{ marginTop: 8, lineHeight: 1.7, marginBottom: 0 }}>
55
+ {ex.desc}
56
+ </Paragraph>
57
+ </Card>
58
+ </Link>
59
+ </Col>
60
+ ))}
61
+ </Row>
62
+ </div>
63
+ );
64
+ }
@@ -0,0 +1,118 @@
1
+ 'use client';
2
+
3
+ import { useState } from 'react';
4
+ import { Typography, Space, Tag, theme } from 'antd';
5
+ import { DynamicTable, type TableColumn } from '@/components/common/DynamicTable/dynamic-table.component';
6
+ import { LimitField } from '@/components/common/fields/assets/components/limit-field.component';
7
+ import { ActionButton } from '@/components/common/button/action-button.component';
8
+ import { Pagination } from '@/components/common/pagination/pagination.component';
9
+
10
+ const { Title, Text } = Typography;
11
+
12
+ interface User {
13
+ id: string;
14
+ name: string;
15
+ email: string;
16
+ role: string;
17
+ }
18
+
19
+ const allUsers: User[] = Array.from({ length: 53 }, (_, i) => ({
20
+ id: String(i + 1),
21
+ name: `User ${i + 1}`,
22
+ email: `user${i + 1}@example.com`,
23
+ role: i % 3 === 0 ? 'Admin' : i % 3 === 1 ? 'Editor' : 'Viewer',
24
+ }));
25
+
26
+ const columns: TableColumn[] = [
27
+ { key: 'name', header: 'Name' },
28
+ { key: 'email', header: 'Email' },
29
+ {
30
+ key: 'role',
31
+ header: 'Role',
32
+ render: (item: User) => {
33
+ const color = item.role === 'Admin' ? 'blue' : item.role === 'Editor' ? 'purple' : 'cyan';
34
+ return <Tag color={color} style={{ borderRadius: 6 }}>{item.role}</Tag>;
35
+ },
36
+ },
37
+ ];
38
+
39
+ export default function TableExamplePage() {
40
+ const { token } = theme.useToken();
41
+ const [isLoading, setIsLoading] = useState(false);
42
+ const [currentPage, setCurrentPage] = useState(1);
43
+ const [limit, setLimit] = useState('10');
44
+ const [selectedIds, setSelectedIds] = useState<string[]>([]);
45
+
46
+ const perPage = Number(limit);
47
+ const totalPages = Math.ceil(allUsers.length / perPage);
48
+ const paginatedData = allUsers.slice((currentPage - 1) * perPage, currentPage * perPage);
49
+
50
+ const refresh = () => {
51
+ setIsLoading(true);
52
+ setTimeout(() => setIsLoading(false), 1000);
53
+ };
54
+
55
+ return (
56
+ <div style={{ maxWidth: 960, margin: '0 auto', padding: 32 }}>
57
+ <div style={{ marginBottom: 24 }}>
58
+ <Title level={2} style={{ fontWeight: 800, margin: 0 }}>DynamicTable Demo</Title>
59
+ <Text type="secondary" style={{ fontSize: 15, display: 'block', marginTop: 4 }}>
60
+ Config-driven Ant Design Table with loading state, checkbox selection, and pagination.
61
+ </Text>
62
+ </div>
63
+
64
+ <div style={{
65
+ background: token.colorBgContainer,
66
+ borderRadius: 12,
67
+ border: `1px solid ${token.colorBorderSecondary}`,
68
+ padding: 24,
69
+ }}>
70
+ <div style={{
71
+ display: 'flex', alignItems: 'center',
72
+ justifyContent: 'space-between', marginBottom: 16,
73
+ flexWrap: 'wrap', gap: 12,
74
+ }}>
75
+ <Space size="middle">
76
+ <LimitField
77
+ limit={limit}
78
+ setLimit={(v) => { setLimit(v); setCurrentPage(1); }}
79
+ totalItems={allUsers.length}
80
+ />
81
+ <ActionButton
82
+ buttonContent="Refresh"
83
+ variant="default"
84
+ handleOpen={refresh}
85
+ btnSize="small"
86
+ />
87
+ </Space>
88
+ {selectedIds.length > 0 && (
89
+ <Text type="secondary" style={{ fontSize: 13 }}>
90
+ {selectedIds.length} selected
91
+ </Text>
92
+ )}
93
+ </div>
94
+
95
+ <DynamicTable
96
+ data={paginatedData}
97
+ isLoading={isLoading}
98
+ config={{ columns }}
99
+ isCheckBox
100
+ selectedIds={selectedIds}
101
+ setSelectedIds={setSelectedIds}
102
+ rowKey="id"
103
+ />
104
+
105
+ {totalPages > 1 && (
106
+ <div style={{ marginTop: 20 }}>
107
+ <Pagination
108
+ currentPage={currentPage}
109
+ totalPages={totalPages}
110
+ setCurrentPage={setCurrentPage}
111
+ total={allUsers.length}
112
+ />
113
+ </div>
114
+ )}
115
+ </div>
116
+ </div>
117
+ );
118
+ }
@@ -0,0 +1,283 @@
1
+ 'use client';
2
+
3
+ import { useState } from 'react';
4
+ import Link from 'next/link';
5
+ import {
6
+ Layout, Typography, Button, Space, Card, Row, Col, Divider,
7
+ Tag, Drawer, List, Grid, App, theme,
8
+ } from 'antd';
9
+ import {
10
+ MenuOutlined, CloseOutlined, GithubOutlined,
11
+ ArrowRightOutlined, AppstoreOutlined, FormOutlined,
12
+ TableOutlined, CodeOutlined, StarOutlined,
13
+ } from '@ant-design/icons';
14
+
15
+ const { Header, Content, Footer } = Layout;
16
+ const { Title, Text, Paragraph } = Typography;
17
+ const { useBreakpoint } = Grid;
18
+
19
+ const features = [
20
+ {
21
+ icon: <AppstoreOutlined style={{ fontSize: 32, color: '#1677ff' }} />,
22
+ title: '22 UI Primitives',
23
+ desc: 'Button, Card, Modal, Table, Tabs, Avatar, Select, Switch, Tooltip, Drawer, Dropdown, and more — all pre-styled with Ant Design.',
24
+ color: '#1677ff',
25
+ },
26
+ {
27
+ icon: <FormOutlined style={{ fontSize: 32, color: '#722ed1' }} />,
28
+ title: 'CustomField System',
29
+ desc: '17 field types with dual-mode: react-hook-form integration or standalone value/setValue.',
30
+ color: '#722ed1',
31
+ },
32
+ {
33
+ icon: <TableOutlined style={{ fontSize: 32, color: '#13c2c2' }} />,
34
+ title: 'DynamicTable',
35
+ desc: 'Ant Design Table wrapper with loading states, empty states, and checkbox selection.',
36
+ color: '#13c2c2',
37
+ },
38
+ {
39
+ icon: <CodeOutlined style={{ fontSize: 32, color: '#eb2f96' }} />,
40
+ title: 'Form Validation',
41
+ desc: 'React Hook Form + Zod schema validation with live error messages and form state tracking.',
42
+ color: '#eb2f96',
43
+ },
44
+ ];
45
+
46
+ const techStack = [
47
+ 'Ant Design 5', 'React Hook Form', 'Zod', 'Next.js 15', 'TypeScript',
48
+ '@ant-design/icons', 'dayjs',
49
+ ];
50
+
51
+ const navLinks = [
52
+ { label: 'Home', href: '/' },
53
+ { label: 'Components', href: '/examples' },
54
+ ];
55
+
56
+ export default function Home() {
57
+ const [mobileOpen, setMobileOpen] = useState(false);
58
+ const screens = useBreakpoint();
59
+ const { token } = theme.useToken();
60
+
61
+ return (
62
+ <Layout style={{ minHeight: '100vh', background: token.colorBgContainer }}>
63
+ {/* Navbar */}
64
+ <Header style={{
65
+ position: 'sticky', top: 0, zIndex: 100,
66
+ background: 'rgba(255,255,255,0.9)', backdropFilter: 'blur(16px)',
67
+ borderBottom: `1px solid ${token.colorBorderSecondary}`,
68
+ display: 'flex', alignItems: 'center', justifyContent: 'space-between',
69
+ padding: '0 24px', height: 64,
70
+ }}>
71
+ <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
72
+ <div style={{
73
+ width: 32, height: 32, borderRadius: 6,
74
+ background: token.colorPrimary, display: 'flex',
75
+ alignItems: 'center', justifyContent: 'center',
76
+ }}>
77
+ <Text strong style={{ color: '#fff', fontSize: 16 }}>F</Text>
78
+ </div>
79
+ <Text strong style={{ fontSize: 16, letterSpacing: '-0.02em' }}>Nexstruct</Text>
80
+ </div>
81
+
82
+ {screens.md && (
83
+ <Space size="small">
84
+ {navLinks.map((link) => (
85
+ <Link key={link.href} href={link.href} passHref legacyBehavior>
86
+ <Button type={link.href === '/' ? 'primary' : 'text'} size="small">
87
+ {link.label}
88
+ </Button>
89
+ </Link>
90
+ ))}
91
+ <Divider type="vertical" />
92
+ <Button type="text" icon={<GithubOutlined />} size="small" href="https://github.com" target="_blank" />
93
+ </Space>
94
+ )}
95
+
96
+ {!screens.md && (
97
+ <Button type="text" icon={<MenuOutlined />} onClick={() => setMobileOpen(true)} />
98
+ )}
99
+ </Header>
100
+
101
+ {/* Mobile Drawer */}
102
+ <Drawer
103
+ title="Menu"
104
+ placement="right"
105
+ onClose={() => setMobileOpen(false)}
106
+ open={mobileOpen}
107
+ closeIcon={<CloseOutlined />}
108
+ width={280}
109
+ >
110
+ <List
111
+ dataSource={navLinks}
112
+ renderItem={(link) => (
113
+ <List.Item>
114
+ <Link href={link.href} passHref legacyBehavior>
115
+ <Button type="link" onClick={() => setMobileOpen(false)}>
116
+ {link.label}
117
+ </Button>
118
+ </Link>
119
+ </List.Item>
120
+ )}
121
+ />
122
+ </Drawer>
123
+
124
+ <Content>
125
+ {/* Hero Section */}
126
+ <div style={{
127
+ background: 'linear-gradient(135deg, #141414 0%, #1a1a2e 50%, #16213e 100%)',
128
+ padding: screens.md ? '100px 48px' : '60px 24px',
129
+ textAlign: 'center',
130
+ }}>
131
+ <Space direction="vertical" size="middle" style={{ width: '100%', maxWidth: 720 }}>
132
+ <Space wrap size="small" justify="center">
133
+ <Tag color="blue" style={{ borderRadius: 12 }}>Ant Design 5</Tag>
134
+ <Tag color="purple" style={{ borderRadius: 12 }}>TypeScript</Tag>
135
+ <Tag color="cyan" style={{ borderRadius: 12 }}>Next.js 15</Tag>
136
+ </Space>
137
+ <Title level={1} style={{
138
+ color: '#fff', fontSize: screens.md ? 52 : 32,
139
+ fontWeight: 800, letterSpacing: '-0.03em', margin: 0,
140
+ }}>
141
+ Build Beautiful Apps with{' '}
142
+ <Text style={{
143
+ background: 'linear-gradient(135deg, #1677ff, #9254de)',
144
+ WebkitBackgroundClip: 'text', WebkitTextFillColor: 'transparent',
145
+ }}>
146
+ Ant Design Components
147
+ </Text>
148
+ </Title>
149
+ <Paragraph style={{
150
+ color: 'rgba(255,255,255,0.75)', fontSize: 18,
151
+ maxWidth: 600, margin: '0 auto', lineHeight: 1.6,
152
+ }}>
153
+ A production-ready component system built on Ant Design — with form validation,
154
+ dynamic tables, dialogs, and 22+ UI primitives.
155
+ </Paragraph>
156
+ <Space size="middle" wrap justify="center">
157
+ <Link href="/examples" passHref legacyBehavior>
158
+ <Button type="primary" size="large" icon={<ArrowRightOutlined />}>
159
+ Explore Components
160
+ </Button>
161
+ </Link>
162
+ <Button size="large" ghost icon={<StarOutlined />} href="#features">
163
+ Learn More
164
+ </Button>
165
+ </Space>
166
+ </Space>
167
+ </div>
168
+
169
+ {/* Feature Cards */}
170
+ <div id="features" style={{ padding: screens.md ? '80px 48px' : '48px 24px', scrollMarginTop: 80 }}>
171
+ <div style={{ textAlign: 'center', marginBottom: 48 }}>
172
+ <Title level={2} style={{ fontWeight: 800, margin: 0 }}>What&apos;s Included</Title>
173
+ <Text type="secondary" style={{ fontSize: 16, display: 'block', marginTop: 8 }}>
174
+ A complete component ecosystem — every piece is pre-built, pre-styled, and ready for production.
175
+ </Text>
176
+ <Divider style={{
177
+ width: 80, minWidth: 80, margin: '16px auto',
178
+ borderTopWidth: 3, borderColor: token.colorPrimary,
179
+ borderRadius: 4,
180
+ }} />
181
+ </div>
182
+ <Row gutter={[24, 24]} justify="center">
183
+ {features.map((f) => (
184
+ <Col xs={24} sm={12} lg={6} key={f.title}>
185
+ <Card
186
+ hoverable
187
+ style={{ height: '100%', borderRadius: 12 }}
188
+ styles={{ body: { padding: 24 } }}
189
+ >
190
+ <div style={{ marginBottom: 16 }}>{f.icon}</div>
191
+ <Title level={4} style={{ fontWeight: 700, margin: 0 }}>{f.title}</Title>
192
+ <Paragraph type="secondary" style={{ marginTop: 8, lineHeight: 1.7 }}>
193
+ {f.desc}
194
+ </Paragraph>
195
+ </Card>
196
+ </Col>
197
+ ))}
198
+ </Row>
199
+ </div>
200
+
201
+ {/* Tech Stack */}
202
+ <div style={{
203
+ padding: screens.md ? '64px 48px' : '40px 24px',
204
+ background: token.colorBgLayout,
205
+ }}>
206
+ <div style={{ textAlign: 'center', maxWidth: 600, margin: '0 auto' }}>
207
+ <Title level={3} style={{ fontWeight: 700, margin: 0 }}>Powered By</Title>
208
+ <Text type="secondary" style={{ display: 'block', margin: '8px 0 24px' }}>
209
+ Built on battle-tested libraries you already trust.
210
+ </Text>
211
+ <Space wrap size="small" justify="center">
212
+ {techStack.map((t) => (
213
+ <Tag key={t} style={{ borderRadius: 12, padding: '4px 12px', fontSize: 13 }}>
214
+ {t}
215
+ </Tag>
216
+ ))}
217
+ </Space>
218
+ </div>
219
+ </div>
220
+
221
+ {/* CTA */}
222
+ <div style={{ padding: screens.md ? '80px 48px' : '48px 24px', textAlign: 'center' }}>
223
+ <Title level={2} style={{ fontWeight: 800 }}>Ready to Explore?</Title>
224
+ <Paragraph type="secondary" style={{ fontSize: 16, marginBottom: 32 }}>
225
+ See every component in action — buttons, forms, tables, dialogs, and more.
226
+ </Paragraph>
227
+ <Link href="/examples" passHref legacyBehavior>
228
+ <Button type="primary" size="large" icon={<ArrowRightOutlined />}>
229
+ View Component Showcase
230
+ </Button>
231
+ </Link>
232
+ </div>
233
+ </Content>
234
+
235
+ {/* Footer */}
236
+ <Footer style={{
237
+ background: token.colorBgElevated,
238
+ borderTop: `1px solid ${token.colorBorderSecondary}`,
239
+ padding: '48px 24px 24px',
240
+ }}>
241
+ <Row gutter={[24, 24]} style={{ maxWidth: 1200, margin: '0 auto' }}>
242
+ <Col xs={24} md={12}>
243
+ <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 8 }}>
244
+ <div style={{
245
+ width: 28, height: 28, borderRadius: 6,
246
+ background: token.colorPrimary, display: 'flex',
247
+ alignItems: 'center', justifyContent: 'center',
248
+ }}>
249
+ <Text strong style={{ color: '#fff', fontSize: 14 }}>F</Text>
250
+ </div>
251
+ <Text strong>Nexstruct</Text>
252
+ </div>
253
+ <Text type="secondary" style={{ display: 'block', maxWidth: 360 }}>
254
+ Scaffolding production-ready Next.js applications with composable, framework-specific component systems.
255
+ </Text>
256
+ </Col>
257
+ <Col xs={12} md={6}>
258
+ <Text strong style={{ opacity: 0.5, textTransform: 'uppercase', fontSize: 12, letterSpacing: '0.05em' }}>Navigate</Text>
259
+ <div style={{ marginTop: 8, display: 'flex', flexDirection: 'column', gap: 4 }}>
260
+ {['Home', 'Components', 'GitHub'].map((l) => (
261
+ <Link key={l} href={l === 'Home' ? '/' : l === 'Components' ? '/examples' : '#'} passHref legacyBehavior>
262
+ <Text style={{ cursor: 'pointer' }} type="secondary">{l}</Text>
263
+ </Link>
264
+ ))}
265
+ </div>
266
+ </Col>
267
+ <Col xs={12} md={6}>
268
+ <Text strong style={{ opacity: 0.5, textTransform: 'uppercase', fontSize: 12, letterSpacing: '0.05em' }}>Tech</Text>
269
+ <div style={{ marginTop: 8, display: 'flex', flexDirection: 'column', gap: 4 }}>
270
+ {['Ant Design 5', 'Next.js 15', 'TypeScript', 'React Hook Form'].map((t) => (
271
+ <Text key={t} type="secondary">{t}</Text>
272
+ ))}
273
+ </div>
274
+ </Col>
275
+ </Row>
276
+ <Divider style={{ borderColor: token.colorBorderSecondary, margin: '24px 0 16px' }} />
277
+ <Text type="secondary" style={{ display: 'block', textAlign: 'center', fontSize: 12, opacity: 0.6 }}>
278
+ Scaffolded with Nexstruct — {new Date().getFullYear()}
279
+ </Text>
280
+ </Footer>
281
+ </Layout>
282
+ );
283
+ }
@@ -0,0 +1,79 @@
1
+ 'use client';
2
+
3
+ import { Table, Typography } from 'antd';
4
+ import type { ColumnsType, TableRowSelection } from 'antd/es/table/interface';
5
+
6
+ const { Text } = Typography;
7
+
8
+ export type TableColumn = {
9
+ key: string;
10
+ header: string;
11
+ className?: string;
12
+ render?: (item: any, index: number) => React.ReactNode;
13
+ };
14
+
15
+ export type TableConfig = {
16
+ columns: TableColumn[];
17
+ emptyMessage?: string;
18
+ rowClassName?: (item: any) => string;
19
+ };
20
+
21
+ interface DynamicTableProps {
22
+ isLoading: boolean;
23
+ config: TableConfig;
24
+ data: any[];
25
+ isCheckBox?: boolean;
26
+ selectedIds?: string[];
27
+ setSelectedIds?: (ids: string[]) => void;
28
+ setSelectObject?: (data: any[]) => void;
29
+ rowKey?: string;
30
+ }
31
+
32
+ export function DynamicTable({
33
+ data, isLoading, config, isCheckBox = false,
34
+ selectedIds = [], setSelectedIds = () => {}, setSelectObject = () => {},
35
+ rowKey = 'id',
36
+ }: DynamicTableProps) {
37
+ const columns: ColumnsType<any> = config.columns.map((col) => ({
38
+ key: col.key,
39
+ title: col.header,
40
+ dataIndex: col.key,
41
+ className: col.className,
42
+ render: col.render ? (_val: any, record: any, index: number) => col.render!(record, index) : undefined,
43
+ ellipsis: true,
44
+ }));
45
+
46
+ const rowSelection: TableRowSelection<any> | undefined = isCheckBox
47
+ ? {
48
+ selectedRowKeys: selectedIds,
49
+ onChange: (selectedRowKeys: React.Key[], selectedRows: any[]) => {
50
+ setSelectedIds(selectedRowKeys as string[]);
51
+ setSelectObject(selectedRows);
52
+ },
53
+ preserveSelectedRowKeys: true,
54
+ }
55
+ : undefined;
56
+
57
+ return (
58
+ <div className="antd-dynamic-table">
59
+ <Table
60
+ columns={columns}
61
+ dataSource={data}
62
+ loading={isLoading}
63
+ rowKey={rowKey}
64
+ rowClassName={(record) => config.rowClassName?.(record) || ''}
65
+ rowSelection={rowSelection}
66
+ pagination={false}
67
+ locale={{
68
+ emptyText: isLoading ? null : (
69
+ <div style={{ padding: 48, textAlign: 'center' }}>
70
+ <Text type="secondary">{config.emptyMessage || 'No data available'}</Text>
71
+ </div>
72
+ ),
73
+ }}
74
+ size="middle"
75
+ scroll={{ x: 'max-content' }}
76
+ />
77
+ </div>
78
+ );
79
+ }