@getjack/jack 0.1.31 → 0.1.33
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.
- package/package.json +1 -1
- package/src/commands/deploys.ts +95 -0
- package/src/commands/link.ts +8 -0
- package/src/commands/mcp.ts +179 -4
- package/src/commands/rollback.ts +53 -0
- package/src/commands/services.ts +100 -20
- package/src/commands/ship.ts +30 -3
- package/src/commands/tokens.ts +134 -0
- package/src/commands/whoami.ts +51 -12
- package/src/index.ts +33 -0
- package/src/lib/agent-files.ts +54 -4
- package/src/lib/agent-integration.ts +4 -166
- package/src/lib/auth/client.ts +11 -1
- package/src/lib/auth/guard.ts +1 -1
- package/src/lib/auth/store.ts +3 -0
- package/src/lib/claude-hooks-installer.ts +55 -0
- package/src/lib/control-plane.ts +78 -40
- package/src/lib/debug.ts +2 -1
- package/src/lib/deploy-upload.ts +6 -0
- package/src/lib/hooks.ts +3 -1
- package/src/lib/managed-deploy.ts +12 -9
- package/src/lib/project-link.ts +6 -0
- package/src/lib/project-operations.ts +68 -22
- package/src/lib/services/token-operations.ts +84 -0
- package/src/lib/telemetry.ts +6 -0
- package/src/mcp/README.md +1 -1
- package/src/mcp/resources/index.ts +174 -16
- package/src/mcp/server.ts +23 -0
- package/src/mcp/tools/index.ts +133 -17
- package/src/mcp/types.ts +1 -0
- package/src/mcp/utils.ts +2 -1
- package/src/templates/index.ts +25 -73
- package/templates/CLAUDE.md +41 -0
- package/templates/ai-chat/.jack.json +10 -5
- package/templates/ai-chat/bun.lock +50 -1
- package/templates/ai-chat/package.json +5 -0
- package/templates/ai-chat/public/app.js +73 -0
- package/templates/ai-chat/public/index.html +14 -197
- package/templates/ai-chat/schema.sql +14 -0
- package/templates/ai-chat/src/index.ts +86 -102
- package/templates/ai-chat/wrangler.jsonc +8 -1
- package/templates/cron/.jack.json +66 -0
- package/templates/cron/bun.lock +23 -0
- package/templates/cron/package.json +16 -0
- package/templates/cron/schema.sql +24 -0
- package/templates/cron/src/index.ts +117 -0
- package/templates/cron/src/jobs.ts +139 -0
- package/templates/cron/src/webhooks.ts +95 -0
- package/templates/cron/tsconfig.json +17 -0
- package/templates/cron/wrangler.jsonc +11 -0
- package/templates/miniapp/.jack.json +1 -1
- package/templates/nextjs/.jack.json +1 -1
- package/templates/nextjs-auth/.jack.json +44 -0
- package/templates/nextjs-auth/app/api/auth/[...all]/route.ts +11 -0
- package/templates/nextjs-auth/app/dashboard/loading.tsx +53 -0
- package/templates/nextjs-auth/app/dashboard/page.tsx +73 -0
- package/templates/nextjs-auth/app/error.tsx +44 -0
- package/templates/nextjs-auth/app/globals.css +1 -0
- package/templates/nextjs-auth/app/health/route.ts +3 -0
- package/templates/nextjs-auth/app/layout.tsx +24 -0
- package/templates/nextjs-auth/app/login/page.tsx +10 -0
- package/templates/nextjs-auth/app/page.tsx +86 -0
- package/templates/nextjs-auth/app/signup/page.tsx +10 -0
- package/templates/nextjs-auth/bun.lock +1065 -0
- package/templates/nextjs-auth/cloudflare-env.d.ts +8 -0
- package/templates/nextjs-auth/components/auth-form.tsx +191 -0
- package/templates/nextjs-auth/components/header.tsx +50 -0
- package/templates/nextjs-auth/components/user-menu.tsx +23 -0
- package/templates/nextjs-auth/lib/auth-client.ts +3 -0
- package/templates/nextjs-auth/lib/auth.ts +43 -0
- package/templates/nextjs-auth/lib/utils.ts +6 -0
- package/templates/nextjs-auth/middleware.ts +33 -0
- package/templates/nextjs-auth/next.config.ts +8 -0
- package/templates/nextjs-auth/open-next.config.ts +6 -0
- package/templates/nextjs-auth/package.json +33 -0
- package/templates/nextjs-auth/postcss.config.mjs +8 -0
- package/templates/nextjs-auth/schema.sql +49 -0
- package/templates/nextjs-auth/tsconfig.json +28 -0
- package/templates/nextjs-auth/wrangler.jsonc +23 -0
- package/templates/nextjs-clerk/.jack.json +54 -0
- package/templates/nextjs-clerk/app/dashboard/page.tsx +69 -0
- package/templates/nextjs-clerk/app/globals.css +1 -0
- package/templates/nextjs-clerk/app/health/route.ts +3 -0
- package/templates/nextjs-clerk/app/layout.tsx +26 -0
- package/templates/nextjs-clerk/app/page.tsx +86 -0
- package/templates/nextjs-clerk/app/sign-in/[[...sign-in]]/page.tsx +9 -0
- package/templates/nextjs-clerk/app/sign-up/[[...sign-up]]/page.tsx +9 -0
- package/templates/nextjs-clerk/bun.lock +1055 -0
- package/templates/nextjs-clerk/cloudflare-env.d.ts +3 -0
- package/templates/nextjs-clerk/components/header.tsx +40 -0
- package/templates/nextjs-clerk/lib/utils.ts +6 -0
- package/templates/nextjs-clerk/middleware.ts +18 -0
- package/templates/nextjs-clerk/next.config.ts +8 -0
- package/templates/nextjs-clerk/open-next.config.ts +6 -0
- package/templates/nextjs-clerk/package.json +31 -0
- package/templates/nextjs-clerk/postcss.config.mjs +8 -0
- package/templates/nextjs-clerk/tsconfig.json +28 -0
- package/templates/nextjs-clerk/wrangler.jsonc +17 -0
- package/templates/nextjs-shadcn/.jack.json +34 -0
- package/templates/nextjs-shadcn/app/dashboard/data.json +614 -0
- package/templates/nextjs-shadcn/app/dashboard/page.tsx +55 -0
- package/templates/nextjs-shadcn/app/globals.css +126 -0
- package/templates/nextjs-shadcn/app/health/route.ts +3 -0
- package/templates/nextjs-shadcn/app/layout.tsx +24 -0
- package/templates/nextjs-shadcn/app/login/page.tsx +19 -0
- package/templates/nextjs-shadcn/app/page.tsx +180 -0
- package/templates/nextjs-shadcn/app/showcase.tsx +1262 -0
- package/templates/nextjs-shadcn/bun.lock +1789 -0
- package/templates/nextjs-shadcn/cloudflare-env.d.ts +4 -0
- package/templates/nextjs-shadcn/components/app-sidebar.tsx +175 -0
- package/templates/nextjs-shadcn/components/chart-area-interactive.tsx +291 -0
- package/templates/nextjs-shadcn/components/data-table.tsx +807 -0
- package/templates/nextjs-shadcn/components/login-form.tsx +95 -0
- package/templates/nextjs-shadcn/components/nav-documents.tsx +92 -0
- package/templates/nextjs-shadcn/components/nav-main.tsx +73 -0
- package/templates/nextjs-shadcn/components/nav-projects.tsx +89 -0
- package/templates/nextjs-shadcn/components/nav-secondary.tsx +42 -0
- package/templates/nextjs-shadcn/components/nav-user.tsx +114 -0
- package/templates/nextjs-shadcn/components/section-cards.tsx +102 -0
- package/templates/nextjs-shadcn/components/site-header.tsx +30 -0
- package/templates/nextjs-shadcn/components/team-switcher.tsx +91 -0
- package/templates/nextjs-shadcn/components/ui/accordion.tsx +66 -0
- package/templates/nextjs-shadcn/components/ui/alert-dialog.tsx +196 -0
- package/templates/nextjs-shadcn/components/ui/alert.tsx +66 -0
- package/templates/nextjs-shadcn/components/ui/aspect-ratio.tsx +11 -0
- package/templates/nextjs-shadcn/components/ui/avatar.tsx +109 -0
- package/templates/nextjs-shadcn/components/ui/badge.tsx +48 -0
- package/templates/nextjs-shadcn/components/ui/breadcrumb.tsx +109 -0
- package/templates/nextjs-shadcn/components/ui/button-group.tsx +83 -0
- package/templates/nextjs-shadcn/components/ui/button.tsx +64 -0
- package/templates/nextjs-shadcn/components/ui/calendar.tsx +220 -0
- package/templates/nextjs-shadcn/components/ui/card.tsx +92 -0
- package/templates/nextjs-shadcn/components/ui/carousel.tsx +241 -0
- package/templates/nextjs-shadcn/components/ui/chart.tsx +357 -0
- package/templates/nextjs-shadcn/components/ui/checkbox.tsx +32 -0
- package/templates/nextjs-shadcn/components/ui/collapsible.tsx +33 -0
- package/templates/nextjs-shadcn/components/ui/combobox.tsx +310 -0
- package/templates/nextjs-shadcn/components/ui/command.tsx +184 -0
- package/templates/nextjs-shadcn/components/ui/context-menu.tsx +252 -0
- package/templates/nextjs-shadcn/components/ui/dialog.tsx +158 -0
- package/templates/nextjs-shadcn/components/ui/direction.tsx +22 -0
- package/templates/nextjs-shadcn/components/ui/drawer.tsx +135 -0
- package/templates/nextjs-shadcn/components/ui/dropdown-menu.tsx +257 -0
- package/templates/nextjs-shadcn/components/ui/empty.tsx +104 -0
- package/templates/nextjs-shadcn/components/ui/field.tsx +248 -0
- package/templates/nextjs-shadcn/components/ui/form.tsx +167 -0
- package/templates/nextjs-shadcn/components/ui/hover-card.tsx +44 -0
- package/templates/nextjs-shadcn/components/ui/input-group.tsx +170 -0
- package/templates/nextjs-shadcn/components/ui/input-otp.tsx +77 -0
- package/templates/nextjs-shadcn/components/ui/input.tsx +21 -0
- package/templates/nextjs-shadcn/components/ui/item.tsx +193 -0
- package/templates/nextjs-shadcn/components/ui/kbd.tsx +28 -0
- package/templates/nextjs-shadcn/components/ui/label.tsx +24 -0
- package/templates/nextjs-shadcn/components/ui/menubar.tsx +276 -0
- package/templates/nextjs-shadcn/components/ui/native-select.tsx +53 -0
- package/templates/nextjs-shadcn/components/ui/navigation-menu.tsx +168 -0
- package/templates/nextjs-shadcn/components/ui/pagination.tsx +127 -0
- package/templates/nextjs-shadcn/components/ui/popover.tsx +89 -0
- package/templates/nextjs-shadcn/components/ui/progress.tsx +31 -0
- package/templates/nextjs-shadcn/components/ui/radio-group.tsx +45 -0
- package/templates/nextjs-shadcn/components/ui/resizable.tsx +53 -0
- package/templates/nextjs-shadcn/components/ui/scroll-area.tsx +58 -0
- package/templates/nextjs-shadcn/components/ui/select.tsx +190 -0
- package/templates/nextjs-shadcn/components/ui/separator.tsx +28 -0
- package/templates/nextjs-shadcn/components/ui/sheet.tsx +143 -0
- package/templates/nextjs-shadcn/components/ui/sidebar.tsx +726 -0
- package/templates/nextjs-shadcn/components/ui/skeleton.tsx +13 -0
- package/templates/nextjs-shadcn/components/ui/slider.tsx +63 -0
- package/templates/nextjs-shadcn/components/ui/sonner.tsx +40 -0
- package/templates/nextjs-shadcn/components/ui/spinner.tsx +16 -0
- package/templates/nextjs-shadcn/components/ui/switch.tsx +35 -0
- package/templates/nextjs-shadcn/components/ui/table.tsx +116 -0
- package/templates/nextjs-shadcn/components/ui/tabs.tsx +91 -0
- package/templates/nextjs-shadcn/components/ui/textarea.tsx +18 -0
- package/templates/nextjs-shadcn/components/ui/toggle-group.tsx +83 -0
- package/templates/nextjs-shadcn/components/ui/toggle.tsx +47 -0
- package/templates/nextjs-shadcn/components/ui/tooltip.tsx +57 -0
- package/templates/nextjs-shadcn/components.json +23 -0
- package/templates/nextjs-shadcn/hooks/use-mobile.ts +19 -0
- package/templates/nextjs-shadcn/lib/utils.ts +6 -0
- package/templates/nextjs-shadcn/next-env.d.ts +6 -0
- package/templates/nextjs-shadcn/next.config.ts +8 -0
- package/templates/nextjs-shadcn/open-next.config.ts +6 -0
- package/templates/nextjs-shadcn/package.json +55 -0
- package/templates/nextjs-shadcn/postcss.config.mjs +8 -0
- package/templates/nextjs-shadcn/tsconfig.json +28 -0
- package/templates/nextjs-shadcn/wrangler.jsonc +23 -0
- package/templates/resend/.jack.json +64 -0
- package/templates/resend/bun.lock +23 -0
- package/templates/resend/package.json +16 -0
- package/templates/resend/schema.sql +13 -0
- package/templates/resend/src/email.ts +165 -0
- package/templates/resend/src/index.ts +108 -0
- package/templates/resend/tsconfig.json +17 -0
- package/templates/resend/wrangler.jsonc +11 -0
- package/templates/saas/.jack.json +1 -1
- package/templates/ai-chat/public/chat.js +0 -149
|
@@ -0,0 +1,1262 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
Accordion,
|
|
5
|
+
AccordionContent,
|
|
6
|
+
AccordionItem,
|
|
7
|
+
AccordionTrigger,
|
|
8
|
+
} from "@/components/ui/accordion";
|
|
9
|
+
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
|
10
|
+
import { Avatar, AvatarFallback } from "@/components/ui/avatar";
|
|
11
|
+
import { Badge } from "@/components/ui/badge";
|
|
12
|
+
import {
|
|
13
|
+
Breadcrumb,
|
|
14
|
+
BreadcrumbItem,
|
|
15
|
+
BreadcrumbLink,
|
|
16
|
+
BreadcrumbList,
|
|
17
|
+
BreadcrumbPage,
|
|
18
|
+
BreadcrumbSeparator,
|
|
19
|
+
} from "@/components/ui/breadcrumb";
|
|
20
|
+
import { Button } from "@/components/ui/button";
|
|
21
|
+
import { Calendar } from "@/components/ui/calendar";
|
|
22
|
+
import {
|
|
23
|
+
Card,
|
|
24
|
+
CardContent,
|
|
25
|
+
CardHeader,
|
|
26
|
+
CardTitle,
|
|
27
|
+
} from "@/components/ui/card";
|
|
28
|
+
import {
|
|
29
|
+
Carousel,
|
|
30
|
+
CarouselContent,
|
|
31
|
+
CarouselItem,
|
|
32
|
+
CarouselNext,
|
|
33
|
+
CarouselPrevious,
|
|
34
|
+
} from "@/components/ui/carousel";
|
|
35
|
+
import { Checkbox } from "@/components/ui/checkbox";
|
|
36
|
+
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible";
|
|
37
|
+
import {
|
|
38
|
+
Command,
|
|
39
|
+
CommandEmpty,
|
|
40
|
+
CommandGroup,
|
|
41
|
+
CommandInput,
|
|
42
|
+
CommandItem,
|
|
43
|
+
CommandList,
|
|
44
|
+
CommandSeparator,
|
|
45
|
+
} from "@/components/ui/command";
|
|
46
|
+
import {
|
|
47
|
+
Dialog,
|
|
48
|
+
DialogContent,
|
|
49
|
+
DialogDescription,
|
|
50
|
+
DialogFooter,
|
|
51
|
+
DialogHeader,
|
|
52
|
+
DialogTitle,
|
|
53
|
+
DialogTrigger,
|
|
54
|
+
} from "@/components/ui/dialog";
|
|
55
|
+
import { HoverCard, HoverCardContent, HoverCardTrigger } from "@/components/ui/hover-card";
|
|
56
|
+
import { Input } from "@/components/ui/input";
|
|
57
|
+
import {
|
|
58
|
+
InputOTP,
|
|
59
|
+
InputOTPGroup,
|
|
60
|
+
InputOTPSeparator,
|
|
61
|
+
InputOTPSlot,
|
|
62
|
+
} from "@/components/ui/input-otp";
|
|
63
|
+
import { Label } from "@/components/ui/label";
|
|
64
|
+
import {
|
|
65
|
+
Pagination,
|
|
66
|
+
PaginationContent,
|
|
67
|
+
PaginationItem,
|
|
68
|
+
PaginationLink,
|
|
69
|
+
PaginationNext,
|
|
70
|
+
PaginationPrevious,
|
|
71
|
+
} from "@/components/ui/pagination";
|
|
72
|
+
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
|
|
73
|
+
import { Progress } from "@/components/ui/progress";
|
|
74
|
+
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
|
|
75
|
+
import { ScrollArea } from "@/components/ui/scroll-area";
|
|
76
|
+
import {
|
|
77
|
+
Select,
|
|
78
|
+
SelectContent,
|
|
79
|
+
SelectItem,
|
|
80
|
+
SelectTrigger,
|
|
81
|
+
SelectValue,
|
|
82
|
+
} from "@/components/ui/select";
|
|
83
|
+
import { Separator } from "@/components/ui/separator";
|
|
84
|
+
import {
|
|
85
|
+
Sheet,
|
|
86
|
+
SheetContent,
|
|
87
|
+
SheetDescription,
|
|
88
|
+
SheetHeader,
|
|
89
|
+
SheetTitle,
|
|
90
|
+
SheetTrigger,
|
|
91
|
+
} from "@/components/ui/sheet";
|
|
92
|
+
import { Skeleton } from "@/components/ui/skeleton";
|
|
93
|
+
import { Slider } from "@/components/ui/slider";
|
|
94
|
+
import { Spinner } from "@/components/ui/spinner";
|
|
95
|
+
import { Switch } from "@/components/ui/switch";
|
|
96
|
+
import {
|
|
97
|
+
Table,
|
|
98
|
+
TableBody,
|
|
99
|
+
TableCell,
|
|
100
|
+
TableHead,
|
|
101
|
+
TableHeader,
|
|
102
|
+
TableRow,
|
|
103
|
+
} from "@/components/ui/table";
|
|
104
|
+
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
|
105
|
+
import { Textarea } from "@/components/ui/textarea";
|
|
106
|
+
import { Toggle } from "@/components/ui/toggle";
|
|
107
|
+
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group";
|
|
108
|
+
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
|
|
109
|
+
import {
|
|
110
|
+
AlertCircle,
|
|
111
|
+
AlignCenter,
|
|
112
|
+
AlignLeft,
|
|
113
|
+
AlignRight,
|
|
114
|
+
Archive,
|
|
115
|
+
ArrowLeft,
|
|
116
|
+
Bell,
|
|
117
|
+
Bold,
|
|
118
|
+
CalendarIcon,
|
|
119
|
+
Check,
|
|
120
|
+
ChevronsUpDown,
|
|
121
|
+
Cloud,
|
|
122
|
+
Copy,
|
|
123
|
+
CreditCard,
|
|
124
|
+
FileText,
|
|
125
|
+
Flag,
|
|
126
|
+
Home,
|
|
127
|
+
Info,
|
|
128
|
+
Italic,
|
|
129
|
+
Laptop,
|
|
130
|
+
Loader2,
|
|
131
|
+
Mail,
|
|
132
|
+
Minus,
|
|
133
|
+
Monitor,
|
|
134
|
+
Moon,
|
|
135
|
+
MoreHorizontal,
|
|
136
|
+
Plus,
|
|
137
|
+
Search,
|
|
138
|
+
Settings,
|
|
139
|
+
Sun,
|
|
140
|
+
Terminal,
|
|
141
|
+
Underline,
|
|
142
|
+
User,
|
|
143
|
+
} from "lucide-react";
|
|
144
|
+
import { useState } from "react";
|
|
145
|
+
|
|
146
|
+
export function ComponentShowcase() {
|
|
147
|
+
const [sliderValue, setSliderValue] = useState([400]);
|
|
148
|
+
const [gpuCount, setGpuCount] = useState(8);
|
|
149
|
+
const [copied, setCopied] = useState(false);
|
|
150
|
+
const [selectedDate, setSelectedDate] = useState<Date | undefined>(new Date());
|
|
151
|
+
const [collapsibleOpen, setCollapsibleOpen] = useState(false);
|
|
152
|
+
|
|
153
|
+
return (
|
|
154
|
+
<div className="columns-1 gap-4 sm:columns-2 lg:columns-3 xl:columns-4 [&>*]:mb-4 [&>*]:break-inside-avoid">
|
|
155
|
+
{/* Payment Form */}
|
|
156
|
+
<Card>
|
|
157
|
+
<CardHeader>
|
|
158
|
+
<CardTitle className="text-base">Payment Method</CardTitle>
|
|
159
|
+
<p className="text-sm text-muted-foreground">
|
|
160
|
+
All transactions are secure and encrypted.
|
|
161
|
+
</p>
|
|
162
|
+
</CardHeader>
|
|
163
|
+
<CardContent className="space-y-4">
|
|
164
|
+
<div className="space-y-1">
|
|
165
|
+
<Label>Name on Card</Label>
|
|
166
|
+
<Input defaultValue="John Doe" />
|
|
167
|
+
</div>
|
|
168
|
+
<div className="grid grid-cols-2 gap-3">
|
|
169
|
+
<div className="space-y-1">
|
|
170
|
+
<Label>Card Number</Label>
|
|
171
|
+
<Input placeholder="1234 5678 9012 3456" />
|
|
172
|
+
</div>
|
|
173
|
+
<div className="space-y-1">
|
|
174
|
+
<Label>CVV</Label>
|
|
175
|
+
<Input placeholder="123" />
|
|
176
|
+
</div>
|
|
177
|
+
</div>
|
|
178
|
+
<p className="text-xs text-muted-foreground">Enter your 16-digit number.</p>
|
|
179
|
+
<div className="grid grid-cols-2 gap-3">
|
|
180
|
+
<div className="space-y-1">
|
|
181
|
+
<Label>Month</Label>
|
|
182
|
+
<Select>
|
|
183
|
+
<SelectTrigger>
|
|
184
|
+
<SelectValue placeholder="MM" />
|
|
185
|
+
</SelectTrigger>
|
|
186
|
+
<SelectContent>
|
|
187
|
+
{Array.from({ length: 12 }, (_, i) => (
|
|
188
|
+
<SelectItem key={i + 1} value={String(i + 1).padStart(2, "0")}>
|
|
189
|
+
{String(i + 1).padStart(2, "0")}
|
|
190
|
+
</SelectItem>
|
|
191
|
+
))}
|
|
192
|
+
</SelectContent>
|
|
193
|
+
</Select>
|
|
194
|
+
</div>
|
|
195
|
+
<div className="space-y-1">
|
|
196
|
+
<Label>Year</Label>
|
|
197
|
+
<Select>
|
|
198
|
+
<SelectTrigger>
|
|
199
|
+
<SelectValue placeholder="YYYY" />
|
|
200
|
+
</SelectTrigger>
|
|
201
|
+
<SelectContent>
|
|
202
|
+
{[2025, 2026, 2027, 2028, 2029].map((y) => (
|
|
203
|
+
<SelectItem key={y} value={String(y)}>
|
|
204
|
+
{y}
|
|
205
|
+
</SelectItem>
|
|
206
|
+
))}
|
|
207
|
+
</SelectContent>
|
|
208
|
+
</Select>
|
|
209
|
+
</div>
|
|
210
|
+
</div>
|
|
211
|
+
<Separator />
|
|
212
|
+
<div>
|
|
213
|
+
<h4 className="mb-1 font-medium text-sm">Billing Address</h4>
|
|
214
|
+
<p className="text-xs text-muted-foreground">
|
|
215
|
+
The billing address associated with your payment method
|
|
216
|
+
</p>
|
|
217
|
+
</div>
|
|
218
|
+
<div className="flex items-center gap-2">
|
|
219
|
+
<Checkbox id="same-address" defaultChecked />
|
|
220
|
+
<Label htmlFor="same-address">Same as shipping address</Label>
|
|
221
|
+
</div>
|
|
222
|
+
<Separator />
|
|
223
|
+
<div className="space-y-1">
|
|
224
|
+
<Label>Comments</Label>
|
|
225
|
+
<Textarea placeholder="Add any additional comments" />
|
|
226
|
+
</div>
|
|
227
|
+
<div className="flex gap-2">
|
|
228
|
+
<Button className="flex-1">Submit</Button>
|
|
229
|
+
<Button variant="outline" className="flex-1">
|
|
230
|
+
Cancel
|
|
231
|
+
</Button>
|
|
232
|
+
</div>
|
|
233
|
+
</CardContent>
|
|
234
|
+
</Card>
|
|
235
|
+
|
|
236
|
+
{/* Status Badges & Chat */}
|
|
237
|
+
<Card>
|
|
238
|
+
<CardContent className="space-y-4 pt-6">
|
|
239
|
+
<div className="flex items-center justify-center gap-2">
|
|
240
|
+
<Badge className="bg-emerald-500/10 text-emerald-500 border-emerald-500/20">
|
|
241
|
+
<span className="mr-1 inline-block size-1.5 rounded-full bg-emerald-500 animate-pulse" />
|
|
242
|
+
Syncing
|
|
243
|
+
</Badge>
|
|
244
|
+
<Badge className="bg-blue-500/10 text-blue-500 border-blue-500/20">
|
|
245
|
+
<span className="mr-1 inline-block size-1.5 rounded-full bg-blue-500 animate-pulse" />
|
|
246
|
+
Updating
|
|
247
|
+
</Badge>
|
|
248
|
+
<Badge className="bg-orange-500/10 text-orange-500 border-orange-500/20">
|
|
249
|
+
<span className="mr-1 inline-block size-1.5 rounded-full bg-orange-500 animate-pulse" />
|
|
250
|
+
Loading
|
|
251
|
+
</Badge>
|
|
252
|
+
</div>
|
|
253
|
+
<div className="rounded-lg border p-3">
|
|
254
|
+
<div className="flex items-center gap-2">
|
|
255
|
+
<Button variant="ghost" size="icon" className="size-8">
|
|
256
|
+
<Plus className="size-4" />
|
|
257
|
+
</Button>
|
|
258
|
+
<span className="flex-1 text-sm text-muted-foreground">Send a message...</span>
|
|
259
|
+
<Button variant="ghost" size="icon" className="size-8">
|
|
260
|
+
<ArrowLeft className="size-4 rotate-90" />
|
|
261
|
+
</Button>
|
|
262
|
+
</div>
|
|
263
|
+
</div>
|
|
264
|
+
<div>
|
|
265
|
+
<h4 className="font-medium text-sm">Price Range</h4>
|
|
266
|
+
<p className="text-xs text-muted-foreground mb-3">
|
|
267
|
+
Set your budget range (${sliderValue[0]} - $800).
|
|
268
|
+
</p>
|
|
269
|
+
<Slider defaultValue={[200, 800]} max={1000} step={50} onValueChange={setSliderValue} />
|
|
270
|
+
</div>
|
|
271
|
+
<div className="flex items-center gap-2 rounded-lg border px-3 py-2">
|
|
272
|
+
<Search className="size-4 text-muted-foreground" />
|
|
273
|
+
<span className="flex-1 text-sm text-muted-foreground">Search...</span>
|
|
274
|
+
<span className="text-xs text-muted-foreground">12 results</span>
|
|
275
|
+
</div>
|
|
276
|
+
<div className="flex items-center gap-2 rounded-lg border px-3 py-2">
|
|
277
|
+
<span className="flex-1 text-sm text-muted-foreground truncate">
|
|
278
|
+
https:// example.com
|
|
279
|
+
</span>
|
|
280
|
+
<Button
|
|
281
|
+
variant="ghost"
|
|
282
|
+
size="icon"
|
|
283
|
+
className="size-7"
|
|
284
|
+
onClick={() => {
|
|
285
|
+
setCopied(true);
|
|
286
|
+
setTimeout(() => setCopied(false), 2000);
|
|
287
|
+
}}
|
|
288
|
+
>
|
|
289
|
+
{copied ? <Check className="size-3.5" /> : <Copy className="size-3.5" />}
|
|
290
|
+
</Button>
|
|
291
|
+
</div>
|
|
292
|
+
<div className="rounded-lg border p-3 space-y-2">
|
|
293
|
+
<Textarea
|
|
294
|
+
placeholder="Ask, Search or Chat..."
|
|
295
|
+
className="border-0 p-0 shadow-none resize-none focus-visible:ring-0"
|
|
296
|
+
rows={2}
|
|
297
|
+
/>
|
|
298
|
+
<div className="flex items-center justify-between">
|
|
299
|
+
<div className="flex items-center gap-1">
|
|
300
|
+
<Button variant="ghost" size="icon" className="size-7">
|
|
301
|
+
<Plus className="size-4" />
|
|
302
|
+
</Button>
|
|
303
|
+
<span className="text-xs text-muted-foreground">Auto</span>
|
|
304
|
+
</div>
|
|
305
|
+
<div className="flex items-center gap-2">
|
|
306
|
+
<span className="text-xs text-muted-foreground">52% used</span>
|
|
307
|
+
<Button size="icon" className="size-7 rounded-full">
|
|
308
|
+
<ArrowLeft className="size-3 rotate-90" />
|
|
309
|
+
</Button>
|
|
310
|
+
</div>
|
|
311
|
+
</div>
|
|
312
|
+
</div>
|
|
313
|
+
<div className="flex items-center gap-2 rounded-lg border px-3 py-2">
|
|
314
|
+
<span className="text-sm">@shadcn</span>
|
|
315
|
+
<Check className="ml-auto size-4 text-blue-500" />
|
|
316
|
+
</div>
|
|
317
|
+
</CardContent>
|
|
318
|
+
</Card>
|
|
319
|
+
|
|
320
|
+
{/* Compute Environment (Radio Group) */}
|
|
321
|
+
<Card>
|
|
322
|
+
<CardHeader>
|
|
323
|
+
<CardTitle className="text-base">Compute Environment</CardTitle>
|
|
324
|
+
<p className="text-sm text-muted-foreground">
|
|
325
|
+
Select the compute environment for your cluster.
|
|
326
|
+
</p>
|
|
327
|
+
</CardHeader>
|
|
328
|
+
<CardContent className="space-y-4">
|
|
329
|
+
<RadioGroup defaultValue="kubernetes">
|
|
330
|
+
<div className="flex items-start gap-3 rounded-lg border p-3 data-[state=checked]:border-primary">
|
|
331
|
+
<RadioGroupItem value="kubernetes" id="k8s" className="mt-0.5" />
|
|
332
|
+
<div>
|
|
333
|
+
<Label htmlFor="k8s" className="font-medium">
|
|
334
|
+
Kubernetes
|
|
335
|
+
</Label>
|
|
336
|
+
<p className="text-xs text-muted-foreground">
|
|
337
|
+
Run GPU workloads on a K8s configured cluster. This is the default.
|
|
338
|
+
</p>
|
|
339
|
+
</div>
|
|
340
|
+
</div>
|
|
341
|
+
<div className="flex items-start gap-3 rounded-lg border p-3">
|
|
342
|
+
<RadioGroupItem value="vm" id="vm" className="mt-0.5" />
|
|
343
|
+
<div>
|
|
344
|
+
<Label htmlFor="vm" className="font-medium">
|
|
345
|
+
Virtual Machine
|
|
346
|
+
</Label>
|
|
347
|
+
<p className="text-xs text-muted-foreground">
|
|
348
|
+
Access a VM configured cluster to run workloads. (Coming soon)
|
|
349
|
+
</p>
|
|
350
|
+
</div>
|
|
351
|
+
</div>
|
|
352
|
+
</RadioGroup>
|
|
353
|
+
<Separator />
|
|
354
|
+
<div className="flex items-center justify-between">
|
|
355
|
+
<div>
|
|
356
|
+
<h4 className="font-medium text-sm">Number of GPUs</h4>
|
|
357
|
+
<p className="text-xs text-muted-foreground">You can add more later.</p>
|
|
358
|
+
</div>
|
|
359
|
+
<div className="flex items-center gap-1">
|
|
360
|
+
<Input className="w-14 text-center" value={gpuCount} readOnly />
|
|
361
|
+
<Button
|
|
362
|
+
variant="outline"
|
|
363
|
+
size="icon"
|
|
364
|
+
className="size-8"
|
|
365
|
+
onClick={() => setGpuCount(Math.max(1, gpuCount - 1))}
|
|
366
|
+
>
|
|
367
|
+
<Minus className="size-3" />
|
|
368
|
+
</Button>
|
|
369
|
+
<Button
|
|
370
|
+
variant="outline"
|
|
371
|
+
size="icon"
|
|
372
|
+
className="size-8"
|
|
373
|
+
onClick={() => setGpuCount(gpuCount + 1)}
|
|
374
|
+
>
|
|
375
|
+
<Plus className="size-3" />
|
|
376
|
+
</Button>
|
|
377
|
+
</div>
|
|
378
|
+
</div>
|
|
379
|
+
<Separator />
|
|
380
|
+
<div className="flex items-center justify-between">
|
|
381
|
+
<div>
|
|
382
|
+
<h4 className="font-medium text-sm">Wallpaper Tinting</h4>
|
|
383
|
+
<p className="text-xs text-muted-foreground">Allow the wallpaper to be tinted.</p>
|
|
384
|
+
</div>
|
|
385
|
+
<Switch defaultChecked />
|
|
386
|
+
</div>
|
|
387
|
+
</CardContent>
|
|
388
|
+
</Card>
|
|
389
|
+
|
|
390
|
+
{/* Actions Bar */}
|
|
391
|
+
<Card>
|
|
392
|
+
<CardContent className="space-y-4 pt-6">
|
|
393
|
+
<div className="flex items-center gap-1">
|
|
394
|
+
<Button variant="outline" size="icon" className="size-8">
|
|
395
|
+
<ArrowLeft className="size-4" />
|
|
396
|
+
</Button>
|
|
397
|
+
<div className="flex flex-1 items-center gap-1 justify-end">
|
|
398
|
+
<Button variant="outline" size="sm">
|
|
399
|
+
Archive
|
|
400
|
+
</Button>
|
|
401
|
+
<Button variant="outline" size="sm">
|
|
402
|
+
Report
|
|
403
|
+
</Button>
|
|
404
|
+
<Button variant="outline" size="sm">
|
|
405
|
+
Snooze
|
|
406
|
+
</Button>
|
|
407
|
+
<Button variant="outline" size="icon" className="size-8">
|
|
408
|
+
<MoreHorizontal className="size-4" />
|
|
409
|
+
</Button>
|
|
410
|
+
</div>
|
|
411
|
+
</div>
|
|
412
|
+
<div className="flex items-center gap-2">
|
|
413
|
+
<Checkbox id="terms" defaultChecked />
|
|
414
|
+
<Label htmlFor="terms">I agree to the terms and conditions</Label>
|
|
415
|
+
</div>
|
|
416
|
+
<Separator className="relative">
|
|
417
|
+
<span className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 bg-card px-2 text-xs text-muted-foreground">
|
|
418
|
+
Appearance Settings
|
|
419
|
+
</span>
|
|
420
|
+
</Separator>
|
|
421
|
+
<Pagination>
|
|
422
|
+
<PaginationContent>
|
|
423
|
+
<PaginationItem>
|
|
424
|
+
<PaginationPrevious href="#" />
|
|
425
|
+
</PaginationItem>
|
|
426
|
+
<PaginationItem>
|
|
427
|
+
<PaginationLink href="#" isActive>
|
|
428
|
+
1
|
|
429
|
+
</PaginationLink>
|
|
430
|
+
</PaginationItem>
|
|
431
|
+
<PaginationItem>
|
|
432
|
+
<PaginationLink href="#">2</PaginationLink>
|
|
433
|
+
</PaginationItem>
|
|
434
|
+
<PaginationItem>
|
|
435
|
+
<PaginationLink href="#">3</PaginationLink>
|
|
436
|
+
</PaginationItem>
|
|
437
|
+
<PaginationItem>
|
|
438
|
+
<PaginationNext href="#" />
|
|
439
|
+
</PaginationItem>
|
|
440
|
+
</PaginationContent>
|
|
441
|
+
</Pagination>
|
|
442
|
+
</CardContent>
|
|
443
|
+
</Card>
|
|
444
|
+
|
|
445
|
+
{/* Survey Toggle Group */}
|
|
446
|
+
<Card>
|
|
447
|
+
<CardHeader>
|
|
448
|
+
<CardTitle className="text-base">How did you hear about us?</CardTitle>
|
|
449
|
+
<p className="text-sm text-muted-foreground">Select the option that best describes...</p>
|
|
450
|
+
</CardHeader>
|
|
451
|
+
<CardContent className="space-y-4">
|
|
452
|
+
<ToggleGroup type="single" defaultValue="social" className="flex-wrap">
|
|
453
|
+
<ToggleGroupItem value="social" className="gap-1">
|
|
454
|
+
<Check className="size-3" />
|
|
455
|
+
Social Media
|
|
456
|
+
</ToggleGroupItem>
|
|
457
|
+
<ToggleGroupItem value="search">Search Engine</ToggleGroupItem>
|
|
458
|
+
<ToggleGroupItem value="referral">Referral</ToggleGroupItem>
|
|
459
|
+
<ToggleGroupItem value="other">Other</ToggleGroupItem>
|
|
460
|
+
</ToggleGroup>
|
|
461
|
+
<Separator />
|
|
462
|
+
<div className="flex flex-col items-center gap-2 py-4">
|
|
463
|
+
<Spinner className="size-6" />
|
|
464
|
+
<h4 className="font-medium text-sm">Processing your request</h4>
|
|
465
|
+
<p className="text-xs text-muted-foreground text-center">
|
|
466
|
+
Please wait while we process your request. Do not refresh the page.
|
|
467
|
+
</p>
|
|
468
|
+
<Button variant="outline" size="sm" className="mt-1">
|
|
469
|
+
Cancel
|
|
470
|
+
</Button>
|
|
471
|
+
</div>
|
|
472
|
+
</CardContent>
|
|
473
|
+
</Card>
|
|
474
|
+
|
|
475
|
+
{/* Text Formatting Toolbar */}
|
|
476
|
+
<Card>
|
|
477
|
+
<CardHeader>
|
|
478
|
+
<CardTitle className="text-base">Text Formatting</CardTitle>
|
|
479
|
+
</CardHeader>
|
|
480
|
+
<CardContent className="space-y-3">
|
|
481
|
+
<div className="flex items-center gap-1">
|
|
482
|
+
<Toggle size="sm" aria-label="Bold" defaultPressed>
|
|
483
|
+
<Bold className="size-4" />
|
|
484
|
+
</Toggle>
|
|
485
|
+
<Toggle size="sm" aria-label="Italic">
|
|
486
|
+
<Italic className="size-4" />
|
|
487
|
+
</Toggle>
|
|
488
|
+
<Toggle size="sm" aria-label="Underline">
|
|
489
|
+
<Underline className="size-4" />
|
|
490
|
+
</Toggle>
|
|
491
|
+
<Separator orientation="vertical" className="mx-1 h-6" />
|
|
492
|
+
<ToggleGroup type="single" defaultValue="left">
|
|
493
|
+
<ToggleGroupItem value="left" size="sm">
|
|
494
|
+
<AlignLeft className="size-4" />
|
|
495
|
+
</ToggleGroupItem>
|
|
496
|
+
<ToggleGroupItem value="center" size="sm">
|
|
497
|
+
<AlignCenter className="size-4" />
|
|
498
|
+
</ToggleGroupItem>
|
|
499
|
+
<ToggleGroupItem value="right" size="sm">
|
|
500
|
+
<AlignRight className="size-4" />
|
|
501
|
+
</ToggleGroupItem>
|
|
502
|
+
</ToggleGroup>
|
|
503
|
+
</div>
|
|
504
|
+
<ToggleGroup type="single" defaultValue="copilot" className="justify-start">
|
|
505
|
+
<ToggleGroupItem value="copilot" className="gap-1 text-xs">
|
|
506
|
+
<Cloud className="size-3" /> Copilot
|
|
507
|
+
</ToggleGroupItem>
|
|
508
|
+
<ToggleGroupItem value="local" className="gap-1 text-xs">
|
|
509
|
+
<Monitor className="size-3" /> Local
|
|
510
|
+
</ToggleGroupItem>
|
|
511
|
+
</ToggleGroup>
|
|
512
|
+
</CardContent>
|
|
513
|
+
</Card>
|
|
514
|
+
|
|
515
|
+
{/* Team Members */}
|
|
516
|
+
<Card>
|
|
517
|
+
<CardContent className="space-y-4 pt-6">
|
|
518
|
+
<div className="flex flex-col items-center gap-2 py-2">
|
|
519
|
+
<div className="flex -space-x-3">
|
|
520
|
+
<Avatar className="border-2 border-background">
|
|
521
|
+
<AvatarFallback>AB</AvatarFallback>
|
|
522
|
+
</Avatar>
|
|
523
|
+
<Avatar className="border-2 border-background">
|
|
524
|
+
<AvatarFallback>CD</AvatarFallback>
|
|
525
|
+
</Avatar>
|
|
526
|
+
</div>
|
|
527
|
+
<h4 className="font-medium text-sm">No Team Members</h4>
|
|
528
|
+
<p className="text-xs text-muted-foreground text-center">
|
|
529
|
+
Invite your team to collaborate on this project.
|
|
530
|
+
</p>
|
|
531
|
+
<Button variant="outline" size="sm">
|
|
532
|
+
<Plus className="mr-1 size-3" /> Invite Members
|
|
533
|
+
</Button>
|
|
534
|
+
</div>
|
|
535
|
+
</CardContent>
|
|
536
|
+
</Card>
|
|
537
|
+
|
|
538
|
+
{/* Data Table */}
|
|
539
|
+
<Card>
|
|
540
|
+
<CardHeader>
|
|
541
|
+
<CardTitle className="text-base">Recent Invoices</CardTitle>
|
|
542
|
+
</CardHeader>
|
|
543
|
+
<CardContent>
|
|
544
|
+
<Table>
|
|
545
|
+
<TableHeader>
|
|
546
|
+
<TableRow>
|
|
547
|
+
<TableHead>Invoice</TableHead>
|
|
548
|
+
<TableHead>Status</TableHead>
|
|
549
|
+
<TableHead className="text-right">Amount</TableHead>
|
|
550
|
+
</TableRow>
|
|
551
|
+
</TableHeader>
|
|
552
|
+
<TableBody>
|
|
553
|
+
<TableRow>
|
|
554
|
+
<TableCell className="font-medium">INV-001</TableCell>
|
|
555
|
+
<TableCell>
|
|
556
|
+
<Badge variant="secondary" className="bg-emerald-500/10 text-emerald-600">
|
|
557
|
+
Paid
|
|
558
|
+
</Badge>
|
|
559
|
+
</TableCell>
|
|
560
|
+
<TableCell className="text-right">$250.00</TableCell>
|
|
561
|
+
</TableRow>
|
|
562
|
+
<TableRow>
|
|
563
|
+
<TableCell className="font-medium">INV-002</TableCell>
|
|
564
|
+
<TableCell>
|
|
565
|
+
<Badge variant="secondary">Pending</Badge>
|
|
566
|
+
</TableCell>
|
|
567
|
+
<TableCell className="text-right">$150.00</TableCell>
|
|
568
|
+
</TableRow>
|
|
569
|
+
<TableRow>
|
|
570
|
+
<TableCell className="font-medium">INV-003</TableCell>
|
|
571
|
+
<TableCell>
|
|
572
|
+
<Badge variant="secondary" className="bg-red-500/10 text-red-600">
|
|
573
|
+
Overdue
|
|
574
|
+
</Badge>
|
|
575
|
+
</TableCell>
|
|
576
|
+
<TableCell className="text-right">$350.00</TableCell>
|
|
577
|
+
</TableRow>
|
|
578
|
+
</TableBody>
|
|
579
|
+
</Table>
|
|
580
|
+
</CardContent>
|
|
581
|
+
</Card>
|
|
582
|
+
|
|
583
|
+
{/* Skeleton Loading */}
|
|
584
|
+
<Card>
|
|
585
|
+
<CardHeader>
|
|
586
|
+
<CardTitle className="text-base">Loading States</CardTitle>
|
|
587
|
+
</CardHeader>
|
|
588
|
+
<CardContent className="space-y-4">
|
|
589
|
+
<div className="flex items-center gap-3">
|
|
590
|
+
<Skeleton className="size-10 rounded-full" />
|
|
591
|
+
<div className="flex-1 space-y-2">
|
|
592
|
+
<Skeleton className="h-4 w-3/4" />
|
|
593
|
+
<Skeleton className="h-3 w-1/2" />
|
|
594
|
+
</div>
|
|
595
|
+
</div>
|
|
596
|
+
<Skeleton className="h-24 w-full" />
|
|
597
|
+
<div className="flex gap-2">
|
|
598
|
+
<Skeleton className="h-9 w-20" />
|
|
599
|
+
<Skeleton className="h-9 w-20" />
|
|
600
|
+
</div>
|
|
601
|
+
</CardContent>
|
|
602
|
+
</Card>
|
|
603
|
+
|
|
604
|
+
{/* Progress & Stats */}
|
|
605
|
+
<Card>
|
|
606
|
+
<CardContent className="space-y-4 pt-6">
|
|
607
|
+
<Tabs defaultValue="overview">
|
|
608
|
+
<TabsList className="w-full">
|
|
609
|
+
<TabsTrigger value="overview" className="flex-1">
|
|
610
|
+
Overview
|
|
611
|
+
</TabsTrigger>
|
|
612
|
+
<TabsTrigger value="analytics" className="flex-1">
|
|
613
|
+
Analytics
|
|
614
|
+
</TabsTrigger>
|
|
615
|
+
</TabsList>
|
|
616
|
+
<TabsContent value="overview" className="mt-3 space-y-3">
|
|
617
|
+
<div className="space-y-1">
|
|
618
|
+
<div className="flex justify-between text-sm">
|
|
619
|
+
<span>Storage</span>
|
|
620
|
+
<span className="text-muted-foreground">75%</span>
|
|
621
|
+
</div>
|
|
622
|
+
<Progress value={75} />
|
|
623
|
+
</div>
|
|
624
|
+
<div className="space-y-1">
|
|
625
|
+
<div className="flex justify-between text-sm">
|
|
626
|
+
<span>Bandwidth</span>
|
|
627
|
+
<span className="text-muted-foreground">45%</span>
|
|
628
|
+
</div>
|
|
629
|
+
<Progress value={45} />
|
|
630
|
+
</div>
|
|
631
|
+
<div className="space-y-1">
|
|
632
|
+
<div className="flex justify-between text-sm">
|
|
633
|
+
<span>Requests</span>
|
|
634
|
+
<span className="text-muted-foreground">92%</span>
|
|
635
|
+
</div>
|
|
636
|
+
<Progress value={92} />
|
|
637
|
+
</div>
|
|
638
|
+
</TabsContent>
|
|
639
|
+
<TabsContent value="analytics" className="mt-3 space-y-3">
|
|
640
|
+
<div className="space-y-1">
|
|
641
|
+
<div className="flex justify-between text-sm">
|
|
642
|
+
<span>Page Views</span>
|
|
643
|
+
<span className="font-medium">12,543</span>
|
|
644
|
+
</div>
|
|
645
|
+
<Progress value={62} />
|
|
646
|
+
</div>
|
|
647
|
+
<div className="space-y-1">
|
|
648
|
+
<div className="flex justify-between text-sm">
|
|
649
|
+
<span>Bounce Rate</span>
|
|
650
|
+
<span className="font-medium">24%</span>
|
|
651
|
+
</div>
|
|
652
|
+
<Progress value={24} />
|
|
653
|
+
</div>
|
|
654
|
+
<div className="space-y-1">
|
|
655
|
+
<div className="flex justify-between text-sm">
|
|
656
|
+
<span>Avg. Session</span>
|
|
657
|
+
<span className="font-medium">3m 42s</span>
|
|
658
|
+
</div>
|
|
659
|
+
<Progress value={55} />
|
|
660
|
+
</div>
|
|
661
|
+
</TabsContent>
|
|
662
|
+
</Tabs>
|
|
663
|
+
</CardContent>
|
|
664
|
+
</Card>
|
|
665
|
+
|
|
666
|
+
{/* Accordion */}
|
|
667
|
+
<Card>
|
|
668
|
+
<CardHeader>
|
|
669
|
+
<CardTitle className="text-base">FAQ</CardTitle>
|
|
670
|
+
</CardHeader>
|
|
671
|
+
<CardContent>
|
|
672
|
+
<Accordion type="single" collapsible defaultValue="item-1">
|
|
673
|
+
<AccordionItem value="item-1">
|
|
674
|
+
<AccordionTrigger className="text-sm">What components are included?</AccordionTrigger>
|
|
675
|
+
<AccordionContent>
|
|
676
|
+
All 57 shadcn/ui components are pre-installed and ready to import.
|
|
677
|
+
</AccordionContent>
|
|
678
|
+
</AccordionItem>
|
|
679
|
+
<AccordionItem value="item-2">
|
|
680
|
+
<AccordionTrigger className="text-sm">How do I deploy?</AccordionTrigger>
|
|
681
|
+
<AccordionContent>
|
|
682
|
+
Run <code className="bg-muted px-1 rounded">jack ship</code> to deploy to production
|
|
683
|
+
instantly.
|
|
684
|
+
</AccordionContent>
|
|
685
|
+
</AccordionItem>
|
|
686
|
+
<AccordionItem value="item-3">
|
|
687
|
+
<AccordionTrigger className="text-sm">Is there a database?</AccordionTrigger>
|
|
688
|
+
<AccordionContent>
|
|
689
|
+
Yes, D1 SQLite database is included and globally replicated.
|
|
690
|
+
</AccordionContent>
|
|
691
|
+
</AccordionItem>
|
|
692
|
+
</Accordion>
|
|
693
|
+
</CardContent>
|
|
694
|
+
</Card>
|
|
695
|
+
|
|
696
|
+
{/* Buttons Grid */}
|
|
697
|
+
<Card>
|
|
698
|
+
<CardHeader>
|
|
699
|
+
<CardTitle className="text-base">Button Variants</CardTitle>
|
|
700
|
+
</CardHeader>
|
|
701
|
+
<CardContent className="space-y-3">
|
|
702
|
+
<div className="flex flex-wrap gap-2">
|
|
703
|
+
<Button size="sm">Primary</Button>
|
|
704
|
+
<Button size="sm" variant="secondary">
|
|
705
|
+
Secondary
|
|
706
|
+
</Button>
|
|
707
|
+
<Button size="sm" variant="outline">
|
|
708
|
+
Outline
|
|
709
|
+
</Button>
|
|
710
|
+
<Button size="sm" variant="destructive">
|
|
711
|
+
Destructive
|
|
712
|
+
</Button>
|
|
713
|
+
<Button size="sm" variant="ghost">
|
|
714
|
+
Ghost
|
|
715
|
+
</Button>
|
|
716
|
+
<Button size="sm" variant="link">
|
|
717
|
+
Link
|
|
718
|
+
</Button>
|
|
719
|
+
</div>
|
|
720
|
+
<Separator />
|
|
721
|
+
<div className="flex flex-wrap gap-2">
|
|
722
|
+
<Button size="sm" disabled>
|
|
723
|
+
<Loader2 className="mr-1 size-3 animate-spin" />
|
|
724
|
+
Loading
|
|
725
|
+
</Button>
|
|
726
|
+
<Button size="sm" variant="outline">
|
|
727
|
+
<CreditCard className="mr-1 size-3" />
|
|
728
|
+
Pay Now
|
|
729
|
+
</Button>
|
|
730
|
+
<Button size="sm" variant="outline">
|
|
731
|
+
<Archive className="mr-1 size-3" />
|
|
732
|
+
Archive
|
|
733
|
+
</Button>
|
|
734
|
+
<Button size="sm" variant="outline">
|
|
735
|
+
<Flag className="mr-1 size-3" />
|
|
736
|
+
Flag
|
|
737
|
+
</Button>
|
|
738
|
+
</div>
|
|
739
|
+
</CardContent>
|
|
740
|
+
</Card>
|
|
741
|
+
|
|
742
|
+
{/* Alerts */}
|
|
743
|
+
<Card>
|
|
744
|
+
<CardHeader>
|
|
745
|
+
<CardTitle className="text-base">Alerts</CardTitle>
|
|
746
|
+
</CardHeader>
|
|
747
|
+
<CardContent className="space-y-3">
|
|
748
|
+
<Alert>
|
|
749
|
+
<Terminal className="size-4" />
|
|
750
|
+
<AlertTitle>Heads up!</AlertTitle>
|
|
751
|
+
<AlertDescription>You can add components using the CLI.</AlertDescription>
|
|
752
|
+
</Alert>
|
|
753
|
+
<Alert variant="destructive">
|
|
754
|
+
<AlertCircle className="size-4" />
|
|
755
|
+
<AlertTitle>Error</AlertTitle>
|
|
756
|
+
<AlertDescription>Your session has expired. Please log in again.</AlertDescription>
|
|
757
|
+
</Alert>
|
|
758
|
+
<Alert className="border-blue-500/50 text-blue-600 [&>svg]:text-blue-600">
|
|
759
|
+
<Info className="size-4" />
|
|
760
|
+
<AlertTitle>Note</AlertTitle>
|
|
761
|
+
<AlertDescription>This feature is in beta. Feedback welcome.</AlertDescription>
|
|
762
|
+
</Alert>
|
|
763
|
+
</CardContent>
|
|
764
|
+
</Card>
|
|
765
|
+
|
|
766
|
+
{/* Calendar */}
|
|
767
|
+
<Card>
|
|
768
|
+
<CardHeader>
|
|
769
|
+
<CardTitle className="text-base">Date Picker</CardTitle>
|
|
770
|
+
</CardHeader>
|
|
771
|
+
<CardContent className="flex justify-center">
|
|
772
|
+
<Calendar
|
|
773
|
+
mode="single"
|
|
774
|
+
selected={selectedDate}
|
|
775
|
+
onSelect={setSelectedDate}
|
|
776
|
+
className="rounded-md border"
|
|
777
|
+
/>
|
|
778
|
+
</CardContent>
|
|
779
|
+
</Card>
|
|
780
|
+
|
|
781
|
+
{/* Dialog & Sheet */}
|
|
782
|
+
<Card>
|
|
783
|
+
<CardHeader>
|
|
784
|
+
<CardTitle className="text-base">Overlays</CardTitle>
|
|
785
|
+
<p className="text-sm text-muted-foreground">Dialog, Sheet & Popover components</p>
|
|
786
|
+
</CardHeader>
|
|
787
|
+
<CardContent className="space-y-3">
|
|
788
|
+
<Dialog>
|
|
789
|
+
<DialogTrigger asChild>
|
|
790
|
+
<Button variant="outline" className="w-full">
|
|
791
|
+
Open Dialog
|
|
792
|
+
</Button>
|
|
793
|
+
</DialogTrigger>
|
|
794
|
+
<DialogContent>
|
|
795
|
+
<DialogHeader>
|
|
796
|
+
<DialogTitle>Edit Profile</DialogTitle>
|
|
797
|
+
<DialogDescription>
|
|
798
|
+
Make changes to your profile here. Click save when done.
|
|
799
|
+
</DialogDescription>
|
|
800
|
+
</DialogHeader>
|
|
801
|
+
<div className="space-y-3 py-4">
|
|
802
|
+
<div className="space-y-1">
|
|
803
|
+
<Label htmlFor="dialog-name">Name</Label>
|
|
804
|
+
<Input id="dialog-name" defaultValue="John Doe" />
|
|
805
|
+
</div>
|
|
806
|
+
<div className="space-y-1">
|
|
807
|
+
<Label htmlFor="dialog-email">Email</Label>
|
|
808
|
+
<Input id="dialog-email" defaultValue="john@example.com" />
|
|
809
|
+
</div>
|
|
810
|
+
</div>
|
|
811
|
+
<DialogFooter>
|
|
812
|
+
<Button type="submit">Save changes</Button>
|
|
813
|
+
</DialogFooter>
|
|
814
|
+
</DialogContent>
|
|
815
|
+
</Dialog>
|
|
816
|
+
<Sheet>
|
|
817
|
+
<SheetTrigger asChild>
|
|
818
|
+
<Button variant="outline" className="w-full">
|
|
819
|
+
Open Sheet
|
|
820
|
+
</Button>
|
|
821
|
+
</SheetTrigger>
|
|
822
|
+
<SheetContent>
|
|
823
|
+
<SheetHeader>
|
|
824
|
+
<SheetTitle>Notifications</SheetTitle>
|
|
825
|
+
<SheetDescription>You have 3 unread notifications.</SheetDescription>
|
|
826
|
+
</SheetHeader>
|
|
827
|
+
<div className="mt-4 space-y-3">
|
|
828
|
+
{[
|
|
829
|
+
{ icon: Mail, title: "New message", desc: "from Alice" },
|
|
830
|
+
{ icon: Bell, title: "Reminder", desc: "Team meeting at 3pm" },
|
|
831
|
+
{ icon: FileText, title: "Document shared", desc: "Q4 Report" },
|
|
832
|
+
].map((item) => (
|
|
833
|
+
<div key={item.title} className="flex items-start gap-3 rounded-lg border p-3">
|
|
834
|
+
<item.icon className="mt-0.5 size-4 text-muted-foreground" />
|
|
835
|
+
<div>
|
|
836
|
+
<p className="text-sm font-medium">{item.title}</p>
|
|
837
|
+
<p className="text-xs text-muted-foreground">{item.desc}</p>
|
|
838
|
+
</div>
|
|
839
|
+
</div>
|
|
840
|
+
))}
|
|
841
|
+
</div>
|
|
842
|
+
</SheetContent>
|
|
843
|
+
</Sheet>
|
|
844
|
+
<Popover>
|
|
845
|
+
<PopoverTrigger asChild>
|
|
846
|
+
<Button variant="outline" className="w-full">
|
|
847
|
+
Open Popover
|
|
848
|
+
</Button>
|
|
849
|
+
</PopoverTrigger>
|
|
850
|
+
<PopoverContent className="w-80">
|
|
851
|
+
<div className="space-y-2">
|
|
852
|
+
<h4 className="font-medium text-sm">Dimensions</h4>
|
|
853
|
+
<p className="text-xs text-muted-foreground">Set the dimensions for the layer.</p>
|
|
854
|
+
<div className="grid grid-cols-2 gap-2">
|
|
855
|
+
<div className="space-y-1">
|
|
856
|
+
<Label className="text-xs">Width</Label>
|
|
857
|
+
<Input defaultValue="100%" className="h-8" />
|
|
858
|
+
</div>
|
|
859
|
+
<div className="space-y-1">
|
|
860
|
+
<Label className="text-xs">Height</Label>
|
|
861
|
+
<Input defaultValue="25px" className="h-8" />
|
|
862
|
+
</div>
|
|
863
|
+
</div>
|
|
864
|
+
</div>
|
|
865
|
+
</PopoverContent>
|
|
866
|
+
</Popover>
|
|
867
|
+
</CardContent>
|
|
868
|
+
</Card>
|
|
869
|
+
|
|
870
|
+
{/* Breadcrumb & Navigation */}
|
|
871
|
+
<Card>
|
|
872
|
+
<CardHeader>
|
|
873
|
+
<CardTitle className="text-base">Navigation</CardTitle>
|
|
874
|
+
</CardHeader>
|
|
875
|
+
<CardContent className="space-y-4">
|
|
876
|
+
<Breadcrumb>
|
|
877
|
+
<BreadcrumbList>
|
|
878
|
+
<BreadcrumbItem>
|
|
879
|
+
<BreadcrumbLink href="#">
|
|
880
|
+
<Home className="size-3.5" />
|
|
881
|
+
</BreadcrumbLink>
|
|
882
|
+
</BreadcrumbItem>
|
|
883
|
+
<BreadcrumbSeparator />
|
|
884
|
+
<BreadcrumbItem>
|
|
885
|
+
<BreadcrumbLink href="#">Components</BreadcrumbLink>
|
|
886
|
+
</BreadcrumbItem>
|
|
887
|
+
<BreadcrumbSeparator />
|
|
888
|
+
<BreadcrumbItem>
|
|
889
|
+
<BreadcrumbPage>Breadcrumb</BreadcrumbPage>
|
|
890
|
+
</BreadcrumbItem>
|
|
891
|
+
</BreadcrumbList>
|
|
892
|
+
</Breadcrumb>
|
|
893
|
+
<Separator />
|
|
894
|
+
<div className="flex items-center gap-1">
|
|
895
|
+
<Tooltip>
|
|
896
|
+
<TooltipTrigger asChild>
|
|
897
|
+
<Button variant="ghost" size="icon" className="size-8">
|
|
898
|
+
<Home className="size-4" />
|
|
899
|
+
</Button>
|
|
900
|
+
</TooltipTrigger>
|
|
901
|
+
<TooltipContent>Home</TooltipContent>
|
|
902
|
+
</Tooltip>
|
|
903
|
+
<Tooltip>
|
|
904
|
+
<TooltipTrigger asChild>
|
|
905
|
+
<Button variant="ghost" size="icon" className="size-8">
|
|
906
|
+
<Settings className="size-4" />
|
|
907
|
+
</Button>
|
|
908
|
+
</TooltipTrigger>
|
|
909
|
+
<TooltipContent>Settings</TooltipContent>
|
|
910
|
+
</Tooltip>
|
|
911
|
+
<Tooltip>
|
|
912
|
+
<TooltipTrigger asChild>
|
|
913
|
+
<Button variant="ghost" size="icon" className="size-8">
|
|
914
|
+
<User className="size-4" />
|
|
915
|
+
</Button>
|
|
916
|
+
</TooltipTrigger>
|
|
917
|
+
<TooltipContent>Profile</TooltipContent>
|
|
918
|
+
</Tooltip>
|
|
919
|
+
<Tooltip>
|
|
920
|
+
<TooltipTrigger asChild>
|
|
921
|
+
<Button variant="ghost" size="icon" className="size-8">
|
|
922
|
+
<Bell className="size-4" />
|
|
923
|
+
</Button>
|
|
924
|
+
</TooltipTrigger>
|
|
925
|
+
<TooltipContent>Notifications</TooltipContent>
|
|
926
|
+
</Tooltip>
|
|
927
|
+
</div>
|
|
928
|
+
<Separator />
|
|
929
|
+
<div className="flex items-center gap-2">
|
|
930
|
+
<Badge variant="outline">v2.4.0</Badge>
|
|
931
|
+
<Badge
|
|
932
|
+
variant="outline"
|
|
933
|
+
className="bg-emerald-500/10 text-emerald-600 border-emerald-500/20"
|
|
934
|
+
>
|
|
935
|
+
Stable
|
|
936
|
+
</Badge>
|
|
937
|
+
<Badge variant="outline" className="bg-blue-500/10 text-blue-600 border-blue-500/20">
|
|
938
|
+
Latest
|
|
939
|
+
</Badge>
|
|
940
|
+
</div>
|
|
941
|
+
</CardContent>
|
|
942
|
+
</Card>
|
|
943
|
+
|
|
944
|
+
{/* OTP Input */}
|
|
945
|
+
<Card>
|
|
946
|
+
<CardHeader>
|
|
947
|
+
<CardTitle className="text-base">Verification Code</CardTitle>
|
|
948
|
+
<p className="text-sm text-muted-foreground">
|
|
949
|
+
Enter the 6-digit code sent to your email.
|
|
950
|
+
</p>
|
|
951
|
+
</CardHeader>
|
|
952
|
+
<CardContent className="flex flex-col items-center gap-4">
|
|
953
|
+
<InputOTP maxLength={6} defaultValue="482">
|
|
954
|
+
<InputOTPGroup>
|
|
955
|
+
<InputOTPSlot index={0} />
|
|
956
|
+
<InputOTPSlot index={1} />
|
|
957
|
+
<InputOTPSlot index={2} />
|
|
958
|
+
</InputOTPGroup>
|
|
959
|
+
<InputOTPSeparator />
|
|
960
|
+
<InputOTPGroup>
|
|
961
|
+
<InputOTPSlot index={3} />
|
|
962
|
+
<InputOTPSlot index={4} />
|
|
963
|
+
<InputOTPSlot index={5} />
|
|
964
|
+
</InputOTPGroup>
|
|
965
|
+
</InputOTP>
|
|
966
|
+
<p className="text-xs text-muted-foreground">
|
|
967
|
+
Didn't receive a code?{" "}
|
|
968
|
+
<button type="button" className="underline underline-offset-4">
|
|
969
|
+
Resend
|
|
970
|
+
</button>
|
|
971
|
+
</p>
|
|
972
|
+
</CardContent>
|
|
973
|
+
</Card>
|
|
974
|
+
|
|
975
|
+
{/* Command Palette */}
|
|
976
|
+
<Card>
|
|
977
|
+
<CardHeader>
|
|
978
|
+
<CardTitle className="text-base">Command Palette</CardTitle>
|
|
979
|
+
</CardHeader>
|
|
980
|
+
<CardContent>
|
|
981
|
+
<Command className="rounded-lg border">
|
|
982
|
+
<CommandInput placeholder="Type a command or search..." />
|
|
983
|
+
<CommandList>
|
|
984
|
+
<CommandEmpty>No results found.</CommandEmpty>
|
|
985
|
+
<CommandGroup heading="Suggestions">
|
|
986
|
+
<CommandItem>
|
|
987
|
+
<CalendarIcon className="mr-2 size-4" />
|
|
988
|
+
<span>Calendar</span>
|
|
989
|
+
</CommandItem>
|
|
990
|
+
<CommandItem>
|
|
991
|
+
<Search className="mr-2 size-4" />
|
|
992
|
+
<span>Search</span>
|
|
993
|
+
</CommandItem>
|
|
994
|
+
<CommandItem>
|
|
995
|
+
<Settings className="mr-2 size-4" />
|
|
996
|
+
<span>Settings</span>
|
|
997
|
+
</CommandItem>
|
|
998
|
+
</CommandGroup>
|
|
999
|
+
<CommandSeparator />
|
|
1000
|
+
<CommandGroup heading="Settings">
|
|
1001
|
+
<CommandItem>
|
|
1002
|
+
<User className="mr-2 size-4" />
|
|
1003
|
+
<span>Profile</span>
|
|
1004
|
+
</CommandItem>
|
|
1005
|
+
<CommandItem>
|
|
1006
|
+
<Mail className="mr-2 size-4" />
|
|
1007
|
+
<span>Mail</span>
|
|
1008
|
+
</CommandItem>
|
|
1009
|
+
</CommandGroup>
|
|
1010
|
+
</CommandList>
|
|
1011
|
+
</Command>
|
|
1012
|
+
</CardContent>
|
|
1013
|
+
</Card>
|
|
1014
|
+
|
|
1015
|
+
{/* Collapsible + HoverCard */}
|
|
1016
|
+
<Card>
|
|
1017
|
+
<CardHeader>
|
|
1018
|
+
<CardTitle className="text-base">Expandable Sections</CardTitle>
|
|
1019
|
+
</CardHeader>
|
|
1020
|
+
<CardContent className="space-y-3">
|
|
1021
|
+
<Collapsible open={collapsibleOpen} onOpenChange={setCollapsibleOpen}>
|
|
1022
|
+
<div className="flex items-center justify-between rounded-lg border px-3 py-2">
|
|
1023
|
+
<span className="text-sm font-medium">3 starred repositories</span>
|
|
1024
|
+
<CollapsibleTrigger asChild>
|
|
1025
|
+
<Button variant="ghost" size="icon" className="size-7">
|
|
1026
|
+
<ChevronsUpDown className="size-3.5" />
|
|
1027
|
+
</Button>
|
|
1028
|
+
</CollapsibleTrigger>
|
|
1029
|
+
</div>
|
|
1030
|
+
<CollapsibleContent className="mt-2 space-y-2">
|
|
1031
|
+
{["shadcn/ui", "vercel/next.js", "tailwindlabs/tailwindcss"].map((repo) => (
|
|
1032
|
+
<div key={repo} className="rounded-lg border px-3 py-2 text-sm">
|
|
1033
|
+
{repo}
|
|
1034
|
+
</div>
|
|
1035
|
+
))}
|
|
1036
|
+
</CollapsibleContent>
|
|
1037
|
+
</Collapsible>
|
|
1038
|
+
<Separator />
|
|
1039
|
+
<div className="flex items-center gap-2">
|
|
1040
|
+
<span className="text-sm">Hover for info:</span>
|
|
1041
|
+
<HoverCard>
|
|
1042
|
+
<HoverCardTrigger asChild>
|
|
1043
|
+
<Button variant="link" className="h-auto p-0 text-sm">
|
|
1044
|
+
@shadcn
|
|
1045
|
+
</Button>
|
|
1046
|
+
</HoverCardTrigger>
|
|
1047
|
+
<HoverCardContent className="w-72">
|
|
1048
|
+
<div className="flex gap-3">
|
|
1049
|
+
<Avatar>
|
|
1050
|
+
<AvatarFallback>SC</AvatarFallback>
|
|
1051
|
+
</Avatar>
|
|
1052
|
+
<div className="space-y-1">
|
|
1053
|
+
<h4 className="text-sm font-semibold">@shadcn</h4>
|
|
1054
|
+
<p className="text-xs text-muted-foreground">
|
|
1055
|
+
Creator of shadcn/ui. Building in the open.
|
|
1056
|
+
</p>
|
|
1057
|
+
<div className="flex items-center text-xs text-muted-foreground">
|
|
1058
|
+
<CalendarIcon className="mr-1 size-3" />
|
|
1059
|
+
Joined December 2021
|
|
1060
|
+
</div>
|
|
1061
|
+
</div>
|
|
1062
|
+
</div>
|
|
1063
|
+
</HoverCardContent>
|
|
1064
|
+
</HoverCard>
|
|
1065
|
+
</div>
|
|
1066
|
+
</CardContent>
|
|
1067
|
+
</Card>
|
|
1068
|
+
|
|
1069
|
+
{/* Carousel */}
|
|
1070
|
+
<Card>
|
|
1071
|
+
<CardHeader>
|
|
1072
|
+
<CardTitle className="text-base">Carousel</CardTitle>
|
|
1073
|
+
</CardHeader>
|
|
1074
|
+
<CardContent>
|
|
1075
|
+
<Carousel className="mx-auto w-full max-w-xs">
|
|
1076
|
+
<CarouselContent>
|
|
1077
|
+
{Array.from({ length: 5 }, (_, i) => (
|
|
1078
|
+
<CarouselItem key={`slide-${i + 1}`}>
|
|
1079
|
+
<div className="p-1">
|
|
1080
|
+
<Card>
|
|
1081
|
+
<CardContent className="flex aspect-square items-center justify-center p-6">
|
|
1082
|
+
<span className="text-3xl font-semibold">{i + 1}</span>
|
|
1083
|
+
</CardContent>
|
|
1084
|
+
</Card>
|
|
1085
|
+
</div>
|
|
1086
|
+
</CarouselItem>
|
|
1087
|
+
))}
|
|
1088
|
+
</CarouselContent>
|
|
1089
|
+
<CarouselPrevious />
|
|
1090
|
+
<CarouselNext />
|
|
1091
|
+
</Carousel>
|
|
1092
|
+
</CardContent>
|
|
1093
|
+
</Card>
|
|
1094
|
+
|
|
1095
|
+
{/* Scroll Area + Tags */}
|
|
1096
|
+
<Card>
|
|
1097
|
+
<CardHeader>
|
|
1098
|
+
<CardTitle className="text-base">Components List</CardTitle>
|
|
1099
|
+
<p className="text-sm text-muted-foreground">Scroll to explore all 57 components</p>
|
|
1100
|
+
</CardHeader>
|
|
1101
|
+
<CardContent>
|
|
1102
|
+
<ScrollArea className="h-48 rounded-md border">
|
|
1103
|
+
<div className="p-4 space-y-2">
|
|
1104
|
+
{[
|
|
1105
|
+
"Accordion",
|
|
1106
|
+
"Alert",
|
|
1107
|
+
"Alert Dialog",
|
|
1108
|
+
"Aspect Ratio",
|
|
1109
|
+
"Avatar",
|
|
1110
|
+
"Badge",
|
|
1111
|
+
"Breadcrumb",
|
|
1112
|
+
"Button",
|
|
1113
|
+
"Calendar",
|
|
1114
|
+
"Card",
|
|
1115
|
+
"Carousel",
|
|
1116
|
+
"Chart",
|
|
1117
|
+
"Checkbox",
|
|
1118
|
+
"Collapsible",
|
|
1119
|
+
"Combobox",
|
|
1120
|
+
"Command",
|
|
1121
|
+
"Context Menu",
|
|
1122
|
+
"Dialog",
|
|
1123
|
+
"Drawer",
|
|
1124
|
+
"Dropdown Menu",
|
|
1125
|
+
"Form",
|
|
1126
|
+
"Hover Card",
|
|
1127
|
+
"Input",
|
|
1128
|
+
"Input OTP",
|
|
1129
|
+
"Label",
|
|
1130
|
+
"Menubar",
|
|
1131
|
+
"Navigation Menu",
|
|
1132
|
+
"Pagination",
|
|
1133
|
+
"Popover",
|
|
1134
|
+
"Progress",
|
|
1135
|
+
"Radio Group",
|
|
1136
|
+
"Resizable",
|
|
1137
|
+
"Scroll Area",
|
|
1138
|
+
"Select",
|
|
1139
|
+
"Separator",
|
|
1140
|
+
"Sheet",
|
|
1141
|
+
"Sidebar",
|
|
1142
|
+
"Skeleton",
|
|
1143
|
+
"Slider",
|
|
1144
|
+
"Sonner",
|
|
1145
|
+
"Spinner",
|
|
1146
|
+
"Switch",
|
|
1147
|
+
"Table",
|
|
1148
|
+
"Tabs",
|
|
1149
|
+
"Textarea",
|
|
1150
|
+
"Toggle",
|
|
1151
|
+
"Toggle Group",
|
|
1152
|
+
"Tooltip",
|
|
1153
|
+
].map((comp) => (
|
|
1154
|
+
<div
|
|
1155
|
+
key={comp}
|
|
1156
|
+
className="flex items-center justify-between rounded px-2 py-1 text-sm hover:bg-muted"
|
|
1157
|
+
>
|
|
1158
|
+
<span>{comp}</span>
|
|
1159
|
+
<Badge variant="outline" className="text-xs">
|
|
1160
|
+
installed
|
|
1161
|
+
</Badge>
|
|
1162
|
+
</div>
|
|
1163
|
+
))}
|
|
1164
|
+
</div>
|
|
1165
|
+
</ScrollArea>
|
|
1166
|
+
</CardContent>
|
|
1167
|
+
</Card>
|
|
1168
|
+
|
|
1169
|
+
{/* Theme Toggle Card */}
|
|
1170
|
+
<Card>
|
|
1171
|
+
<CardHeader>
|
|
1172
|
+
<CardTitle className="text-base">Appearance</CardTitle>
|
|
1173
|
+
<p className="text-sm text-muted-foreground">Customize your experience</p>
|
|
1174
|
+
</CardHeader>
|
|
1175
|
+
<CardContent className="space-y-4">
|
|
1176
|
+
<div className="grid grid-cols-3 gap-2">
|
|
1177
|
+
{[
|
|
1178
|
+
{ icon: Sun, label: "Light" },
|
|
1179
|
+
{ icon: Moon, label: "Dark" },
|
|
1180
|
+
{ icon: Laptop, label: "System" },
|
|
1181
|
+
].map((theme) => (
|
|
1182
|
+
<Button
|
|
1183
|
+
key={theme.label}
|
|
1184
|
+
variant={theme.label === "System" ? "default" : "outline"}
|
|
1185
|
+
size="sm"
|
|
1186
|
+
className="flex-col gap-1 h-auto py-3"
|
|
1187
|
+
>
|
|
1188
|
+
<theme.icon className="size-4" />
|
|
1189
|
+
<span className="text-xs">{theme.label}</span>
|
|
1190
|
+
</Button>
|
|
1191
|
+
))}
|
|
1192
|
+
</div>
|
|
1193
|
+
<Separator />
|
|
1194
|
+
<div className="space-y-3">
|
|
1195
|
+
<div className="flex items-center justify-between">
|
|
1196
|
+
<div>
|
|
1197
|
+
<p className="text-sm font-medium">Notifications</p>
|
|
1198
|
+
<p className="text-xs text-muted-foreground">Receive push notifications</p>
|
|
1199
|
+
</div>
|
|
1200
|
+
<Switch defaultChecked />
|
|
1201
|
+
</div>
|
|
1202
|
+
<div className="flex items-center justify-between">
|
|
1203
|
+
<div>
|
|
1204
|
+
<p className="text-sm font-medium">Marketing emails</p>
|
|
1205
|
+
<p className="text-xs text-muted-foreground">Receive emails about new features</p>
|
|
1206
|
+
</div>
|
|
1207
|
+
<Switch />
|
|
1208
|
+
</div>
|
|
1209
|
+
<div className="flex items-center justify-between">
|
|
1210
|
+
<div>
|
|
1211
|
+
<p className="text-sm font-medium">Social notifications</p>
|
|
1212
|
+
<p className="text-xs text-muted-foreground">
|
|
1213
|
+
Receive notifications for friend requests
|
|
1214
|
+
</p>
|
|
1215
|
+
</div>
|
|
1216
|
+
<Switch defaultChecked />
|
|
1217
|
+
</div>
|
|
1218
|
+
</div>
|
|
1219
|
+
</CardContent>
|
|
1220
|
+
</Card>
|
|
1221
|
+
|
|
1222
|
+
{/* User Profile Card */}
|
|
1223
|
+
<Card>
|
|
1224
|
+
<CardContent className="pt-6">
|
|
1225
|
+
<div className="flex flex-col items-center gap-3 text-center">
|
|
1226
|
+
<Avatar className="size-16">
|
|
1227
|
+
<AvatarFallback className="text-lg">JD</AvatarFallback>
|
|
1228
|
+
</Avatar>
|
|
1229
|
+
<div>
|
|
1230
|
+
<h4 className="font-semibold">Jane Doe</h4>
|
|
1231
|
+
<p className="text-sm text-muted-foreground">jane@example.com</p>
|
|
1232
|
+
</div>
|
|
1233
|
+
<div className="flex gap-4 text-center">
|
|
1234
|
+
<div>
|
|
1235
|
+
<p className="text-lg font-semibold">142</p>
|
|
1236
|
+
<p className="text-xs text-muted-foreground">Posts</p>
|
|
1237
|
+
</div>
|
|
1238
|
+
<Separator orientation="vertical" className="h-10" />
|
|
1239
|
+
<div>
|
|
1240
|
+
<p className="text-lg font-semibold">2.4k</p>
|
|
1241
|
+
<p className="text-xs text-muted-foreground">Followers</p>
|
|
1242
|
+
</div>
|
|
1243
|
+
<Separator orientation="vertical" className="h-10" />
|
|
1244
|
+
<div>
|
|
1245
|
+
<p className="text-lg font-semibold">891</p>
|
|
1246
|
+
<p className="text-xs text-muted-foreground">Following</p>
|
|
1247
|
+
</div>
|
|
1248
|
+
</div>
|
|
1249
|
+
<div className="flex gap-2 w-full">
|
|
1250
|
+
<Button size="sm" className="flex-1">
|
|
1251
|
+
Follow
|
|
1252
|
+
</Button>
|
|
1253
|
+
<Button size="sm" variant="outline" className="flex-1">
|
|
1254
|
+
Message
|
|
1255
|
+
</Button>
|
|
1256
|
+
</div>
|
|
1257
|
+
</div>
|
|
1258
|
+
</CardContent>
|
|
1259
|
+
</Card>
|
|
1260
|
+
</div>
|
|
1261
|
+
);
|
|
1262
|
+
}
|