create-einja-app 0.2.17 → 0.2.19

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 (275) hide show
  1. package/README.md +1 -0
  2. package/dist/cli.js +685 -1715
  3. package/dist/cli.js.map +1 -1
  4. package/package.json +2 -2
  5. package/templates/default/.claude/hooks/einja/playwright-resize.sh +12 -2
  6. package/templates/default/.claude/settings.json +16 -0
  7. package/templates/default/.cursor/commands/task-vibe-kanban-loop.md +107 -42
  8. package/templates/default/.env.develop +0 -4
  9. package/templates/default/.env.example +1 -0
  10. package/templates/default/.env.preview +0 -4
  11. package/templates/default/.env.staging +19 -0
  12. package/templates/default/.github/actions/ci/action.yml +39 -0
  13. package/templates/default/.github/actions/migrate/action.yml +39 -0
  14. package/templates/default/.github/actions/neon-export-env/action.yml +28 -0
  15. package/templates/default/.github/actions/setup/action.yml +20 -0
  16. package/templates/default/.github/workflows/claude.yml +1 -0
  17. package/templates/default/.github/workflows/{cleanup-neon-branches.yml → cleanup-pr-preview-db.yml} +28 -24
  18. package/templates/default/.github/workflows/cleanup-pr-preview-on-close.yml +50 -0
  19. package/templates/default/.github/workflows/deploy-pr-preview.yml +398 -0
  20. package/templates/default/.github/workflows/deploy-stable-branches.yml +259 -0
  21. package/templates/default/.github/workflows/release-create-einja-app.yml +95 -0
  22. package/templates/default/.mcp.json +29 -11
  23. package/templates/default/.serena/project.yml +4 -0
  24. package/templates/default/.vscode/settings.json +18 -0
  25. package/templates/default/CLAUDE.md +129 -353
  26. package/templates/default/README.md +5 -14
  27. package/templates/default/apps/admin/next.config.ts +11 -0
  28. package/templates/default/apps/admin/package.json +55 -0
  29. package/templates/default/apps/admin/postcss.config.cjs +5 -0
  30. package/templates/default/apps/admin/src/app/(auth)/forgot-password/page.tsx +97 -0
  31. package/templates/default/apps/admin/src/app/(auth)/layout.tsx +18 -0
  32. package/templates/default/apps/admin/src/app/(auth)/otp/page.tsx +121 -0
  33. package/templates/default/apps/admin/src/app/(auth)/sign-in/page.tsx +145 -0
  34. package/templates/default/apps/admin/src/app/(auth)/sign-up/page.tsx +199 -0
  35. package/templates/default/apps/admin/src/app/(errors)/401/page.tsx +27 -0
  36. package/templates/default/apps/admin/src/app/(errors)/403/page.tsx +28 -0
  37. package/templates/default/apps/admin/src/app/(errors)/500/page.tsx +29 -0
  38. package/templates/default/apps/admin/src/app/(errors)/layout.tsx +7 -0
  39. package/templates/default/apps/admin/src/app/(errors)/maintenance/page.tsx +25 -0
  40. package/templates/default/apps/admin/src/app/dashboard/_components/analytics-chart.tsx +68 -0
  41. package/templates/default/apps/admin/src/app/dashboard/_components/analytics.tsx +182 -0
  42. package/templates/default/apps/admin/src/app/dashboard/_components/dashboard-page.tsx +74 -0
  43. package/templates/default/apps/admin/src/app/dashboard/_components/metric-cards.tsx +49 -0
  44. package/templates/default/apps/admin/src/app/dashboard/_components/overview-chart.tsx +73 -0
  45. package/templates/default/apps/admin/src/app/dashboard/_components/recent-sales.tsx +75 -0
  46. package/templates/default/apps/admin/src/app/dashboard/apps/_components/apps-page.tsx +135 -0
  47. package/templates/default/apps/admin/src/app/dashboard/apps/page.tsx +10 -0
  48. package/templates/default/apps/admin/src/app/dashboard/chats/_components/chat-list.tsx +82 -0
  49. package/templates/default/apps/admin/src/app/dashboard/chats/_components/chat-messages.tsx +194 -0
  50. package/templates/default/apps/admin/src/app/dashboard/chats/_components/chats-page.tsx +99 -0
  51. package/templates/default/apps/admin/src/app/dashboard/chats/_components/new-chat.tsx +118 -0
  52. package/templates/default/apps/admin/src/app/dashboard/chats/page.tsx +10 -0
  53. package/templates/default/apps/admin/src/app/dashboard/layout.tsx +9 -0
  54. package/templates/default/apps/admin/src/app/dashboard/not-found.tsx +14 -0
  55. package/templates/default/apps/admin/src/app/dashboard/page.tsx +10 -0
  56. package/templates/default/apps/admin/src/app/dashboard/settings/_components/content-section.tsx +20 -0
  57. package/templates/default/apps/admin/src/app/dashboard/settings/_components/sidebar-nav.tsx +66 -0
  58. package/templates/default/apps/admin/src/app/dashboard/settings/account/page.tsx +173 -0
  59. package/templates/default/apps/admin/src/app/dashboard/settings/appearance/page.tsx +156 -0
  60. package/templates/default/apps/admin/src/app/dashboard/settings/display/page.tsx +125 -0
  61. package/templates/default/apps/admin/src/app/dashboard/settings/layout.tsx +30 -0
  62. package/templates/default/apps/admin/src/app/dashboard/settings/notifications/page.tsx +196 -0
  63. package/templates/default/apps/admin/src/app/dashboard/settings/page.tsx +5 -0
  64. package/templates/default/apps/admin/src/app/dashboard/settings/profile/page.tsx +176 -0
  65. package/templates/default/apps/admin/src/app/dashboard/tasks/_components/data-table-bulk-actions.tsx +183 -0
  66. package/templates/default/apps/admin/src/app/dashboard/tasks/_components/data-table-row-actions.tsx +79 -0
  67. package/templates/default/apps/admin/src/app/dashboard/tasks/_components/tasks-columns.tsx +107 -0
  68. package/templates/default/apps/admin/src/app/dashboard/tasks/_components/tasks-dialogs.tsx +71 -0
  69. package/templates/default/apps/admin/src/app/dashboard/tasks/_components/tasks-import-dialog.tsx +106 -0
  70. package/templates/default/apps/admin/src/app/dashboard/tasks/_components/tasks-multi-delete-dialog.tsx +90 -0
  71. package/templates/default/apps/admin/src/app/dashboard/tasks/_components/tasks-mutate-drawer.tsx +207 -0
  72. package/templates/default/apps/admin/src/app/dashboard/tasks/_components/tasks-page.tsx +31 -0
  73. package/templates/default/apps/admin/src/app/dashboard/tasks/_components/tasks-primary-buttons.tsx +19 -0
  74. package/templates/default/apps/admin/src/app/dashboard/tasks/_components/tasks-provider.tsx +37 -0
  75. package/templates/default/apps/admin/src/app/dashboard/tasks/_components/tasks-table.tsx +155 -0
  76. package/templates/default/apps/admin/src/app/dashboard/tasks/page.tsx +14 -0
  77. package/templates/default/apps/admin/src/app/dashboard/users/_components/data-table-bulk-actions.tsx +136 -0
  78. package/templates/default/apps/admin/src/app/dashboard/users/_components/data-table-row-actions.tsx +62 -0
  79. package/templates/default/apps/admin/src/app/dashboard/users/_components/users-action-dialog.tsx +297 -0
  80. package/templates/default/apps/admin/src/app/dashboard/users/_components/users-columns.tsx +121 -0
  81. package/templates/default/apps/admin/src/app/dashboard/users/_components/users-delete-dialog.tsx +72 -0
  82. package/templates/default/apps/admin/src/app/dashboard/users/_components/users-dialogs.tsx +49 -0
  83. package/templates/default/apps/admin/src/app/dashboard/users/_components/users-invite-dialog.tsx +139 -0
  84. package/templates/default/apps/admin/src/app/dashboard/users/_components/users-multi-delete-dialog.tsx +89 -0
  85. package/templates/default/apps/admin/src/app/dashboard/users/_components/users-page.tsx +30 -0
  86. package/templates/default/apps/admin/src/app/dashboard/users/_components/users-primary-buttons.tsx +19 -0
  87. package/templates/default/apps/admin/src/app/dashboard/users/_components/users-provider.tsx +35 -0
  88. package/templates/default/apps/admin/src/app/dashboard/users/_components/users-table.tsx +157 -0
  89. package/templates/default/apps/admin/src/app/dashboard/users/page.tsx +10 -0
  90. package/templates/default/apps/admin/src/app/globals.css +109 -0
  91. package/templates/default/apps/admin/src/app/layout.tsx +32 -0
  92. package/templates/default/apps/admin/src/app/not-found.tsx +14 -0
  93. package/templates/default/apps/admin/src/app/page.tsx +5 -0
  94. package/templates/default/apps/admin/src/components/layout/admin-layout.tsx +16 -0
  95. package/templates/default/apps/admin/src/components/layout/app-sidebar.tsx +52 -0
  96. package/templates/default/apps/admin/src/components/layout/nav-config.ts +131 -0
  97. package/templates/default/apps/admin/src/components/providers/theme-provider.tsx +10 -0
  98. package/templates/default/apps/admin/src/components/shared/long-text.tsx +78 -0
  99. package/templates/default/apps/admin/src/components/shared/search-input.tsx +16 -0
  100. package/templates/default/apps/admin/src/components/shared/select-dropdown.tsx +64 -0
  101. package/templates/default/apps/admin/src/data/apps.tsx +116 -0
  102. package/templates/default/apps/admin/src/data/chats.ts +114 -0
  103. package/templates/default/apps/admin/src/data/tasks.ts +114 -0
  104. package/templates/default/apps/admin/src/data/users.ts +90 -0
  105. package/templates/default/apps/admin/src/hooks/use-dialog-state.ts +17 -0
  106. package/templates/default/apps/admin/src/hooks/use-table-url-state.ts +243 -0
  107. package/templates/default/apps/admin/src/lib/show-submitted-data.tsx +12 -0
  108. package/templates/default/apps/admin/src/types/table.d.ts +9 -0
  109. package/templates/default/apps/admin/tsconfig.json +32 -0
  110. package/templates/default/apps/web/next.config.ts +1 -0
  111. package/templates/default/apps/web/package.json +0 -22
  112. package/templates/default/apps/web/postcss.config.cjs +0 -1
  113. package/templates/default/apps/web/src/app/(authenticated)/dashboard/page.tsx +4 -20
  114. package/templates/default/apps/web/src/app/(authenticated)/data/_components/UserTable.tsx +4 -4
  115. package/templates/default/apps/web/src/app/(authenticated)/data/page.tsx +1 -1
  116. package/templates/default/apps/web/src/app/(authenticated)/profile/page.tsx +1 -1
  117. package/templates/default/apps/web/src/app/error.tsx +8 -70
  118. package/templates/default/apps/web/src/app/global-error.tsx +8 -70
  119. package/templates/default/apps/web/src/app/globals.css +20 -0
  120. package/templates/default/apps/web/src/app/not-found.tsx +5 -39
  121. package/templates/default/apps/web/src/app/page.tsx +27 -203
  122. package/templates/default/apps/web/src/app/signin/page.tsx +27 -191
  123. package/templates/default/apps/web/src/app/signup/page.tsx +33 -240
  124. package/templates/default/apps/web/src/components/dashboard/dashboard-stats.tsx +11 -75
  125. package/templates/default/apps/web/src/components/shared/Sidebar.tsx +3 -3
  126. package/templates/default/apps/web/src/components/shared/header.tsx +17 -112
  127. package/templates/default/apps/web/tsconfig.json +0 -6
  128. package/templates/default/biome.json +1 -2
  129. package/templates/default/components.json +2 -2
  130. package/templates/default/docker-compose.yml +1 -1
  131. package/templates/default/gitignore +4 -0
  132. package/templates/default/package.json +1 -0
  133. package/templates/default/packages/admin-ui/catalog/catalog.css +54 -0
  134. package/templates/default/packages/admin-ui/catalog/catalog.tsx +401 -0
  135. package/templates/default/packages/admin-ui/catalog/index.html +12 -0
  136. package/templates/default/packages/admin-ui/catalog/main.tsx +9 -0
  137. package/templates/default/packages/admin-ui/components.json +21 -0
  138. package/templates/default/packages/admin-ui/package.json +105 -0
  139. package/templates/default/packages/admin-ui/src/command-menu/index.tsx +174 -0
  140. package/templates/default/packages/admin-ui/src/data-table/bulk-actions.tsx +215 -0
  141. package/templates/default/packages/admin-ui/src/data-table/column-header.tsx +73 -0
  142. package/templates/default/packages/admin-ui/src/data-table/data-table.tsx +127 -0
  143. package/templates/default/packages/admin-ui/src/data-table/faceted-filter.tsx +148 -0
  144. package/templates/default/packages/admin-ui/src/data-table/index.tsx +9 -0
  145. package/templates/default/packages/admin-ui/src/data-table/pagination.tsx +101 -0
  146. package/templates/default/packages/admin-ui/src/data-table/toolbar.tsx +87 -0
  147. package/templates/default/packages/admin-ui/src/data-table/view-options.tsx +57 -0
  148. package/templates/default/packages/admin-ui/src/hooks/use-mobile.tsx +23 -0
  149. package/templates/default/packages/admin-ui/src/layout/header.tsx +55 -0
  150. package/templates/default/packages/admin-ui/src/layout/index.ts +10 -0
  151. package/templates/default/packages/admin-ui/src/layout/main.tsx +23 -0
  152. package/templates/default/packages/admin-ui/src/layout/nav-group.tsx +111 -0
  153. package/templates/default/packages/admin-ui/src/layout/nav-user.tsx +114 -0
  154. package/templates/default/packages/admin-ui/src/layout/theme-switch.tsx +40 -0
  155. package/templates/default/packages/admin-ui/src/layout/types.ts +21 -0
  156. package/templates/default/packages/admin-ui/src/lib/utils.ts +6 -0
  157. package/templates/default/packages/admin-ui/src/styles/base.css +65 -0
  158. package/templates/default/packages/admin-ui/src/styles/tokens.css +91 -0
  159. package/templates/default/packages/admin-ui/src/tanstack-table.d.ts +10 -0
  160. package/templates/default/packages/admin-ui/src/ui/alert-dialog.tsx +157 -0
  161. package/templates/default/packages/admin-ui/src/ui/alert.tsx +66 -0
  162. package/templates/default/packages/admin-ui/src/ui/avatar.tsx +53 -0
  163. package/templates/default/packages/admin-ui/src/ui/badge.tsx +46 -0
  164. package/templates/default/packages/admin-ui/src/ui/breadcrumb.tsx +108 -0
  165. package/templates/default/packages/admin-ui/src/ui/button.tsx +59 -0
  166. package/templates/default/packages/admin-ui/src/ui/calendar.tsx +69 -0
  167. package/templates/default/packages/admin-ui/src/ui/card.tsx +92 -0
  168. package/templates/default/packages/admin-ui/src/ui/chart.tsx +345 -0
  169. package/templates/default/packages/admin-ui/src/ui/checkbox.tsx +32 -0
  170. package/templates/default/packages/admin-ui/src/ui/collapsible.tsx +27 -0
  171. package/templates/default/packages/admin-ui/src/ui/command.tsx +161 -0
  172. package/templates/default/packages/admin-ui/src/ui/confirm-dialog.tsx +72 -0
  173. package/templates/default/packages/admin-ui/src/ui/date-picker.tsx +53 -0
  174. package/templates/default/packages/admin-ui/src/ui/dialog.tsx +143 -0
  175. package/templates/default/packages/admin-ui/src/ui/dropdown-menu.tsx +257 -0
  176. package/templates/default/packages/admin-ui/src/ui/form.tsx +168 -0
  177. package/templates/default/packages/admin-ui/src/ui/input-otp.tsx +84 -0
  178. package/templates/default/packages/admin-ui/src/ui/input.tsx +21 -0
  179. package/templates/default/packages/admin-ui/src/ui/label.tsx +24 -0
  180. package/templates/default/packages/admin-ui/src/ui/pagination.tsx +126 -0
  181. package/templates/default/packages/admin-ui/src/ui/password-input.tsx +46 -0
  182. package/templates/default/packages/admin-ui/src/ui/popover.tsx +48 -0
  183. package/templates/default/packages/admin-ui/src/ui/progress.tsx +31 -0
  184. package/templates/default/packages/admin-ui/src/ui/radio-group.tsx +45 -0
  185. package/templates/default/packages/admin-ui/src/ui/scroll-area.tsx +52 -0
  186. package/templates/default/packages/admin-ui/src/ui/select.tsx +185 -0
  187. package/templates/default/packages/admin-ui/src/ui/separator.tsx +28 -0
  188. package/templates/default/packages/admin-ui/src/ui/sheet.tsx +149 -0
  189. package/templates/default/packages/admin-ui/src/ui/sidebar.tsx +728 -0
  190. package/templates/default/packages/admin-ui/src/ui/skeleton.tsx +13 -0
  191. package/templates/default/packages/admin-ui/src/ui/sonner.tsx +25 -0
  192. package/templates/default/packages/admin-ui/src/ui/switch.tsx +31 -0
  193. package/templates/default/packages/admin-ui/src/ui/table.tsx +116 -0
  194. package/templates/default/packages/admin-ui/src/ui/tabs.tsx +66 -0
  195. package/templates/default/packages/admin-ui/src/ui/textarea.tsx +18 -0
  196. package/templates/default/packages/admin-ui/src/ui/toggle-group.tsx +60 -0
  197. package/templates/default/packages/admin-ui/src/ui/toggle.tsx +44 -0
  198. package/templates/default/packages/admin-ui/src/ui/tooltip.tsx +61 -0
  199. package/templates/default/packages/admin-ui/tsconfig.json +8 -0
  200. package/templates/default/packages/admin-ui/vite.config.ts +11 -0
  201. package/templates/default/packages/config/package.json +0 -2
  202. package/templates/default/packages/server-core/package.json +1 -0
  203. package/templates/default/packages/ui/components.json +21 -0
  204. package/templates/default/packages/ui/package.json +42 -5
  205. package/templates/default/packages/ui/src/accordion.tsx +1 -1
  206. package/templates/default/packages/ui/src/alert-dialog.tsx +4 -4
  207. package/templates/default/packages/ui/src/alert.tsx +1 -1
  208. package/templates/default/packages/ui/src/avatar.tsx +1 -1
  209. package/templates/default/packages/ui/src/badge.tsx +1 -1
  210. package/templates/default/packages/ui/src/breadcrumb.tsx +1 -1
  211. package/templates/default/packages/ui/src/button.tsx +1 -1
  212. package/templates/default/packages/ui/src/card.tsx +1 -1
  213. package/templates/default/packages/ui/src/checkbox.tsx +1 -1
  214. package/templates/default/packages/ui/src/dialog.tsx +3 -3
  215. package/templates/default/packages/ui/src/drawer.tsx +3 -3
  216. package/templates/default/packages/ui/src/dropdown-menu.tsx +3 -3
  217. package/templates/default/packages/ui/src/form.tsx +2 -2
  218. package/templates/default/packages/ui/src/hover-card.tsx +2 -2
  219. package/templates/default/packages/ui/src/input.tsx +1 -1
  220. package/templates/default/packages/ui/src/label.tsx +1 -1
  221. package/templates/default/packages/ui/src/pagination.tsx +2 -2
  222. package/templates/default/packages/ui/src/popover.tsx +2 -2
  223. package/templates/default/packages/ui/src/progress.tsx +1 -1
  224. package/templates/default/packages/ui/src/select.tsx +2 -2
  225. package/templates/default/packages/ui/src/separator.tsx +1 -1
  226. package/templates/default/packages/ui/src/skeleton.tsx +1 -1
  227. package/templates/default/packages/ui/src/table.tsx +1 -1
  228. package/templates/default/packages/ui/src/tabs.tsx +1 -1
  229. package/templates/default/packages/ui/src/textarea.tsx +1 -1
  230. package/templates/default/packages/ui/src/tooltip.tsx +3 -3
  231. package/templates/default/packages/ui/src/typography.tsx +1 -1
  232. package/templates/default/packages/ui/tsconfig.json +1 -6
  233. package/templates/default/pnpm-lock.yaml +1319 -936
  234. package/templates/default/postcss.config.cjs +0 -1
  235. package/templates/default/turbo.json +11 -5
  236. package/templates/default/worktree.config.json +5 -0
  237. package/templates/default/.env.ci +0 -32
  238. package/templates/default/.github/workflows/ci.yml +0 -96
  239. package/templates/default/.github/workflows/preview-db.yml +0 -134
  240. package/templates/default/.playwright-mcp/dashboard.png +0 -0
  241. package/templates/default/.playwright-mcp/web-home.png +0 -0
  242. package/templates/default/apps/web/panda.config.ts +0 -114
  243. package/templates/default/apps/web/src/components/ui/accordion.tsx +0 -64
  244. package/templates/default/apps/web/src/components/ui/alert-dialog.tsx +0 -135
  245. package/templates/default/apps/web/src/components/ui/alert.tsx +0 -60
  246. package/templates/default/apps/web/src/components/ui/aspect-ratio.tsx +0 -9
  247. package/templates/default/apps/web/src/components/ui/avatar.tsx +0 -41
  248. package/templates/default/apps/web/src/components/ui/badge.tsx +0 -39
  249. package/templates/default/apps/web/src/components/ui/breadcrumb.tsx +0 -101
  250. package/templates/default/apps/web/src/components/ui/button.tsx +0 -56
  251. package/templates/default/apps/web/src/components/ui/card.tsx +0 -75
  252. package/templates/default/apps/web/src/components/ui/checkbox.tsx +0 -29
  253. package/templates/default/apps/web/src/components/ui/data-table.tsx +0 -189
  254. package/templates/default/apps/web/src/components/ui/dialog-hook.tsx +0 -210
  255. package/templates/default/apps/web/src/components/ui/dialog.tsx +0 -129
  256. package/templates/default/apps/web/src/components/ui/drawer.tsx +0 -124
  257. package/templates/default/apps/web/src/components/ui/dropdown-menu.tsx +0 -228
  258. package/templates/default/apps/web/src/components/ui/form.tsx +0 -152
  259. package/templates/default/apps/web/src/components/ui/hover-card.tsx +0 -38
  260. package/templates/default/apps/web/src/components/ui/input.tsx +0 -21
  261. package/templates/default/apps/web/src/components/ui/label.tsx +0 -21
  262. package/templates/default/apps/web/src/components/ui/pagination.tsx +0 -105
  263. package/templates/default/apps/web/src/components/ui/popover.tsx +0 -42
  264. package/templates/default/apps/web/src/components/ui/progress.tsx +0 -28
  265. package/templates/default/apps/web/src/components/ui/select.tsx +0 -170
  266. package/templates/default/apps/web/src/components/ui/separator.tsx +0 -28
  267. package/templates/default/apps/web/src/components/ui/skeleton.tsx +0 -13
  268. package/templates/default/apps/web/src/components/ui/sonner.tsx +0 -25
  269. package/templates/default/apps/web/src/components/ui/table.tsx +0 -92
  270. package/templates/default/apps/web/src/components/ui/tabs.tsx +0 -54
  271. package/templates/default/apps/web/src/components/ui/textarea.tsx +0 -18
  272. package/templates/default/apps/web/src/components/ui/tooltip.tsx +0 -57
  273. package/templates/default/apps/web/src/components/ui/typography.tsx +0 -158
  274. package/templates/default/packages/config/panda.config.ts +0 -114
  275. package/templates/default/panda.config.ts +0 -114
