{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "kitchen-sink", "title": "Mira Component Kitchen Sink", "description": "The complete horizontally scrolling shadcn Create card collection.", "dependencies": [ "lucide-react@^1.31.0", "react-qr-code@^2.2.0", "recharts@3.8.0", "shadcn@^4.16.2" ], "registryDependencies": [ "https://samlinville.github.io/slds/r/accordion.json", "https://samlinville.github.io/slds/r/alert.json", "https://samlinville.github.io/slds/r/alert-dialog.json", "https://samlinville.github.io/slds/r/avatar.json", "https://samlinville.github.io/slds/r/badge.json", "https://samlinville.github.io/slds/r/breadcrumb.json", "https://samlinville.github.io/slds/r/button.json", "https://samlinville.github.io/slds/r/button-group.json", "https://samlinville.github.io/slds/r/calendar.json", "https://samlinville.github.io/slds/r/card.json", "https://samlinville.github.io/slds/r/chart.json", "https://samlinville.github.io/slds/r/checkbox.json", "https://samlinville.github.io/slds/r/combobox.json", "https://samlinville.github.io/slds/r/dialog.json", "https://samlinville.github.io/slds/r/dropdown-menu.json", "https://samlinville.github.io/slds/r/empty.json", "https://samlinville.github.io/slds/r/field.json", "https://samlinville.github.io/slds/r/input.json", "https://samlinville.github.io/slds/r/input-group.json", "https://samlinville.github.io/slds/r/item.json", "https://samlinville.github.io/slds/r/kbd.json", "https://samlinville.github.io/slds/r/label.json", "https://samlinville.github.io/slds/r/native-select.json", "https://samlinville.github.io/slds/r/progress.json", "https://samlinville.github.io/slds/r/radio-group.json", "https://samlinville.github.io/slds/r/select.json", "https://samlinville.github.io/slds/r/separator.json", "https://samlinville.github.io/slds/r/sidebar.json", "https://samlinville.github.io/slds/r/skeleton.json", "https://samlinville.github.io/slds/r/slider.json", "https://samlinville.github.io/slds/r/spinner.json", "https://samlinville.github.io/slds/r/switch.json", "https://samlinville.github.io/slds/r/table.json", "https://samlinville.github.io/slds/r/tabs.json", "https://samlinville.github.io/slds/r/textarea.json", "https://samlinville.github.io/slds/r/toggle-group.json", "https://samlinville.github.io/slds/r/tooltip.json", "https://samlinville.github.io/slds/r/utils.json" ], "files": [ { "path": "src/blocks/kitchen-sink/additional-card-stacks.tsx", "content": "import { ActivateAgentDialog } from \"./preview-cards/activate-agent-dialog\"\nimport { AnalyticsCard } from \"./preview-cards/analytics-card\"\nimport { AnomalyAlert } from \"./preview-cards/anomaly-alert\"\nimport { BarChartCard } from \"./preview-cards/bar-chart-card\"\nimport { BookAppointment } from \"./preview-cards/book-appointment\"\nimport { CodespacesCard } from \"./preview-cards/codespaces-card\"\nimport { ContributionsActivity } from \"./preview-cards/contributions-activity\"\nimport { Contributors } from \"./preview-cards/contributors\"\nimport { EnvironmentVariables } from \"./preview-cards/environment-variables\"\nimport { FeedbackForm } from \"./preview-cards/feedback-form\"\nimport { FileUpload } from \"./preview-cards/file-upload\"\nimport { GithubProfile } from \"./preview-cards/github-profile\"\nimport { IconPreviewGrid } from \"./preview-cards/icon-preview-grid\"\nimport { InviteTeam } from \"./preview-cards/invite-team\"\nimport { Invoice } from \"./preview-cards/invoice\"\nimport { LiveWaveformCard } from \"./preview-cards/live-waveform\"\nimport { NoTeamMembers } from \"./preview-cards/no-team-members\"\nimport { NotFound } from \"./preview-cards/not-found\"\nimport { ObservabilityCard } from \"./preview-cards/observability-card\"\nimport { PieChartCard } from \"./preview-cards/pie-chart-card\"\nimport { ReportBug } from \"./preview-cards/report-bug\"\nimport { ShippingAddress } from \"./preview-cards/shipping-address\"\nimport { Shortcuts } from \"./preview-cards/shortcuts\"\nimport { SkeletonLoading } from \"./preview-cards/skeleton-loading\"\nimport { SleepReport } from \"./preview-cards/sleep-report\"\nimport { StyleOverview } from \"./preview-cards/style-overview\"\nimport { TypographySpecimen } from \"./preview-cards/typography-specimen\"\nimport { UIElements } from \"./preview-cards/ui-elements\"\nimport { UsageCard } from \"./preview-cards/usage-card\"\nimport { Visitors } from \"./preview-cards/visitors\"\nimport { WeeklyFitnessSummary } from \"./preview-cards/weekly-fitness-summary\"\n\nexport function AdditionalCardStacks() {\n return (\n <>\n
\n \n \n
\n \n
\n \n \n
\n
\n \n
\n \n
\n \n \n
\n
\n \n \n \n \n
\n
\n \n \n \n \n \n
\n
\n \n \n \n \n
\n
\n \n \n \n \n \n
\n
\n \n \n \n \n \n
\n \n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/additional-card-stacks.tsx" }, { "path": "src/blocks/kitchen-sink/cards/account-access.tsx", "content": "\"use client\"\n\nimport { Button } from \"@/components/ui/button\"\nimport {\n Card,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n} from \"@/components/ui/card\"\nimport { Field, FieldGroup, FieldLabel } from \"@/components/ui/field\"\nimport { Input } from \"@/components/ui/input\"\nimport {\n Item,\n ItemContent,\n ItemDescription,\n ItemMedia,\n ItemTitle,\n} from \"@/components/ui/item\"\nimport { IconPlaceholder } from \"../components/icon-placeholder\"\n\nexport function AccountAccess() {\n return (\n \n \n Account Access\n \n Update your credentials or re-authenticate.\n \n \n \n \n \n Email Address\n \n \n \n
\n \n Current Password\n \n \n Forgot?\n \n
\n \n
\n
\n
\n \n \n }>\n \n \n \n \n Danger Zone\n \n Archive account and remove catalog\n \n \n \n \n \n
\n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/cards/account-access.tsx" }, { "path": "src/blocks/kitchen-sink/cards/album-card.tsx", "content": "import { Badge } from \"@/components/ui/badge\"\nimport {\n Card,\n CardContent,\n CardDescription,\n CardFooter,\n CardTitle,\n} from \"@/components/ui/card\"\nimport { Separator } from \"@/components/ui/separator\"\n\nexport function AlbumCard() {\n return (\n \n \n
\n \n $26,033.79\n
\n
\n Synthetic Horizons EP\n \n Released Aug 14, 2023\n \n
\n
\n \n \n
\n
\n \n Tracks\n \n 6 Tracks\n
\n
\n \n Cumulative Streams\n \n 6,198,524\n
\n
\n
\n
\n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/cards/album-card.tsx" }, { "path": "src/blocks/kitchen-sink/cards/card-overview.tsx", "content": "\"use client\"\n\nimport { Bar, BarChart, XAxis } from \"recharts\"\n\nimport { Badge } from \"@/components/ui/badge\"\nimport { Button } from \"@/components/ui/button\"\nimport {\n Card,\n CardContent,\n CardDescription,\n CardTitle,\n} from \"@/components/ui/card\"\nimport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n type ChartConfig,\n} from \"@/components/ui/chart\"\n\nconst activityData = [\n { month: \"Jan\", amount: 40 },\n { month: \"Feb\", amount: 55 },\n { month: \"Mar\", amount: 35 },\n { month: \"Apr\", amount: 60 },\n { month: \"May\", amount: 45 },\n { month: \"Jun\", amount: 50 },\n { month: \"Jul\", amount: 65 },\n { month: \"Aug\", amount: 40 },\n { month: \"Sep\", amount: 55 },\n { month: \"Oct\", amount: 70 },\n { month: \"Nov\", amount: 45 },\n { month: \"Dec\", amount: 80 },\n]\n\nconst chartConfig = {\n amount: {\n label: \"Activity\",\n color: \"var(--chart-2)\",\n },\n} satisfies ChartConfig\n\nexport function CardOverview() {\n return (\n
\n \n \n Card Balance\n US$12.94\n \n US$11,337.06 Available\n \n \n \n \n \n
\n Payment Due\n 1 Apr\n
\n \n
\n
\n \n \n
\n Yearly Activity\n +US$0.25 Daily Cash\n
\n \n \n String(v).slice(0, 1)}\n className=\"text-[10px]\"\n />\n }\n />\n \n \n \n
\n
\n
\n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/cards/card-overview.tsx" }, { "path": "src/blocks/kitchen-sink/cards/catalog-toolbar.tsx", "content": "\"use client\"\n\nimport { Button } from \"@/components/ui/button\"\nimport {\n InputGroup,\n InputGroupAddon,\n InputGroupInput,\n} from \"@/components/ui/input-group\"\nimport { ToggleGroup, ToggleGroupItem } from \"@/components/ui/toggle-group\"\nimport { IconPlaceholder } from \"../components/icon-placeholder\"\n\nexport function CatalogToolbar() {\n return (\n
\n \n \n \n \n \n \n \n \n All Tracks\n Releases\n Top Earners\n \n
\n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/cards/catalog-toolbar.tsx" }, { "path": "src/blocks/kitchen-sink/cards/claimable-balance.tsx", "content": "import { Badge } from \"@/components/ui/badge\"\nimport {\n Card,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n} from \"@/components/ui/card\"\nimport { Item, ItemContent } from \"@/components/ui/item\"\nimport { Separator } from \"@/components/ui/separator\"\n\nexport function ClaimableBalance() {\n return (\n \n \n Claimable Balance\n $0.00\n \n \n Pending Setup\n \n \n \n \n \n
\n \n Net Royalties\n \n $0.00\n
\n
\n \n Processing Fee\n \n -$0.00\n
\n \n
\n \n Total Ready to Claim\n \n \n $0.00 USD\n \n
\n
\n
\n
\n \n \n Once your bank is connected, balances over $10.00 are automatically\n eligible for monthly distribution on the 15th of each month.\n \n \n
\n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/cards/claimable-balance.tsx" }, { "path": "src/blocks/kitchen-sink/cards/contribution-history.tsx", "content": "\"use client\"\n\nimport { Bar, BarChart, XAxis } from \"recharts\"\n\nimport { Button } from \"@/components/ui/button\"\nimport {\n Card,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n} from \"@/components/ui/card\"\nimport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n type ChartConfig,\n} from \"@/components/ui/chart\"\nimport { Item, ItemContent, ItemDescription } from \"@/components/ui/item\"\n\nconst chartData = [\n { month: \"Dec\", amount: 800 },\n { month: \"Jan\", amount: 1100 },\n { month: \"Feb\", amount: 900 },\n { month: \"Mar\", amount: 1300 },\n { month: \"Apr\", amount: 750 },\n { month: \"May\", amount: 1400 },\n]\n\nconst chartConfig = {\n amount: {\n label: \"Contribution\",\n color: \"var(--chart-2)\",\n },\n} satisfies ChartConfig\n\nexport function ContributionHistory() {\n const isRounded = true\n\n return (\n \n \n Contribution History\n Last 6 months of activity\n \n \n \n \n \n }\n />\n \n \n \n \n \n
\n \n \n \n Upcoming\n \n \n May 25, 2024\n \n \n $1,000 scheduled\n \n \n \n \n \n \n Auto-Save Plan\n \n \n Accelerated\n \n \n Recurring weekly\n \n \n \n
\n
\n \n \n \n
\n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/cards/contribution-history.tsx" }, { "path": "src/blocks/kitchen-sink/cards/cover-art.tsx", "content": "import { Button } from \"@/components/ui/button\"\nimport {\n Card,\n CardContent,\n CardDescription,\n CardFooter,\n} from \"@/components/ui/card\"\nimport { Item } from \"@/components/ui/item\"\nimport { Label } from \"@/components/ui/label\"\nimport { IconPlaceholder } from \"../components/icon-placeholder\"\n\nexport function CoverArt() {\n return (\n \n \n \n Cover Art\n \n \n \n \n \n \n \n \n \n }\n nativeButton={false}\n >\n Upload Artwork\n \n \n Minimum 3000 × 3000px\n
\n JPEG or PNG only\n
\n
\n
\n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/cards/cover-art.tsx" }, { "path": "src/blocks/kitchen-sink/cards/dividend-income.tsx", "content": "\"use client\"\n\nimport { Bar, BarChart } from \"recharts\"\n\nimport { Button } from \"@/components/ui/button\"\nimport {\n Card,\n CardAction,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n} from \"@/components/ui/card\"\nimport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n type ChartConfig,\n} from \"@/components/ui/chart\"\nimport {\n Item,\n ItemContent,\n ItemDescription,\n ItemGroup,\n ItemTitle,\n} from \"@/components/ui/item\"\nimport { IconPlaceholder } from \"../components/icon-placeholder\"\n\nconst HOLDINGS = [\n {\n name: \"Vanguard VIG\",\n shares: \"450 Shares\",\n amount: \"$1,842.10\",\n data: [\n { q: \"Q1\", value: 380 },\n { q: \"Q2\", value: 420 },\n { q: \"Q3\", value: 390 },\n { q: \"Q4\", value: 652 },\n ],\n },\n {\n name: \"S&P 500 VOO\",\n shares: \"112 Shares\",\n amount: \"$928.40\",\n data: [\n { q: \"Q1\", value: 180 },\n { q: \"Q2\", value: 210 },\n { q: \"Q3\", value: 320 },\n { q: \"Q4\", value: 218 },\n ],\n },\n {\n name: \"Apple AAPL\",\n shares: \"85 Shares\",\n amount: \"$340.00\",\n data: [\n { q: \"Q1\", value: 60 },\n { q: \"Q2\", value: 70 },\n { q: \"Q3\", value: 120 },\n { q: \"Q4\", value: 90 },\n ],\n },\n {\n name: \"Realty Income\",\n shares: \"320 Shares\",\n amount: \"$1,139.50\",\n data: [\n { q: \"Q1\", value: 240 },\n { q: \"Q2\", value: 260 },\n { q: \"Q3\", value: 280 },\n { q: \"Q4\", value: 360 },\n ],\n },\n]\n\nconst miniChartConfig = {\n value: {\n label: \"Dividend\",\n color: \"var(--chart-2)\",\n },\n} satisfies ChartConfig\n\nexport function DividendIncome() {\n const isRounded = true\n\n return (\n \n \n Q2 Dividend Income\n \n Quarterly dividend payouts across your portfolio holdings.\n \n \n \n \n \n \n \n {HOLDINGS.map((holding) => (\n \n \n {holding.name}\n {holding.shares}\n \n \n \n }\n />\n \n \n \n \n {holding.amount}\n \n \n ))}\n \n \n \n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/cards/dividend-income.tsx" }, { "path": "src/blocks/kitchen-sink/cards/empty-connect-bank.tsx", "content": "import { Button } from \"@/components/ui/button\"\nimport { Card, CardContent } from \"@/components/ui/card\"\nimport {\n Empty,\n EmptyContent,\n EmptyDescription,\n EmptyHeader,\n EmptyMedia,\n EmptyTitle,\n} from \"@/components/ui/empty\"\nimport { IconPlaceholder } from \"../components/icon-placeholder\"\n\nexport function EmptyConnectBank() {\n return (\n \n \n \n \n \n \n \n Connect Bank\n \n Link your payout method to receive monthly royalty distributions\n automatically.\n \n \n \n \n \n \n \n \n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/cards/empty-connect-bank.tsx" }, { "path": "src/blocks/kitchen-sink/cards/empty-distribute-track.tsx", "content": "import { Button } from \"@/components/ui/button\"\nimport { Card, CardContent } from \"@/components/ui/card\"\nimport {\n Empty,\n EmptyContent,\n EmptyDescription,\n EmptyHeader,\n EmptyMedia,\n EmptyTitle,\n} from \"@/components/ui/empty\"\nimport { IconPlaceholder } from \"../components/icon-placeholder\"\n\nexport function EmptyDistributeTrack() {\n return (\n \n \n \n \n \n \n \n Distribute Track\n \n Upload your first master to start reaching listeners on Spotify,\n Apple Music, and more.\n \n \n \n \n \n \n \n \n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/cards/empty-distribute-track.tsx" }, { "path": "src/blocks/kitchen-sink/cards/empty-explore-catalog.tsx", "content": "import { Button } from \"@/components/ui/button\"\nimport { Card, CardContent } from \"@/components/ui/card\"\nimport {\n Empty,\n EmptyContent,\n EmptyDescription,\n EmptyHeader,\n EmptyMedia,\n EmptyTitle,\n} from \"@/components/ui/empty\"\nimport { IconPlaceholder } from \"../components/icon-placeholder\"\n\nexport function EmptyExploreCatalog() {\n return (\n \n \n \n \n \n \n \n Explore Catalog\n \n Check your ISRC codes, metadata, and visual assets before going\n live.\n \n \n \n \n \n \n \n \n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/cards/empty-explore-catalog.tsx" }, { "path": "src/blocks/kitchen-sink/cards/faq.tsx", "content": "\"use client\"\n\nimport {\n Accordion,\n AccordionContent,\n AccordionItem,\n AccordionTrigger,\n} from \"@/components/ui/accordion\"\nimport { Button } from \"@/components/ui/button\"\nimport { Card, CardContent, CardFooter } from \"@/components/ui/card\"\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from \"@/components/ui/tabs\"\n\nconst GENERAL_QUESTIONS = [\n {\n q: \"How secure is my financial data with Ledger?\",\n a: \"We use bank-level AES-256 encryption, SOC 2 Type II certified infrastructure, and never store your credentials. All connections use read-only access tokens. We are a SEC registered investment advisor.\",\n },\n {\n q: \"How do I connect my bank or investment accounts?\",\n a: \"Go to Settings > Linked Accounts and search for your institution. We support over 12,000 banks and brokerages via Plaid and MX.\",\n },\n {\n q: \"Can I export my data for tax purposes?\",\n a: \"Yes. Navigate to Reports > Tax Export to download a CSV or PDF summary of your transactions, dividends, and capital gains for any tax year.\",\n },\n]\n\nconst BILLING_QUESTIONS = [\n {\n q: \"What is the difference between Basic and Pro pricing tiers?\",\n a: \"Basic includes budgeting, goal tracking, and up to 3 linked accounts. Pro adds unlimited accounts, dividend tracking, portfolio analysis, and priority support.\",\n },\n {\n q: \"How do I cancel my subscription?\",\n a: \"Go to Settings > Billing > Manage Plan and click Cancel. Your access continues until the end of your current billing period.\",\n },\n {\n q: \"Do you offer a free trial?\",\n a: \"Yes. All new accounts start with a 14-day Pro trial. No credit card required.\",\n },\n]\n\nconst GOALS_QUESTIONS = [\n {\n q: \"How do I set up a custom financial goal?\",\n a: \"Click New Goal from the Savings Targets card. Choose a category, set a target amount and date, and we'll calculate the monthly contribution needed.\",\n },\n {\n q: \"Can I track multiple goals at once?\",\n a: \"Yes. Pro accounts can track unlimited goals. Basic accounts support up to 3 active goals.\",\n },\n {\n q: \"How are monthly contributions calculated?\",\n a: \"We divide the remaining amount by the number of months until your target date, adjusted for your current savings rate and any auto-transfer schedules.\",\n },\n]\n\nfunction QuestionList({\n questions,\n}: {\n questions: { q: string; a: string }[]\n}) {\n return (\n \n {questions.map((item, index) => (\n \n {item.q}\n {item.a}\n \n ))}\n \n )\n}\n\nexport function Faq() {\n return (\n \n \n \n \n \n General\n \n \n Billing\n \n \n Goals\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/cards/faq.tsx" }, { "path": "src/blocks/kitchen-sink/cards/front-door.tsx", "content": "import { Badge } from \"@/components/ui/badge\"\nimport {\n Card,\n CardAction,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n} from \"@/components/ui/card\"\nimport { IconPlaceholder } from \"../components/icon-placeholder\"\n\nexport function FrontDoor() {\n return (\n \n \n Front Door\n Smart Lock Pro\n \n
\n Locked\n \n
\n
\n
\n \n
\n \n Live\n \n
\n
\n
\n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/cards/front-door.tsx" }, { "path": "src/blocks/kitchen-sink/cards/index-investing.tsx", "content": "import {\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n} from \"@/components/ui/card\"\n\nexport function IndexInvesting() {\n return (\n \n \n Dollar-Cost Averaging\n \n A strategy for building wealth over time.\n \n \n \n \n \n Over time\n \n , this smooths out the average cost of your investments. When prices\n drop, your fixed amount buys more shares. When prices rise, you buy\n fewer. The result is a lower average cost per share compared to\n lump-sum investing during volatile periods.\n \n \n \n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/cards/index-investing.tsx" }, { "path": "src/blocks/kitchen-sink/cards/kitchen-island.tsx", "content": "\"use client\"\n\nimport * as React from \"react\"\n\nimport {\n Card,\n CardAction,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n} from \"@/components/ui/card\"\nimport {\n Item,\n ItemActions,\n ItemContent,\n ItemGroup,\n ItemMedia,\n ItemTitle,\n} from \"@/components/ui/item\"\nimport { Slider } from \"@/components/ui/slider\"\nimport { Switch } from \"@/components/ui/switch\"\nimport { ToggleGroup, ToggleGroupItem } from \"@/components/ui/toggle-group\"\nimport { IconPlaceholder } from \"../components/icon-placeholder\"\n\nconst SCENES = {\n cooking: { brightness: [90], colorTemp: [70], volume: [30], fade: [0] },\n dining: { brightness: [50], colorTemp: [40], volume: [20], fade: [60] },\n nightlight: { brightness: [15], colorTemp: [20], volume: [0], fade: [80] },\n focus: { brightness: [100], colorTemp: [85], volume: [0], fade: [0] },\n} as const\n\nexport function KitchenIsland() {\n const [enabled, setEnabled] = React.useState(true)\n const [scene, setScene] = React.useState(\"cooking\")\n const [brightness, setBrightness] = React.useState([90])\n const [colorTemp, setColorTemp] = React.useState([70])\n const [volume, setVolume] = React.useState([30])\n const [fade, setFade] = React.useState([0])\n\n const handleSceneChange = (value: string) => {\n if (!value) return\n setScene(value)\n const preset = SCENES[value as keyof typeof SCENES]\n setBrightness([...preset.brightness])\n setColorTemp([...preset.colorTemp])\n setVolume([...preset.volume])\n setFade([...preset.fade])\n }\n\n return (\n \n \n Kitchen Island\n Hue Color Ambient\n \n \n \n \n \n
\n Scenes\n handleSceneChange(value[0] ?? \"cooking\")}\n variant=\"outline\"\n spacing={1}\n className=\"flex-wrap\"\n >\n \n Cooking\n \n \n Dining\n \n \n Nightlight\n \n \n Focus\n \n \n
\n \n \n \n \n \n \n Brightness\n \n \n \n setBrightness(Array.isArray(value) ? [...value] : [value])\n }\n max={100}\n disabled={!enabled}\n className=\"w-full\"\n />\n \n \n \n \n \n \n \n Color Temp\n \n \n \n setColorTemp(Array.isArray(value) ? [...value] : [value])\n }\n max={100}\n disabled={!enabled}\n />\n \n \n \n \n \n \n \n Volume\n \n \n \n setVolume(Array.isArray(value) ? [...value] : [value])\n }\n max={100}\n disabled={!enabled}\n />\n \n \n \n \n \n \n \n Fade\n \n \n \n setFade(Array.isArray(value) ? [...value] : [value])\n }\n max={100}\n disabled={!enabled}\n />\n \n \n \n
\n
\n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/cards/kitchen-island.tsx" }, { "path": "src/blocks/kitchen-sink/cards/loading-card.tsx", "content": "import { Card, CardContent, CardHeader } from \"@/components/ui/card\"\nimport { Skeleton } from \"@/components/ui/skeleton\"\n\nexport function LoadingCard() {\n return (\n \n \n \n \n \n \n \n
\n \n \n \n
\n
\n \n \n
\n
\n
\n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/cards/loading-card.tsx" }, { "path": "src/blocks/kitchen-sink/cards/new-milestone.tsx", "content": "\"use client\"\n\nimport { Button } from \"@/components/ui/button\"\nimport {\n Card,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n} from \"@/components/ui/card\"\nimport { Field, FieldGroup, FieldLabel } from \"@/components/ui/field\"\nimport { Input } from \"@/components/ui/input\"\n\nexport function NewMilestone() {\n return (\n \n \n Set a new milestone\n \n Define your financial target and we'll help you pace your\n savings.\n \n \n \n \n \n Goal Name\n \n \n
\n \n Target Amount\n \n \n \n Target Date\n \n \n
\n
\n
\n \n \n \n \n
\n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/cards/new-milestone.tsx" }, { "path": "src/blocks/kitchen-sink/cards/notification-settings.tsx", "content": "\"use client\"\n\nimport * as React from \"react\"\n\nimport { Button } from \"@/components/ui/button\"\nimport {\n Card,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n} from \"@/components/ui/card\"\nimport { Checkbox } from \"@/components/ui/checkbox\"\nimport {\n Field,\n FieldContent,\n FieldDescription,\n FieldGroup,\n FieldLabel,\n} from \"@/components/ui/field\"\n\nconst NOTIFICATIONS = [\n {\n id: \"transactions\",\n label: \"Transaction alerts\",\n description: \"Deposits, withdrawals, and transfers.\",\n defaultChecked: true,\n },\n {\n id: \"security\",\n label: \"Security alerts\",\n description: \"Login attempts and account changes.\",\n defaultChecked: true,\n },\n {\n id: \"goals\",\n label: \"Goal milestones\",\n description: \"Updates at 25%, 50%, 75%, and 100%.\",\n defaultChecked: false,\n },\n {\n id: \"market\",\n label: \"Market updates\",\n description: \"Daily portfolio summary and price alerts.\",\n defaultChecked: false,\n },\n]\n\nexport function NotificationSettings() {\n const [checked, setChecked] = React.useState>(\n Object.fromEntries(NOTIFICATIONS.map((n) => [n.id, n.defaultChecked]))\n )\n\n const allChecked = NOTIFICATIONS.every((n) => checked[n.id])\n const someChecked = NOTIFICATIONS.some((n) => checked[n.id]) && !allChecked\n\n const handleSelectAll = (value: boolean) => {\n setChecked(Object.fromEntries(NOTIFICATIONS.map((n) => [n.id, value])))\n }\n\n const handleToggle = (id: string, value: boolean) => {\n setChecked((prev) => ({ ...prev, [id]: value }))\n }\n\n return (\n \n \n Notifications\n \n Choose what you want to be notified about.\n \n \n \n \n \n handleSelectAll(!!v)}\n />\n \n Select all\n \n \n {NOTIFICATIONS.map((n) => (\n \n handleToggle(n.id, !!v)}\n />\n \n {n.label}\n {n.description}\n \n \n ))}\n \n \n \n \n \n \n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/cards/notification-settings.tsx" }, { "path": "src/blocks/kitchen-sink/cards/payments.tsx", "content": "\"use client\"\n\nimport {\n Breadcrumb,\n BreadcrumbItem,\n BreadcrumbLink,\n BreadcrumbList,\n BreadcrumbPage,\n BreadcrumbSeparator,\n} from \"@/components/ui/breadcrumb\"\nimport { Button } from \"@/components/ui/button\"\nimport { Card, CardContent, CardHeader } from \"@/components/ui/card\"\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from \"@/components/ui/dropdown-menu\"\nimport {\n Item,\n ItemContent,\n ItemDescription,\n ItemGroup,\n ItemMedia,\n ItemTitle,\n} from \"@/components/ui/item\"\nimport { IconPlaceholder } from \"../components/icon-placeholder\"\n\nexport function Payments() {\n return (\n \n \n \n \n \n Home\n \n \n \n \n }\n >\n \n Account options\n \n \n \n Profile\n Statements\n Documents\n \n \n \n \n \n \n Payments\n \n \n \n \n \n \n }>\n \n \n \n \n Change transfer limit\n \n Adjust how much you can send from your balance.\n \n \n \n \n }>\n \n \n \n \n Scheduled transfers\n \n Set up a transfer to send at a later date.\n \n \n \n \n }>\n \n \n \n \n Direct Debits\n \n Set up and manage regular payments.\n \n \n \n \n }>\n \n \n \n \n Recurring card payments\n \n Manage your repeated card transactions.\n \n \n \n \n \n \n \n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/cards/payments.tsx" }, { "path": "src/blocks/kitchen-sink/cards/payout-threshold.tsx", "content": "\"use client\"\n\nimport * as React from \"react\"\n\nimport { Button } from \"@/components/ui/button\"\nimport {\n Card,\n CardAction,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n} from \"@/components/ui/card\"\nimport {\n Field,\n FieldDescription,\n FieldGroup,\n FieldLabel,\n} from \"@/components/ui/field\"\nimport {\n Select,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/components/ui/select\"\nimport { Slider } from \"@/components/ui/slider\"\nimport { Textarea } from \"@/components/ui/textarea\"\nimport { IconPlaceholder } from \"../components/icon-placeholder\"\n\nconst CURRENCIES = [\n { label: \"USD — United States Dollar\", value: \"usd\" },\n { label: \"EUR — Euro\", value: \"eur\" },\n { label: \"GBP — British Pound\", value: \"gbp\" },\n { label: \"JPY — Japanese Yen\", value: \"jpy\" },\n]\n\nexport function PayoutThreshold() {\n const [amount, setAmount] = React.useState([2500])\n\n return (\n \n \n Payout Threshold\n \n Set the minimum balance required before a payout is triggered.\n \n \n \n \n \n \n \n \n \n Preferred Currency\n \n \n \n \n
\n \n Minimum Payout Amount\n \n \n ${amount[0].toFixed(2)}\n \n
\n \n setAmount(Array.isArray(value) ? [...value] : [value])\n }\n min={50}\n max={10000}\n step={50}\n />\n
\n $50 (MIN)\n $10,000 (MAX)\n
\n
\n \n Notes\n \n \n
\n
\n \n \n \n
\n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/cards/payout-threshold.tsx" }, { "path": "src/blocks/kitchen-sink/cards/power-usage.tsx", "content": "\"use client\"\n\nimport { Bar, BarChart, XAxis } from \"recharts\"\n\nimport {\n Card,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n} from \"@/components/ui/card\"\nimport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n type ChartConfig,\n} from \"@/components/ui/chart\"\nimport { Progress } from \"@/components/ui/progress\"\nimport { Separator } from \"@/components/ui/separator\"\n\nconst chartData = [\n { hour: \"6a\", usage: 1.2 },\n { hour: \"8a\", usage: 2.8 },\n { hour: \"10a\", usage: 3.1 },\n { hour: \"12p\", usage: 2.4 },\n { hour: \"2p\", usage: 3.4 },\n { hour: \"4p\", usage: 2.9 },\n { hour: \"6p\", usage: 3.8 },\n { hour: \"8p\", usage: 3.2 },\n]\n\nconst chartConfig = {\n usage: {\n label: \"Usage (kW)\",\n color: \"var(--chart-2)\",\n },\n} satisfies ChartConfig\n\nexport function PowerUsage() {\n const isRounded = true\n\n return (\n \n \n Power Usage\n Whole Home\n \n \n \n \n \n }\n />\n \n \n \n \n
\n
\n \n Currently Using\n \n 3.4 kW\n
\n
\n Solar Gen\n \n +1.2 kW\n \n
\n
\n
\n \n Battery Level\n
\n \n 85%\n
\n
\n
\n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/cards/power-usage.tsx" }, { "path": "src/blocks/kitchen-sink/cards/preferences.tsx", "content": "import { Button } from \"@/components/ui/button\"\nimport {\n Card,\n CardAction,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n} from \"@/components/ui/card\"\nimport {\n Field,\n FieldContent,\n FieldDescription,\n FieldGroup,\n FieldLabel,\n FieldSeparator,\n} from \"@/components/ui/field\"\nimport {\n Select,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/components/ui/select\"\nimport { Switch } from \"@/components/ui/switch\"\nimport { IconPlaceholder } from \"../components/icon-placeholder\"\n\nconst CURRENCIES = [\n { label: \"USD — United States Dollar\", value: \"usd\" },\n { label: \"EUR — Euro\", value: \"eur\" },\n { label: \"GBP — British Pound\", value: \"gbp\" },\n { label: \"JPY — Japanese Yen\", value: \"jpy\" },\n]\n\nexport function Preferences() {\n return (\n \n \n Preferences\n \n Manage your account settings and notifications.\n \n \n \n \n \n \n \n \n Default Currency\n \n \n \n \n \n \n Public Statistics\n \n \n Allow others to see your total stream count and listening\n activity\n \n \n \n \n \n \n \n \n Email Notifications\n \n \n Monthly royalty reports and distribution updates\n \n \n \n \n \n \n \n \n \n \n \n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/cards/preferences.tsx" }, { "path": "src/blocks/kitchen-sink/cards/qr-connect.tsx", "content": "\"use client\"\n\nimport QRCode from \"react-qr-code\"\n\nimport { Button } from \"@/components/ui/button\"\nimport {\n Card,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n} from \"@/components/ui/card\"\n\nexport function QrConnect() {\n return (\n \n \n
\n \n
\n
\n \n Scan to connect your mobile device\n \n Open the Ledger mobile app and scan this code to link your device.\n \n \n \n \n \n
\n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/cards/qr-connect.tsx" }, { "path": "src/blocks/kitchen-sink/cards/receiving-method.tsx", "content": "\"use client\"\n\nimport { Button } from \"@/components/ui/button\"\nimport {\n Card,\n CardAction,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n} from \"@/components/ui/card\"\nimport {\n Field,\n FieldContent,\n FieldDescription,\n FieldGroup,\n FieldLabel,\n FieldLegend,\n FieldSet,\n FieldTitle,\n} from \"@/components/ui/field\"\nimport { Input } from \"@/components/ui/input\"\nimport { RadioGroup, RadioGroupItem } from \"@/components/ui/radio-group\"\nimport { IconPlaceholder } from \"../components/icon-placeholder\"\n\nexport function ReceivingMethod() {\n return (\n \n \n Payout Preferences\n Receiving Method\n \n \n \n \n \n \n \n \n Account Holder Name\n \n \n \n
\n Receiving Method\n \n \n \n \n \n Bank Transfer\n SWIFT / IBAN\n \n \n \n \n \n \n \n PayPal\n \n Instant Payout\n \n \n \n \n \n
\n \n IBAN / Account Number\n \n \n
\n
\n \n \n \n
\n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/cards/receiving-method.tsx" }, { "path": "src/blocks/kitchen-sink/cards/recent-transactions.tsx", "content": "\"use client\"\n\nimport { Button } from \"@/components/ui/button\"\nimport {\n Card,\n CardAction,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n} from \"@/components/ui/card\"\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"@/components/ui/dropdown-menu\"\nimport { Table, TableBody, TableCell, TableRow } from \"@/components/ui/table\"\nimport { IconPlaceholder } from \"../components/icon-placeholder\"\n\nexport function RecentTransactions() {\n return (\n \n \n Recent Transactions\n Your latest account activity.\n \n \n \n \n \n \n \n \n \n
\n \n
\n
\n \n
\n Blue Bottle Coffee\n \n Food & Drink\n \n
\n
\n \n Today, 10:24 AM\n \n \n \n -$6.50\n \n \n \n \n }\n >\n \n \n \n View details\n Add note\n Categorize\n \n Dispute\n \n \n \n
\n \n \n
\n \n
\n
\n \n
\n Whole Foods Market\n \n Groceries\n \n
\n
\n \n Yesterday\n \n \n \n -$142.30\n \n \n \n \n }\n >\n \n \n \n View details\n Add note\n Categorize\n \n Dispute\n \n \n \n
\n \n \n
\n \n
\n
\n \n
\n Stripe Payout\n Income\n
\n
\n \n Oct 12\n \n \n \n +$4,200.00\n \n \n \n \n }\n >\n \n \n \n View details\n Add note\n Categorize\n \n Dispute\n \n \n \n
\n \n \n
\n \n
\n
\n \n
\n Uber Technologies\n \n Transport\n \n
\n
\n \n Oct 11\n \n \n \n -$24.10\n \n \n \n \n }\n >\n \n \n \n View details\n Add note\n Categorize\n \n Dispute\n \n \n \n
\n \n \n
\n \n
\n
\n \n
\n Netflix Subscription\n \n Entertainment\n \n
\n
\n \n Oct 10\n \n \n \n -$19.99\n \n \n \n \n }\n >\n \n \n \n View details\n Add note\n Categorize\n \n Dispute\n \n \n \n
\n
\n
\n
\n
\n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/cards/recent-transactions.tsx" }, { "path": "src/blocks/kitchen-sink/cards/release-catalog.tsx", "content": "\"use client\"\n\nimport { Badge } from \"@/components/ui/badge\"\nimport { Card, CardContent, CardHeader } from \"@/components/ui/card\"\nimport {\n InputGroup,\n InputGroupAddon,\n InputGroupInput,\n} from \"@/components/ui/input-group\"\nimport {\n Item,\n ItemContent,\n ItemDescription,\n ItemGroup,\n ItemMedia,\n ItemTitle,\n} from \"@/components/ui/item\"\nimport { ToggleGroup, ToggleGroupItem } from \"@/components/ui/toggle-group\"\nimport { IconPlaceholder } from \"../components/icon-placeholder\"\n\nconst HOLDINGS = [\n {\n ticker: \"VOO\",\n name: \"Vanguard S&P 500 ETF\",\n type: \"ETF\",\n added: \"Jan 2021\",\n shares: \"112\",\n value: \"$48,230.40\",\n },\n {\n ticker: \"VIG\",\n name: \"Vanguard Dividend Appreciation\",\n type: \"ETF\",\n added: \"Mar 2022\",\n shares: \"450\",\n value: \"$26,033.79\",\n },\n {\n ticker: \"AAPL\",\n name: \"Apple Inc.\",\n type: \"Stock\",\n added: \"Nov 2020\",\n shares: \"85\",\n value: \"$18,488.90\",\n },\n {\n ticker: \"O\",\n name: \"Realty Income Corp\",\n type: \"REIT\",\n added: \"Jun 2023\",\n shares: \"320\",\n value: \"$15,136.59\",\n },\n]\n\nexport function ReleaseCatalog() {\n return (\n \n \n
\n \n \n \n \n \n \n \n Stocks\n ETFs\n REITs\n \n
\n
\n \n \n {HOLDINGS.map((holding) => (\n \n \n
\n {holding.ticker}\n
\n
\n \n {holding.name}\n \n {holding.shares} Shares · {holding.added}\n \n \n
\n {holding.type}\n
\n \n Value\n \n \n {holding.value}\n \n
\n
\n
\n ))}\n
\n
\n
\n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/cards/release-catalog.tsx" }, { "path": "src/blocks/kitchen-sink/cards/roller-shades.tsx", "content": "\"use client\"\n\nimport * as React from \"react\"\n\nimport {\n Card,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n} from \"@/components/ui/card\"\nimport { Slider } from \"@/components/ui/slider\"\nimport { ToggleGroup, ToggleGroupItem } from \"@/components/ui/toggle-group\"\n\nexport function RollerShades() {\n const [position, setPosition] = React.useState([50])\n\n const preset =\n position[0] <= 10 ? \"open\" : position[0] >= 90 ? \"closed\" : \"half\"\n\n return (\n \n \n Living Room\n Roller Shades\n \n \n
\n \n
\n
\n \n Open\n \n \n setPosition(Array.isArray(value) ? [...value] : [value])\n }\n max={100}\n className=\"flex-1\"\n />\n \n Close\n \n
\n
\n \n {\n const v = value[0]\n if (v === \"open\") setPosition([0])\n if (v === \"half\") setPosition([50])\n if (v === \"closed\") setPosition([100])\n }}\n variant=\"outline\"\n spacing={1}\n className=\"w-full\"\n >\n \n Open\n \n \n Half\n \n \n Closed\n \n \n \n
\n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/cards/roller-shades.tsx" }, { "path": "src/blocks/kitchen-sink/cards/savings-progress.tsx", "content": "\"use client\"\n\nimport { Label, Pie, PieChart } from \"recharts\"\n\nimport { Card, CardContent, CardFooter } from \"@/components/ui/card\"\nimport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n type ChartConfig,\n} from \"@/components/ui/chart\"\nimport { Separator } from \"@/components/ui/separator\"\n\nconst chartData = [\n { name: \"saved\", value: 24000, fill: \"var(--color-saved)\" },\n { name: \"remaining\", value: 6000, fill: \"var(--color-remaining)\" },\n]\n\nconst chartConfig = {\n saved: {\n label: \"Saved\",\n color: \"var(--chart-2)\",\n },\n remaining: {\n label: \"Remaining\",\n color: \"var(--chart-1)\",\n },\n} satisfies ChartConfig\n\nexport function SavingsProgress() {\n return (\n \n \n \n \n }\n />\n \n {\n if (viewBox && \"cx\" in viewBox && \"cy\" in viewBox) {\n return (\n \n \n $24,000\n \n \n 80% of $30,000\n \n \n )\n }\n }}\n />\n \n \n \n \n \n
\n \n Projected Finish\n \n October 2024\n
\n \n
\n Monthly Average\n $1,250\n
\n \n
\n Top Contributor\n Auto-Transfer\n
\n
\n
\n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/cards/savings-progress.tsx" }, { "path": "src/blocks/kitchen-sink/cards/savings-targets.tsx", "content": "import { Button } from \"@/components/ui/button\"\nimport {\n Card,\n CardAction,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n} from \"@/components/ui/card\"\nimport {\n Field,\n FieldDescription,\n FieldGroup,\n FieldLabel,\n} from \"@/components/ui/field\"\nimport {\n InputGroup,\n InputGroupAddon,\n InputGroupInput,\n InputGroupText,\n} from \"@/components/ui/input-group\"\nimport {\n Item,\n ItemContent,\n ItemDescription,\n ItemFooter,\n ItemGroup,\n} from \"@/components/ui/item\"\nimport { NativeSelect, NativeSelectOption } from \"@/components/ui/native-select\"\nimport { Progress } from \"@/components/ui/progress\"\n\nexport function SavingsTargets() {\n return (\n
\n \n \n Savings Targets\n Active milestones for 2024\n \n \n \n \n \n \n \n \n \n Retirement\n \n \n $420,000\n \n \n \n \n \n 65% achieved\n \n \n $273,000\n \n \n \n \n \n \n Real Estate\n \n \n $85,000\n \n \n \n \n \n 32% achieved\n \n \n $27,200\n \n \n \n \n \n \n \n You have not met your targets for this year.\n \n \n \n \n \n Buy Investment\n \n \n \n \n Amount to Invest\n \n \n $\n \n \n \n \n \n Order Type\n \n \n Market Order\n \n \n Limit Order\n \n Stop Order\n \n \n Market orders execute at the current price.\n \n \n
\n
\n \n Estimated Shares\n \n 1.95\n
\n
\n \n Buying Power\n \n \n $12,450.00\n \n
\n
\n
\n
\n \n \n \n Trades are typically executed within minutes during market hours.\n \n \n
\n
\n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/cards/savings-targets.tsx" }, { "path": "src/blocks/kitchen-sink/cards/sidebar-nav.tsx", "content": "\"use client\"\n\nimport { Card } from \"@/components/ui/card\"\nimport {\n Sidebar,\n SidebarContent,\n SidebarGroup,\n SidebarGroupContent,\n SidebarGroupLabel,\n SidebarMenu,\n SidebarMenuButton,\n SidebarMenuItem,\n SidebarProvider,\n SidebarSeparator,\n} from \"@/components/ui/sidebar\"\nimport { IconPlaceholder } from \"../components/icon-placeholder\"\n\nexport function SidebarNav() {\n return (\n
\n \n \n \n \n \n Overview\n \n \n \n \n \n Dashboard\n \n \n \n \n \n Transactions\n \n \n \n \n \n Investments\n \n \n \n \n \n Accounts\n \n \n \n \n \n Spending\n \n \n \n \n \n \n \n Planning\n \n \n \n \n \n Goals\n \n \n \n \n \n Budget\n \n \n \n \n \n Reports\n \n \n \n \n \n Documents\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n Account\n \n \n \n \n \n Profile\n \n \n \n \n \n Billing\n \n \n \n \n \n Notifications\n \n \n \n \n \n Security\n \n \n \n \n \n Appearance\n \n \n \n \n \n \n \n Support\n \n \n \n \n \n Help Center\n \n \n \n \n \n Contact Us\n \n \n \n \n \n Documentation\n \n \n \n \n \n Status\n \n \n \n \n \n \n \n \n \n
\n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/cards/sidebar-nav.tsx" }, { "path": "src/blocks/kitchen-sink/cards/social-links.tsx", "content": "import { Button } from \"@/components/ui/button\"\nimport {\n Card,\n CardContent,\n CardFooter,\n CardHeader,\n CardTitle,\n} from \"@/components/ui/card\"\nimport { Field, FieldGroup, FieldLabel } from \"@/components/ui/field\"\nimport {\n InputGroup,\n InputGroupAddon,\n InputGroupInput,\n} from \"@/components/ui/input-group\"\nimport { IconPlaceholder } from \"../components/icon-placeholder\"\n\nexport function SocialLinks() {\n return (\n \n \n Social Links\n \n \n \n \n Spotify Artist URL\n \n \n \n \n \n \n \n \n Instagram Handle\n \n \n \n \n \n \n \n \n SoundCloud URL\n \n \n \n \n \n \n \n \n Website\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/cards/social-links.tsx" }, { "path": "src/blocks/kitchen-sink/cards/stock-performance.tsx", "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { Area, AreaChart, CartesianGrid } from \"recharts\"\n\nimport {\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n} from \"@/components/ui/card\"\nimport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n type ChartConfig,\n} from \"@/components/ui/chart\"\nimport {\n Combobox,\n ComboboxContent,\n ComboboxEmpty,\n ComboboxInput,\n ComboboxItem,\n ComboboxList,\n} from \"@/components/ui/combobox\"\nimport { Field, FieldGroup, FieldLabel } from \"@/components/ui/field\"\nimport { Separator } from \"@/components/ui/separator\"\n\nconst TICKERS = [\"VOO\", \"VIG\", \"AAPL\", \"MSFT\", \"GOOGL\", \"AMZN\", \"TSLA\"]\n\nconst CHART_DATA: Record = {\n VOO: [\n { month: \"Jan\", price: 412 },\n { month: \"Feb\", price: 438 },\n { month: \"Mar\", price: 395 },\n { month: \"Apr\", price: 450 },\n { month: \"May\", price: 420 },\n { month: \"Jun\", price: 462 },\n ],\n AAPL: [\n { month: \"Jan\", price: 185 },\n { month: \"Feb\", price: 210 },\n { month: \"Mar\", price: 172 },\n { month: \"Apr\", price: 198 },\n { month: \"May\", price: 178 },\n { month: \"Jun\", price: 215 },\n ],\n}\n\nconst DEFAULT_DATA = [\n { month: \"Jan\", price: 100 },\n { month: \"Feb\", price: 118 },\n { month: \"Mar\", price: 95 },\n { month: \"Apr\", price: 125 },\n { month: \"May\", price: 108 },\n { month: \"Jun\", price: 130 },\n]\n\nconst chartConfig = {\n price: {\n label: \"Price\",\n color: \"var(--chart-1)\",\n },\n} satisfies ChartConfig\n\nexport function StockPerformance() {\n const [ticker, setTicker] = React.useState(\"VOO\")\n\n const data = CHART_DATA[ticker] ?? DEFAULT_DATA\n\n return (\n \n \n Stock Performance\n 6-month price history.\n \n \n \n \n Ticker\n {\n if (value !== null) setTicker(value)\n }}\n >\n \n \n No tickers found.\n \n {(item) => (\n \n {item}\n \n )}\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n }\n />\n \n \n \n \n \n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/cards/stock-performance.tsx" }, { "path": "src/blocks/kitchen-sink/cards/syncing-state.tsx", "content": "import { Button } from \"@/components/ui/button\"\nimport { Card, CardContent } from \"@/components/ui/card\"\nimport {\n Empty,\n EmptyContent,\n EmptyDescription,\n EmptyHeader,\n EmptyMedia,\n EmptyTitle,\n} from \"@/components/ui/empty\"\nimport { Spinner } from \"@/components/ui/spinner\"\n\nexport function SyncingState() {\n return (\n \n \n \n \n \n \n \n Syncing your accounts\n \n We're pulling in your latest transactions. This usually takes\n a few seconds.\n \n \n \n \n \n \n \n \n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/cards/syncing-state.tsx" }, { "path": "src/blocks/kitchen-sink/cards/transfer-funds.tsx", "content": "import { Button } from \"@/components/ui/button\"\nimport {\n Card,\n CardAction,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n} from \"@/components/ui/card\"\nimport { Field, FieldGroup, FieldLabel } from \"@/components/ui/field\"\nimport {\n InputGroup,\n InputGroupAddon,\n InputGroupInput,\n InputGroupText,\n} from \"@/components/ui/input-group\"\nimport { Item, ItemContent } from \"@/components/ui/item\"\nimport {\n Select,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/components/ui/select\"\nimport { Separator } from \"@/components/ui/separator\"\nimport { IconPlaceholder } from \"../components/icon-placeholder\"\n\nconst FROM_ACCOUNTS = [\n { label: \"Main Checking (··8402) — $12,450.00\", value: \"checking\" },\n { label: \"Business (··7731) — $8,920.00\", value: \"business\" },\n]\n\nconst TO_ACCOUNTS = [\n { label: \"High Yield Savings (··1192) — $42,100.00\", value: \"savings\" },\n { label: \"Investment (··3349) — $18,200.00\", value: \"investment\" },\n]\n\nexport function TransferFunds() {\n return (\n \n \n Transfer Funds\n \n Move money between your connected accounts.\n \n \n \n \n \n \n \n \n \n Amount to Transfer\n \n \n \n $\n \n \n \n \n \n From Account\n \n \n \n To Account\n \n \n \n \n
\n \n Estimated arrival\n \n Today, Apr 14\n
\n \n
\n \n Transaction fee\n \n $0.00\n
\n \n
\n Total amount\n \n $1,200.00\n \n
\n
\n
\n
\n
\n \n \n \n
\n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/cards/transfer-funds.tsx" }, { "path": "src/blocks/kitchen-sink/cards/upcoming-payments.tsx", "content": "\"use client\"\n\nimport * as React from \"react\"\n\nimport { Badge } from \"@/components/ui/badge\"\nimport { Calendar } from \"@/components/ui/calendar\"\nimport {\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n} from \"@/components/ui/card\"\nimport {\n Item,\n ItemContent,\n ItemDescription,\n ItemGroup,\n ItemTitle,\n} from \"@/components/ui/item\"\n\nexport function UpcomingPayments() {\n const [date, setDate] = React.useState(new Date())\n\n return (\n \n \n Upcoming Payments\n \n Select a date to view scheduled payments.\n \n \n \n \n \n \n \n \n \n Netflix Subscription\n Apr 15, 2024\n \n $19.99\n \n \n \n Rent Payment\n Apr 1, 2024\n \n $2,400.00\n \n \n \n Auto Insurance\n Apr 22, 2024\n \n $186.00\n \n \n \n \n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/cards/upcoming-payments.tsx" }, { "path": "src/blocks/kitchen-sink/components/demo-icon.tsx", "content": "export { IconPlaceholder as DemoIcon } from \"./icon-placeholder\"\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/components/demo-icon.tsx" }, { "path": "src/blocks/kitchen-sink/components/icon-placeholder.tsx", "content": "import type { ComponentProps } from \"react\"\nimport {\n ActivityIcon,\n AlertCircleIcon,\n ArrowLeftIcon,\n ArrowLeftRightIcon,\n ArrowRightIcon,\n AudioLinesIcon,\n BellIcon,\n BookOpenIcon,\n Building2Icon,\n CalendarIcon,\n CameraIcon,\n CarIcon,\n CheckCircle2Icon,\n CheckIcon,\n ChevronDownIcon,\n ChevronRightIcon,\n ChevronUpIcon,\n CircleAlertIcon,\n CircleHelpIcon,\n CirclePlusIcon,\n CloudIcon,\n CoffeeIcon,\n ContainerIcon,\n CopyIcon,\n CreditCardIcon,\n DownloadIcon,\n FileBarChartIcon,\n FileTextIcon,\n GaugeIcon,\n GlobeIcon,\n ImageIcon,\n InfoIcon,\n LayoutDashboardIcon,\n LockIcon,\n LockKeyholeIcon,\n Loader2Icon,\n MessageSquareIcon,\n MinusIcon,\n MonitorIcon,\n MoreHorizontalIcon,\n PaintbrushIcon,\n PieChartIcon,\n PlusIcon,\n RefreshCwIcon,\n RepeatIcon,\n SearchIcon,\n ServerIcon,\n SettingsIcon,\n ShareIcon,\n ShieldIcon,\n ShoppingBagIcon,\n ShoppingCartIcon,\n SquareIcon,\n SunIcon,\n TargetIcon,\n TerminalIcon,\n ThermometerIcon,\n TimerIcon,\n TrendingUpIcon,\n TrashIcon,\n TvIcon,\n UserIcon,\n UploadCloudIcon,\n Volume2Icon,\n WalletIcon,\n XIcon,\n ZapIcon,\n type LucideIcon,\n} from \"lucide-react\"\n\nconst icons: Record = {\n ActivityIcon,\n AlertCircleIcon,\n ArrowLeftIcon,\n ArrowLeftRightIcon,\n ArrowRightIcon,\n AudioLinesIcon,\n BellIcon,\n BookOpenIcon,\n Building2Icon,\n CalendarIcon,\n CameraIcon,\n CarIcon,\n CheckCircle2Icon,\n CheckIcon,\n ChevronDownIcon,\n ChevronRightIcon,\n ChevronUpIcon,\n CircleAlertIcon,\n CircleHelpIcon,\n CirclePlusIcon,\n CloudIcon,\n CoffeeIcon,\n ContainerIcon,\n CopyIcon,\n CreditCardIcon,\n DownloadIcon,\n FileBarChartIcon,\n FileTextIcon,\n GaugeIcon,\n GlobeIcon,\n ImageIcon,\n InfoIcon,\n LayoutDashboardIcon,\n LockIcon,\n LockKeyholeIcon,\n Loader2Icon,\n MessageSquareIcon,\n MinusIcon,\n MonitorIcon,\n MoreHorizontalIcon,\n PaintbrushIcon,\n PieChartIcon,\n PlusIcon,\n RefreshCwIcon,\n RepeatIcon,\n SearchIcon,\n ServerIcon,\n SettingsIcon,\n ShareIcon,\n ShieldIcon,\n ShoppingBagIcon,\n ShoppingCartIcon,\n SunIcon,\n TargetIcon,\n TerminalIcon,\n ThermometerIcon,\n TimerIcon,\n TrendingUpIcon,\n TrashIcon,\n TvIcon,\n UserIcon,\n UploadCloudIcon,\n Volume2Icon,\n WalletIcon,\n XIcon,\n ZapIcon,\n}\n\ntype IconPlaceholderProps = ComponentProps<\"svg\"> & {\n lucide: string\n tabler?: string\n hugeicons?: string\n phosphor?: string\n remixicon?: string\n}\n\nexport function IconPlaceholder({\n lucide,\n tabler: _tabler,\n hugeicons: _hugeicons,\n phosphor: _phosphor,\n remixicon: _remixicon,\n ...props\n}: IconPlaceholderProps) {\n void _tabler\n void _hugeicons\n void _phosphor\n void _remixicon\n\n const Icon = icons[lucide] ?? SquareIcon\n\n return \n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/components/icon-placeholder.tsx" }, { "path": "src/blocks/kitchen-sink/index.tsx", "content": "import { AdditionalCardStacks } from \"./additional-card-stacks\"\nimport { AccountAccess } from \"./cards/account-access\"\nimport { CardOverview } from \"./cards/card-overview\"\nimport { ClaimableBalance } from \"./cards/claimable-balance\"\nimport { ContributionHistory } from \"./cards/contribution-history\"\nimport { CoverArt } from \"./cards/cover-art\"\nimport { DividendIncome } from \"./cards/dividend-income\"\nimport { EmptyConnectBank } from \"./cards/empty-connect-bank\"\nimport { EmptyDistributeTrack } from \"./cards/empty-distribute-track\"\nimport { EmptyExploreCatalog } from \"./cards/empty-explore-catalog\"\nimport { Faq } from \"./cards/faq\"\nimport { FrontDoor } from \"./cards/front-door\"\nimport { IndexInvesting } from \"./cards/index-investing\"\nimport { KitchenIsland } from \"./cards/kitchen-island\"\nimport { LoadingCard } from \"./cards/loading-card\"\nimport { NewMilestone } from \"./cards/new-milestone\"\nimport { NotificationSettings } from \"./cards/notification-settings\"\nimport { Payments } from \"./cards/payments\"\nimport { PayoutThreshold } from \"./cards/payout-threshold\"\nimport { PowerUsage } from \"./cards/power-usage\"\nimport { Preferences } from \"./cards/preferences\"\nimport { QrConnect } from \"./cards/qr-connect\"\nimport { ReceivingMethod } from \"./cards/receiving-method\"\nimport { RecentTransactions } from \"./cards/recent-transactions\"\nimport { ReleaseCatalog } from \"./cards/release-catalog\"\nimport { RollerShades } from \"./cards/roller-shades\"\nimport { SavingsProgress } from \"./cards/savings-progress\"\nimport { SavingsTargets } from \"./cards/savings-targets\"\nimport { SidebarNav } from \"./cards/sidebar-nav\"\nimport { SocialLinks } from \"./cards/social-links\"\nimport { StockPerformance } from \"./cards/stock-performance\"\nimport { SyncingState } from \"./cards/syncing-state\"\nimport { TransferFunds } from \"./cards/transfer-funds\"\nimport { UpcomingPayments } from \"./cards/upcoming-payments\"\n\nexport default function Preview02Example() {\n return (\n \n
\n \n
\n \n \n \n \n \n \n
\n
\n \n \n \n \n \n
\n
\n \n \n
\n
\n \n \n
\n
\n \n \n
\n
\n \n
\n
\n \n \n \n \n \n
\n
\n \n \n \n \n \n
\n
\n \n \n \n \n \n
\n \n
\n \n \n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/index.tsx" }, { "path": "src/blocks/kitchen-sink/preview-cards/activate-agent-dialog.tsx", "content": "\"use client\"\n\nimport { Alert, AlertDescription } from \"@/components/ui/alert\"\nimport { Badge } from \"@/components/ui/badge\"\nimport { Button } from \"@/components/ui/button\"\nimport {\n Card,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n} from \"@/components/ui/card\"\nimport {\n Item,\n ItemContent,\n ItemGroup,\n ItemMedia,\n ItemTitle,\n} from \"@/components/ui/item\"\nimport { IconPlaceholder } from \"../components/icon-placeholder\"\n\n// Agent feature descriptions.\nconst agentFeatures = [\n {\n id: \"code-reviews\",\n content: (\n <>\n Code reviews with full codebase context to catch{\" \"}\n hard-to-find bugs.\n \n ),\n },\n {\n id: \"code-suggestions\",\n content: (\n <>\n Code suggestions validated in sandboxes before you\n merge.\n \n ),\n },\n {\n id: \"root-cause\",\n content: (\n <>\n Root-cause analysis for production issues with\n deployment context.{\" \"}\n \n Requires Observability Plus\n \n \n ),\n },\n]\n\nexport function ActivateAgentDialog() {\n return (\n \n \n Ship faster & safer with Vercel Agent\n \n Your use is subject to Vercel's{\" \"}\n Public Beta Agreement and{\" \"}\n AI Product Terms.\n \n \n \n \n {agentFeatures.map((feature) => (\n \n \n \n \n \n \n {feature.content}\n \n \n \n ))}\n \n \n \n Pro teams get $100 in Vercel Agent trial credit for 2 weeks after\n activation.\n \n \n \n \n \n \n \n \n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/preview-cards/activate-agent-dialog.tsx" }, { "path": "src/blocks/kitchen-sink/preview-cards/analytics-card.tsx", "content": "\"use client\"\n\nimport { Area, AreaChart } from \"recharts\"\n\nimport { Badge } from \"@/components/ui/badge\"\nimport { Button } from \"@/components/ui/button\"\nimport {\n Card,\n CardAction,\n CardDescription,\n CardHeader,\n CardTitle,\n} from \"@/components/ui/card\"\nimport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n type ChartConfig,\n} from \"@/components/ui/chart\"\n\n// Monthly visitor data for the area chart.\nconst chartData = [\n { month: \"January\", visitors: 186 },\n { month: \"February\", visitors: 305 },\n { month: \"March\", visitors: 237 },\n { month: \"April\", visitors: 73 },\n { month: \"May\", visitors: 209 },\n { month: \"June\", visitors: 214 },\n]\n\n// Chart configuration for the visitors dataset.\nconst chartConfig = {\n visitors: {\n label: \"Visitors\",\n color: \"var(--chart-1)\",\n },\n} satisfies ChartConfig\n\nexport function AnalyticsCard() {\n return (\n \n \n Analytics\n \n 418.2K Visitors +10%\n \n \n \n \n \n \n \n }\n />\n \n \n \n \n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/preview-cards/analytics-card.tsx" }, { "path": "src/blocks/kitchen-sink/preview-cards/anomaly-alert.tsx", "content": "\"use client\"\n\nimport { Button } from \"@/components/ui/button\"\nimport { Card, CardContent } from \"@/components/ui/card\"\nimport {\n Empty,\n EmptyContent,\n EmptyDescription,\n EmptyHeader,\n EmptyTitle,\n} from \"@/components/ui/empty\"\n\nexport function AnomalyAlert() {\n return (\n \n \n \n \n Get alerted for anomalies\n \n Automatically monitor your projects for anomalies and get\n notified.\n \n \n \n \n \n \n \n \n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/preview-cards/anomaly-alert.tsx" }, { "path": "src/blocks/kitchen-sink/preview-cards/bar-chart-card.tsx", "content": "\"use client\"\n\nimport { Bar, BarChart, CartesianGrid, XAxis } from \"recharts\"\n\nimport { Button } from \"@/components/ui/button\"\nimport {\n Card,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n} from \"@/components/ui/card\"\nimport {\n ChartContainer,\n ChartLegend,\n ChartLegendContent,\n ChartTooltip,\n ChartTooltipContent,\n type ChartConfig,\n} from \"@/components/ui/chart\"\n\nconst barChartData = [\n { month: \"January\", desktop: 186, mobile: 80 },\n { month: \"February\", desktop: 305, mobile: 200 },\n { month: \"March\", desktop: 237, mobile: 120 },\n { month: \"April\", desktop: 73, mobile: 190 },\n { month: \"May\", desktop: 209, mobile: 130 },\n { month: \"June\", desktop: 214, mobile: 140 },\n]\n\nconst barChartConfig = {\n desktop: {\n label: \"Desktop\",\n color: \"var(--chart-1)\",\n },\n mobile: {\n label: \"Mobile\",\n color: \"var(--chart-2)\",\n },\n} satisfies ChartConfig\n\nconst desktopTotal = barChartData.reduce((sum, item) => sum + item.desktop, 0)\nconst mobileTotal = barChartData.reduce((sum, item) => sum + item.mobile, 0)\nconst desktopDelta = Math.round(\n ((desktopTotal - mobileTotal) / mobileTotal) * 100\n)\nconst desktopDeltaPrefix = desktopDelta > 0 ? \"+\" : \"\"\n\nexport function BarChartCard() {\n const isRounded = true\n\n return (\n \n \n Traffic channels\n \n Monthly desktop and mobile traffic for the last six months—compare\n volume and mix across platforms and devices at a glance.\n \n \n \n \n \n \n String(value).slice(0, 3)}\n />\n }\n />\n } />\n \n \n \n \n
\n
\n
\n Desktop\n
\n
\n {desktopTotal.toLocaleString()}\n
\n
\n
\n
\n Mobile\n
\n
\n {mobileTotal.toLocaleString()}\n
\n
\n
\n
\n Mix Delta\n
\n
\n {desktopDeltaPrefix}\n {desktopDelta}%\n
\n
\n
\n
\n \n \n \n
\n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/preview-cards/bar-chart-card.tsx" }, { "path": "src/blocks/kitchen-sink/preview-cards/book-appointment.tsx", "content": "\"use client\"\n\nimport { Alert, AlertDescription, AlertTitle } from \"@/components/ui/alert\"\nimport { Button } from \"@/components/ui/button\"\nimport {\n Card,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n} from \"@/components/ui/card\"\nimport { Field, FieldGroup, FieldLabel } from \"@/components/ui/field\"\nimport { ToggleGroup, ToggleGroupItem } from \"@/components/ui/toggle-group\"\n\nexport function BookAppointment() {\n return (\n \n \n Book Appointment\n Dr. Sarah Chen · Cardiology\n \n \n \n \n Available on March 18, 2026\n \n {[\"9:00 AM\", \"10:30 AM\", \"11:00 AM\", \"1:30 PM\"].map(\n (time, index) => (\n \n {time}\n \n )\n )}\n \n \n \n \n New patient?\n Please arrive 15 minutes early.\n \n \n \n \n \n \n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/preview-cards/book-appointment.tsx" }, { "path": "src/blocks/kitchen-sink/preview-cards/codespaces-card.tsx", "content": "\"use client\"\n\nimport * as React from \"react\"\n\nimport { Button } from \"@/components/ui/button\"\nimport { Card, CardContent } from \"@/components/ui/card\"\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"@/components/ui/dropdown-menu\"\nimport {\n Empty,\n EmptyContent,\n EmptyDescription,\n EmptyHeader,\n EmptyMedia,\n EmptyTitle,\n} from \"@/components/ui/empty\"\nimport { Field, FieldDescription, FieldLabel } from \"@/components/ui/field\"\nimport {\n InputGroup,\n InputGroupAddon,\n InputGroupButton,\n InputGroupInput,\n} from \"@/components/ui/input-group\"\nimport {\n Item,\n ItemActions,\n ItemContent,\n ItemDescription,\n ItemTitle,\n} from \"@/components/ui/item\"\nimport { Separator } from \"@/components/ui/separator\"\nimport { Spinner } from \"@/components/ui/spinner\"\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from \"@/components/ui/tabs\"\nimport {\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from \"@/components/ui/tooltip\"\nimport { IconPlaceholder } from \"../components/icon-placeholder\"\n\nexport function CodespacesCard() {\n const [isCreatingCodespace, setIsCreatingCodespace] = React.useState(false)\n return (\n \n \n \n \n Codespaces\n Local\n \n \n \n \n Codespaces\n Your workspaces in the cloud\n \n \n \n }\n >\n \n \n \n Create a codespace on main\n \n \n \n }\n >\n \n \n \n \n \n \n New with options...\n \n \n \n Configure container\n \n \n \n Set up prebuilds\n \n \n \n \n \n \n Manage codespaces\n \n \n \n Share deep link\n \n \n \n What are codespaces?\n \n \n \n \n \n \n \n \n \n \n \n \n No codespaces\n \n You don't have any codespaces with this repository\n checked out\n \n \n \n {\n setIsCreatingCodespace(true)\n setTimeout(() => {\n setIsCreatingCodespace(false)\n }, 2000)\n }}\n disabled={isCreatingCodespace}\n >\n {isCreatingCodespace ? (\n \n ) : (\n \"\"\n )}\n Create Codespace\n \n \n Learn more about codespaces\n \n \n \n \n
\n Codespace usage for this repository is paid for by{\" \"}\n shadcn.\n
\n
\n \n \n \n \n \n Clone\n \n \n \n \n }\n >\n \n \n \n Which remote URL should I use?\n \n \n \n \n \n \n HTTPS\n SSH\n GitHub CLI\n \n
\n \n \n \n HTTPS URL\n \n \n \n \n \n \n \n \n \n \n Clone using the web URL.\n \n \n \n \n \n \n SSH URL\n \n \n \n \n \n \n \n \n \n \n Use a password-protected SSH key.\n \n \n \n \n \n \n CLI Command\n \n \n \n \n \n \n \n \n \n \n Work fast with our official CLI.{\" \"}\n Learn more\n \n \n \n
\n
\n \n
\n \n \n Open with GitHub Desktop\n \n \n \n Download ZIP\n \n
\n
\n
\n
\n
\n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/preview-cards/codespaces-card.tsx" }, { "path": "src/blocks/kitchen-sink/preview-cards/contributions-activity.tsx", "content": "\"use client\"\n\nimport { Button } from \"@/components/ui/button\"\nimport {\n Card,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n} from \"@/components/ui/card\"\nimport { Checkbox } from \"@/components/ui/checkbox\"\nimport {\n Field,\n FieldContent,\n FieldDescription,\n FieldGroup,\n FieldLabel,\n FieldLegend,\n FieldSet,\n} from \"@/components/ui/field\"\n\nexport function ContributionsActivity() {\n return (\n \n \n Contributions & Activity\n \n Manage your contributions and activity visibility.\n \n \n \n
\n \n
\n \n Contributions & activity\n \n \n \n \n \n \n Make profile private and hide activity\n \n \n Enabling this will hide your contributions and activity\n from your GitHub profile and from social features like\n followers, stars, feeds, leaderboards and releases.\n \n \n \n \n
\n
\n
\n
\n \n \n \n
\n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/preview-cards/contributions-activity.tsx" }, { "path": "src/blocks/kitchen-sink/preview-cards/contributors.tsx", "content": "\"use client\"\n\nimport { Avatar, AvatarFallback, AvatarImage } from \"@/components/ui/avatar\"\nimport { Badge } from \"@/components/ui/badge\"\nimport {\n Card,\n CardContent,\n CardFooter,\n CardHeader,\n CardTitle,\n} from \"@/components/ui/card\"\n\n// GitHub usernames displayed as contributor avatars.\nconst usernames = [\n \"shadcn\",\n \"vercel\",\n \"nextjs\",\n \"tailwindlabs\",\n \"typescript-lang\",\n \"eslint\",\n \"prettier\",\n \"babel\",\n \"webpack\",\n \"rollup\",\n \"parcel\",\n \"vite\",\n \"react\",\n \"vue\",\n \"angular\",\n \"solid\",\n]\n\nexport function Contributors() {\n return (\n \n \n \n Contributors 312\n \n \n \n
\n {usernames.map((username) => (\n \n \n {username.charAt(0)}\n \n ))}\n
\n
\n \n \n + 810 contributors\n \n \n
\n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/preview-cards/contributors.tsx" }, { "path": "src/blocks/kitchen-sink/preview-cards/environment-variables.tsx", "content": "\"use client\"\n\nimport { Button } from \"@/components/ui/button\"\nimport {\n Card,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n} from \"@/components/ui/card\"\n\nexport function EnvironmentVariables() {\n return (\n \n \n Environment Variables\n Production · 8 variables\n \n \n {[\n { key: \"DATABASE_URL\", masked: true },\n { key: \"NEXT_PUBLIC_API\", masked: false },\n { key: \"STRIPE_SECRET\", masked: true },\n ].map((env) => (\n \n {env.key}\n \n {env.masked ? \"••••••••\" : \"https://api.example.com\"}\n \n \n ))}\n \n \n \n \n \n \n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/preview-cards/environment-variables.tsx" }, { "path": "src/blocks/kitchen-sink/preview-cards/feedback-form.tsx", "content": "\"use client\"\n\nimport { Button } from \"@/components/ui/button\"\nimport { Card, CardContent, CardFooter } from \"@/components/ui/card\"\nimport { Field, FieldGroup, FieldLabel } from \"@/components/ui/field\"\nimport { NativeSelect, NativeSelectOption } from \"@/components/ui/native-select\"\nimport { Textarea } from \"@/components/ui/textarea\"\n\nexport function FeedbackForm() {\n return (\n \n \n
\n \n \n Topic\n \n Select a topic\n AI\n \n Accounts and Access Controls\n \n Billing\n \n CDN (Firewall, Caching)\n \n \n CI/CD (Builds, Deployments, Environment Variables)\n \n \n Dashboard Interface (Navigation, UI Issues)\n \n Domains\n \n Frameworks\n \n \n Marketplace and Integrations\n \n \n Observability (Observability, Logs, Monitoring)\n \n Storage\n \n \n \n Feedback\n \n \n \n
\n
\n \n \n Submit\n \n \n
\n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/preview-cards/feedback-form.tsx" }, { "path": "src/blocks/kitchen-sink/preview-cards/file-upload.tsx", "content": "\"use client\"\n\nimport { Button } from \"@/components/ui/button\"\nimport {\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n} from \"@/components/ui/card\"\nimport {\n Empty,\n EmptyContent,\n EmptyDescription,\n EmptyHeader,\n EmptyMedia,\n EmptyTitle,\n} from \"@/components/ui/empty\"\nimport { IconPlaceholder } from \"../components/icon-placeholder\"\n\nexport function FileUpload() {\n return (\n \n \n File Upload\n Drag and drop or browse\n \n \n \n \n \n \n \n Upload files\n PNG, JPG, PDF up to 10MB\n \n \n \n \n \n \n \n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/preview-cards/file-upload.tsx" }, { "path": "src/blocks/kitchen-sink/preview-cards/github-profile.tsx", "content": "\"use client\"\n\nimport { Button } from \"@/components/ui/button\"\nimport {\n Card,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n} from \"@/components/ui/card\"\nimport {\n Field,\n FieldDescription,\n FieldGroup,\n FieldLabel,\n} from \"@/components/ui/field\"\nimport { Input } from \"@/components/ui/input\"\nimport { NativeSelect, NativeSelectOption } from \"@/components/ui/native-select\"\nimport { Textarea } from \"@/components/ui/textarea\"\n\nexport function GithubProfile() {\n return (\n \n \n Profile\n Manage your profile information.\n \n \n
\n \n \n Name\n \n \n Your name may appear around GitHub where you contribute or are\n mentioned. You can remove it at any time.\n \n \n \n Public Email\n \n \n m@shadcn.com\n \n \n m@gmail.com\n \n \n \n You can manage verified email addresses in your{\" \"}\n email settings.\n \n \n \n Bio\n \n \n You can @mention other users and organizations to\n link to them.\n \n \n \n
\n
\n \n \n \n
\n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/preview-cards/github-profile.tsx" }, { "path": "src/blocks/kitchen-sink/preview-cards/icon-preview-grid.tsx", "content": "\"use client\"\n\nimport { type IconLibraryName } from \"shadcn/icons\"\n\nimport { Card, CardContent } from \"@/components/ui/card\"\nimport { DemoIcon } from \"../components/demo-icon\"\n\nconst PREVIEW_ICONS = [\n {\n lucide: \"CopyIcon\",\n tabler: \"IconCopy\",\n hugeicons: \"Copy01Icon\",\n phosphor: \"CopyIcon\",\n remixicon: \"RiFileCopyLine\",\n },\n {\n lucide: \"CircleAlertIcon\",\n tabler: \"IconExclamationCircle\",\n hugeicons: \"AlertCircleIcon\",\n phosphor: \"WarningCircleIcon\",\n remixicon: \"RiErrorWarningLine\",\n },\n {\n lucide: \"TrashIcon\",\n tabler: \"IconTrash\",\n hugeicons: \"Delete02Icon\",\n phosphor: \"TrashIcon\",\n remixicon: \"RiDeleteBinLine\",\n },\n {\n lucide: \"ShareIcon\",\n tabler: \"IconShare\",\n hugeicons: \"Share03Icon\",\n phosphor: \"ShareIcon\",\n remixicon: \"RiShareLine\",\n },\n {\n lucide: \"ShoppingBagIcon\",\n tabler: \"IconShoppingBag\",\n hugeicons: \"ShoppingBag01Icon\",\n phosphor: \"BagIcon\",\n remixicon: \"RiShoppingBagLine\",\n },\n {\n lucide: \"MoreHorizontalIcon\",\n tabler: \"IconDots\",\n hugeicons: \"MoreHorizontalCircle01Icon\",\n phosphor: \"DotsThreeIcon\",\n remixicon: \"RiMoreLine\",\n },\n {\n lucide: \"Loader2Icon\",\n tabler: \"IconLoader\",\n hugeicons: \"Loading03Icon\",\n phosphor: \"SpinnerIcon\",\n remixicon: \"RiLoaderLine\",\n },\n {\n lucide: \"PlusIcon\",\n tabler: \"IconPlus\",\n hugeicons: \"PlusSignIcon\",\n phosphor: \"PlusIcon\",\n remixicon: \"RiAddLine\",\n },\n {\n lucide: \"MinusIcon\",\n tabler: \"IconMinus\",\n hugeicons: \"MinusSignIcon\",\n phosphor: \"MinusIcon\",\n remixicon: \"RiSubtractLine\",\n },\n {\n lucide: \"ArrowLeftIcon\",\n tabler: \"IconArrowLeft\",\n hugeicons: \"ArrowLeft02Icon\",\n phosphor: \"ArrowLeftIcon\",\n remixicon: \"RiArrowLeftLine\",\n },\n {\n lucide: \"ArrowRightIcon\",\n tabler: \"IconArrowRight\",\n hugeicons: \"ArrowRight02Icon\",\n phosphor: \"ArrowRightIcon\",\n remixicon: \"RiArrowRightLine\",\n },\n {\n lucide: \"CheckIcon\",\n tabler: \"IconCheck\",\n hugeicons: \"Tick02Icon\",\n phosphor: \"CheckIcon\",\n remixicon: \"RiCheckLine\",\n },\n {\n lucide: \"ChevronDownIcon\",\n tabler: \"IconChevronDown\",\n hugeicons: \"ArrowDown01Icon\",\n phosphor: \"CaretDownIcon\",\n remixicon: \"RiArrowDownSLine\",\n },\n {\n lucide: \"ChevronRightIcon\",\n tabler: \"IconChevronRight\",\n hugeicons: \"ArrowRight01Icon\",\n phosphor: \"CaretRightIcon\",\n remixicon: \"RiArrowRightSLine\",\n },\n {\n lucide: \"SearchIcon\",\n tabler: \"IconSearch\",\n hugeicons: \"Search01Icon\",\n phosphor: \"MagnifyingGlassIcon\",\n remixicon: \"RiSearchLine\",\n },\n {\n lucide: \"SettingsIcon\",\n tabler: \"IconSettings\",\n hugeicons: \"Settings01Icon\",\n phosphor: \"GearIcon\",\n remixicon: \"RiSettingsLine\",\n },\n] satisfies Record[]\n\nexport function IconPreviewGrid() {\n return (\n \n \n
\n {PREVIEW_ICONS.map((icon, index) => (\n \n \n
\n ))}\n \n
\n
\n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/preview-cards/icon-preview-grid.tsx" }, { "path": "src/blocks/kitchen-sink/preview-cards/invite-team.tsx", "content": "\"use client\"\n\nimport { Button } from \"@/components/ui/button\"\nimport {\n Card,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n} from \"@/components/ui/card\"\nimport { Field, FieldLabel } from \"@/components/ui/field\"\nimport { Input } from \"@/components/ui/input\"\nimport {\n InputGroup,\n InputGroupAddon,\n InputGroupButton,\n InputGroupInput,\n} from \"@/components/ui/input-group\"\nimport {\n Select,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/components/ui/select\"\nimport { Separator } from \"@/components/ui/separator\"\nimport { IconPlaceholder } from \"../components/icon-placeholder\"\n\nexport function InviteTeam() {\n return (\n \n \n Invite Team\n Add members to your workspace\n \n \n
\n {[\n { email: \"alex@example.com\", role: \"Editor\" },\n { email: \"sam@example.com\", role: \"Viewer\" },\n ].map((invite) => (\n
\n \n \n \n \n \n \n \n Admin\n Editor\n Viewer\n \n \n \n
\n ))}\n
\n \n \n \n Or share invite link\n \n \n \n \n \n \n \n \n \n
\n \n \n \n
\n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/preview-cards/invite-team.tsx" }, { "path": "src/blocks/kitchen-sink/preview-cards/invoice.tsx", "content": "\"use client\"\n\nimport { Badge } from \"@/components/ui/badge\"\nimport { Button } from \"@/components/ui/button\"\nimport {\n Card,\n CardAction,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n} from \"@/components/ui/card\"\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/components/ui/table\"\n\nconst INVOICE_ITEMS = [\n { item: \"Design System License\", qty: 1, unitPrice: 499 },\n { item: \"Priority Support\", qty: 12, unitPrice: 99 },\n { item: \"Custom Components\", qty: 3, unitPrice: 250 },\n] as const\n\nconst subtotal = INVOICE_ITEMS.reduce(\n (sum, row) => sum + row.qty * row.unitPrice,\n 0\n)\nconst tax = 0\nconst totalDue = subtotal + tax\n\nfunction formatCurrency(value: number) {\n return new Intl.NumberFormat(\"en-US\", {\n style: \"currency\",\n currency: \"USD\",\n maximumFractionDigits: 2,\n }).format(value)\n}\n\nexport function Invoice() {\n return (\n \n \n Invoice #INV-2847\n Due March 30, 2026\n \n Pending\n \n \n \n \n \n \n Item\n Qty\n Rate\n Amount\n \n \n \n {INVOICE_ITEMS.map((row) => (\n \n {row.item}\n \n {row.qty}\n \n \n {formatCurrency(row.unitPrice)}\n \n \n {formatCurrency(row.qty * row.unitPrice)}\n \n \n ))}\n \n \n Subtotal\n \n \n {formatCurrency(subtotal)}\n \n \n \n \n Tax\n \n $0.00\n \n \n \n Total Due\n \n \n {formatCurrency(totalDue)}\n \n \n \n
\n
\n \n \n \n \n
\n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/preview-cards/invoice.tsx" }, { "path": "src/blocks/kitchen-sink/preview-cards/live-waveform.tsx", "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { useEffect, useRef, useState } from \"react\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Button } from \"@/components/ui/button\"\nimport {\n Card,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n} from \"@/components/ui/card\"\n\nconst LiveWaveform = ({\n active = false,\n processing = false,\n deviceId,\n barWidth = 3,\n barGap = 1,\n barRadius = 1.5,\n barColor,\n fadeEdges = true,\n fadeWidth = 24,\n barHeight: baseBarHeight = 4,\n height = 64,\n sensitivity = 1,\n smoothingTimeConstant = 0.8,\n fftSize = 256,\n historySize = 60,\n updateRate = 30,\n mode = \"static\",\n onError,\n onStreamReady,\n onStreamEnd,\n className,\n ...props\n}: React.HTMLAttributes & {\n active?: boolean\n processing?: boolean\n deviceId?: string\n barWidth?: number\n barHeight?: number\n barGap?: number\n barRadius?: number\n barColor?: string\n fadeEdges?: boolean\n fadeWidth?: number\n height?: string | number\n sensitivity?: number\n smoothingTimeConstant?: number\n fftSize?: number\n historySize?: number\n updateRate?: number\n mode?: \"scrolling\" | \"static\"\n onError?: (error: Error) => void\n onStreamReady?: (stream: MediaStream) => void\n onStreamEnd?: () => void\n}) => {\n const canvasRef = useRef(null)\n const containerRef = useRef(null)\n const historyRef = useRef([])\n const analyserRef = useRef(null)\n const audioContextRef = useRef(null)\n const streamRef = useRef(null)\n const animationRef = useRef(0)\n const lastUpdateRef = useRef(0)\n const processingAnimationRef = useRef(null)\n const lastActiveDataRef = useRef([])\n const transitionProgressRef = useRef(0)\n const staticBarsRef = useRef([])\n const needsRedrawRef = useRef(true)\n const gradientCacheRef = useRef(null)\n const lastWidthRef = useRef(0)\n const heightStyle = typeof height === \"number\" ? `${height}px` : height\n\n // Handle canvas resizing.\n useEffect(() => {\n const canvas = canvasRef.current\n const container = containerRef.current\n if (!canvas || !container) return\n const resizeObserver = new ResizeObserver(() => {\n const rect = container.getBoundingClientRect()\n const dpr = window.devicePixelRatio || 1\n canvas.width = rect.width * dpr\n canvas.height = rect.height * dpr\n canvas.style.width = `${rect.width}px`\n canvas.style.height = `${rect.height}px`\n const ctx = canvas.getContext(\"2d\")\n if (ctx) {\n ctx.scale(dpr, dpr)\n }\n gradientCacheRef.current = null\n lastWidthRef.current = rect.width\n needsRedrawRef.current = true\n })\n resizeObserver.observe(container)\n return () => resizeObserver.disconnect()\n }, [])\n\n useEffect(() => {\n if (processing && !active) {\n let time = 0\n transitionProgressRef.current = 0\n const animateProcessing = () => {\n time += 0.03\n transitionProgressRef.current = Math.min(\n 1,\n transitionProgressRef.current + 0.02\n )\n const processingData = []\n const barCount = Math.floor(\n (containerRef.current?.getBoundingClientRect().width || 200) /\n (barWidth + barGap)\n )\n if (mode === \"static\") {\n const halfCount = Math.floor(barCount / 2)\n for (let i = 0; i < barCount; i++) {\n const normalizedPosition = (i - halfCount) / halfCount\n const centerWeight = 1 - Math.abs(normalizedPosition) * 0.4\n const wave1 = Math.sin(time * 1.5 + normalizedPosition * 3) * 0.25\n const wave2 = Math.sin(time * 0.8 - normalizedPosition * 2) * 0.2\n const wave3 = Math.cos(time * 2 + normalizedPosition) * 0.15\n const combinedWave = wave1 + wave2 + wave3\n const processingValue = (0.2 + combinedWave) * centerWeight\n let finalValue = processingValue\n if (\n lastActiveDataRef.current.length > 0 &&\n transitionProgressRef.current < 1\n ) {\n const lastDataIndex = Math.min(\n i,\n lastActiveDataRef.current.length - 1\n )\n const lastValue = lastActiveDataRef.current[lastDataIndex] || 0\n finalValue =\n lastValue * (1 - transitionProgressRef.current) +\n processingValue * transitionProgressRef.current\n }\n processingData.push(Math.max(0.05, Math.min(1, finalValue)))\n }\n } else {\n for (let i = 0; i < barCount; i++) {\n const normalizedPosition = (i - barCount / 2) / (barCount / 2)\n const centerWeight = 1 - Math.abs(normalizedPosition) * 0.4\n const wave1 = Math.sin(time * 1.5 + i * 0.15) * 0.25\n const wave2 = Math.sin(time * 0.8 - i * 0.1) * 0.2\n const wave3 = Math.cos(time * 2 + i * 0.05) * 0.15\n const combinedWave = wave1 + wave2 + wave3\n const processingValue = (0.2 + combinedWave) * centerWeight\n let finalValue = processingValue\n if (\n lastActiveDataRef.current.length > 0 &&\n transitionProgressRef.current < 1\n ) {\n const lastDataIndex = Math.floor(\n (i / barCount) * lastActiveDataRef.current.length\n )\n const lastValue = lastActiveDataRef.current[lastDataIndex] || 0\n finalValue =\n lastValue * (1 - transitionProgressRef.current) +\n processingValue * transitionProgressRef.current\n }\n processingData.push(Math.max(0.05, Math.min(1, finalValue)))\n }\n }\n if (mode === \"static\") {\n staticBarsRef.current = processingData\n } else {\n historyRef.current = processingData\n }\n needsRedrawRef.current = true\n processingAnimationRef.current =\n requestAnimationFrame(animateProcessing)\n }\n animateProcessing()\n return () => {\n if (processingAnimationRef.current) {\n cancelAnimationFrame(processingAnimationRef.current)\n }\n }\n } else if (!active && !processing) {\n const hasData =\n mode === \"static\"\n ? staticBarsRef.current.length > 0\n : historyRef.current.length > 0\n if (hasData) {\n let fadeProgress = 0\n const fadeToIdle = () => {\n fadeProgress += 0.03\n if (fadeProgress < 1) {\n if (mode === \"static\") {\n staticBarsRef.current = staticBarsRef.current.map(\n (value) => value * (1 - fadeProgress)\n )\n } else {\n historyRef.current = historyRef.current.map(\n (value) => value * (1 - fadeProgress)\n )\n }\n needsRedrawRef.current = true\n requestAnimationFrame(fadeToIdle)\n } else {\n if (mode === \"static\") {\n staticBarsRef.current = []\n } else {\n historyRef.current = []\n }\n }\n }\n fadeToIdle()\n }\n }\n }, [processing, active, barWidth, barGap, mode])\n\n // Handle microphone setup and teardown.\n useEffect(() => {\n if (!active) {\n if (streamRef.current) {\n streamRef.current.getTracks().forEach((track) => track.stop())\n streamRef.current = null\n onStreamEnd?.()\n }\n if (\n audioContextRef.current &&\n audioContextRef.current.state !== \"closed\"\n ) {\n audioContextRef.current.close()\n audioContextRef.current = null\n }\n if (animationRef.current) {\n cancelAnimationFrame(animationRef.current)\n animationRef.current = 0\n }\n return\n }\n const setupMicrophone = async () => {\n try {\n const stream = await navigator.mediaDevices.getUserMedia({\n audio: deviceId\n ? {\n deviceId: { exact: deviceId },\n echoCancellation: true,\n noiseSuppression: true,\n autoGainControl: true,\n }\n : {\n echoCancellation: true,\n noiseSuppression: true,\n autoGainControl: true,\n },\n })\n streamRef.current = stream\n onStreamReady?.(stream)\n const AudioContextConstructor =\n window.AudioContext ||\n (window as unknown as { webkitAudioContext: typeof AudioContext })\n .webkitAudioContext\n const audioContext = new AudioContextConstructor()\n const analyser = audioContext.createAnalyser()\n analyser.fftSize = fftSize\n analyser.smoothingTimeConstant = smoothingTimeConstant\n const source = audioContext.createMediaStreamSource(stream)\n source.connect(analyser)\n audioContextRef.current = audioContext\n analyserRef.current = analyser\n historyRef.current = []\n } catch (error) {\n onError?.(error as Error)\n }\n }\n setupMicrophone()\n return () => {\n if (streamRef.current) {\n streamRef.current.getTracks().forEach((track) => track.stop())\n streamRef.current = null\n onStreamEnd?.()\n }\n if (\n audioContextRef.current &&\n audioContextRef.current.state !== \"closed\"\n ) {\n audioContextRef.current.close()\n audioContextRef.current = null\n }\n if (animationRef.current) {\n cancelAnimationFrame(animationRef.current)\n animationRef.current = 0\n }\n }\n }, [\n active,\n deviceId,\n fftSize,\n smoothingTimeConstant,\n onError,\n onStreamReady,\n onStreamEnd,\n ])\n\n // Animation loop.\n useEffect(() => {\n const canvas = canvasRef.current\n if (!canvas) return\n const ctx = canvas.getContext(\"2d\")\n if (!ctx) return\n let rafId: number\n const animate = (currentTime: number) => {\n const rect = canvas.getBoundingClientRect()\n if (active && currentTime - lastUpdateRef.current > updateRate) {\n lastUpdateRef.current = currentTime\n if (analyserRef.current) {\n const dataArray = new Uint8Array(\n analyserRef.current.frequencyBinCount\n )\n analyserRef.current.getByteFrequencyData(dataArray)\n if (mode === \"static\") {\n const startFreq = Math.floor(dataArray.length * 0.05)\n const endFreq = Math.floor(dataArray.length * 0.4)\n const relevantData = dataArray.slice(startFreq, endFreq)\n const barCount = Math.floor(rect.width / (barWidth + barGap))\n const halfCount = Math.floor(barCount / 2)\n const newBars: number[] = []\n for (let i = halfCount - 1; i >= 0; i--) {\n const dataIndex = Math.floor(\n (i / halfCount) * relevantData.length\n )\n const value = Math.min(\n 1,\n (relevantData[dataIndex] / 255) * sensitivity\n )\n newBars.push(Math.max(0.05, value))\n }\n for (let i = 0; i < halfCount; i++) {\n const dataIndex = Math.floor(\n (i / halfCount) * relevantData.length\n )\n const value = Math.min(\n 1,\n (relevantData[dataIndex] / 255) * sensitivity\n )\n newBars.push(Math.max(0.05, value))\n }\n staticBarsRef.current = newBars\n lastActiveDataRef.current = newBars\n } else {\n let sum = 0\n const startFreq = Math.floor(dataArray.length * 0.05)\n const endFreq = Math.floor(dataArray.length * 0.4)\n const relevantData = dataArray.slice(startFreq, endFreq)\n for (let i = 0; i < relevantData.length; i++) {\n sum += relevantData[i]\n }\n const average = (sum / relevantData.length / 255) * sensitivity\n historyRef.current.push(Math.min(1, Math.max(0.05, average)))\n lastActiveDataRef.current = [...historyRef.current]\n if (historyRef.current.length > historySize) {\n historyRef.current.shift()\n }\n }\n needsRedrawRef.current = true\n }\n }\n if (!needsRedrawRef.current && !active) {\n rafId = requestAnimationFrame(animate)\n return\n }\n needsRedrawRef.current = active\n ctx.clearRect(0, 0, rect.width, rect.height)\n const computedBarColor =\n barColor ||\n (() => {\n const style = getComputedStyle(canvas)\n const color = style.color\n return color || \"#000\"\n })()\n const step = barWidth + barGap\n const barCount = Math.floor(rect.width / step)\n const centerY = rect.height / 2\n if (mode === \"static\") {\n const dataToRender = processing\n ? staticBarsRef.current\n : active\n ? staticBarsRef.current\n : staticBarsRef.current.length > 0\n ? staticBarsRef.current\n : []\n for (let i = 0; i < barCount && i < dataToRender.length; i++) {\n const value = dataToRender[i] || 0.1\n const x = i * step\n const bh = Math.max(baseBarHeight, value * rect.height * 0.8)\n const y = centerY - bh / 2\n ctx.fillStyle = computedBarColor\n ctx.globalAlpha = 0.4 + value * 0.6\n if (barRadius > 0) {\n ctx.beginPath()\n ctx.roundRect(x, y, barWidth, bh, barRadius)\n ctx.fill()\n } else {\n ctx.fillRect(x, y, barWidth, bh)\n }\n }\n } else {\n for (let i = 0; i < barCount && i < historyRef.current.length; i++) {\n const dataIndex = historyRef.current.length - 1 - i\n const value = historyRef.current[dataIndex] || 0.1\n const x = rect.width - (i + 1) * step\n const bh = Math.max(baseBarHeight, value * rect.height * 0.8)\n const y = centerY - bh / 2\n ctx.fillStyle = computedBarColor\n ctx.globalAlpha = 0.4 + value * 0.6\n if (barRadius > 0) {\n ctx.beginPath()\n ctx.roundRect(x, y, barWidth, bh, barRadius)\n ctx.fill()\n } else {\n ctx.fillRect(x, y, barWidth, bh)\n }\n }\n }\n if (fadeEdges && fadeWidth > 0 && rect.width > 0) {\n if (!gradientCacheRef.current || lastWidthRef.current !== rect.width) {\n const gradient = ctx.createLinearGradient(0, 0, rect.width, 0)\n const fadePercent = Math.min(0.3, fadeWidth / rect.width)\n gradient.addColorStop(0, \"rgba(255,255,255,1)\")\n gradient.addColorStop(fadePercent, \"rgba(255,255,255,0)\")\n gradient.addColorStop(1 - fadePercent, \"rgba(255,255,255,0)\")\n gradient.addColorStop(1, \"rgba(255,255,255,1)\")\n gradientCacheRef.current = gradient\n lastWidthRef.current = rect.width\n }\n ctx.globalCompositeOperation = \"destination-out\"\n ctx.fillStyle = gradientCacheRef.current\n ctx.fillRect(0, 0, rect.width, rect.height)\n ctx.globalCompositeOperation = \"source-over\"\n }\n ctx.globalAlpha = 1\n rafId = requestAnimationFrame(animate)\n }\n rafId = requestAnimationFrame(animate)\n return () => {\n if (rafId) {\n cancelAnimationFrame(rafId)\n }\n }\n }, [\n active,\n processing,\n sensitivity,\n updateRate,\n historySize,\n barWidth,\n baseBarHeight,\n barGap,\n barRadius,\n barColor,\n fadeEdges,\n fadeWidth,\n mode,\n ])\n\n return (\n \n {!active && !processing && (\n
\n )}\n \n
\n )\n}\n\nexport function LiveWaveformCard() {\n const [active, setActive] = useState(false)\n const [processing, setProcessing] = useState(true)\n const [mode, setMode] = useState<\"static\" | \"scrolling\">(\"static\")\n\n const handleToggleActive = () => {\n setActive(!active)\n if (!active) {\n setProcessing(false)\n }\n }\n\n const handleToggleProcessing = () => {\n setProcessing(!processing)\n if (!processing) {\n setActive(false)\n }\n }\n\n return (\n \n \n Live Audio Waveform\n \n Real-time microphone input visualization with audio reactivity\n \n \n \n \n \n \n \n {active ? \"Stop\" : \"Start\"} Listening\n \n \n {processing ? \"Stop\" : \"Start\"} Processing\n \n setMode(mode === \"static\" ? \"scrolling\" : \"static\")}\n >\n {mode === \"static\" ? \"Static\" : \"Scrolling\"}\n \n \n \n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/preview-cards/live-waveform.tsx" }, { "path": "src/blocks/kitchen-sink/preview-cards/no-team-members.tsx", "content": "\"use client\"\n\nimport {\n Avatar,\n AvatarFallback,\n AvatarGroup,\n AvatarImage,\n} from \"@/components/ui/avatar\"\nimport { Button } from \"@/components/ui/button\"\nimport { Card, CardContent } from \"@/components/ui/card\"\nimport {\n Empty,\n EmptyContent,\n EmptyDescription,\n EmptyHeader,\n EmptyMedia,\n EmptyTitle,\n} from \"@/components/ui/empty\"\n\nexport function NoTeamMembers() {\n return (\n \n \n \n \n \n \n \n \n CN\n \n \n \n LR\n \n \n \n ER\n \n \n \n No Team Members\n \n Invite your team to collaborate on this project.\n \n \n \n \n \n \n \n \n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/preview-cards/no-team-members.tsx" }, { "path": "src/blocks/kitchen-sink/preview-cards/not-found.tsx", "content": "\"use client\"\n\nimport { Button } from \"@/components/ui/button\"\nimport { Card, CardContent } from \"@/components/ui/card\"\nimport {\n Empty,\n EmptyContent,\n EmptyDescription,\n EmptyHeader,\n EmptyTitle,\n} from \"@/components/ui/empty\"\nimport {\n InputGroup,\n InputGroupAddon,\n InputGroupInput,\n} from \"@/components/ui/input-group\"\nimport { Kbd } from \"@/components/ui/kbd\"\nimport { IconPlaceholder } from \"../components/icon-placeholder\"\n\nexport function NotFound() {\n return (\n \n \n \n \n 404 - Not Found\n \n The page you're looking for doesn't exist. Try searching\n for what you need below.\n \n \n \n \n \n \n \n \n \n /\n \n \n \n \n \n \n \n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/preview-cards/not-found.tsx" }, { "path": "src/blocks/kitchen-sink/preview-cards/observability-card.tsx", "content": "\"use client\"\n\nimport { Badge } from \"@/components/ui/badge\"\nimport { Button } from \"@/components/ui/button\"\nimport {\n Card,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n} from \"@/components/ui/card\"\nimport { IconPlaceholder } from \"../components/icon-placeholder\"\n\nexport function ObservabilityCard() {\n return (\n \n
\n \n \n Observability Plus is replacing Monitoring\n \n Switch to the improved way to explore your data, with natural\n language. Monitoring will no longer be available on the Pro plan in\n November, 2025\n \n \n \n \n \n Warning\n \n \n \n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/preview-cards/observability-card.tsx" }, { "path": "src/blocks/kitchen-sink/preview-cards/pie-chart-card.tsx", "content": "\"use client\"\n\nimport { Label, Pie, PieChart } from \"recharts\"\n\nimport { Badge } from \"@/components/ui/badge\"\nimport {\n Card,\n CardAction,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n} from \"@/components/ui/card\"\nimport {\n ChartContainer,\n ChartLegend,\n ChartLegendContent,\n ChartTooltip,\n ChartTooltipContent,\n type ChartConfig,\n} from \"@/components/ui/chart\"\nimport { Progress } from \"@/components/ui/progress\"\n\nconst pieChartData = [\n { browser: \"chrome\", visitors: 275, fill: \"var(--color-chrome)\" },\n { browser: \"safari\", visitors: 200, fill: \"var(--color-safari)\" },\n { browser: \"firefox\", visitors: 287, fill: \"var(--color-firefox)\" },\n { browser: \"edge\", visitors: 173, fill: \"var(--color-edge)\" },\n]\n\nconst pieChartConfig = {\n visitors: {\n label: \"Visitors\",\n },\n chrome: {\n label: \"Chrome\",\n color: \"var(--chart-1)\",\n },\n safari: {\n label: \"Safari\",\n color: \"var(--chart-2)\",\n },\n firefox: {\n label: \"Firefox\",\n color: \"var(--chart-3)\",\n },\n edge: {\n label: \"Edge\",\n color: \"var(--chart-4)\",\n },\n} satisfies ChartConfig\n\nexport function PieChartCard() {\n const totalVisitors = pieChartData.reduce(\n (sum, item) => sum + item.visitors,\n 0\n )\n const topBrowser = pieChartData.reduce((max, item) =>\n item.visitors > max.visitors ? item : max\n )\n const topBrowserShare = Math.round(\n (topBrowser.visitors / totalVisitors) * 100\n )\n const topBrowserLabel =\n pieChartConfig[topBrowser.browser as keyof typeof pieChartConfig]?.label ??\n \"Top\"\n\n return (\n \n \n Browser Share\n January - June 2026\n \n {topBrowserLabel}\n \n \n \n \n \n }\n />\n \n {\n if (viewBox && \"cx\" in viewBox && \"cy\" in viewBox) {\n return (\n \n \n {totalVisitors.toLocaleString()}\n \n \n Visitors\n \n \n )\n }\n }}\n />\n \n }\n className=\"translate-y-2\"\n />\n \n \n \n \n
\n {topBrowserLabel}\n \n {topBrowserShare}%\n \n
\n \n
\n
\n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/preview-cards/pie-chart-card.tsx" }, { "path": "src/blocks/kitchen-sink/preview-cards/report-bug.tsx", "content": "\"use client\"\n\nimport { Button } from \"@/components/ui/button\"\nimport {\n Card,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n} from \"@/components/ui/card\"\nimport { Field, FieldGroup, FieldLabel } from \"@/components/ui/field\"\nimport { Input } from \"@/components/ui/input\"\nimport {\n Select,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/components/ui/select\"\nimport { Textarea } from \"@/components/ui/textarea\"\n\nexport function ReportBug() {\n return (\n \n \n Report Bug\n Help us fix issues faster.\n \n \n \n \n Title\n \n \n
\n \n Severity\n \n \n \n \n \n \n Critical\n High\n Medium\n Low\n \n \n \n \n \n Component\n \n \n \n \n \n \n Dashboard\n Auth\n API\n Billing\n \n \n \n \n
\n \n Steps to reproduce\n \n \n
\n
\n \n \n \n \n \n \n
\n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/preview-cards/report-bug.tsx" }, { "path": "src/blocks/kitchen-sink/preview-cards/shipping-address.tsx", "content": "\"use client\"\n\nimport { Button } from \"@/components/ui/button\"\nimport {\n Card,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n} from \"@/components/ui/card\"\nimport { Checkbox } from \"@/components/ui/checkbox\"\nimport { Field, FieldGroup, FieldLabel } from \"@/components/ui/field\"\nimport { Input } from \"@/components/ui/input\"\nimport {\n Select,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/components/ui/select\"\n\nexport function ShippingAddress() {\n return (\n \n \n Shipping Address\n Where should we deliver?\n \n \n \n \n Street address\n \n \n \n Apt / Suite\n \n \n \n \n City\n \n \n \n State\n \n \n \n \n \n \n California\n New York\n Texas\n \n \n \n \n \n \n \n ZIP Code\n \n \n \n Country\n \n \n \n \n \n \n United States\n Canada\n United Kingdom\n \n \n \n \n \n \n \n \n Save as default address\n \n \n \n \n \n \n \n \n \n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/preview-cards/shipping-address.tsx" }, { "path": "src/blocks/kitchen-sink/preview-cards/shortcuts.tsx", "content": "import * as React from \"react\"\n\nimport { Card, CardContent } from \"@/components/ui/card\"\nimport {\n Item,\n ItemActions,\n ItemGroup,\n ItemHeader,\n ItemSeparator,\n ItemTitle,\n} from \"@/components/ui/item\"\nimport { Kbd } from \"@/components/ui/kbd\"\n\nconst shortcuts = [\n { label: \"Search\", keys: [\"⌘\", \"K\"] },\n { label: \"Quick Actions\", keys: [\"⌘\", \"J\"] },\n { label: \"New File\", keys: [\"⌘\", \"N\"] },\n { label: \"Save\", keys: [\"⌘\", \"S\"] },\n { label: \"Toggle Sidebar\", keys: [\"⌘\", \"B\"] },\n] as const\n\nexport function Shortcuts() {\n return (\n \n \n
\n
Shortcuts
\n \n {shortcuts.map(({ label, keys }, i) => (\n \n {i > 0 && }\n \n \n {label}\n \n
\n {keys.map((key) => (\n {key}\n ))}\n
\n
\n
\n \n
\n ))}\n
\n
\n
\n
\n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/preview-cards/shortcuts.tsx" }, { "path": "src/blocks/kitchen-sink/preview-cards/skeleton-loading.tsx", "content": "\"use client\"\n\nimport { Card, CardContent } from \"@/components/ui/card\"\nimport { Skeleton } from \"@/components/ui/skeleton\"\n\nexport function SkeletonLoading() {\n return (\n \n \n
\n \n
\n \n \n
\n
\n
\n \n \n \n
\n
\n \n \n
\n
\n
\n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/preview-cards/skeleton-loading.tsx" }, { "path": "src/blocks/kitchen-sink/preview-cards/sleep-report.tsx", "content": "\"use client\"\n\nimport { Bar, BarChart } from \"recharts\"\n\nimport { Badge } from \"@/components/ui/badge\"\nimport { Button } from \"@/components/ui/button\"\nimport {\n Card,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n} from \"@/components/ui/card\"\nimport { ChartContainer, type ChartConfig } from \"@/components/ui/chart\"\n\nconst sleepChartData = [\n { hour: \"10pm\", deep: 0, light: 30, rem: 0 },\n { hour: \"11pm\", deep: 20, light: 10, rem: 0 },\n { hour: \"12am\", deep: 40, light: 0, rem: 10 },\n { hour: \"1am\", deep: 30, light: 5, rem: 15 },\n { hour: \"2am\", deep: 10, light: 20, rem: 30 },\n { hour: \"3am\", deep: 25, light: 10, rem: 20 },\n { hour: \"4am\", deep: 15, light: 25, rem: 10 },\n { hour: \"5am\", deep: 5, light: 35, rem: 15 },\n { hour: \"6am\", deep: 0, light: 20, rem: 25 },\n]\n\nconst sleepChartConfig = {\n deep: {\n label: \"Deep\",\n color: \"var(--chart-1)\",\n },\n light: {\n label: \"Light\",\n color: \"var(--chart-2)\",\n },\n rem: {\n label: \"REM\",\n color: \"var(--chart-3)\",\n },\n} satisfies ChartConfig\n\nexport function SleepReport() {\n return (\n \n \n Sleep Report\n Last night · 7h 24m\n \n \n \n \n \n \n \n \n \n
\n {[\n { label: \"Deep\", value: \"2h 10m\" },\n { label: \"Light\", value: \"3h 48m\" },\n { label: \"REM\", value: \"1h 26m\" },\n { label: \"Score\", value: \"84\" },\n ].map((s) => (\n
\n
{s.value}
\n
{s.label}
\n
\n ))}\n
\n
\n \n Good\n \n \n
\n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/preview-cards/sleep-report.tsx" }, { "path": "src/blocks/kitchen-sink/preview-cards/style-overview.tsx", "content": "\"use client\"\n\nimport * as React from \"react\"\n\nimport { Card, CardContent } from \"@/components/ui/card\"\n\nexport function StyleOverview() {\n return (\n \n \n
\n
\n Mira - Inter\n
\n
\n Designers love packing quirky glyphs into test phrases. This is a\n preview of the typography styles.\n
\n
\n
\n {[\n \"--background\",\n \"--foreground\",\n \"--primary\",\n \"--secondary\",\n \"--muted\",\n \"--accent\",\n \"--border\",\n \"--chart-1\",\n \"--chart-2\",\n \"--chart-3\",\n \"--chart-4\",\n \"--chart-5\",\n ].map((variant) => (\n \n \n \n
\n ))}\n
\n \n
\n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/preview-cards/style-overview.tsx" }, { "path": "src/blocks/kitchen-sink/preview-cards/typography-specimen.tsx", "content": "\"use client\"\n\nimport { Button } from \"@/components/ui/button\"\nimport { Card, CardContent, CardFooter } from \"@/components/ui/card\"\nimport {\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n} from \"@/components/ui/dialog\"\nimport { Field, FieldGroup, FieldLabel } from \"@/components/ui/field\"\nimport { Input } from \"@/components/ui/input\"\nimport {\n Select,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/components/ui/select\"\nimport { Textarea } from \"@/components/ui/textarea\"\n\nexport function TypographySpecimen() {\n return (\n \n \n
\n Inherit - Inter\n
\n

