create-ej-app 3.2.0 → 5.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 (316) hide show
  1. package/LICENSE +1 -1
  2. package/cli.js +5 -1
  3. package/cli.ts +40 -33
  4. package/package.json +4 -4
  5. package/template/base/.env.example +10 -9
  6. package/template/base/.eslintrc.cjs +17 -15
  7. package/template/base/components.json +1 -1
  8. package/template/base/drizzle.config.ts +11 -0
  9. package/template/base/next.config.mjs +1 -12
  10. package/template/base/package.json +63 -56
  11. package/template/base/postcss.config.mjs +8 -0
  12. package/template/base/prettier.config.mjs +11 -0
  13. package/template/base/public/vercel.svg +1 -0
  14. package/template/base/src/app/(app)/dashboard/layout.tsx +14 -0
  15. package/template/base/src/app/(app)/dashboard/page.tsx +0 -7
  16. package/template/base/src/app/(app)/layout.tsx +55 -20
  17. package/template/base/src/app/(app)/roles/[id]/actions.ts +59 -0
  18. package/template/base/src/app/(app)/roles/[id]/page.tsx +46 -0
  19. package/template/base/src/app/(app)/roles/[id]/render.tsx +264 -0
  20. package/template/base/src/app/(app)/roles/[id]/validation.ts +22 -0
  21. package/template/base/src/app/(app)/roles/actions.ts +33 -0
  22. package/template/base/src/app/(app)/roles/page.tsx +52 -0
  23. package/template/base/src/app/(app)/roles/render.tsx +80 -0
  24. package/template/base/src/app/(app)/settings/actions.ts +11 -12
  25. package/template/base/src/app/(app)/settings/layout.tsx +14 -0
  26. package/template/base/src/app/(app)/settings/page.tsx +1 -10
  27. package/template/base/src/app/(app)/settings/render.tsx +11 -17
  28. package/template/base/src/app/(app)/settings/validation.ts +5 -0
  29. package/template/base/src/app/(app)/tasks/[id]/actions.ts +69 -124
  30. package/template/base/src/app/(app)/tasks/[id]/page.tsx +37 -3
  31. package/template/base/src/app/(app)/tasks/[id]/render.tsx +162 -93
  32. package/template/base/src/app/(app)/tasks/[id]/validation.ts +18 -0
  33. package/template/base/src/app/(app)/tasks/actions.ts +34 -64
  34. package/template/base/src/app/(app)/tasks/page.tsx +15 -9
  35. package/template/base/src/app/(app)/tasks/render.tsx +28 -6
  36. package/template/base/src/app/(app)/tasks/statusEnum.ts +3 -0
  37. package/template/base/src/app/(app)/users/[id]/actions.ts +47 -62
  38. package/template/base/src/app/(app)/users/[id]/page.tsx +15 -8
  39. package/template/base/src/app/(app)/users/[id]/render.tsx +119 -34
  40. package/template/base/src/app/(app)/users/[id]/validation.ts +18 -0
  41. package/template/base/src/app/(app)/users/actions.ts +28 -49
  42. package/template/base/src/app/(app)/users/page.tsx +22 -9
  43. package/template/base/src/app/(app)/users/render.tsx +47 -3
  44. package/template/base/src/app/(auth)/layout.tsx +7 -0
  45. package/template/base/src/app/(auth)/login/page.tsx +2 -2
  46. package/template/base/src/app/(auth)/login/render.tsx +146 -0
  47. package/template/base/src/app/(marketing)/layout.tsx +1 -1
  48. package/template/base/src/app/(marketing)/page.tsx +8 -7
  49. package/template/base/src/app/favicon.ico +0 -0
  50. package/template/base/src/app/layout.tsx +14 -17
  51. package/template/base/src/components/app-nav-command.tsx +18 -0
  52. package/template/base/src/components/data-table/data-table-column-header.tsx +2 -2
  53. package/template/base/src/components/icons.tsx +21 -5
  54. package/template/base/src/components/ui/alert-dialog.tsx +1 -1
  55. package/template/base/src/components/ui/command.tsx +1 -1
  56. package/template/base/src/components/ui/dialog.tsx +1 -1
  57. package/template/base/src/components/ui/sonner.tsx +31 -0
  58. package/template/base/src/components/user-avatar.tsx +4 -2
  59. package/template/base/src/data-access/resource.ts +85 -0
  60. package/template/base/src/data-access/role-permission.ts +45 -0
  61. package/template/base/src/data-access/role.ts +105 -0
  62. package/template/base/src/data-access/task.ts +141 -0
  63. package/template/base/src/data-access/user.ts +141 -0
  64. package/template/base/src/db/index.ts +14 -0
  65. package/template/base/src/db/schema.ts +287 -0
  66. package/template/base/src/env.mjs +10 -30
  67. package/template/base/src/hooks/use-lock-body.tsx +2 -1
  68. package/template/base/src/lib/auth.ts +32 -23
  69. package/template/base/src/lib/currentUser.ts +8 -0
  70. package/template/base/src/lib/s3Client.ts +156 -0
  71. package/template/base/src/lib/safe-action.ts +19 -0
  72. package/template/base/src/lib/sortOrderEnum.ts +2 -0
  73. package/template/base/src/use-case/role-permission.ts +19 -0
  74. package/template/base/src/use-case/role.ts +110 -0
  75. package/template/base/src/use-case/task.ts +166 -0
  76. package/template/base/src/use-case/user.ts +121 -0
  77. package/template/base/tailwind.config.ts +5 -4
  78. package/template/base/tsconfig.json +3 -2
  79. package/template/new/.env.example +13 -0
  80. package/template/new/components.json +22 -0
  81. package/template/new/drizzle.config.ts +10 -0
  82. package/template/new/eslint.config.mjs +18 -0
  83. package/template/new/next.config.ts +14 -0
  84. package/template/new/package.json +81 -0
  85. package/template/new/postcss.config.mjs +5 -0
  86. package/template/new/prettier.config.mjs +11 -0
  87. package/template/new/public/placeholder.svg +1 -0
  88. package/template/new/src/app/(auth)/login/email-login-form.tsx +97 -0
  89. package/template/new/src/app/(auth)/login/page.tsx +72 -0
  90. package/template/new/src/app/(auth)/login/social-login-buttons.tsx +69 -0
  91. package/template/new/src/app/api/auth/[...all]/route.ts +4 -0
  92. package/template/new/src/app/favicon.ico +0 -0
  93. package/template/new/src/app/globals.css +128 -0
  94. package/template/new/src/app/layout.tsx +50 -0
  95. package/template/new/src/app/page.tsx +3 -0
  96. package/template/new/src/components/loader.tsx +25 -0
  97. package/template/new/src/components/react-query-provider.tsx +12 -0
  98. package/template/new/src/components/screen-size.tsx +40 -0
  99. package/template/new/src/components/theme-toggle.tsx +22 -0
  100. package/template/new/src/components/ui/button.tsx +60 -0
  101. package/template/new/src/components/ui/card.tsx +92 -0
  102. package/template/new/src/components/ui/form.tsx +167 -0
  103. package/template/new/src/components/ui/input.tsx +21 -0
  104. package/template/new/src/components/ui/label.tsx +24 -0
  105. package/template/new/src/components/ui/separator.tsx +28 -0
  106. package/template/new/src/components/ui/sonner.tsx +40 -0
  107. package/template/new/src/db/index.ts +7 -0
  108. package/template/new/src/db/schema.ts +74 -0
  109. package/template/new/src/env.ts +42 -0
  110. package/template/new/src/lib/auth-client.ts +18 -0
  111. package/template/new/src/lib/auth.ts +67 -0
  112. package/template/new/src/lib/safe-action.ts +15 -0
  113. package/template/new/src/lib/toast-message.ts +15 -0
  114. package/template/new/tsconfig.json +49 -0
  115. package/template/prisma/.env.example +16 -0
  116. package/template/prisma/.eslintrc.cjs +24 -0
  117. package/template/prisma/components.json +17 -0
  118. package/template/prisma/next.config.mjs +15 -0
  119. package/template/prisma/package.json +80 -0
  120. package/template/prisma/public/next.svg +1 -0
  121. package/template/prisma/src/app/(app)/dashboard/page.tsx +19 -0
  122. package/template/prisma/src/app/(app)/layout.tsx +90 -0
  123. package/template/prisma/src/app/(app)/settings/actions.ts +18 -0
  124. package/template/prisma/src/app/(app)/settings/loading.tsx +28 -0
  125. package/template/prisma/src/app/(app)/settings/page.tsx +28 -0
  126. package/template/prisma/src/app/(app)/settings/render.tsx +113 -0
  127. package/template/prisma/src/app/(app)/tasks/[id]/actions.ts +147 -0
  128. package/template/prisma/src/app/(app)/tasks/[id]/page.tsx +25 -0
  129. package/template/prisma/src/app/(app)/tasks/[id]/render.tsx +413 -0
  130. package/template/prisma/src/app/(app)/tasks/actions.ts +69 -0
  131. package/template/prisma/src/app/(app)/tasks/page.tsx +53 -0
  132. package/template/prisma/src/app/(app)/tasks/render.tsx +107 -0
  133. package/template/prisma/src/app/(app)/users/[id]/actions.ts +83 -0
  134. package/template/prisma/src/app/(app)/users/[id]/page.tsx +32 -0
  135. package/template/prisma/src/app/(app)/users/[id]/render.tsx +240 -0
  136. package/template/prisma/src/app/(app)/users/actions.ts +55 -0
  137. package/template/prisma/src/app/(app)/users/page.tsx +49 -0
  138. package/template/prisma/src/app/(app)/users/render.tsx +80 -0
  139. package/template/prisma/src/app/(auth)/layout.tsx +20 -0
  140. package/template/prisma/src/app/(auth)/login/page.tsx +49 -0
  141. package/template/prisma/src/app/(marketing)/layout.tsx +42 -0
  142. package/template/prisma/src/app/(marketing)/page.tsx +96 -0
  143. package/template/prisma/src/app/api/auth/[...nextauth]/route.ts +7 -0
  144. package/template/prisma/src/app/favicon.ico +0 -0
  145. package/template/prisma/src/app/layout.tsx +34 -0
  146. package/template/prisma/src/components/app-nav-command.tsx +160 -0
  147. package/template/prisma/src/components/dark-mode-toggle.tsx +43 -0
  148. package/template/prisma/src/components/data-table/data-table-column-header.tsx +91 -0
  149. package/template/prisma/src/components/data-table/data-table-faceted-filter.tsx +149 -0
  150. package/template/prisma/src/components/data-table/data-table-loading.tsx +77 -0
  151. package/template/prisma/src/components/data-table/data-table-pagination.tsx +94 -0
  152. package/template/prisma/src/components/data-table/data-table-toolbar.tsx +78 -0
  153. package/template/prisma/src/components/data-table/data-table-types.ts +17 -0
  154. package/template/prisma/src/components/data-table/data-table-view-options.tsx +59 -0
  155. package/template/prisma/src/components/data-table/data-table.tsx +301 -0
  156. package/template/prisma/src/components/data-table/simple-data-table.tsx +109 -0
  157. package/template/prisma/src/components/empty-placeholder.tsx +78 -0
  158. package/template/prisma/src/components/heading.tsx +17 -0
  159. package/template/prisma/src/components/icons.tsx +85 -0
  160. package/template/prisma/src/components/main-nav.tsx +64 -0
  161. package/template/prisma/src/components/shell.tsx +13 -0
  162. package/template/prisma/src/components/side-nav.tsx +51 -0
  163. package/template/prisma/src/components/site-footer.tsx +31 -0
  164. package/template/prisma/src/components/system-info.tsx +36 -0
  165. package/template/prisma/src/components/ui/alert-dialog.tsx +141 -0
  166. package/template/prisma/src/components/ui/avatar.tsx +50 -0
  167. package/template/prisma/src/components/ui/badge.tsx +36 -0
  168. package/template/prisma/src/components/ui/button.tsx +56 -0
  169. package/template/prisma/src/components/ui/card.tsx +79 -0
  170. package/template/prisma/src/components/ui/checkbox.tsx +30 -0
  171. package/template/prisma/src/components/ui/command.tsx +155 -0
  172. package/template/prisma/src/components/ui/dialog.tsx +122 -0
  173. package/template/prisma/src/components/ui/dropdown-menu.tsx +200 -0
  174. package/template/prisma/src/components/ui/form.tsx +176 -0
  175. package/template/prisma/src/components/ui/input.tsx +25 -0
  176. package/template/prisma/src/components/ui/label.tsx +26 -0
  177. package/template/prisma/src/components/ui/popover.tsx +31 -0
  178. package/template/prisma/src/components/ui/select.tsx +160 -0
  179. package/template/prisma/src/components/ui/separator.tsx +31 -0
  180. package/template/prisma/src/components/ui/skeleton.tsx +15 -0
  181. package/template/prisma/src/components/ui/table.tsx +117 -0
  182. package/template/prisma/src/components/user-account-nav.tsx +60 -0
  183. package/template/prisma/src/components/user-avatar.tsx +25 -0
  184. package/template/prisma/src/env.mjs +78 -0
  185. package/template/prisma/src/hooks/use-debounce.ts +17 -0
  186. package/template/prisma/src/hooks/use-lock-body.tsx +12 -0
  187. package/template/prisma/src/lib/auth.ts +80 -0
  188. package/template/prisma/src/lib/cn.ts +4 -0
  189. package/template/prisma/src/lib/delay.ts +2 -0
  190. package/template/prisma/src/lib/formatDate.ts +11 -0
  191. package/template/prisma/src/lib/generateLabel.ts +5 -0
  192. package/template/prisma/src/lib/siteConfig.ts +4 -0
  193. package/template/prisma/src/styles/globals.css +76 -0
  194. package/template/prisma/tailwind.config.ts +80 -0
  195. package/template/prisma/tsconfig.json +46 -0
  196. package/template/prisma-advanced/src/lib/cn.ts +4 -0
  197. package/template/prisma-advanced/src/lib/delay.ts +2 -0
  198. package/template/prisma-advanced/src/lib/siteConfig.ts +4 -0
  199. /package/template/{advanced/src/styles → base/src/app}/globals.css +0 -0
  200. /package/template/{advanced/src/hooks/use-debounce.ts → base/src/hooks/use-debounce.tsx} +0 -0
  201. /package/template/{advanced → new}/src/lib/cn.ts +0 -0
  202. /package/template/{advanced → new}/src/lib/delay.ts +0 -0
  203. /package/template/{advanced → new}/src/lib/siteConfig.ts +0 -0
  204. /package/template/{base → prisma}/postcss.config.cjs +0 -0
  205. /package/template/{base → prisma}/prettier.config.ts +0 -0
  206. /package/template/{base → prisma}/prisma/schema.prisma +0 -0
  207. /package/template/{base → prisma}/src/app/(auth)/login/user-auth-form.tsx +0 -0
  208. /package/template/{base → prisma}/src/app/api/upload/route.ts +0 -0
  209. /package/template/{advanced → prisma}/src/components/mobile-nav.tsx +0 -0
  210. /package/template/{base → prisma}/src/components/theme-provider.tsx +0 -0
  211. /package/template/{base → prisma}/src/components/ui/textarea.tsx +0 -0
  212. /package/template/{base → prisma}/src/components/ui/toast.tsx +0 -0
  213. /package/template/{base → prisma}/src/components/ui/toaster.tsx +0 -0
  214. /package/template/{base → prisma}/src/components/ui/use-toast.ts +0 -0
  215. /package/template/{base → prisma}/src/lib/db.ts +0 -0
  216. /package/template/{base → prisma}/src/lib/storageClient.ts +0 -0
  217. /package/template/{base → prisma}/src/styles/editor.css +0 -0
  218. /package/template/{base → prisma}/src/types/UnwrapPromise.ts +0 -0
  219. /package/template/{advanced → prisma-advanced}/.env.example +0 -0
  220. /package/template/{advanced → prisma-advanced}/.eslintrc.cjs +0 -0
  221. /package/template/{advanced → prisma-advanced}/components.json +0 -0
  222. /package/template/{advanced → prisma-advanced}/next.config.mjs +0 -0
  223. /package/template/{advanced → prisma-advanced}/package.json +0 -0
  224. /package/template/{advanced → prisma-advanced}/postcss.config.cjs +0 -0
  225. /package/template/{advanced → prisma-advanced}/prettier.config.ts +0 -0
  226. /package/template/{advanced → prisma-advanced}/prisma/schema.prisma +0 -0
  227. /package/template/{advanced → prisma-advanced}/public/next.svg +0 -0
  228. /package/template/{advanced → prisma-advanced}/src/app/(app)/dashboard/page.tsx +0 -0
  229. /package/template/{advanced → prisma-advanced}/src/app/(app)/layout.tsx +0 -0
  230. /package/template/{advanced → prisma-advanced}/src/app/(app)/roles/[id]/actions.ts +0 -0
  231. /package/template/{advanced → prisma-advanced}/src/app/(app)/roles/[id]/page.tsx +0 -0
  232. /package/template/{advanced → prisma-advanced}/src/app/(app)/roles/[id]/render.tsx +0 -0
  233. /package/template/{advanced → prisma-advanced}/src/app/(app)/roles/actions.ts +0 -0
  234. /package/template/{advanced → prisma-advanced}/src/app/(app)/roles/page.tsx +0 -0
  235. /package/template/{advanced → prisma-advanced}/src/app/(app)/roles/render.tsx +0 -0
  236. /package/template/{advanced → prisma-advanced}/src/app/(app)/settings/actions.ts +0 -0
  237. /package/template/{advanced → prisma-advanced}/src/app/(app)/settings/loading.tsx +0 -0
  238. /package/template/{advanced → prisma-advanced}/src/app/(app)/settings/page.tsx +0 -0
  239. /package/template/{advanced → prisma-advanced}/src/app/(app)/settings/render.tsx +0 -0
  240. /package/template/{advanced → prisma-advanced}/src/app/(app)/tasks/[id]/actions.ts +0 -0
  241. /package/template/{advanced → prisma-advanced}/src/app/(app)/tasks/[id]/page.tsx +0 -0
  242. /package/template/{advanced → prisma-advanced}/src/app/(app)/tasks/[id]/render.tsx +0 -0
  243. /package/template/{advanced → prisma-advanced}/src/app/(app)/tasks/actions.ts +0 -0
  244. /package/template/{advanced → prisma-advanced}/src/app/(app)/tasks/page.tsx +0 -0
  245. /package/template/{advanced → prisma-advanced}/src/app/(app)/tasks/render.tsx +0 -0
  246. /package/template/{advanced → prisma-advanced}/src/app/(app)/users/[id]/actions.ts +0 -0
  247. /package/template/{advanced → prisma-advanced}/src/app/(app)/users/[id]/page.tsx +0 -0
  248. /package/template/{advanced → prisma-advanced}/src/app/(app)/users/[id]/render.tsx +0 -0
  249. /package/template/{advanced → prisma-advanced}/src/app/(app)/users/actions.ts +0 -0
  250. /package/template/{advanced → prisma-advanced}/src/app/(app)/users/page.tsx +0 -0
  251. /package/template/{advanced → prisma-advanced}/src/app/(app)/users/render.tsx +0 -0
  252. /package/template/{advanced → prisma-advanced}/src/app/(auth)/layout.tsx +0 -0
  253. /package/template/{advanced → prisma-advanced}/src/app/(auth)/login/page.tsx +0 -0
  254. /package/template/{advanced → prisma-advanced}/src/app/(auth)/login/user-auth-form.tsx +0 -0
  255. /package/template/{advanced → prisma-advanced}/src/app/(marketing)/layout.tsx +0 -0
  256. /package/template/{advanced → prisma-advanced}/src/app/(marketing)/page.tsx +0 -0
  257. /package/template/{advanced → prisma-advanced}/src/app/api/auth/[...nextauth]/route.ts +0 -0
  258. /package/template/{advanced → prisma-advanced}/src/app/api/upload/route.ts +0 -0
  259. /package/template/{advanced → prisma-advanced}/src/app/favicon.ico +0 -0
  260. /package/template/{advanced → prisma-advanced}/src/app/layout.tsx +0 -0
  261. /package/template/{advanced → prisma-advanced}/src/components/app-nav-command.tsx +0 -0
  262. /package/template/{advanced → prisma-advanced}/src/components/dark-mode-toggle.tsx +0 -0
  263. /package/template/{advanced → prisma-advanced}/src/components/data-table/data-table-column-header.tsx +0 -0
  264. /package/template/{advanced → prisma-advanced}/src/components/data-table/data-table-faceted-filter.tsx +0 -0
  265. /package/template/{advanced → prisma-advanced}/src/components/data-table/data-table-loading.tsx +0 -0
  266. /package/template/{advanced → prisma-advanced}/src/components/data-table/data-table-pagination.tsx +0 -0
  267. /package/template/{advanced → prisma-advanced}/src/components/data-table/data-table-toolbar.tsx +0 -0
  268. /package/template/{advanced → prisma-advanced}/src/components/data-table/data-table-types.ts +0 -0
  269. /package/template/{advanced → prisma-advanced}/src/components/data-table/data-table-view-options.tsx +0 -0
  270. /package/template/{advanced → prisma-advanced}/src/components/data-table/data-table.tsx +0 -0
  271. /package/template/{advanced → prisma-advanced}/src/components/data-table/simple-data-table.tsx +0 -0
  272. /package/template/{advanced → prisma-advanced}/src/components/empty-placeholder.tsx +0 -0
  273. /package/template/{advanced → prisma-advanced}/src/components/heading.tsx +0 -0
  274. /package/template/{advanced → prisma-advanced}/src/components/icons.tsx +0 -0
  275. /package/template/{advanced → prisma-advanced}/src/components/main-nav.tsx +0 -0
  276. /package/template/{advanced → prisma-advanced}/src/components/shell.tsx +0 -0
  277. /package/template/{advanced → prisma-advanced}/src/components/side-nav.tsx +0 -0
  278. /package/template/{advanced → prisma-advanced}/src/components/site-footer.tsx +0 -0
  279. /package/template/{advanced → prisma-advanced}/src/components/system-info.tsx +0 -0
  280. /package/template/{advanced → prisma-advanced}/src/components/theme-provider.tsx +0 -0
  281. /package/template/{advanced → prisma-advanced}/src/components/ui/alert-dialog.tsx +0 -0
  282. /package/template/{advanced → prisma-advanced}/src/components/ui/avatar.tsx +0 -0
  283. /package/template/{advanced → prisma-advanced}/src/components/ui/badge.tsx +0 -0
  284. /package/template/{advanced → prisma-advanced}/src/components/ui/button.tsx +0 -0
  285. /package/template/{advanced → prisma-advanced}/src/components/ui/card.tsx +0 -0
  286. /package/template/{advanced → prisma-advanced}/src/components/ui/checkbox.tsx +0 -0
  287. /package/template/{advanced → prisma-advanced}/src/components/ui/command.tsx +0 -0
  288. /package/template/{advanced → prisma-advanced}/src/components/ui/dialog.tsx +0 -0
  289. /package/template/{advanced → prisma-advanced}/src/components/ui/dropdown-menu.tsx +0 -0
  290. /package/template/{advanced → prisma-advanced}/src/components/ui/form.tsx +0 -0
  291. /package/template/{advanced → prisma-advanced}/src/components/ui/input.tsx +0 -0
  292. /package/template/{advanced → prisma-advanced}/src/components/ui/label.tsx +0 -0
  293. /package/template/{advanced → prisma-advanced}/src/components/ui/popover.tsx +0 -0
  294. /package/template/{advanced → prisma-advanced}/src/components/ui/select.tsx +0 -0
  295. /package/template/{advanced → prisma-advanced}/src/components/ui/separator.tsx +0 -0
  296. /package/template/{advanced → prisma-advanced}/src/components/ui/skeleton.tsx +0 -0
  297. /package/template/{advanced → prisma-advanced}/src/components/ui/table.tsx +0 -0
  298. /package/template/{advanced → prisma-advanced}/src/components/ui/textarea.tsx +0 -0
  299. /package/template/{advanced → prisma-advanced}/src/components/ui/toast.tsx +0 -0
  300. /package/template/{advanced → prisma-advanced}/src/components/ui/toaster.tsx +0 -0
  301. /package/template/{advanced → prisma-advanced}/src/components/ui/use-toast.ts +0 -0
  302. /package/template/{advanced → prisma-advanced}/src/components/user-account-nav.tsx +0 -0
  303. /package/template/{advanced → prisma-advanced}/src/components/user-avatar.tsx +0 -0
  304. /package/template/{advanced → prisma-advanced}/src/env.mjs +0 -0
  305. /package/template/{base → prisma-advanced}/src/hooks/use-debounce.ts +0 -0
  306. /package/template/{advanced → prisma-advanced}/src/hooks/use-lock-body.tsx +0 -0
  307. /package/template/{advanced → prisma-advanced}/src/lib/auth.ts +0 -0
  308. /package/template/{advanced → prisma-advanced}/src/lib/db.ts +0 -0
  309. /package/template/{advanced → prisma-advanced}/src/lib/formatDate.ts +0 -0
  310. /package/template/{advanced → prisma-advanced}/src/lib/generateLabel.ts +0 -0
  311. /package/template/{advanced → prisma-advanced}/src/lib/storageClient.ts +0 -0
  312. /package/template/{advanced → prisma-advanced}/src/styles/editor.css +0 -0
  313. /package/template/{base → prisma-advanced}/src/styles/globals.css +0 -0
  314. /package/template/{advanced → prisma-advanced}/src/types/UnwrapPromise.ts +0 -0
  315. /package/template/{advanced → prisma-advanced}/tailwind.config.ts +0 -0
  316. /package/template/{advanced → prisma-advanced}/tsconfig.json +0 -0