@@ -0,0 +1,108 @@
1
+ import { Slot } from "@radix-ui/react-slot";
2
+ import { ChevronRight, MoreHorizontal } from "lucide-react";
3
+ import type * as React from "react";
4
+
5
+ import { cn } from "../lib/utils";
6
+
7
+ function Breadcrumb({ ...props }: React.ComponentProps<"nav">) {
8
+ return <nav aria-label="breadcrumb" data-slot="breadcrumb" {...props} />;
9
+ }
10
+
11
+ function BreadcrumbList({ className, ...props }: React.ComponentProps<"ol">) {
12
+ return (
13
+ <ol
14
+ data-slot="breadcrumb-list"
15
+ className={cn(
16
+ "text-muted-foreground flex flex-wrap items-center gap-1.5 text-sm break-words sm:gap-2.5",
17
+ className,
18
+ )}
19
+ {...props}
20
+ />
21
+ );
22
+ }
23
+
24
+ function BreadcrumbItem({ className, ...props }: React.ComponentProps<"li">) {
25
+ return (
26
+ <li
27
+ data-slot="breadcrumb-item"
28
+ className={cn("inline-flex items-center gap-1.5", className)}
29
+ {...props}
30
+ />
31
+ );
32
+ }
33
+
34
+ function BreadcrumbLink({
35
+ asChild,
36
+ className,
37
+ ...props
38
+ }: React.ComponentProps<"a"> & {
39
+ asChild?: boolean;
40
+ }) {
41
+ const Comp = asChild ? Slot : "a";
42
+
43
+ return (
44
+ <Comp
45
+ data-slot="breadcrumb-link"
46
+ className={cn("hover:text-foreground transition-colors", className)}
47
+ {...props}
48
+ />
49
+ );
50
+ }
51
+
52
+ function BreadcrumbPage({ className, ...props }: React.ComponentProps<"span">) {
53
+ return (
54
+ <span
55
+ data-slot="breadcrumb-page"
56
+ aria-disabled="true"
57
+ aria-current="page"
58
+ className={cn("text-foreground font-normal", className)}
59
+ {...props}
60
+ />
61
+ );
62
+ }
63
+
64
+ function BreadcrumbSeparator({
65
+ children,
66
+ className,
67
+ ...props
68
+ }: React.ComponentProps<"li">) {
69
+ return (
70
+ <li
71
+ data-slot="breadcrumb-separator"
72
+ role="presentation"
73
+ aria-hidden="true"
74
+ className={cn("[&>svg]:size-3.5", className)}
75
+ {...props}
76
+ >
77
+ {children ?? <ChevronRight />}
78
+ </li>
79
+ );
80
+ }
81
+
82
+ function BreadcrumbEllipsis({
83
+ className,
84
+ ...props
85
+ }: React.ComponentProps<"span">) {
86
+ return (
87
+ <span
88
+ data-slot="breadcrumb-ellipsis"
89
+ role="presentation"
90
+ aria-hidden="true"
91
+ className={cn("flex size-9 items-center justify-center", className)}
92
+ {...props}
93
+ >
94
+ <MoreHorizontal className="size-4" />
95
+ <span className="sr-only">More</span>
96
+ </span>
97
+ );
98
+ }
99
+
100
+ export {
101
+ Breadcrumb,
102
+ BreadcrumbList,
103
+ BreadcrumbItem,
104
+ BreadcrumbLink,
105
+ BreadcrumbPage,
106
+ BreadcrumbSeparator,
107
+ BreadcrumbEllipsis,
108
+ };
@@ -0,0 +1,59 @@
1
+ import { Slot } from "@radix-ui/react-slot";
2
+ import { type VariantProps, cva } from "class-variance-authority";
3
+ import type * as React from "react";
4
+
5
+ import { cn } from "../lib/utils";
6
+
7
+ const buttonVariants = cva(
8
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
9
+ {
10
+ variants: {
11
+ variant: {
12
+ default:
13
+ "bg-primary text-primary-foreground shadow-xs hover:bg-primary/90",
14
+ destructive:
15
+ "bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
16
+ outline:
17
+ "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
18
+ secondary:
19
+ "bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
20
+ ghost:
21
+ "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
22
+ link: "text-primary underline-offset-4 hover:underline",
23
+ },
24
+ size: {
25
+ default: "h-9 px-4 py-2 has-[>svg]:px-3",
26
+ sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
27
+ lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
28
+ icon: "size-9",
29
+ },
30
+ },
31
+ defaultVariants: {
32
+ variant: "default",
33
+ size: "default",
34
+ },
35
+ },
36
+ );
37
+
38
+ function Button({
39
+ className,
40
+ variant,
41
+ size,
42
+ asChild = false,
43
+ ...props
44
+ }: React.ComponentProps<"button"> &
45
+ VariantProps<typeof buttonVariants> & {
46
+ asChild?: boolean;
47
+ }) {
48
+ const Comp = asChild ? Slot : "button";
49
+
50
+ return (
51
+ <Comp
52
+ data-slot="button"
53
+ className={cn(buttonVariants({ variant, size, className }))}
54
+ {...props}
55
+ />
56
+ );
57
+ }
58
+
59
+ export { Button, buttonVariants };
@@ -0,0 +1,69 @@
1
+ "use client";
2
+
3
+ import { ChevronLeftIcon, ChevronRightIcon } from "lucide-react";
4
+ import { DayPicker } from "react-day-picker";
5
+ import type * as React from "react";
6
+
7
+ import { cn } from "../lib/utils";
8
+ import { buttonVariants } from "./button";
9
+
10
+ function Calendar({
11
+ className,
12
+ classNames,
13
+ showOutsideDays = true,
14
+ ...props
15
+ }: React.ComponentProps<typeof DayPicker>) {
16
+ return (
17
+ <DayPicker
18
+ showOutsideDays={showOutsideDays}
19
+ className={cn("p-3", className)}
20
+ classNames={{
21
+ months: "flex flex-col sm:flex-row gap-2",
22
+ month: "flex flex-col gap-4",
23
+ month_caption: "flex justify-center pt-1 relative items-center w-full",
24
+ caption_label: "text-sm font-medium",
25
+ nav: "flex items-center gap-1",
26
+ button_previous: cn(
27
+ buttonVariants({ variant: "outline" }),
28
+ "absolute left-1 top-0 size-7 bg-transparent p-0 opacity-50 hover:opacity-100"
29
+ ),
30
+ button_next: cn(
31
+ buttonVariants({ variant: "outline" }),
32
+ "absolute right-1 top-0 size-7 bg-transparent p-0 opacity-50 hover:opacity-100"
33
+ ),
34
+ month_grid: "w-full border-collapse space-x-1",
35
+ weekdays: "flex",
36
+ weekday: "text-muted-foreground rounded-md w-8 font-normal text-[0.8rem]",
37
+ week: "flex w-full mt-2",
38
+ day: cn(
39
+ "relative p-0 text-center text-sm focus-within:relative focus-within:z-[var(--z-sidebar-rail)] [&:has([aria-selected])]:bg-accent [&:has([aria-selected].day-range-end)]:rounded-r-md [&:has([aria-selected].day-outside)]:bg-accent/50",
40
+ props.mode === "range"
41
+ ? "[&:has(>.day-range-end)]:rounded-r-md [&:has(>.day-range-start)]:rounded-l-md first:[&:has([aria-selected])]:rounded-l-md last:[&:has([aria-selected])]:rounded-r-md"
42
+ : "[&:has([aria-selected])]:rounded-md"
43
+ ),
44
+ day_button: cn(
45
+ buttonVariants({ variant: "ghost" }),
46
+ "size-8 p-0 font-normal aria-selected:opacity-100"
47
+ ),
48
+ range_end: "day-range-end aria-selected:rounded-r-md",
49
+ range_start: "day-range-start aria-selected:rounded-l-md",
50
+ selected: "bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground",
51
+ today: "bg-accent text-accent-foreground",
52
+ outside: "day-outside text-muted-foreground aria-selected:text-muted-foreground opacity-50",
53
+ disabled: "text-muted-foreground opacity-50",
54
+ range_middle: "aria-selected:bg-accent aria-selected:text-accent-foreground",
55
+ hidden: "invisible",
56
+ ...classNames,
57
+ }}
58
+ components={{
59
+ Chevron: ({ orientation }) => {
60
+ const Icon = orientation === "left" ? ChevronLeftIcon : ChevronRightIcon;
61
+ return <Icon className="size-4" />;
62
+ },
63
+ }}
64
+ {...props}
65
+ />
66
+ );
67
+ }
68
+
69
+ export { Calendar };
@@ -0,0 +1,92 @@
1
+ import type * as React from "react";
2
+
3
+ import { cn } from "../lib/utils";
4
+
5
+ function Card({ className, ...props }: React.ComponentProps<"div">) {
6
+ return (
7
+ <div
8
+ data-slot="card"
9
+ className={cn(
10
+ "bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm",
11
+ className,
12
+ )}
13
+ {...props}
14
+ />
15
+ );
16
+ }
17
+
18
+ function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
19
+ return (
20
+ <div
21
+ data-slot="card-header"
22
+ className={cn(
23
+ "@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-1.5 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6",
24
+ className,
25
+ )}
26
+ {...props}
27
+ />
28
+ );
29
+ }
30
+
31
+ function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
32
+ return (
33
+ <div
34
+ data-slot="card-title"
35
+ className={cn("leading-none font-semibold", className)}
36
+ {...props}
37
+ />
38
+ );
39
+ }
40
+
41
+ function CardDescription({ className, ...props }: React.ComponentProps<"div">) {
42
+ return (
43
+ <div
44
+ data-slot="card-description"
45
+ className={cn("text-muted-foreground text-sm", className)}
46
+ {...props}
47
+ />
48
+ );
49
+ }
50
+
51
+ function CardAction({ className, ...props }: React.ComponentProps<"div">) {
52
+ return (
53
+ <div
54
+ data-slot="card-action"
55
+ className={cn(
56
+ "col-start-2 row-span-2 row-start-1 self-start justify-self-end",
57
+ className,
58
+ )}
59
+ {...props}
60
+ />
61
+ );
62
+ }
63
+
64
+ function CardContent({ className, ...props }: React.ComponentProps<"div">) {
65
+ return (
66
+ <div
67
+ data-slot="card-content"
68
+ className={cn("px-6", className)}
69
+ {...props}
70
+ />
71
+ );
72
+ }
73
+
74
+ function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
75
+ return (
76
+ <div
77
+ data-slot="card-footer"
78
+ className={cn("flex items-center px-6 [.border-t]:pt-6", className)}
79
+ {...props}
80
+ />
81
+ );
82
+ }
83
+
84
+ export {
85
+ Card,
86
+ CardHeader,
87
+ CardFooter,
88
+ CardTitle,
89
+ CardAction,
90
+ CardDescription,
91
+ CardContent,
92
+ };
@@ -0,0 +1,345 @@
1
+ "use client";
2
+
3
+ import * as React from "react";
4
+ import * as RechartsPrimitive from "recharts";
5
+ import { cn } from "../lib/utils";
6
+
7
+ // Chart Context
8
+ const ChartContext = React.createContext<ChartConfig | null>(null);
9
+
10
+ function useChart() {
11
+ const context = React.useContext(ChartContext);
12
+ if (!context) {
13
+ throw new Error("useChart must be used within a <ChartContainer />");
14
+ }
15
+ return context;
16
+ }
17
+
18
+ // Chart Container
19
+ interface ChartContainerProps
20
+ extends React.ComponentProps<"div">,
21
+ React.ComponentProps<typeof RechartsPrimitive.ResponsiveContainer> {
22
+ config: ChartConfig;
23
+ children: React.ComponentProps<
24
+ typeof RechartsPrimitive.ResponsiveContainer
25
+ >["children"];
26
+ }
27
+
28
+ const ChartContainer = React.forwardRef<HTMLDivElement, ChartContainerProps>(
29
+ ({ id, className, children, config, ...props }, ref) => {
30
+ const uniqueId = React.useId();
31
+ const chartId = `chart-${id || uniqueId.replace(/:/g, "")}`;
32
+
33
+ return (
34
+ <ChartContext.Provider value={config}>
35
+ <div
36
+ data-chart={chartId}
37
+ ref={ref}
38
+ className={cn(
39
+ "flex aspect-video justify-center text-xs [&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-border/50 [&_.recharts-curve.recharts-tooltip-cursor]:stroke-border [&_.recharts-dot[stroke='#fff']]:stroke-transparent [&_.recharts-layer]:outline-none [&_.recharts-polar-grid_[stroke='#ccc']]:stroke-border [&_.recharts-radial-bar-background-sector]:fill-muted [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-muted [&_.recharts-reference-line_[stroke='#ccc']]:stroke-border [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-sector]:outline-none [&_.recharts-surface]:outline-none",
40
+ className
41
+ )}
42
+ {...props}
43
+ >
44
+ <ChartStyle id={chartId} config={config} />
45
+ <RechartsPrimitive.ResponsiveContainer>
46
+ {children}
47
+ </RechartsPrimitive.ResponsiveContainer>
48
+ </div>
49
+ </ChartContext.Provider>
50
+ );
51
+ }
52
+ );
53
+ ChartContainer.displayName = "ChartContainer";
54
+
55
+ // Chart Style
56
+ interface ChartStyleProps {
57
+ id: string;
58
+ config: ChartConfig;
59
+ }
60
+
61
+ const ChartStyle = ({ id, config }: ChartStyleProps) => {
62
+ const colorConfig = Object.entries(config).filter(
63
+ ([, config]) => config.theme || config.color
64
+ );
65
+
66
+ if (!colorConfig.length) {
67
+ return null;
68
+ }
69
+
70
+ return (
71
+ <style
72
+ dangerouslySetInnerHTML={{
73
+ __html: Object.entries(config)
74
+ .filter(([, config]) => config.theme || config.color)
75
+ .map(([key, itemConfig]) => {
76
+ const color =
77
+ typeof itemConfig === "object" && "color" in itemConfig
78
+ ? itemConfig.color
79
+ : undefined;
80
+ const theme =
81
+ typeof itemConfig === "object" && "theme" in itemConfig
82
+ ? itemConfig.theme
83
+ : undefined;
84
+
85
+ return color
86
+ ? `[data-chart=${id}] .color-${key} { color: ${color}; fill: ${color}; }`
87
+ : theme
88
+ ? Object.entries(theme)
89
+ .map(
90
+ ([mode, value]) =>
91
+ `${mode === "light" ? "" : `.dark `}[data-chart=${id}] .color-${key} { color: ${value}; fill: ${value}; }`
92
+ )
93
+ .join("\n")
94
+ : "";
95
+ })
96
+ .join("\n"),
97
+ }}
98
+ />
99
+ );
100
+ };
101
+
102
+ // Chart Tooltip
103
+ interface ChartTooltipProps
104
+ extends React.ComponentProps<typeof RechartsPrimitive.Tooltip> {
105
+ hideLabel?: boolean;
106
+ hideIndicator?: boolean;
107
+ indicator?: "line" | "dot" | "dashed";
108
+ nameKey?: string;
109
+ labelKey?: string;
110
+ }
111
+
112
+ const ChartTooltip = RechartsPrimitive.Tooltip;
113
+
114
+ interface ChartTooltipContentProps
115
+ extends Omit<React.ComponentProps<typeof RechartsPrimitive.Tooltip>, "content">,
116
+ Omit<React.ComponentProps<"div">, "content"> {
117
+ hideLabel?: boolean;
118
+ hideIndicator?: boolean;
119
+ indicator?: "line" | "dot" | "dashed";
120
+ nameKey?: string;
121
+ labelKey?: string;
122
+ labelClassName?: string;
123
+ }
124
+
125
+ const ChartTooltipContent = React.forwardRef<
126
+ HTMLDivElement,
127
+ ChartTooltipContentProps
128
+ >(
129
+ (
130
+ {
131
+ active,
132
+ payload,
133
+ className,
134
+ indicator = "dot",
135
+ hideLabel = false,
136
+ hideIndicator = false,
137
+ label,
138
+ labelFormatter,
139
+ labelClassName,
140
+ formatter,
141
+ color,
142
+ nameKey,
143
+ labelKey,
144
+ },
145
+ ref
146
+ ) => {
147
+ const { config } = useChart();
148
+
149
+ const tooltipLabel = React.useMemo(() => {
150
+ if (hideLabel || !payload?.length) {
151
+ return null;
152
+ }
153
+
154
+ const [item] = payload;
155
+ const key = `${labelKey || item.dataKey || item.name || "value"}`;
156
+ const itemConfig = config[key];
157
+ const value =
158
+ !labelKey && typeof label === "string"
159
+ ? config[label]?.label || label
160
+ : itemConfig?.label;
161
+
162
+ if (labelFormatter) {
163
+ return (
164
+ <div className={cn("font-medium", labelClassName)}>
165
+ {labelFormatter(value, payload)}
166
+ </div>
167
+ );
168
+ }
169
+
170
+ if (!value) {
171
+ return null;
172
+ }
173
+
174
+ return <div className={cn("font-medium", labelClassName)}>{value}</div>;
175
+ }, [
176
+ label,
177
+ labelFormatter,
178
+ payload,
179
+ hideLabel,
180
+ labelClassName,
181
+ config,
182
+ labelKey,
183
+ ]);
184
+
185
+ if (!active || !payload?.length) {
186
+ return null;
187
+ }
188
+
189
+ return (
190
+ <div
191
+ ref={ref}
192
+ className={cn(
193
+ "grid min-w-[8rem] items-start gap-1.5 rounded-lg border border-border/50 bg-background px-2.5 py-1.5 text-xs shadow-xl",
194
+ className
195
+ )}
196
+ >
197
+ {tooltipLabel}
198
+ <div className="grid gap-1.5">
199
+ {payload.map((item, index) => {
200
+ const key = `${nameKey || item.name || item.dataKey || "value"}`;
201
+ const itemConfig = config[key];
202
+ const indicatorColor = color || item.payload.fill || item.color;
203
+
204
+ return (
205
+ <div
206
+ key={item.dataKey}
207
+ className={cn(
208
+ "flex w-full items-center text-xs leading-none",
209
+ hideIndicator ? "gap-0" : "gap-1.5"
210
+ )}
211
+ >
212
+ {!hideIndicator && (
213
+ <div
214
+ className={cn(
215
+ "shrink-0 rounded-[2px] border-[--color-border] bg-[--color-bg]",
216
+ {
217
+ "h-2.5 w-2.5": indicator === "dot",
218
+ "w-1": indicator === "line",
219
+ "w-0 border-[1.5px] border-dashed bg-transparent":
220
+ indicator === "dashed",
221
+ "my-0.5": hideLabel && indicator === "dashed",
222
+ }
223
+ )}
224
+ style={
225
+ {
226
+ "--color-bg": indicatorColor,
227
+ "--color-border": indicatorColor,
228
+ } as React.CSSProperties
229
+ }
230
+ />
231
+ )}
232
+ <div
233
+ className={cn(
234
+ "flex flex-1 justify-between leading-none",
235
+ hideIndicator ? "items-end" : "items-center"
236
+ )}
237
+ >
238
+ <div className="grid gap-1.5">
239
+ <span className="text-muted-foreground">
240
+ {itemConfig?.label || item.name}
241
+ </span>
242
+ </div>
243
+ {item.value && (
244
+ <span className="font-mono font-medium tabular-nums text-foreground">
245
+ {formatter
246
+ ? formatter(item.value, item.name, item, index, payload)
247
+ : item.value.toLocaleString()}
248
+ </span>
249
+ )}
250
+ </div>
251
+ </div>
252
+ );
253
+ })}
254
+ </div>
255
+ </div>
256
+ );
257
+ }
258
+ );
259
+ ChartTooltipContent.displayName = "ChartTooltipContent";
260
+
261
+ // Chart Legend
262
+ const ChartLegend = RechartsPrimitive.Legend;
263
+
264
+ interface ChartLegendContentProps
265
+ extends React.ComponentProps<"div">,
266
+ Pick<RechartsPrimitive.LegendProps, "payload" | "verticalAlign"> {
267
+ hideIcon?: boolean;
268
+ nameKey?: string;
269
+ }
270
+
271
+ const ChartLegendContent = React.forwardRef<
272
+ HTMLDivElement,
273
+ ChartLegendContentProps
274
+ >(({ className, hideIcon = false, payload, verticalAlign = "bottom", nameKey }, ref) => {
275
+ const { config } = useChart();
276
+
277
+ if (!payload?.length) {
278
+ return null;
279
+ }
280
+
281
+ return (
282
+ <div
283
+ ref={ref}
284
+ className={cn(
285
+ "flex items-center justify-center gap-4",
286
+ verticalAlign === "top" ? "pb-3" : "pt-3",
287
+ className
288
+ )}
289
+ >
290
+ {payload.map((item) => {
291
+ const key = `${nameKey || item.dataKey || "value"}`;
292
+ const itemConfig = config[key];
293
+
294
+ return (
295
+ <div
296
+ key={item.value}
297
+ className={cn(
298
+ "flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground"
299
+ )}
300
+ >
301
+ {itemConfig?.icon && !hideIcon ? (
302
+ <itemConfig.icon />
303
+ ) : (
304
+ <div
305
+ className="h-2 w-2 shrink-0 rounded-[2px]"
306
+ style={{
307
+ backgroundColor: item.color,
308
+ }}
309
+ />
310
+ )}
311
+ <span className="text-xs text-muted-foreground">
312
+ {itemConfig?.label || item.value}
313
+ </span>
314
+ </div>
315
+ );
316
+ })}
317
+ </div>
318
+ );
319
+ });
320
+ ChartLegendContent.displayName = "ChartLegendContent";
321
+
322
+ // Chart Config Type
323
+ interface ChartConfig {
324
+ [key: string]:
325
+ | {
326
+ label?: React.ReactNode;
327
+ icon?: React.ComponentType;
328
+ color?: string;
329
+ theme?: {
330
+ light?: string;
331
+ dark?: string;
332
+ };
333
+ }
334
+ | undefined;
335
+ }
336
+
337
+ export {
338
+ ChartContainer,
339
+ ChartTooltip,
340
+ ChartTooltipContent,
341
+ ChartLegend,
342
+ ChartLegendContent,
343
+ ChartStyle,
344
+ };
345
+ export type { ChartConfig };
@@ -0,0 +1,32 @@
1
+ "use client";
2
+
3
+ import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
4
+ import { CheckIcon } from "lucide-react";
5
+ import type * as React from "react";
6
+
7
+ import { cn } from "../lib/utils";
8
+
9
+ function Checkbox({
10
+ className,
11
+ ...props
12
+ }: React.ComponentProps<typeof CheckboxPrimitive.Root>) {
13
+ return (
14
+ <CheckboxPrimitive.Root
15
+ data-slot="checkbox"
16
+ className={cn(
17
+ "peer border-input dark:bg-input/30 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:data-[state=checked]:bg-primary data-[state=checked]:border-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive size-4 shrink-0 rounded-[4px] border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
18
+ className,
19
+ )}
20
+ {...props}
21
+ >
22
+ <CheckboxPrimitive.Indicator
23
+ data-slot="checkbox-indicator"
24
+ className="flex items-center justify-center text-current transition-none"
25
+ >
26
+ <CheckIcon className="size-3.5" />
27
+ </CheckboxPrimitive.Indicator>
28
+ </CheckboxPrimitive.Root>
29
+ );
30
+ }
31
+
32
+ export { Checkbox };