\n Designing with rhythm and hierarchy.\n

\n

\n A strong body style keeps long-form content readable and balances the\n visual weight of headings.\n

\n

\n Thoughtful spacing and cadence help paragraphs scan quickly without\n feeling dense.\n

\n
\n \n \n }\n >\n Share Feedback\n \n \n \n Share Feedback\n \n Let us know how we can improve your experience.\n \n \n \n
\n \n Name\n \n \n \n Email\n \n \n
\n \n Category\n \n \n \n \n \n \n General\n Bug Report\n Feature Request\n Improvement\n \n \n \n \n \n Message\n \n \n
\n \n }>\n Cancel\n \n \n \n
\n
\n
\n
\n )\n}\n", "type": "registry:component", "target": "@components/blocks/kitchen-sink/preview-cards/typography-specimen.tsx" }, { "path": "src/blocks/kitchen-sink/preview-cards/ui-elements.tsx", "content": "\"use client\"\n\nimport * as React from \"react\"\n\nimport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogTitle,\n AlertDialogTrigger,\n} from \"@/components/ui/alert-dialog\"\nimport { Badge } from \"@/components/ui/badge\"\nimport { Button } from \"@/components/ui/button\"\nimport { ButtonGroup } from \"@/components/ui/button-group\"\nimport { Card, CardContent } from \"@/components/ui/card\"\nimport { Checkbox } from \"@/components/ui/checkbox\"\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"@/components/ui/dropdown-menu\"\nimport { Field, FieldGroup } from \"@/components/ui/field\"\nimport {\n InputGroup,\n InputGroupAddon,\n InputGroupInput,\n InputGroupText,\n} from \"@/components/ui/input-group\"\nimport {\n Item,\n ItemActions,\n ItemContent,\n ItemDescription,\n ItemTitle,\n} from \"@/components/ui/item\"\nimport { RadioGroup, RadioGroupItem } from \"@/components/ui/radio-group\"\nimport { Slider } from \"@/components/ui/slider\"\nimport { Switch } from \"@/components/ui/switch\"\nimport { Textarea } from \"@/components/ui/textarea\"\nimport { IconPlaceholder } from \"../components/icon-placeholder\"\n\nexport function UIElements() {\n const [sliderValue, setSliderValue] = React.useState([500])\n const handleSliderValueChange = React.useCallback(\n (value: number | readonly number[]) => {\n if (typeof value === \"number\") {\n setSliderValue([value])\n } else {\n setSliderValue([...value])\n }\n },\n []\n )\n\n return (\n \n \n
\n
\n \n \n \n \n
\n \n \n Two-factor authentication\n \n Verify via email or phone number.\n \n \n \n \n \n \n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n