@getjack/jack 0.1.32 → 0.1.34

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 (196) hide show
  1. package/package.json +1 -1
  2. package/src/commands/deploys.ts +95 -0
  3. package/src/commands/link.ts +8 -0
  4. package/src/commands/mcp.ts +179 -4
  5. package/src/commands/rollback.ts +53 -0
  6. package/src/commands/secrets.ts +3 -1
  7. package/src/commands/services.ts +11 -1
  8. package/src/commands/ship.ts +3 -1
  9. package/src/commands/tokens.ts +16 -1
  10. package/src/commands/whoami.ts +43 -8
  11. package/src/index.ts +16 -0
  12. package/src/lib/agent-files.ts +54 -4
  13. package/src/lib/agent-integration.ts +4 -166
  14. package/src/lib/claude-hooks-installer.ts +55 -0
  15. package/src/lib/control-plane.ts +78 -40
  16. package/src/lib/crypto.ts +84 -0
  17. package/src/lib/debug.ts +2 -1
  18. package/src/lib/deploy-upload.ts +13 -3
  19. package/src/lib/hooks.ts +4 -3
  20. package/src/lib/managed-deploy.ts +12 -9
  21. package/src/lib/project-link.ts +6 -0
  22. package/src/lib/project-operations.ts +92 -30
  23. package/src/lib/prompts.ts +2 -2
  24. package/src/lib/telemetry.ts +2 -0
  25. package/src/mcp/README.md +1 -1
  26. package/src/mcp/resources/index.ts +1 -16
  27. package/src/mcp/server.ts +23 -0
  28. package/src/mcp/tools/index.ts +133 -17
  29. package/src/mcp/types.ts +1 -0
  30. package/src/mcp/utils.ts +2 -1
  31. package/src/templates/index.ts +25 -73
  32. package/templates/CLAUDE.md +62 -0
  33. package/templates/ai-chat/.jack.json +10 -5
  34. package/templates/ai-chat/bun.lock +50 -1
  35. package/templates/ai-chat/package.json +5 -0
  36. package/templates/ai-chat/public/app.js +73 -0
  37. package/templates/ai-chat/public/index.html +14 -197
  38. package/templates/ai-chat/schema.sql +14 -0
  39. package/templates/ai-chat/src/index.ts +86 -102
  40. package/templates/ai-chat/wrangler.jsonc +8 -1
  41. package/templates/cron/.jack.json +66 -0
  42. package/templates/cron/bun.lock +23 -0
  43. package/templates/cron/package.json +16 -0
  44. package/templates/cron/schema.sql +24 -0
  45. package/templates/cron/src/index.ts +117 -0
  46. package/templates/cron/src/jobs.ts +139 -0
  47. package/templates/cron/src/webhooks.ts +95 -0
  48. package/templates/cron/tsconfig.json +17 -0
  49. package/templates/cron/wrangler.jsonc +11 -0
  50. package/templates/miniapp/.jack.json +1 -1
  51. package/templates/nextjs/.jack.json +1 -1
  52. package/templates/nextjs-auth/.jack.json +44 -0
  53. package/templates/nextjs-auth/app/api/auth/[...all]/route.ts +11 -0
  54. package/templates/nextjs-auth/app/dashboard/loading.tsx +53 -0
  55. package/templates/nextjs-auth/app/dashboard/page.tsx +73 -0
  56. package/templates/nextjs-auth/app/error.tsx +44 -0
  57. package/templates/nextjs-auth/app/globals.css +1 -0
  58. package/templates/nextjs-auth/app/health/route.ts +3 -0
  59. package/templates/nextjs-auth/app/layout.tsx +24 -0
  60. package/templates/nextjs-auth/app/login/page.tsx +10 -0
  61. package/templates/nextjs-auth/app/page.tsx +86 -0
  62. package/templates/nextjs-auth/app/signup/page.tsx +10 -0
  63. package/templates/nextjs-auth/bun.lock +1065 -0
  64. package/templates/nextjs-auth/cloudflare-env.d.ts +8 -0
  65. package/templates/nextjs-auth/components/auth-form.tsx +191 -0
  66. package/templates/nextjs-auth/components/header.tsx +50 -0
  67. package/templates/nextjs-auth/components/user-menu.tsx +23 -0
  68. package/templates/nextjs-auth/lib/auth-client.ts +3 -0
  69. package/templates/nextjs-auth/lib/auth.ts +43 -0
  70. package/templates/nextjs-auth/lib/utils.ts +6 -0
  71. package/templates/nextjs-auth/middleware.ts +33 -0
  72. package/templates/nextjs-auth/next.config.ts +8 -0
  73. package/templates/nextjs-auth/open-next.config.ts +6 -0
  74. package/templates/nextjs-auth/package.json +33 -0
  75. package/templates/nextjs-auth/postcss.config.mjs +8 -0
  76. package/templates/nextjs-auth/schema.sql +49 -0
  77. package/templates/nextjs-auth/tsconfig.json +28 -0
  78. package/templates/nextjs-auth/wrangler.jsonc +23 -0
  79. package/templates/nextjs-clerk/.jack.json +54 -0
  80. package/templates/nextjs-clerk/app/dashboard/page.tsx +69 -0
  81. package/templates/nextjs-clerk/app/globals.css +1 -0
  82. package/templates/nextjs-clerk/app/health/route.ts +3 -0
  83. package/templates/nextjs-clerk/app/layout.tsx +28 -0
  84. package/templates/nextjs-clerk/app/page.tsx +86 -0
  85. package/templates/nextjs-clerk/app/sign-in/[[...sign-in]]/page.tsx +9 -0
  86. package/templates/nextjs-clerk/app/sign-up/[[...sign-up]]/page.tsx +9 -0
  87. package/templates/nextjs-clerk/bun.lock +1055 -0
  88. package/templates/nextjs-clerk/cloudflare-env.d.ts +3 -0
  89. package/templates/nextjs-clerk/components/header.tsx +40 -0
  90. package/templates/nextjs-clerk/lib/utils.ts +6 -0
  91. package/templates/nextjs-clerk/middleware.ts +18 -0
  92. package/templates/nextjs-clerk/next.config.ts +8 -0
  93. package/templates/nextjs-clerk/open-next.config.ts +6 -0
  94. package/templates/nextjs-clerk/package.json +31 -0
  95. package/templates/nextjs-clerk/postcss.config.mjs +8 -0
  96. package/templates/nextjs-clerk/tsconfig.json +28 -0
  97. package/templates/nextjs-clerk/wrangler.jsonc +17 -0
  98. package/templates/nextjs-shadcn/.jack.json +34 -0
  99. package/templates/nextjs-shadcn/app/dashboard/data.json +614 -0
  100. package/templates/nextjs-shadcn/app/dashboard/page.tsx +55 -0
  101. package/templates/nextjs-shadcn/app/globals.css +126 -0
  102. package/templates/nextjs-shadcn/app/health/route.ts +3 -0
  103. package/templates/nextjs-shadcn/app/layout.tsx +24 -0
  104. package/templates/nextjs-shadcn/app/login/page.tsx +19 -0
  105. package/templates/nextjs-shadcn/app/page.tsx +180 -0
  106. package/templates/nextjs-shadcn/app/showcase.tsx +1262 -0
  107. package/templates/nextjs-shadcn/bun.lock +1789 -0
  108. package/templates/nextjs-shadcn/cloudflare-env.d.ts +4 -0
  109. package/templates/nextjs-shadcn/components/app-sidebar.tsx +175 -0
  110. package/templates/nextjs-shadcn/components/chart-area-interactive.tsx +291 -0
  111. package/templates/nextjs-shadcn/components/data-table.tsx +807 -0
  112. package/templates/nextjs-shadcn/components/login-form.tsx +95 -0
  113. package/templates/nextjs-shadcn/components/nav-documents.tsx +92 -0
  114. package/templates/nextjs-shadcn/components/nav-main.tsx +73 -0
  115. package/templates/nextjs-shadcn/components/nav-projects.tsx +89 -0
  116. package/templates/nextjs-shadcn/components/nav-secondary.tsx +42 -0
  117. package/templates/nextjs-shadcn/components/nav-user.tsx +114 -0
  118. package/templates/nextjs-shadcn/components/section-cards.tsx +102 -0
  119. package/templates/nextjs-shadcn/components/site-header.tsx +30 -0
  120. package/templates/nextjs-shadcn/components/team-switcher.tsx +91 -0
  121. package/templates/nextjs-shadcn/components/ui/accordion.tsx +66 -0
  122. package/templates/nextjs-shadcn/components/ui/alert-dialog.tsx +196 -0
  123. package/templates/nextjs-shadcn/components/ui/alert.tsx +66 -0
  124. package/templates/nextjs-shadcn/components/ui/aspect-ratio.tsx +11 -0
  125. package/templates/nextjs-shadcn/components/ui/avatar.tsx +109 -0
  126. package/templates/nextjs-shadcn/components/ui/badge.tsx +48 -0
  127. package/templates/nextjs-shadcn/components/ui/breadcrumb.tsx +109 -0
  128. package/templates/nextjs-shadcn/components/ui/button-group.tsx +83 -0
  129. package/templates/nextjs-shadcn/components/ui/button.tsx +64 -0
  130. package/templates/nextjs-shadcn/components/ui/calendar.tsx +220 -0
  131. package/templates/nextjs-shadcn/components/ui/card.tsx +92 -0
  132. package/templates/nextjs-shadcn/components/ui/carousel.tsx +241 -0
  133. package/templates/nextjs-shadcn/components/ui/chart.tsx +357 -0
  134. package/templates/nextjs-shadcn/components/ui/checkbox.tsx +32 -0
  135. package/templates/nextjs-shadcn/components/ui/collapsible.tsx +33 -0
  136. package/templates/nextjs-shadcn/components/ui/combobox.tsx +310 -0
  137. package/templates/nextjs-shadcn/components/ui/command.tsx +184 -0
  138. package/templates/nextjs-shadcn/components/ui/context-menu.tsx +252 -0
  139. package/templates/nextjs-shadcn/components/ui/dialog.tsx +158 -0
  140. package/templates/nextjs-shadcn/components/ui/direction.tsx +22 -0
  141. package/templates/nextjs-shadcn/components/ui/drawer.tsx +135 -0
  142. package/templates/nextjs-shadcn/components/ui/dropdown-menu.tsx +257 -0
  143. package/templates/nextjs-shadcn/components/ui/empty.tsx +104 -0
  144. package/templates/nextjs-shadcn/components/ui/field.tsx +248 -0
  145. package/templates/nextjs-shadcn/components/ui/form.tsx +167 -0
  146. package/templates/nextjs-shadcn/components/ui/hover-card.tsx +44 -0
  147. package/templates/nextjs-shadcn/components/ui/input-group.tsx +170 -0
  148. package/templates/nextjs-shadcn/components/ui/input-otp.tsx +77 -0
  149. package/templates/nextjs-shadcn/components/ui/input.tsx +21 -0
  150. package/templates/nextjs-shadcn/components/ui/item.tsx +193 -0
  151. package/templates/nextjs-shadcn/components/ui/kbd.tsx +28 -0
  152. package/templates/nextjs-shadcn/components/ui/label.tsx +24 -0
  153. package/templates/nextjs-shadcn/components/ui/menubar.tsx +276 -0
  154. package/templates/nextjs-shadcn/components/ui/native-select.tsx +53 -0
  155. package/templates/nextjs-shadcn/components/ui/navigation-menu.tsx +168 -0
  156. package/templates/nextjs-shadcn/components/ui/pagination.tsx +127 -0
  157. package/templates/nextjs-shadcn/components/ui/popover.tsx +89 -0
  158. package/templates/nextjs-shadcn/components/ui/progress.tsx +31 -0
  159. package/templates/nextjs-shadcn/components/ui/radio-group.tsx +45 -0
  160. package/templates/nextjs-shadcn/components/ui/resizable.tsx +53 -0
  161. package/templates/nextjs-shadcn/components/ui/scroll-area.tsx +58 -0
  162. package/templates/nextjs-shadcn/components/ui/select.tsx +190 -0
  163. package/templates/nextjs-shadcn/components/ui/separator.tsx +28 -0
  164. package/templates/nextjs-shadcn/components/ui/sheet.tsx +143 -0
  165. package/templates/nextjs-shadcn/components/ui/sidebar.tsx +726 -0
  166. package/templates/nextjs-shadcn/components/ui/skeleton.tsx +13 -0
  167. package/templates/nextjs-shadcn/components/ui/slider.tsx +63 -0
  168. package/templates/nextjs-shadcn/components/ui/sonner.tsx +40 -0
  169. package/templates/nextjs-shadcn/components/ui/spinner.tsx +16 -0
  170. package/templates/nextjs-shadcn/components/ui/switch.tsx +35 -0
  171. package/templates/nextjs-shadcn/components/ui/table.tsx +116 -0
  172. package/templates/nextjs-shadcn/components/ui/tabs.tsx +91 -0
  173. package/templates/nextjs-shadcn/components/ui/textarea.tsx +18 -0
  174. package/templates/nextjs-shadcn/components/ui/toggle-group.tsx +83 -0
  175. package/templates/nextjs-shadcn/components/ui/toggle.tsx +47 -0
  176. package/templates/nextjs-shadcn/components/ui/tooltip.tsx +57 -0
  177. package/templates/nextjs-shadcn/components.json +23 -0
  178. package/templates/nextjs-shadcn/hooks/use-mobile.ts +19 -0
  179. package/templates/nextjs-shadcn/lib/utils.ts +6 -0
  180. package/templates/nextjs-shadcn/next-env.d.ts +6 -0
  181. package/templates/nextjs-shadcn/next.config.ts +8 -0
  182. package/templates/nextjs-shadcn/open-next.config.ts +6 -0
  183. package/templates/nextjs-shadcn/package.json +55 -0
  184. package/templates/nextjs-shadcn/postcss.config.mjs +8 -0
  185. package/templates/nextjs-shadcn/tsconfig.json +28 -0
  186. package/templates/nextjs-shadcn/wrangler.jsonc +23 -0
  187. package/templates/resend/.jack.json +64 -0
  188. package/templates/resend/bun.lock +23 -0
  189. package/templates/resend/package.json +16 -0
  190. package/templates/resend/schema.sql +13 -0
  191. package/templates/resend/src/email.ts +165 -0
  192. package/templates/resend/src/index.ts +108 -0
  193. package/templates/resend/tsconfig.json +17 -0
  194. package/templates/resend/wrangler.jsonc +11 -0
  195. package/templates/saas/.jack.json +1 -1
  196. package/templates/ai-chat/public/chat.js +0 -149