@@ -0,0 +1,78 @@
1
+ import * as React from 'react'
2
+
3
+ import { Icons } from '@/components/icons'
4
+ import { cn } from '@/lib/cn'
5
+
6
+ interface EmptyPlaceholderProps extends React.HTMLAttributes<HTMLDivElement> {}
7
+
8
+ export function EmptyPlaceholder({
9
+ className,
10
+ children,
11
+ ...props
12
+ }: EmptyPlaceholderProps) {
13
+ return (
14
+ <div
15
+ className={cn(
16
+ 'flex min-h-[400px] flex-col items-center justify-center rounded-md border border-dashed p-8 text-center animate-in fade-in-50',
17
+ className
18
+ )}
19
+ {...props}
20
+ >
21
+ <div className="mx-auto flex max-w-[420px] flex-col items-center justify-center text-center">
22
+ {children}
23
+ </div>
24
+ </div>
25
+ )
26
+ }
27
+
28
+ interface EmptyPlaceholderIconProps
29
+ extends Partial<React.SVGProps<SVGSVGElement>> {
30
+ name: keyof typeof Icons
31
+ }
32
+
33
+ EmptyPlaceholder.Icon = function EmptyPlaceHolderIcon({
34
+ name,
35
+ className
36
+ }: EmptyPlaceholderIconProps) {
37
+ const Icon = Icons[name]
38
+
39
+ if (!Icon) {
40
+ return null
41
+ }
42
+
43
+ return (
44
+ <div className="flex h-20 w-20 items-center justify-center rounded-full bg-muted">
45
+ <Icon className={cn('h-10 w-10', className)} />
46
+ </div>
47
+ )
48
+ }
49
+
50
+ interface EmptyPlacholderTitleProps
51
+ extends React.HTMLAttributes<HTMLHeadingElement> {}
52
+
53
+ EmptyPlaceholder.Title = function EmptyPlaceholderTitle({
54
+ className,
55
+ ...props
56
+ }: EmptyPlacholderTitleProps) {
57
+ return (
58
+ <h2 className={cn('mt-6 text-xl font-semibold', className)} {...props} />
59
+ )
60
+ }
61
+
62
+ interface EmptyPlacholderDescriptionProps
63
+ extends React.HTMLAttributes<HTMLParagraphElement> {}
64
+
65
+ EmptyPlaceholder.Description = function EmptyPlaceholderDescription({
66
+ className,
67
+ ...props
68
+ }: EmptyPlacholderDescriptionProps) {
69
+ return (
70
+ <p
71
+ className={cn(
72
+ 'mb-8 mt-2 text-center text-sm font-normal leading-6 text-muted-foreground',
73
+ className
74
+ )}
75
+ {...props}
76
+ />
77
+ )
78
+ }
@@ -0,0 +1,17 @@
1
+ import { FC, ReactNode } from 'react'
2
+
3
+ export const Heading: FC<{
4
+ heading: string
5
+ text?: string
6
+ children?: ReactNode
7
+ }> = ({ heading, text, children }) => {
8
+ return (
9
+ <div className="flex items-center justify-between px-2">
10
+ <div className="grid gap-1">
11
+ <h1 className="font-heading text-3xl md:text-4xl">{heading}</h1>
12
+ {text && <p className="text-lg text-muted-foreground">{text}</p>}
13
+ </div>
14
+ {children}
15
+ </div>
16
+ )
17
+ }
@@ -0,0 +1,85 @@
1
+ import { cn } from '@/lib/cn'
2
+ import {
3
+ ArrowDown,
4
+ ArrowRight,
5
+ ArrowUp,
6
+ ArrowUpDown,
7
+ Biohazard,
8
+ Check,
9
+ ChevronLeft,
10
+ ChevronRight,
11
+ ChevronsLeft,
12
+ ChevronsRight,
13
+ ClipboardList,
14
+ Download,
15
+ Edit,
16
+ EyeOff,
17
+ Github,
18
+ Laptop,
19
+ LayoutDashboard,
20
+ Loader2,
21
+ LogIn,
22
+ LogOut,
23
+ LucideIcon,
24
+ LucideProps,
25
+ Moon,
26
+ Plus,
27
+ PlusCircle,
28
+ Save,
29
+ Settings,
30
+ Settings2,
31
+ Sun,
32
+ Trash,
33
+ User,
34
+ X
35
+ } from 'lucide-react'
36
+
37
+ export type Icon = LucideIcon
38
+
39
+ export const Icons = {
40
+ logo: Biohazard,
41
+ sun: Sun,
42
+ moon: Moon,
43
+ laptop: Laptop,
44
+ chevronLeft: ChevronLeft,
45
+ arrowRight: ArrowRight,
46
+ github: Github,
47
+ google: ({ ...props }: LucideProps) => (
48
+ <svg
49
+ aria-hidden="true"
50
+ focusable="false"
51
+ data-prefix="fab"
52
+ data-icon="google"
53
+ role="img"
54
+ xmlns="http://www.w3.org/2000/svg"
55
+ viewBox="0 0 30 30"
56
+ {...props}
57
+ className={cn('fill-current', props.className)}
58
+ >
59
+ <path d="M 15.003906 3 C 8.3749062 3 3 8.373 3 15 C 3 21.627 8.3749062 27 15.003906 27 C 25.013906 27 27.269078 17.707 26.330078 13 L 25 13 L 22.732422 13 L 15 13 L 15 17 L 22.738281 17 C 21.848702 20.448251 18.725955 23 15 23 C 10.582 23 7 19.418 7 15 C 7 10.582 10.582 7 15 7 C 17.009 7 18.839141 7.74575 20.244141 8.96875 L 23.085938 6.1289062 C 20.951937 4.1849063 18.116906 3 15.003906 3 z"></path>
60
+ </svg>
61
+ ),
62
+ login: LogIn,
63
+ logout: LogOut,
64
+ user: User,
65
+ spinner: Loader2,
66
+ settings: Settings,
67
+ close: X,
68
+ add: Plus,
69
+ edit: Edit,
70
+ save: Save,
71
+ delete: Trash,
72
+ download: Download,
73
+ dashboard: LayoutDashboard,
74
+ task: ClipboardList,
75
+ arrowUp: ArrowUp,
76
+ arrowDown: ArrowDown,
77
+ arrowUpDown: ArrowUpDown,
78
+ eyeOff: EyeOff,
79
+ plusCircle: PlusCircle,
80
+ check: Check,
81
+ chevronsLeft: ChevronsLeft,
82
+ chevronsRight: ChevronsRight,
83
+ chevronRight: ChevronRight,
84
+ mixer: Settings2
85
+ }
@@ -0,0 +1,64 @@
1
+ 'use client'
2
+
3
+ import Link from 'next/link'
4
+ import { useSelectedLayoutSegment } from 'next/navigation'
5
+ import { FC, useState } from 'react'
6
+
7
+ import { Icons } from '@/components/icons'
8
+ import { MobileNav } from '@/components/mobile-nav'
9
+ import { cn } from '@/lib/cn'
10
+ import { siteConfig } from '@/lib/siteConfig'
11
+
12
+ type MainNavItem = {
13
+ title: string
14
+ href: string
15
+ disabled?: boolean
16
+ }
17
+
18
+ type MainNavProps = {
19
+ logoLink?: string
20
+ items?: MainNavItem[]
21
+ }
22
+
23
+ export const MainNav: FC<MainNavProps> = ({ logoLink = '/', items }) => {
24
+ const [showMobileMenu, setShowMobileMenu] = useState(false)
25
+ const segment = useSelectedLayoutSegment()
26
+
27
+ return (
28
+ <div className="flex md:gap-10">
29
+ <Link href={logoLink} className="hidden items-center space-x-2 md:flex">
30
+ <Icons.logo />
31
+ <span className="hidden font-bold sm:inline-block">
32
+ {siteConfig.name}
33
+ </span>
34
+ </Link>
35
+ {items?.length ? (
36
+ <nav className="hidden gap-6 md:flex">
37
+ {items?.map((item, i) => (
38
+ <Link
39
+ key={i}
40
+ href={item.disabled ? '#' : item.href}
41
+ className={cn(
42
+ 'flex items-center text-lg font-medium transition-colors hover:text-foreground/80 sm:text-sm',
43
+ item.href.startsWith(`/${segment}`)
44
+ ? 'text-foreground'
45
+ : 'text-foreground/60',
46
+ item.disabled && 'cursor-not-allowed opacity-80'
47
+ )}
48
+ >
49
+ {item.title}
50
+ </Link>
51
+ ))}
52
+ </nav>
53
+ ) : undefined}
54
+ <button
55
+ className="flex items-center space-x-2 md:hidden"
56
+ onClick={() => setShowMobileMenu(prev => !prev)}
57
+ >
58
+ {showMobileMenu ? <Icons.close /> : <Icons.logo />}
59
+ <span className="font-bold">Menu</span>
60
+ </button>
61
+ {showMobileMenu && items?.length && <MobileNav items={items} />}
62
+ </div>
63
+ )
64
+ }
@@ -0,0 +1,13 @@
1
+ import { FC } from 'react'
2
+
3
+ import { cn } from '@/lib/cn'
4
+
5
+ interface ShellProps extends React.HTMLAttributes<HTMLDivElement> {}
6
+
7
+ export const Shell: FC<ShellProps> = ({ children, className, ...props }) => {
8
+ return (
9
+ <div className={cn('grid items-start gap-8 p-1', className)} {...props}>
10
+ {children}
11
+ </div>
12
+ )
13
+ }
@@ -0,0 +1,51 @@
1
+ 'use client'
2
+
3
+ import Link from 'next/link'
4
+ import { usePathname } from 'next/navigation'
5
+
6
+ import { Icons } from '@/components/icons'
7
+ import { cn } from '@/lib/cn'
8
+ import { FC } from 'react'
9
+
10
+ type IconKeys = keyof typeof Icons
11
+
12
+ interface SideNavProps {
13
+ items: {
14
+ title: string
15
+ href?: string | null
16
+ disabled?: boolean | null
17
+ icon?: IconKeys | null
18
+ }[]
19
+ }
20
+
21
+ export const SideNav: FC<SideNavProps> = ({ items }) => {
22
+ const path = usePathname()
23
+
24
+ if (!items?.length) return null
25
+
26
+ return (
27
+ <nav className="grid items-start gap-2">
28
+ {items.map((item, index) => {
29
+ const Icon = Icons[item.icon || 'arrowRight']
30
+ return (
31
+ item.href && (
32
+ <Link key={index} href={item.disabled ? '/' : item.href}>
33
+ <span
34
+ className={cn(
35
+ 'group flex items-center rounded-md px-3 py-2 text-sm font-medium',
36
+ path.includes(item.href)
37
+ ? 'bg-accent'
38
+ : 'transparent underline-offset-4 hover:underline',
39
+ item.disabled && 'cursor-not-allowed opacity-80'
40
+ )}
41
+ >
42
+ <Icon className="mr-2 h-4 w-4" />
43
+ <span>{item.title}</span>
44
+ </span>
45
+ </Link>
46
+ )
47
+ )
48
+ })}
49
+ </nav>
50
+ )
51
+ }
@@ -0,0 +1,31 @@
1
+ import { FC, HTMLAttributes } from 'react'
2
+
3
+ import { DarkModeToggle } from '@/components/dark-mode-toggle'
4
+ import { Icons } from '@/components/icons'
5
+ import { cn } from '@/lib/cn'
6
+ import { siteConfig } from '@/lib/siteConfig'
7
+
8
+ export const SiteFooter: FC<HTMLAttributes<HTMLElement>> = ({ className }) => {
9
+ return (
10
+ <footer className={cn(className)}>
11
+ <div className="container flex flex-col items-center justify-between gap-2 py-4 sm:flex-row">
12
+ <div className="flex flex-col items-center gap-2 sm:flex-row">
13
+ <Icons.logo />
14
+ <p className="text-center text-sm leading-loose sm:text-left">
15
+ {siteConfig.name}. Built by{' '}
16
+ <a
17
+ href="https://github.com/ejekanshjain"
18
+ target="_blank"
19
+ rel="noreferrer"
20
+ className="font-medium underline underline-offset-4"
21
+ >
22
+ ejekanshjain
23
+ </a>
24
+ .
25
+ </p>
26
+ </div>
27
+ <DarkModeToggle />
28
+ </div>
29
+ </footer>
30
+ )
31
+ }
@@ -0,0 +1,36 @@
1
+ 'use client'
2
+
3
+ import { FC, ReactNode } from 'react'
4
+
5
+ import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
6
+ import { Separator } from '@/components/ui/separator'
7
+
8
+ type SystemInfoProps = {
9
+ items: {
10
+ label: string
11
+ value: string | ReactNode
12
+ }[]
13
+ }
14
+
15
+ export const SystemInfo: FC<SystemInfoProps> = ({ items }) => {
16
+ return (
17
+ <Card className="max-w-[600px]">
18
+ <CardHeader>
19
+ <CardTitle>System Information</CardTitle>
20
+ </CardHeader>
21
+ <CardContent>
22
+ <dl className="grid gap-4">
23
+ {items.map((item, i) => (
24
+ <div key={i}>
25
+ <dt className="font-semibold">{item.label}</dt>
26
+ <dd>{item.value}</dd>
27
+ {i < items.length - 1 ? (
28
+ <Separator className="mt-2" />
29
+ ) : undefined}
30
+ </div>
31
+ ))}
32
+ </dl>
33
+ </CardContent>
34
+ </Card>
35
+ )
36
+ }
@@ -0,0 +1,141 @@
1
+ 'use client'
2
+
3
+ import * as AlertDialogPrimitive from '@radix-ui/react-alert-dialog'
4
+ import * as React from 'react'
5
+
6
+ import { buttonVariants } from '@/components/ui/button'
7
+ import { cn } from '@/lib/cn'
8
+
9
+ const AlertDialog = AlertDialogPrimitive.Root
10
+
11
+ const AlertDialogTrigger = AlertDialogPrimitive.Trigger
12
+
13
+ const AlertDialogPortal = AlertDialogPrimitive.Portal
14
+
15
+ const AlertDialogOverlay = React.forwardRef<
16
+ React.ElementRef<typeof AlertDialogPrimitive.Overlay>,
17
+ React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Overlay>
18
+ >(({ className, ...props }, ref) => (
19
+ <AlertDialogPrimitive.Overlay
20
+ className={cn(
21
+ 'fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',
22
+ className
23
+ )}
24
+ {...props}
25
+ ref={ref}
26
+ />
27
+ ))
28
+ AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName
29
+
30
+ const AlertDialogContent = React.forwardRef<
31
+ React.ElementRef<typeof AlertDialogPrimitive.Content>,
32
+ React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Content>
33
+ >(({ className, ...props }, ref) => (
34
+ <AlertDialogPortal>
35
+ <AlertDialogOverlay />
36
+ <AlertDialogPrimitive.Content
37
+ ref={ref}
38
+ className={cn(
39
+ 'fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg',
40
+ className
41
+ )}
42
+ {...props}
43
+ />
44
+ </AlertDialogPortal>
45
+ ))
46
+ AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName
47
+
48
+ const AlertDialogHeader = ({
49
+ className,
50
+ ...props
51
+ }: React.HTMLAttributes<HTMLDivElement>) => (
52
+ <div
53
+ className={cn(
54
+ 'flex flex-col space-y-2 text-center sm:text-left',
55
+ className
56
+ )}
57
+ {...props}
58
+ />
59
+ )
60
+ AlertDialogHeader.displayName = 'AlertDialogHeader'
61
+
62
+ const AlertDialogFooter = ({
63
+ className,
64
+ ...props
65
+ }: React.HTMLAttributes<HTMLDivElement>) => (
66
+ <div
67
+ className={cn(
68
+ 'flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2',
69
+ className
70
+ )}
71
+ {...props}
72
+ />
73
+ )
74
+ AlertDialogFooter.displayName = 'AlertDialogFooter'
75
+
76
+ const AlertDialogTitle = React.forwardRef<
77
+ React.ElementRef<typeof AlertDialogPrimitive.Title>,
78
+ React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Title>
79
+ >(({ className, ...props }, ref) => (
80
+ <AlertDialogPrimitive.Title
81
+ ref={ref}
82
+ className={cn('text-lg font-semibold', className)}
83
+ {...props}
84
+ />
85
+ ))
86
+ AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName
87
+
88
+ const AlertDialogDescription = React.forwardRef<
89
+ React.ElementRef<typeof AlertDialogPrimitive.Description>,
90
+ React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Description>
91
+ >(({ className, ...props }, ref) => (
92
+ <AlertDialogPrimitive.Description
93
+ ref={ref}
94
+ className={cn('text-sm text-muted-foreground', className)}
95
+ {...props}
96
+ />
97
+ ))
98
+ AlertDialogDescription.displayName =
99
+ AlertDialogPrimitive.Description.displayName
100
+
101
+ const AlertDialogAction = React.forwardRef<
102
+ React.ElementRef<typeof AlertDialogPrimitive.Action>,
103
+ React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Action>
104
+ >(({ className, ...props }, ref) => (
105
+ <AlertDialogPrimitive.Action
106
+ ref={ref}
107
+ className={cn(buttonVariants(), className)}
108
+ {...props}
109
+ />
110
+ ))
111
+ AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName
112
+
113
+ const AlertDialogCancel = React.forwardRef<
114
+ React.ElementRef<typeof AlertDialogPrimitive.Cancel>,
115
+ React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Cancel>
116
+ >(({ className, ...props }, ref) => (
117
+ <AlertDialogPrimitive.Cancel
118
+ ref={ref}
119
+ className={cn(
120
+ buttonVariants({ variant: 'outline' }),
121
+ 'mt-2 sm:mt-0',
122
+ className
123
+ )}
124
+ {...props}
125
+ />
126
+ ))
127
+ AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName
128
+
129
+ export {
130
+ AlertDialog,
131
+ AlertDialogAction,
132
+ AlertDialogCancel,
133
+ AlertDialogContent,
134
+ AlertDialogDescription,
135
+ AlertDialogFooter,
136
+ AlertDialogHeader,
137
+ AlertDialogOverlay,
138
+ AlertDialogPortal,
139
+ AlertDialogTitle,
140
+ AlertDialogTrigger
141
+ }
@@ -0,0 +1,50 @@
1
+ 'use client'
2
+
3
+ import * as AvatarPrimitive from '@radix-ui/react-avatar'
4
+ import * as React from 'react'
5
+
6
+ import { cn } from '@/lib/cn'
7
+
8
+ const Avatar = React.forwardRef<
9
+ React.ElementRef<typeof AvatarPrimitive.Root>,
10
+ React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>
11
+ >(({ className, ...props }, ref) => (
12
+ <AvatarPrimitive.Root
13
+ ref={ref}
14
+ className={cn(
15
+ 'relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full',
16
+ className
17
+ )}
18
+ {...props}
19
+ />
20
+ ))
21
+ Avatar.displayName = AvatarPrimitive.Root.displayName
22
+
23
+ const AvatarImage = React.forwardRef<
24
+ React.ElementRef<typeof AvatarPrimitive.Image>,
25
+ React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image>
26
+ >(({ className, ...props }, ref) => (
27
+ <AvatarPrimitive.Image
28
+ ref={ref}
29
+ className={cn('aspect-square h-full w-full', className)}
30
+ {...props}
31
+ />
32
+ ))
33
+ AvatarImage.displayName = AvatarPrimitive.Image.displayName
34
+
35
+ const AvatarFallback = React.forwardRef<
36
+ React.ElementRef<typeof AvatarPrimitive.Fallback>,
37
+ React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback>
38
+ >(({ className, ...props }, ref) => (
39
+ <AvatarPrimitive.Fallback
40
+ ref={ref}
41
+ className={cn(
42
+ 'flex h-full w-full items-center justify-center rounded-full bg-muted',
43
+ className
44
+ )}
45
+ {...props}
46
+ />
47
+ ))
48
+ AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName
49
+
50
+ export { Avatar, AvatarFallback, AvatarImage }
@@ -0,0 +1,36 @@
1
+ import { cva, type VariantProps } from 'class-variance-authority'
2
+ import * as React from 'react'
3
+
4
+ import { cn } from '@/lib/cn'
5
+
6
+ const badgeVariants = cva(
7
+ 'inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2',
8
+ {
9
+ variants: {
10
+ variant: {
11
+ default:
12
+ 'border-transparent bg-primary text-primary-foreground hover:bg-primary/80',
13
+ secondary:
14
+ 'border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80',
15
+ destructive:
16
+ 'border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80',
17
+ outline: 'text-foreground'
18
+ }
19
+ },
20
+ defaultVariants: {
21
+ variant: 'default'
22
+ }
23
+ }
24
+ )
25
+
26
+ export interface BadgeProps
27
+ extends React.HTMLAttributes<HTMLDivElement>,
28
+ VariantProps<typeof badgeVariants> {}
29
+
30
+ function Badge({ className, variant, ...props }: BadgeProps) {
31
+ return (
32
+ <div className={cn(badgeVariants({ variant }), className)} {...props} />
33
+ )
34
+ }
35
+
36
+ export { Badge, badgeVariants }
@@ -0,0 +1,56 @@
1
+ import { Slot } from '@radix-ui/react-slot'
2
+ import { cva, type VariantProps } from 'class-variance-authority'
3
+ import * as React from 'react'
4
+
5
+ import { cn } from '@/lib/cn'
6
+
7
+ const buttonVariants = cva(
8
+ 'inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',
9
+ {
10
+ variants: {
11
+ variant: {
12
+ default: 'bg-primary text-primary-foreground hover:bg-primary/90',
13
+ destructive:
14
+ 'bg-destructive text-destructive-foreground hover:bg-destructive/90',
15
+ outline:
16
+ 'border border-input bg-background hover:bg-accent hover:text-accent-foreground',
17
+ secondary:
18
+ 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
19
+ ghost: 'hover:bg-accent hover:text-accent-foreground',
20
+ link: 'text-primary underline-offset-4 hover:underline'
21
+ },
22
+ size: {
23
+ default: 'h-10 px-4 py-2',
24
+ sm: 'h-9 rounded-md px-3',
25
+ lg: 'h-11 rounded-md px-8',
26
+ icon: 'h-10 w-10'
27
+ }
28
+ },
29
+ defaultVariants: {
30
+ variant: 'default',
31
+ size: 'default'
32
+ }
33
+ }
34
+ )
35
+
36
+ export interface ButtonProps
37
+ extends React.ButtonHTMLAttributes<HTMLButtonElement>,
38
+ VariantProps<typeof buttonVariants> {
39
+ asChild?: boolean
40
+ }
41
+
42
+ const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
43
+ ({ className, variant, size, asChild = false, ...props }, ref) => {
44
+ const Comp = asChild ? Slot : 'button'
45
+ return (
46
+ <Comp
47
+ className={cn(buttonVariants({ variant, size, className }))}
48
+ ref={ref}
49
+ {...props}
50
+ />
51
+ )
52
+ }
53
+ )
54
+ Button.displayName = 'Button'
55
+
56
+ export { Button, buttonVariants }