create-einja-app 0.2.15 → 0.2.18

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 (272) hide show
  1. package/package.json +2 -2
  2. package/templates/default/.claude/hooks/einja/biome-format.sh +2 -2
  3. package/templates/default/.claude/hooks/einja/playwright-resize.sh +12 -2
  4. package/templates/default/.claude/settings.json +15 -0
  5. package/templates/default/.cursor/commands/task-vibe-kanban-loop.md +107 -42
  6. package/templates/default/.env.develop +0 -4
  7. package/templates/default/.env.example +1 -0
  8. package/templates/default/.env.preview +0 -4
  9. package/templates/default/.env.staging +19 -0
  10. package/templates/default/.github/actions/ci/action.yml +39 -0
  11. package/templates/default/.github/actions/migrate/action.yml +39 -0
  12. package/templates/default/.github/actions/neon-export-env/action.yml +28 -0
  13. package/templates/default/.github/actions/setup/action.yml +20 -0
  14. package/templates/default/.github/workflows/claude.yml +1 -0
  15. package/templates/default/.github/workflows/{cleanup-neon-branches.yml → cleanup-pr-preview-db.yml} +28 -24
  16. package/templates/default/.github/workflows/cleanup-pr-preview-on-close.yml +50 -0
  17. package/templates/default/.github/workflows/deploy-pr-preview.yml +398 -0
  18. package/templates/default/.github/workflows/deploy-stable-branches.yml +259 -0
  19. package/templates/default/.github/workflows/release-create-einja-app.yml +95 -0
  20. package/templates/default/.mcp.json +6 -9
  21. package/templates/default/.serena/project.yml +22 -1
  22. package/templates/default/CLAUDE.md +52 -10
  23. package/templates/default/README.md +5 -14
  24. package/templates/default/apps/admin/next.config.ts +11 -0
  25. package/templates/default/apps/admin/package.json +55 -0
  26. package/templates/default/apps/admin/postcss.config.cjs +5 -0
  27. package/templates/default/apps/admin/src/app/(auth)/forgot-password/page.tsx +97 -0
  28. package/templates/default/apps/admin/src/app/(auth)/layout.tsx +18 -0
  29. package/templates/default/apps/admin/src/app/(auth)/otp/page.tsx +121 -0
  30. package/templates/default/apps/admin/src/app/(auth)/sign-in/page.tsx +145 -0
  31. package/templates/default/apps/admin/src/app/(auth)/sign-up/page.tsx +199 -0
  32. package/templates/default/apps/admin/src/app/(errors)/401/page.tsx +27 -0
  33. package/templates/default/apps/admin/src/app/(errors)/403/page.tsx +28 -0
  34. package/templates/default/apps/admin/src/app/(errors)/500/page.tsx +29 -0
  35. package/templates/default/apps/admin/src/app/(errors)/layout.tsx +7 -0
  36. package/templates/default/apps/admin/src/app/(errors)/maintenance/page.tsx +25 -0
  37. package/templates/default/apps/admin/src/app/dashboard/_components/analytics-chart.tsx +68 -0
  38. package/templates/default/apps/admin/src/app/dashboard/_components/analytics.tsx +182 -0
  39. package/templates/default/apps/admin/src/app/dashboard/_components/dashboard-page.tsx +74 -0
  40. package/templates/default/apps/admin/src/app/dashboard/_components/metric-cards.tsx +49 -0
  41. package/templates/default/apps/admin/src/app/dashboard/_components/overview-chart.tsx +73 -0
  42. package/templates/default/apps/admin/src/app/dashboard/_components/recent-sales.tsx +75 -0
  43. package/templates/default/apps/admin/src/app/dashboard/apps/_components/apps-page.tsx +135 -0
  44. package/templates/default/apps/admin/src/app/dashboard/apps/page.tsx +10 -0
  45. package/templates/default/apps/admin/src/app/dashboard/chats/_components/chat-list.tsx +82 -0
  46. package/templates/default/apps/admin/src/app/dashboard/chats/_components/chat-messages.tsx +194 -0
  47. package/templates/default/apps/admin/src/app/dashboard/chats/_components/chats-page.tsx +99 -0
  48. package/templates/default/apps/admin/src/app/dashboard/chats/_components/new-chat.tsx +118 -0
  49. package/templates/default/apps/admin/src/app/dashboard/chats/page.tsx +10 -0
  50. package/templates/default/apps/admin/src/app/dashboard/layout.tsx +9 -0
  51. package/templates/default/apps/admin/src/app/dashboard/not-found.tsx +14 -0
  52. package/templates/default/apps/admin/src/app/dashboard/page.tsx +10 -0
  53. package/templates/default/apps/admin/src/app/dashboard/settings/_components/content-section.tsx +20 -0
  54. package/templates/default/apps/admin/src/app/dashboard/settings/_components/sidebar-nav.tsx +66 -0
  55. package/templates/default/apps/admin/src/app/dashboard/settings/account/page.tsx +173 -0
  56. package/templates/default/apps/admin/src/app/dashboard/settings/appearance/page.tsx +156 -0
  57. package/templates/default/apps/admin/src/app/dashboard/settings/display/page.tsx +125 -0
  58. package/templates/default/apps/admin/src/app/dashboard/settings/layout.tsx +30 -0
  59. package/templates/default/apps/admin/src/app/dashboard/settings/notifications/page.tsx +196 -0
  60. package/templates/default/apps/admin/src/app/dashboard/settings/page.tsx +5 -0
  61. package/templates/default/apps/admin/src/app/dashboard/settings/profile/page.tsx +176 -0
  62. package/templates/default/apps/admin/src/app/dashboard/tasks/_components/data-table-bulk-actions.tsx +183 -0
  63. package/templates/default/apps/admin/src/app/dashboard/tasks/_components/data-table-row-actions.tsx +79 -0
  64. package/templates/default/apps/admin/src/app/dashboard/tasks/_components/tasks-columns.tsx +107 -0
  65. package/templates/default/apps/admin/src/app/dashboard/tasks/_components/tasks-dialogs.tsx +71 -0
  66. package/templates/default/apps/admin/src/app/dashboard/tasks/_components/tasks-import-dialog.tsx +106 -0
  67. package/templates/default/apps/admin/src/app/dashboard/tasks/_components/tasks-multi-delete-dialog.tsx +90 -0
  68. package/templates/default/apps/admin/src/app/dashboard/tasks/_components/tasks-mutate-drawer.tsx +207 -0
  69. package/templates/default/apps/admin/src/app/dashboard/tasks/_components/tasks-page.tsx +31 -0
  70. package/templates/default/apps/admin/src/app/dashboard/tasks/_components/tasks-primary-buttons.tsx +19 -0
  71. package/templates/default/apps/admin/src/app/dashboard/tasks/_components/tasks-provider.tsx +37 -0
  72. package/templates/default/apps/admin/src/app/dashboard/tasks/_components/tasks-table.tsx +155 -0
  73. package/templates/default/apps/admin/src/app/dashboard/tasks/page.tsx +14 -0
  74. package/templates/default/apps/admin/src/app/dashboard/users/_components/data-table-bulk-actions.tsx +136 -0
  75. package/templates/default/apps/admin/src/app/dashboard/users/_components/data-table-row-actions.tsx +62 -0
  76. package/templates/default/apps/admin/src/app/dashboard/users/_components/users-action-dialog.tsx +297 -0
  77. package/templates/default/apps/admin/src/app/dashboard/users/_components/users-columns.tsx +121 -0
  78. package/templates/default/apps/admin/src/app/dashboard/users/_components/users-delete-dialog.tsx +72 -0
  79. package/templates/default/apps/admin/src/app/dashboard/users/_components/users-dialogs.tsx +49 -0
  80. package/templates/default/apps/admin/src/app/dashboard/users/_components/users-invite-dialog.tsx +139 -0
  81. package/templates/default/apps/admin/src/app/dashboard/users/_components/users-multi-delete-dialog.tsx +89 -0
  82. package/templates/default/apps/admin/src/app/dashboard/users/_components/users-page.tsx +30 -0
  83. package/templates/default/apps/admin/src/app/dashboard/users/_components/users-primary-buttons.tsx +19 -0
  84. package/templates/default/apps/admin/src/app/dashboard/users/_components/users-provider.tsx +35 -0
  85. package/templates/default/apps/admin/src/app/dashboard/users/_components/users-table.tsx +157 -0
  86. package/templates/default/apps/admin/src/app/dashboard/users/page.tsx +10 -0
  87. package/templates/default/apps/admin/src/app/globals.css +109 -0
  88. package/templates/default/apps/admin/src/app/layout.tsx +32 -0
  89. package/templates/default/apps/admin/src/app/not-found.tsx +14 -0
  90. package/templates/default/apps/admin/src/app/page.tsx +5 -0
  91. package/templates/default/apps/admin/src/components/layout/admin-layout.tsx +16 -0
  92. package/templates/default/apps/admin/src/components/layout/app-sidebar.tsx +52 -0
  93. package/templates/default/apps/admin/src/components/layout/nav-config.ts +131 -0
  94. package/templates/default/apps/admin/src/components/providers/theme-provider.tsx +10 -0
  95. package/templates/default/apps/admin/src/components/shared/long-text.tsx +78 -0
  96. package/templates/default/apps/admin/src/components/shared/search-input.tsx +16 -0
  97. package/templates/default/apps/admin/src/components/shared/select-dropdown.tsx +64 -0
  98. package/templates/default/apps/admin/src/data/apps.tsx +116 -0
  99. package/templates/default/apps/admin/src/data/chats.ts +114 -0
  100. package/templates/default/apps/admin/src/data/tasks.ts +114 -0
  101. package/templates/default/apps/admin/src/data/users.ts +90 -0
  102. package/templates/default/apps/admin/src/hooks/use-dialog-state.ts +17 -0
  103. package/templates/default/apps/admin/src/hooks/use-table-url-state.ts +243 -0
  104. package/templates/default/apps/admin/src/lib/show-submitted-data.tsx +12 -0
  105. package/templates/default/apps/admin/src/types/table.d.ts +9 -0
  106. package/templates/default/apps/admin/tsconfig.json +32 -0
  107. package/templates/default/apps/web/next.config.ts +1 -0
  108. package/templates/default/apps/web/package.json +1 -22
  109. package/templates/default/apps/web/postcss.config.cjs +0 -1
  110. package/templates/default/apps/web/src/app/(authenticated)/dashboard/page.tsx +4 -20
  111. package/templates/default/apps/web/src/app/(authenticated)/data/_components/UserTable.tsx +4 -4
  112. package/templates/default/apps/web/src/app/(authenticated)/data/page.tsx +1 -1
  113. package/templates/default/apps/web/src/app/(authenticated)/profile/page.tsx +1 -1
  114. package/templates/default/apps/web/src/app/error.tsx +8 -70
  115. package/templates/default/apps/web/src/app/global-error.tsx +8 -70
  116. package/templates/default/apps/web/src/app/globals.css +20 -0
  117. package/templates/default/apps/web/src/app/not-found.tsx +5 -39
  118. package/templates/default/apps/web/src/app/page.tsx +27 -203
  119. package/templates/default/apps/web/src/app/signin/page.tsx +27 -191
  120. package/templates/default/apps/web/src/app/signup/page.tsx +33 -240
  121. package/templates/default/apps/web/src/components/dashboard/dashboard-stats.tsx +11 -75
  122. package/templates/default/apps/web/src/components/shared/Sidebar.tsx +3 -3
  123. package/templates/default/apps/web/src/components/shared/header.tsx +17 -112
  124. package/templates/default/apps/web/tsconfig.json +0 -6
  125. package/templates/default/biome.json +30 -2
  126. package/templates/default/components.json +2 -2
  127. package/templates/default/docker-compose.yml +1 -1
  128. package/templates/default/gitignore +4 -0
  129. package/templates/default/package.json +2 -0
  130. package/templates/default/packages/admin-ui/catalog/catalog.css +54 -0
  131. package/templates/default/packages/admin-ui/catalog/catalog.tsx +401 -0
  132. package/templates/default/packages/admin-ui/catalog/index.html +12 -0
  133. package/templates/default/packages/admin-ui/catalog/main.tsx +9 -0
  134. package/templates/default/packages/admin-ui/components.json +21 -0
  135. package/templates/default/packages/admin-ui/package.json +105 -0
  136. package/templates/default/packages/admin-ui/src/command-menu/index.tsx +174 -0
  137. package/templates/default/packages/admin-ui/src/data-table/bulk-actions.tsx +215 -0
  138. package/templates/default/packages/admin-ui/src/data-table/column-header.tsx +73 -0
  139. package/templates/default/packages/admin-ui/src/data-table/data-table.tsx +127 -0
  140. package/templates/default/packages/admin-ui/src/data-table/faceted-filter.tsx +148 -0
  141. package/templates/default/packages/admin-ui/src/data-table/index.tsx +9 -0
  142. package/templates/default/packages/admin-ui/src/data-table/pagination.tsx +101 -0
  143. package/templates/default/packages/admin-ui/src/data-table/toolbar.tsx +87 -0
  144. package/templates/default/packages/admin-ui/src/data-table/view-options.tsx +57 -0
  145. package/templates/default/packages/admin-ui/src/hooks/use-mobile.tsx +23 -0
  146. package/templates/default/packages/admin-ui/src/layout/header.tsx +55 -0
  147. package/templates/default/packages/admin-ui/src/layout/index.ts +10 -0
  148. package/templates/default/packages/admin-ui/src/layout/main.tsx +23 -0
  149. package/templates/default/packages/admin-ui/src/layout/nav-group.tsx +111 -0
  150. package/templates/default/packages/admin-ui/src/layout/nav-user.tsx +114 -0
  151. package/templates/default/packages/admin-ui/src/layout/theme-switch.tsx +40 -0
  152. package/templates/default/packages/admin-ui/src/layout/types.ts +21 -0
  153. package/templates/default/packages/admin-ui/src/lib/utils.ts +6 -0
  154. package/templates/default/packages/admin-ui/src/styles/base.css +65 -0
  155. package/templates/default/packages/admin-ui/src/styles/tokens.css +91 -0
  156. package/templates/default/packages/admin-ui/src/tanstack-table.d.ts +10 -0
  157. package/templates/default/packages/admin-ui/src/ui/alert-dialog.tsx +157 -0
  158. package/templates/default/packages/admin-ui/src/ui/alert.tsx +66 -0
  159. package/templates/default/packages/admin-ui/src/ui/avatar.tsx +53 -0
  160. package/templates/default/packages/admin-ui/src/ui/badge.tsx +46 -0
  161. package/templates/default/packages/admin-ui/src/ui/breadcrumb.tsx +108 -0
  162. package/templates/default/packages/admin-ui/src/ui/button.tsx +59 -0
  163. package/templates/default/packages/admin-ui/src/ui/calendar.tsx +69 -0
  164. package/templates/default/packages/admin-ui/src/ui/card.tsx +92 -0
  165. package/templates/default/packages/admin-ui/src/ui/chart.tsx +345 -0
  166. package/templates/default/packages/admin-ui/src/ui/checkbox.tsx +32 -0
  167. package/templates/default/packages/admin-ui/src/ui/collapsible.tsx +27 -0
  168. package/templates/default/packages/admin-ui/src/ui/command.tsx +161 -0
  169. package/templates/default/packages/admin-ui/src/ui/confirm-dialog.tsx +72 -0
  170. package/templates/default/packages/admin-ui/src/ui/date-picker.tsx +53 -0
  171. package/templates/default/packages/admin-ui/src/ui/dialog.tsx +143 -0
  172. package/templates/default/packages/admin-ui/src/ui/dropdown-menu.tsx +257 -0
  173. package/templates/default/packages/admin-ui/src/ui/form.tsx +168 -0
  174. package/templates/default/packages/admin-ui/src/ui/input-otp.tsx +84 -0
  175. package/templates/default/packages/admin-ui/src/ui/input.tsx +21 -0
  176. package/templates/default/packages/admin-ui/src/ui/label.tsx +24 -0
  177. package/templates/default/packages/admin-ui/src/ui/pagination.tsx +126 -0
  178. package/templates/default/packages/admin-ui/src/ui/password-input.tsx +46 -0
  179. package/templates/default/packages/admin-ui/src/ui/popover.tsx +48 -0
  180. package/templates/default/packages/admin-ui/src/ui/progress.tsx +31 -0
  181. package/templates/default/packages/admin-ui/src/ui/radio-group.tsx +45 -0
  182. package/templates/default/packages/admin-ui/src/ui/scroll-area.tsx +52 -0
  183. package/templates/default/packages/admin-ui/src/ui/select.tsx +185 -0
  184. package/templates/default/packages/admin-ui/src/ui/separator.tsx +28 -0
  185. package/templates/default/packages/admin-ui/src/ui/sheet.tsx +149 -0
  186. package/templates/default/packages/admin-ui/src/ui/sidebar.tsx +728 -0
  187. package/templates/default/packages/admin-ui/src/ui/skeleton.tsx +13 -0
  188. package/templates/default/packages/admin-ui/src/ui/sonner.tsx +25 -0
  189. package/templates/default/packages/admin-ui/src/ui/switch.tsx +31 -0
  190. package/templates/default/packages/admin-ui/src/ui/table.tsx +116 -0
  191. package/templates/default/packages/admin-ui/src/ui/tabs.tsx +66 -0
  192. package/templates/default/packages/admin-ui/src/ui/textarea.tsx +18 -0
  193. package/templates/default/packages/admin-ui/src/ui/toggle-group.tsx +60 -0
  194. package/templates/default/packages/admin-ui/src/ui/toggle.tsx +44 -0
  195. package/templates/default/packages/admin-ui/src/ui/tooltip.tsx +61 -0
  196. package/templates/default/packages/admin-ui/tsconfig.json +8 -0
  197. package/templates/default/packages/admin-ui/vite.config.ts +11 -0
  198. package/templates/default/packages/config/package.json +0 -2
  199. package/templates/default/packages/server-core/package.json +2 -0
  200. package/templates/default/packages/ui/components.json +21 -0
  201. package/templates/default/packages/ui/package.json +42 -5
  202. package/templates/default/packages/ui/src/accordion.tsx +1 -1
  203. package/templates/default/packages/ui/src/alert-dialog.tsx +4 -4
  204. package/templates/default/packages/ui/src/alert.tsx +1 -1
  205. package/templates/default/packages/ui/src/avatar.tsx +1 -1
  206. package/templates/default/packages/ui/src/badge.tsx +1 -1
  207. package/templates/default/packages/ui/src/breadcrumb.tsx +1 -1
  208. package/templates/default/packages/ui/src/button.tsx +1 -1
  209. package/templates/default/packages/ui/src/card.tsx +1 -1
  210. package/templates/default/packages/ui/src/checkbox.tsx +1 -1
  211. package/templates/default/packages/ui/src/dialog.tsx +3 -3
  212. package/templates/default/packages/ui/src/drawer.tsx +3 -3
  213. package/templates/default/packages/ui/src/dropdown-menu.tsx +3 -3
  214. package/templates/default/packages/ui/src/form.tsx +2 -2
  215. package/templates/default/packages/ui/src/hover-card.tsx +2 -2
  216. package/templates/default/packages/ui/src/input.tsx +1 -1
  217. package/templates/default/packages/ui/src/label.tsx +1 -1
  218. package/templates/default/packages/ui/src/pagination.tsx +2 -2
  219. package/templates/default/packages/ui/src/popover.tsx +2 -2
  220. package/templates/default/packages/ui/src/progress.tsx +1 -1
  221. package/templates/default/packages/ui/src/select.tsx +2 -2
  222. package/templates/default/packages/ui/src/separator.tsx +1 -1
  223. package/templates/default/packages/ui/src/skeleton.tsx +1 -1
  224. package/templates/default/packages/ui/src/table.tsx +1 -1
  225. package/templates/default/packages/ui/src/tabs.tsx +1 -1
  226. package/templates/default/packages/ui/src/textarea.tsx +1 -1
  227. package/templates/default/packages/ui/src/tooltip.tsx +3 -3
  228. package/templates/default/packages/ui/src/typography.tsx +1 -1
  229. package/templates/default/packages/ui/tsconfig.json +1 -6
  230. package/templates/default/pnpm-lock.yaml +1319 -936
  231. package/templates/default/postcss.config.cjs +0 -1
  232. package/templates/default/turbo.json +17 -8
  233. package/templates/default/worktree.config.json +5 -0
  234. package/templates/default/.env.ci +0 -32
  235. package/templates/default/.github/workflows/ci.yml +0 -99
  236. package/templates/default/.github/workflows/preview-db.yml +0 -134
  237. package/templates/default/.playwright-mcp/dashboard.png +0 -0
  238. package/templates/default/.playwright-mcp/web-home.png +0 -0
  239. package/templates/default/apps/web/panda.config.ts +0 -114
  240. package/templates/default/apps/web/src/components/ui/accordion.tsx +0 -64
  241. package/templates/default/apps/web/src/components/ui/alert-dialog.tsx +0 -135
  242. package/templates/default/apps/web/src/components/ui/alert.tsx +0 -60
  243. package/templates/default/apps/web/src/components/ui/aspect-ratio.tsx +0 -9
  244. package/templates/default/apps/web/src/components/ui/avatar.tsx +0 -41
  245. package/templates/default/apps/web/src/components/ui/badge.tsx +0 -39
  246. package/templates/default/apps/web/src/components/ui/breadcrumb.tsx +0 -101
  247. package/templates/default/apps/web/src/components/ui/button.tsx +0 -56
  248. package/templates/default/apps/web/src/components/ui/card.tsx +0 -75
  249. package/templates/default/apps/web/src/components/ui/checkbox.tsx +0 -29
  250. package/templates/default/apps/web/src/components/ui/data-table.tsx +0 -189
  251. package/templates/default/apps/web/src/components/ui/dialog-hook.tsx +0 -210
  252. package/templates/default/apps/web/src/components/ui/dialog.tsx +0 -129
  253. package/templates/default/apps/web/src/components/ui/drawer.tsx +0 -124
  254. package/templates/default/apps/web/src/components/ui/dropdown-menu.tsx +0 -228
  255. package/templates/default/apps/web/src/components/ui/form.tsx +0 -152
  256. package/templates/default/apps/web/src/components/ui/hover-card.tsx +0 -38
  257. package/templates/default/apps/web/src/components/ui/input.tsx +0 -21
  258. package/templates/default/apps/web/src/components/ui/label.tsx +0 -21
  259. package/templates/default/apps/web/src/components/ui/pagination.tsx +0 -105
  260. package/templates/default/apps/web/src/components/ui/popover.tsx +0 -42
  261. package/templates/default/apps/web/src/components/ui/progress.tsx +0 -28
  262. package/templates/default/apps/web/src/components/ui/select.tsx +0 -170
  263. package/templates/default/apps/web/src/components/ui/separator.tsx +0 -28
  264. package/templates/default/apps/web/src/components/ui/skeleton.tsx +0 -13
  265. package/templates/default/apps/web/src/components/ui/sonner.tsx +0 -25
  266. package/templates/default/apps/web/src/components/ui/table.tsx +0 -92
  267. package/templates/default/apps/web/src/components/ui/tabs.tsx +0 -54
  268. package/templates/default/apps/web/src/components/ui/textarea.tsx +0 -18
  269. package/templates/default/apps/web/src/components/ui/tooltip.tsx +0 -57
  270. package/templates/default/apps/web/src/components/ui/typography.tsx +0 -158
  271. package/templates/default/packages/config/panda.config.ts +0 -114
  272. 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 };