@@ -0,0 +1,13 @@
1
+ import { cn } from "@/lib/utils"
2
+
3
+ function Skeleton({ className, ...props }: React.ComponentProps<"div">) {
4
+ return (
5
+ <div
6
+ data-slot="skeleton"
7
+ className={cn("bg-accent animate-pulse rounded-md", className)}
8
+ {...props}
9
+ />
10
+ )
11
+ }
12
+
13
+ export { Skeleton }
@@ -0,0 +1,63 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import { Slider as SliderPrimitive } from "radix-ui"
5
+
6
+ import { cn } from "@/lib/utils"
7
+
8
+ function Slider({
9
+ className,
10
+ defaultValue,
11
+ value,
12
+ min = 0,
13
+ max = 100,
14
+ ...props
15
+ }: React.ComponentProps<typeof SliderPrimitive.Root>) {
16
+ const _values = React.useMemo(
17
+ () =>
18
+ Array.isArray(value)
19
+ ? value
20
+ : Array.isArray(defaultValue)
21
+ ? defaultValue
22
+ : [min, max],
23
+ [value, defaultValue, min, max]
24
+ )
25
+
26
+ return (
27
+ <SliderPrimitive.Root
28
+ data-slot="slider"
29
+ defaultValue={defaultValue}
30
+ value={value}
31
+ min={min}
32
+ max={max}
33
+ className={cn(
34
+ "relative flex w-full touch-none items-center select-none data-[disabled]:opacity-50 data-[orientation=vertical]:h-full data-[orientation=vertical]:min-h-44 data-[orientation=vertical]:w-auto data-[orientation=vertical]:flex-col",
35
+ className
36
+ )}
37
+ {...props}
38
+ >
39
+ <SliderPrimitive.Track
40
+ data-slot="slider-track"
41
+ className={cn(
42
+ "bg-muted relative grow overflow-hidden rounded-full data-[orientation=horizontal]:h-1.5 data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-1.5"
43
+ )}
44
+ >
45
+ <SliderPrimitive.Range
46
+ data-slot="slider-range"
47
+ className={cn(
48
+ "bg-primary absolute data-[orientation=horizontal]:h-full data-[orientation=vertical]:w-full"
49
+ )}
50
+ />
51
+ </SliderPrimitive.Track>
52
+ {Array.from({ length: _values.length }, (_, index) => (
53
+ <SliderPrimitive.Thumb
54
+ data-slot="slider-thumb"
55
+ key={index}
56
+ className="border-primary ring-ring/50 block size-4 shrink-0 rounded-full border bg-white shadow-sm transition-[color,box-shadow] hover:ring-4 focus-visible:ring-4 focus-visible:outline-hidden disabled:pointer-events-none disabled:opacity-50"
57
+ />
58
+ ))}
59
+ </SliderPrimitive.Root>
60
+ )
61
+ }
62
+
63
+ export { Slider }
@@ -0,0 +1,40 @@
1
+ "use client"
2
+
3
+ import {
4
+ CircleCheckIcon,
5
+ InfoIcon,
6
+ Loader2Icon,
7
+ OctagonXIcon,
8
+ TriangleAlertIcon,
9
+ } from "lucide-react"
10
+ import { useTheme } from "next-themes"
11
+ import { Toaster as Sonner, type ToasterProps } from "sonner"
12
+
13
+ const Toaster = ({ ...props }: ToasterProps) => {
14
+ const { theme = "system" } = useTheme()
15
+
16
+ return (
17
+ <Sonner
18
+ theme={theme as ToasterProps["theme"]}
19
+ className="toaster group"
20
+ icons={{
21
+ success: <CircleCheckIcon className="size-4" />,
22
+ info: <InfoIcon className="size-4" />,
23
+ warning: <TriangleAlertIcon className="size-4" />,
24
+ error: <OctagonXIcon className="size-4" />,
25
+ loading: <Loader2Icon className="size-4 animate-spin" />,
26
+ }}
27
+ style={
28
+ {
29
+ "--normal-bg": "var(--popover)",
30
+ "--normal-text": "var(--popover-foreground)",
31
+ "--normal-border": "var(--border)",
32
+ "--border-radius": "var(--radius)",
33
+ } as React.CSSProperties
34
+ }
35
+ {...props}
36
+ />
37
+ )
38
+ }
39
+
40
+ export { Toaster }
@@ -0,0 +1,16 @@
1
+ import { Loader2Icon } from "lucide-react"
2
+
3
+ import { cn } from "@/lib/utils"
4
+
5
+ function Spinner({ className, ...props }: React.ComponentProps<"svg">) {
6
+ return (
7
+ <Loader2Icon
8
+ role="status"
9
+ aria-label="Loading"
10
+ className={cn("size-4 animate-spin", className)}
11
+ {...props}
12
+ />
13
+ )
14
+ }
15
+
16
+ export { Spinner }
@@ -0,0 +1,35 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import { Switch as SwitchPrimitive } from "radix-ui"
5
+
6
+ import { cn } from "@/lib/utils"
7
+
8
+ function Switch({
9
+ className,
10
+ size = "default",
11
+ ...props
12
+ }: React.ComponentProps<typeof SwitchPrimitive.Root> & {
13
+ size?: "sm" | "default"
14
+ }) {
15
+ return (
16
+ <SwitchPrimitive.Root
17
+ data-slot="switch"
18
+ data-size={size}
19
+ className={cn(
20
+ "peer data-[state=checked]:bg-primary data-[state=unchecked]:bg-input focus-visible:border-ring focus-visible:ring-ring/50 dark:data-[state=unchecked]:bg-input/80 group/switch inline-flex shrink-0 items-center rounded-full border border-transparent shadow-xs transition-all outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-[1.15rem] data-[size=default]:w-8 data-[size=sm]:h-3.5 data-[size=sm]:w-6",
21
+ className
22
+ )}
23
+ {...props}
24
+ >
25
+ <SwitchPrimitive.Thumb
26
+ data-slot="switch-thumb"
27
+ className={cn(
28
+ "bg-background dark:data-[state=unchecked]:bg-foreground dark:data-[state=checked]:bg-primary-foreground pointer-events-none block rounded-full ring-0 transition-transform group-data-[size=default]/switch:size-4 group-data-[size=sm]/switch:size-3 data-[state=checked]:translate-x-[calc(100%-2px)] data-[state=unchecked]:translate-x-0"
29
+ )}
30
+ />
31
+ </SwitchPrimitive.Root>
32
+ )
33
+ }
34
+
35
+ export { Switch }
@@ -0,0 +1,116 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+
5
+ import { cn } from "@/lib/utils"
6
+
7
+ function Table({ className, ...props }: React.ComponentProps<"table">) {
8
+ return (
9
+ <div
10
+ data-slot="table-container"
11
+ className="relative w-full overflow-x-auto"
12
+ >
13
+ <table
14
+ data-slot="table"
15
+ className={cn("w-full caption-bottom text-sm", className)}
16
+ {...props}
17
+ />
18
+ </div>
19
+ )
20
+ }
21
+
22
+ function TableHeader({ className, ...props }: React.ComponentProps<"thead">) {
23
+ return (
24
+ <thead
25
+ data-slot="table-header"
26
+ className={cn("[&_tr]:border-b", className)}
27
+ {...props}
28
+ />
29
+ )
30
+ }
31
+
32
+ function TableBody({ className, ...props }: React.ComponentProps<"tbody">) {
33
+ return (
34
+ <tbody
35
+ data-slot="table-body"
36
+ className={cn("[&_tr:last-child]:border-0", className)}
37
+ {...props}
38
+ />
39
+ )
40
+ }
41
+
42
+ function TableFooter({ className, ...props }: React.ComponentProps<"tfoot">) {
43
+ return (
44
+ <tfoot
45
+ data-slot="table-footer"
46
+ className={cn(
47
+ "bg-muted/50 border-t font-medium [&>tr]:last:border-b-0",
48
+ className
49
+ )}
50
+ {...props}
51
+ />
52
+ )
53
+ }
54
+
55
+ function TableRow({ className, ...props }: React.ComponentProps<"tr">) {
56
+ return (
57
+ <tr
58
+ data-slot="table-row"
59
+ className={cn(
60
+ "hover:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors",
61
+ className
62
+ )}
63
+ {...props}
64
+ />
65
+ )
66
+ }
67
+
68
+ function TableHead({ className, ...props }: React.ComponentProps<"th">) {
69
+ return (
70
+ <th
71
+ data-slot="table-head"
72
+ className={cn(
73
+ "text-foreground h-10 px-2 text-left align-middle font-medium whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
74
+ className
75
+ )}
76
+ {...props}
77
+ />
78
+ )
79
+ }
80
+
81
+ function TableCell({ className, ...props }: React.ComponentProps<"td">) {
82
+ return (
83
+ <td
84
+ data-slot="table-cell"
85
+ className={cn(
86
+ "p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
87
+ className
88
+ )}
89
+ {...props}
90
+ />
91
+ )
92
+ }
93
+
94
+ function TableCaption({
95
+ className,
96
+ ...props
97
+ }: React.ComponentProps<"caption">) {
98
+ return (
99
+ <caption
100
+ data-slot="table-caption"
101
+ className={cn("text-muted-foreground mt-4 text-sm", className)}
102
+ {...props}
103
+ />
104
+ )
105
+ }
106
+
107
+ export {
108
+ Table,
109
+ TableHeader,
110
+ TableBody,
111
+ TableFooter,
112
+ TableHead,
113
+ TableRow,
114
+ TableCell,
115
+ TableCaption,
116
+ }
@@ -0,0 +1,91 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import { cva, type VariantProps } from "class-variance-authority"
5
+ import { Tabs as TabsPrimitive } from "radix-ui"
6
+
7
+ import { cn } from "@/lib/utils"
8
+
9
+ function Tabs({
10
+ className,
11
+ orientation = "horizontal",
12
+ ...props
13
+ }: React.ComponentProps<typeof TabsPrimitive.Root>) {
14
+ return (
15
+ <TabsPrimitive.Root
16
+ data-slot="tabs"
17
+ data-orientation={orientation}
18
+ orientation={orientation}
19
+ className={cn(
20
+ "group/tabs flex gap-2 data-[orientation=horizontal]:flex-col",
21
+ className
22
+ )}
23
+ {...props}
24
+ />
25
+ )
26
+ }
27
+
28
+ const tabsListVariants = cva(
29
+ "rounded-lg p-[3px] group-data-[orientation=horizontal]/tabs:h-9 data-[variant=line]:rounded-none group/tabs-list text-muted-foreground inline-flex w-fit items-center justify-center group-data-[orientation=vertical]/tabs:h-fit group-data-[orientation=vertical]/tabs:flex-col",
30
+ {
31
+ variants: {
32
+ variant: {
33
+ default: "bg-muted",
34
+ line: "gap-1 bg-transparent",
35
+ },
36
+ },
37
+ defaultVariants: {
38
+ variant: "default",
39
+ },
40
+ }
41
+ )
42
+
43
+ function TabsList({
44
+ className,
45
+ variant = "default",
46
+ ...props
47
+ }: React.ComponentProps<typeof TabsPrimitive.List> &
48
+ VariantProps<typeof tabsListVariants>) {
49
+ return (
50
+ <TabsPrimitive.List
51
+ data-slot="tabs-list"
52
+ data-variant={variant}
53
+ className={cn(tabsListVariants({ variant }), className)}
54
+ {...props}
55
+ />
56
+ )
57
+ }
58
+
59
+ function TabsTrigger({
60
+ className,
61
+ ...props
62
+ }: React.ComponentProps<typeof TabsPrimitive.Trigger>) {
63
+ return (
64
+ <TabsPrimitive.Trigger
65
+ data-slot="tabs-trigger"
66
+ className={cn(
67
+ "focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring text-foreground/60 hover:text-foreground dark:text-muted-foreground dark:hover:text-foreground relative inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-2 py-1 text-sm font-medium whitespace-nowrap transition-all group-data-[orientation=vertical]/tabs:w-full group-data-[orientation=vertical]/tabs:justify-start focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 group-data-[variant=default]/tabs-list:data-[state=active]:shadow-sm group-data-[variant=line]/tabs-list:data-[state=active]:shadow-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
68
+ "group-data-[variant=line]/tabs-list:bg-transparent group-data-[variant=line]/tabs-list:data-[state=active]:bg-transparent dark:group-data-[variant=line]/tabs-list:data-[state=active]:border-transparent dark:group-data-[variant=line]/tabs-list:data-[state=active]:bg-transparent",
69
+ "data-[state=active]:bg-background dark:data-[state=active]:text-foreground dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/30 data-[state=active]:text-foreground",
70
+ "after:bg-foreground after:absolute after:opacity-0 after:transition-opacity group-data-[orientation=horizontal]/tabs:after:inset-x-0 group-data-[orientation=horizontal]/tabs:after:bottom-[-5px] group-data-[orientation=horizontal]/tabs:after:h-0.5 group-data-[orientation=vertical]/tabs:after:inset-y-0 group-data-[orientation=vertical]/tabs:after:-right-1 group-data-[orientation=vertical]/tabs:after:w-0.5 group-data-[variant=line]/tabs-list:data-[state=active]:after:opacity-100",
71
+ className
72
+ )}
73
+ {...props}
74
+ />
75
+ )
76
+ }
77
+
78
+ function TabsContent({
79
+ className,
80
+ ...props
81
+ }: React.ComponentProps<typeof TabsPrimitive.Content>) {
82
+ return (
83
+ <TabsPrimitive.Content
84
+ data-slot="tabs-content"
85
+ className={cn("flex-1 outline-none", className)}
86
+ {...props}
87
+ />
88
+ )
89
+ }
90
+
91
+ export { Tabs, TabsList, TabsTrigger, TabsContent, tabsListVariants }
@@ -0,0 +1,18 @@
1
+ import * as React from "react"
2
+
3
+ import { cn } from "@/lib/utils"
4
+
5
+ function Textarea({ className, ...props }: React.ComponentProps<"textarea">) {
6
+ return (
7
+ <textarea
8
+ data-slot="textarea"
9
+ className={cn(
10
+ "border-input placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
11
+ className
12
+ )}
13
+ {...props}
14
+ />
15
+ )
16
+ }
17
+
18
+ export { Textarea }
@@ -0,0 +1,83 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import { type VariantProps } from "class-variance-authority"
5
+ import { ToggleGroup as ToggleGroupPrimitive } from "radix-ui"
6
+
7
+ import { cn } from "@/lib/utils"
8
+ import { toggleVariants } from "@/components/ui/toggle"
9
+
10
+ const ToggleGroupContext = React.createContext<
11
+ VariantProps<typeof toggleVariants> & {
12
+ spacing?: number
13
+ }
14
+ >({
15
+ size: "default",
16
+ variant: "default",
17
+ spacing: 0,
18
+ })
19
+
20
+ function ToggleGroup({
21
+ className,
22
+ variant,
23
+ size,
24
+ spacing = 0,
25
+ children,
26
+ ...props
27
+ }: React.ComponentProps<typeof ToggleGroupPrimitive.Root> &
28
+ VariantProps<typeof toggleVariants> & {
29
+ spacing?: number
30
+ }) {
31
+ return (
32
+ <ToggleGroupPrimitive.Root
33
+ data-slot="toggle-group"
34
+ data-variant={variant}
35
+ data-size={size}
36
+ data-spacing={spacing}
37
+ style={{ "--gap": spacing } as React.CSSProperties}
38
+ className={cn(
39
+ "group/toggle-group flex w-fit items-center gap-[--spacing(var(--gap))] rounded-md data-[spacing=default]:data-[variant=outline]:shadow-xs",
40
+ className
41
+ )}
42
+ {...props}
43
+ >
44
+ <ToggleGroupContext.Provider value={{ variant, size, spacing }}>
45
+ {children}
46
+ </ToggleGroupContext.Provider>
47
+ </ToggleGroupPrimitive.Root>
48
+ )
49
+ }
50
+
51
+ function ToggleGroupItem({
52
+ className,
53
+ children,
54
+ variant,
55
+ size,
56
+ ...props
57
+ }: React.ComponentProps<typeof ToggleGroupPrimitive.Item> &
58
+ VariantProps<typeof toggleVariants>) {
59
+ const context = React.useContext(ToggleGroupContext)
60
+
61
+ return (
62
+ <ToggleGroupPrimitive.Item
63
+ data-slot="toggle-group-item"
64
+ data-variant={context.variant || variant}
65
+ data-size={context.size || size}
66
+ data-spacing={context.spacing}
67
+ className={cn(
68
+ toggleVariants({
69
+ variant: context.variant || variant,
70
+ size: context.size || size,
71
+ }),
72
+ "w-auto min-w-0 shrink-0 px-3 focus:z-10 focus-visible:z-10",
73
+ "data-[spacing=0]:rounded-none data-[spacing=0]:shadow-none data-[spacing=0]:first:rounded-l-md data-[spacing=0]:last:rounded-r-md data-[spacing=0]:data-[variant=outline]:border-l-0 data-[spacing=0]:data-[variant=outline]:first:border-l",
74
+ className
75
+ )}
76
+ {...props}
77
+ >
78
+ {children}
79
+ </ToggleGroupPrimitive.Item>
80
+ )
81
+ }
82
+
83
+ export { ToggleGroup, ToggleGroupItem }
@@ -0,0 +1,47 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import { cva, type VariantProps } from "class-variance-authority"
5
+ import { Toggle as TogglePrimitive } from "radix-ui"
6
+
7
+ import { cn } from "@/lib/utils"
8
+
9
+ const toggleVariants = cva(
10
+ "inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium hover:bg-muted hover:text-muted-foreground disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0 focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] outline-none transition-[color,box-shadow] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive whitespace-nowrap",
11
+ {
12
+ variants: {
13
+ variant: {
14
+ default: "bg-transparent",
15
+ outline:
16
+ "border border-input bg-transparent shadow-xs hover:bg-accent hover:text-accent-foreground",
17
+ },
18
+ size: {
19
+ default: "h-9 px-2 min-w-9",
20
+ sm: "h-8 px-1.5 min-w-8",
21
+ lg: "h-10 px-2.5 min-w-10",
22
+ },
23
+ },
24
+ defaultVariants: {
25
+ variant: "default",
26
+ size: "default",
27
+ },
28
+ }
29
+ )
30
+
31
+ function Toggle({
32
+ className,
33
+ variant,
34
+ size,
35
+ ...props
36
+ }: React.ComponentProps<typeof TogglePrimitive.Root> &
37
+ VariantProps<typeof toggleVariants>) {
38
+ return (
39
+ <TogglePrimitive.Root
40
+ data-slot="toggle"
41
+ className={cn(toggleVariants({ variant, size, className }))}
42
+ {...props}
43
+ />
44
+ )
45
+ }
46
+
47
+ export { Toggle, toggleVariants }
@@ -0,0 +1,57 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import { Tooltip as TooltipPrimitive } from "radix-ui"
5
+
6
+ import { cn } from "@/lib/utils"
7
+
8
+ function TooltipProvider({
9
+ delayDuration = 0,
10
+ ...props
11
+ }: React.ComponentProps<typeof TooltipPrimitive.Provider>) {
12
+ return (
13
+ <TooltipPrimitive.Provider
14
+ data-slot="tooltip-provider"
15
+ delayDuration={delayDuration}
16
+ {...props}
17
+ />
18
+ )
19
+ }
20
+
21
+ function Tooltip({
22
+ ...props
23
+ }: React.ComponentProps<typeof TooltipPrimitive.Root>) {
24
+ return <TooltipPrimitive.Root data-slot="tooltip" {...props} />
25
+ }
26
+
27
+ function TooltipTrigger({
28
+ ...props
29
+ }: React.ComponentProps<typeof TooltipPrimitive.Trigger>) {
30
+ return <TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props} />
31
+ }
32
+
33
+ function TooltipContent({
34
+ className,
35
+ sideOffset = 0,
36
+ children,
37
+ ...props
38
+ }: React.ComponentProps<typeof TooltipPrimitive.Content>) {
39
+ return (
40
+ <TooltipPrimitive.Portal>
41
+ <TooltipPrimitive.Content
42
+ data-slot="tooltip-content"
43
+ sideOffset={sideOffset}
44
+ className={cn(
45
+ "bg-foreground text-background animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-fit origin-(--radix-tooltip-content-transform-origin) rounded-md px-3 py-1.5 text-xs text-balance",
46
+ className
47
+ )}
48
+ {...props}
49
+ >
50
+ {children}
51
+ <TooltipPrimitive.Arrow className="bg-foreground fill-foreground z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]" />
52
+ </TooltipPrimitive.Content>
53
+ </TooltipPrimitive.Portal>
54
+ )
55
+ }
56
+
57
+ export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }
@@ -0,0 +1,23 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema.json",
3
+ "style": "new-york",
4
+ "rsc": true,
5
+ "tsx": true,
6
+ "tailwind": {
7
+ "config": "",
8
+ "css": "app/globals.css",
9
+ "baseColor": "zinc",
10
+ "cssVariables": true,
11
+ "prefix": ""
12
+ },
13
+ "iconLibrary": "lucide",
14
+ "rtl": false,
15
+ "aliases": {
16
+ "components": "@/components",
17
+ "utils": "@/lib/utils",
18
+ "ui": "@/components/ui",
19
+ "lib": "@/lib",
20
+ "hooks": "@/hooks"
21
+ },
22
+ "registries": {}
23
+ }
@@ -0,0 +1,19 @@
1
+ import * as React from "react"
2
+
3
+ const MOBILE_BREAKPOINT = 768
4
+
5
+ export function useIsMobile() {
6
+ const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined)
7
+
8
+ React.useEffect(() => {
9
+ const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`)
10
+ const onChange = () => {
11
+ setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
12
+ }
13
+ mql.addEventListener("change", onChange)
14
+ setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
15
+ return () => mql.removeEventListener("change", onChange)
16
+ }, [])
17
+
18
+ return !!isMobile
19
+ }
@@ -0,0 +1,6 @@
1
+ import { type ClassValue, clsx } from "clsx";
2
+ import { twMerge } from "tailwind-merge";
3
+
4
+ export function cn(...inputs: ClassValue[]) {
5
+ return twMerge(clsx(inputs));
6
+ }
@@ -0,0 +1,6 @@
1
+ /// <reference types="next" />
2
+ /// <reference types="next/image-types/global" />
3
+ /// <reference path="./.next/types/routes.d.ts" />
4
+
5
+ // NOTE: This file should not be edited
6
+ // see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
@@ -0,0 +1,8 @@
1
+ import { initOpenNextCloudflareForDev } from "@opennextjs/cloudflare";
2
+ import type { NextConfig } from "next";
3
+
4
+ initOpenNextCloudflareForDev();
5
+
6
+ const nextConfig: NextConfig = {};
7
+
8
+ export default nextConfig;
@@ -0,0 +1,6 @@
1
+ import { defineCloudflareConfig } from "@opennextjs/cloudflare";
2
+ import r2IncrementalCache from "@opennextjs/cloudflare/overrides/incremental-cache/r2-incremental-cache";
3
+
4
+ export default defineCloudflareConfig({
5
+ incrementalCache: r2IncrementalCache,
6
+ });