@static-ui/registry 0.0.1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/index.json +1184 -68
  2. package/package.json +33 -14
  3. package/registry.json +649 -0
package/dist/index.json CHANGED
@@ -1,505 +1,1621 @@
1
1
  [
2
2
  {
3
3
  "name": "accordion",
4
+ "type": "components:ui",
5
+ "frameworks": [
6
+ "react",
7
+ "nextjs",
8
+ "remix"
9
+ ],
4
10
  "dependencies": [
5
11
  "@base-ui/react"
6
12
  ],
13
+ "registryDependencies": [],
7
14
  "files": [
8
15
  {
9
16
  "name": "accordion.tsx",
10
- "content": "\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport { Accordion as BaseAccordion } from \"@base-ui/react/accordion\"\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nconst Accordion = BaseAccordion.Root\r\n\r\nconst AccordionItem = React.forwardRef<\r\n HTMLDivElement,\r\n React.ComponentPropsWithoutRef<typeof BaseAccordion.Item>\r\n>(({ className, ...props }, ref) => (\r\n <BaseAccordion.Item ref={ref} className={cn(\"border-b border-neutral-200 py-2\", className)} {...props} />\r\n))\r\nAccordionItem.displayName = \"AccordionItem\"\r\n\r\nconst AccordionHeader = BaseAccordion.Header\r\n\r\nconst AccordionTrigger = React.forwardRef<\r\n HTMLButtonElement,\r\n React.ComponentPropsWithoutRef<typeof BaseAccordion.Trigger>\r\n>(({ className, children, ...props }, ref) => (\r\n <BaseAccordion.Header className=\"flex\">\r\n <BaseAccordion.Trigger\r\n ref={ref}\r\n className={cn(\r\n \"flex flex-1 items-center justify-between py-4 text-sm font-medium transition-all hover:underline text-left\",\r\n \"group data-[panel-open]:text-neutral-900\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n {children}\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n width=\"16\"\r\n height=\"16\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n strokeWidth=\"2\"\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n className=\"h-4 w-4 shrink-0 text-neutral-500 transition-transform duration-200 group-data-[panel-open]:rotate-180\"\r\n >\r\n <polyline points=\"6 9 12 15 18 9\" />\r\n </svg>\r\n </BaseAccordion.Trigger>\r\n </BaseAccordion.Header>\r\n))\r\nAccordionTrigger.displayName = \"AccordionTrigger\"\r\n\r\nconst AccordionContent = React.forwardRef<\r\n HTMLDivElement,\r\n React.ComponentPropsWithoutRef<typeof BaseAccordion.Panel>\r\n>(({ className, children, ...props }, ref) => (\r\n <BaseAccordion.Panel\r\n ref={ref}\r\n className={cn(\r\n \"overflow-hidden text-sm transition-all animate-accordion-up data-[panel-open]:animate-accordion-down\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n))\r\nAccordionContent.displayName = \"AccordionContent\"\r\n\r\nexport { Accordion, AccordionItem, AccordionHeader, AccordionTrigger, AccordionContent }"
17
+ "content": "import { Accordion as AccordionPrimitive } from \"@base-ui/react/accordion\"\r\nimport { ChevronDownIcon, ChevronUpIcon } from \"lucide-react\"\r\n\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nfunction Accordion({ className, ...props }: AccordionPrimitive.Root.Props) {\r\n return (\r\n <AccordionPrimitive.Root\r\n data-slot=\"accordion\"\r\n className={cn(\"flex w-full flex-col\", className)}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction AccordionItem({ className, ...props }: AccordionPrimitive.Item.Props) {\r\n return (\r\n <AccordionPrimitive.Item\r\n data-slot=\"accordion-item\"\r\n className={cn(\"not-last:border-b\", className)}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction AccordionTrigger({\r\n className,\r\n children,\r\n ...props\r\n}: AccordionPrimitive.Trigger.Props) {\r\n return (\r\n <AccordionPrimitive.Header className=\"flex\">\r\n <AccordionPrimitive.Trigger\r\n data-slot=\"accordion-trigger\"\r\n className={cn(\r\n \"group/accordion-trigger relative flex flex-1 items-start justify-between rounded-lg border border-transparent py-2.5 text-left text-sm font-medium transition-all outline-none hover:underline focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 focus-visible:after:border-ring aria-disabled:pointer-events-none aria-disabled:opacity-50 **:data-[slot=accordion-trigger-icon]:ml-auto **:data-[slot=accordion-trigger-icon]:size-4 **:data-[slot=accordion-trigger-icon]:text-muted-foreground\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n {children}\r\n <ChevronDownIcon\r\n data-slot=\"accordion-trigger-icon\"\r\n className=\"pointer-events-none shrink-0 group-aria-expanded/accordion-trigger:hidden\"\r\n />\r\n <ChevronUpIcon\r\n data-slot=\"accordion-trigger-icon\"\r\n className=\"pointer-events-none hidden shrink-0 group-aria-expanded/accordion-trigger:inline\"\r\n />\r\n </AccordionPrimitive.Trigger>\r\n </AccordionPrimitive.Header>\r\n )\r\n}\r\n\r\nfunction AccordionContent({\r\n className,\r\n children,\r\n ...props\r\n}: AccordionPrimitive.Panel.Props) {\r\n return (\r\n <AccordionPrimitive.Panel\r\n data-slot=\"accordion-content\"\r\n className=\"overflow-hidden text-sm data-open:animate-accordion-down data-closed:animate-accordion-up\"\r\n {...props}\r\n >\r\n <div\r\n className={cn(\r\n \"h-(--accordion-panel-height) pt-0 pb-2.5 data-ending-style:h-0 data-starting-style:h-0 [&_a]:underline [&_a]:underline-offset-3 [&_a]:hover:text-foreground [&_p:not(:last-child)]:mb-4\",\r\n className\r\n )}\r\n >\r\n {children}\r\n </div>\r\n </AccordionPrimitive.Panel>\r\n )\r\n}\r\n\r\nexport { Accordion, AccordionItem, AccordionTrigger, AccordionContent }\r\n"
18
+ }
19
+ ]
20
+ },
21
+ {
22
+ "name": "ai-chat-layout",
23
+ "type": "components:ui",
24
+ "frameworks": [
25
+ "react",
26
+ "nextjs",
27
+ "vue",
28
+ "nuxt",
29
+ "solid",
30
+ "svelte",
31
+ "astro",
32
+ "remix"
33
+ ],
34
+ "dependencies": [
35
+ "@base-ui/react"
36
+ ],
37
+ "registryDependencies": [
38
+ "ai-sidebar"
39
+ ],
40
+ "files": [
41
+ {
42
+ "name": "ai-chat-layout.tsx",
43
+ "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { cn } from \"@/lib/utils\"\n\nexport interface AiChatLayoutProps extends React.HTMLAttributes<HTMLDivElement> {\n sidebar: React.ReactNode\n children: React.ReactNode\n headerContent?: React.ReactNode\n}\n\nconst AiChatLayout = React.forwardRef<HTMLDivElement, AiChatLayoutProps>(\n ({ className, sidebar, children, headerContent, ...props }, ref) => {\n const [sidebarOpen, setSidebarOpen] = React.useState(false)\n\n return (\n <div\n ref={ref}\n className={cn(\n \"flex h-dvh w-full overflow-hidden bg-background text-foreground\",\n className\n )}\n {...props}\n >\n {/* Mobile sidebar backdrop */}\n {sidebarOpen && (\n <div\n className=\"fixed inset-0 z-40 bg-black/50 lg:hidden\"\n onClick={() => setSidebarOpen(false)}\n aria-hidden=\"true\"\n />\n )}\n\n {/* Sidebar */}\n <aside\n className={cn(\n \"fixed inset-y-0 left-0 z-50 flex w-72 flex-col border-r border-border bg-background p-3 transition-transform duration-200\",\n \"lg:static lg:z-auto lg:translate-x-0\",\n sidebarOpen ? \"translate-x-0\" : \"-translate-x-full\"\n )}\n aria-label=\"Chat sidebar\"\n >\n {sidebar}\n </aside>\n\n {/* Main area */}\n <div className=\"flex flex-1 flex-col min-w-0\">\n {/* Header */}\n {headerContent && (\n <header className=\"flex items-center gap-3 border-b border-border px-4 py-3\">\n <button\n type=\"button\"\n onClick={() => setSidebarOpen(!sidebarOpen)}\n className={cn(\n \"flex size-8 items-center justify-center rounded-lg text-muted-foreground lg:hidden\",\n \"hover:bg-muted hover:text-foreground\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n )}\n aria-label={sidebarOpen ? \"Close sidebar\" : \"Open sidebar\"}\n aria-expanded={sidebarOpen}\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <line x1=\"3\" y1=\"12\" x2=\"21\" y2=\"12\" />\n <line x1=\"3\" y1=\"6\" x2=\"21\" y2=\"6\" />\n <line x1=\"3\" y1=\"18\" x2=\"21\" y2=\"18\" />\n </svg>\n </button>\n {headerContent}\n </header>\n )}\n\n {/* Content area */}\n {children}\n </div>\n </div>\n )\n }\n)\nAiChatLayout.displayName = \"AiChatLayout\"\n\nexport { AiChatLayout }\n"
44
+ }
45
+ ]
46
+ },
47
+ {
48
+ "name": "ai-chat",
49
+ "type": "components:ui",
50
+ "frameworks": [
51
+ "react",
52
+ "nextjs",
53
+ "vue",
54
+ "nuxt",
55
+ "solid",
56
+ "svelte",
57
+ "astro",
58
+ "remix"
59
+ ],
60
+ "dependencies": [
61
+ "@base-ui/react"
62
+ ],
63
+ "registryDependencies": [
64
+ "ai-message",
65
+ "ai-prompt"
66
+ ],
67
+ "files": [
68
+ {
69
+ "name": "ai-chat.tsx",
70
+ "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { cn } from \"@/lib/utils\"\nimport { AiMessage } from \"./ai-message\"\nimport { AiPrompt } from \"./ai-prompt\"\n\nexport interface ChatMessage {\n id: string\n role: \"user\" | \"assistant\"\n content: string\n timestamp?: string\n}\n\nexport interface AiChatProps extends React.HTMLAttributes<HTMLDivElement> {\n messages: ChatMessage[]\n onSend?: (message: string) => void\n loading?: boolean\n promptPlaceholder?: string\n}\n\nconst AiChat = React.forwardRef<HTMLDivElement, AiChatProps>(\n ({ className, messages, onSend, loading, promptPlaceholder, ...props }, ref) => {\n const listRef = React.useRef<HTMLDivElement>(null)\n\n React.useEffect(() => {\n if (listRef.current) {\n listRef.current.scrollTo({\n top: listRef.current.scrollHeight,\n behavior: \"smooth\",\n })\n }\n }, [messages])\n\n return (\n <div\n ref={ref}\n className={cn(\"flex flex-1 flex-col min-h-0\", className)}\n {...props}\n >\n <div\n ref={listRef}\n className=\"flex-1 overflow-y-auto px-4 py-4\"\n role=\"list\"\n aria-label=\"Chat messages\"\n aria-live=\"polite\"\n >\n <div className=\"mx-auto flex max-w-2xl flex-col gap-4\">\n {messages.length === 0 && (\n <div className=\"flex flex-1 items-center justify-center py-12\">\n <p className=\"text-sm text-muted-foreground text-center\">\n Start a conversation by sending a message below.\n </p>\n </div>\n )}\n {messages.map((msg) => (\n <AiMessage\n key={msg.id}\n role={msg.role}\n content={msg.content}\n timestamp={msg.timestamp}\n />\n ))}\n {loading && (\n <div className=\"flex items-center gap-2 px-1\" role=\"status\" aria-label=\"AI is typing\">\n <div className=\"flex size-8 items-center justify-center rounded-full bg-primary text-primary-foreground text-xs font-semibold\">\n AI\n </div>\n <div className=\"flex gap-1\">\n <span className=\"size-2 animate-bounce rounded-full bg-muted-foreground/40\" style={{ animationDelay: \"0ms\" }} />\n <span className=\"size-2 animate-bounce rounded-full bg-muted-foreground/40\" style={{ animationDelay: \"150ms\" }} />\n <span className=\"size-2 animate-bounce rounded-full bg-muted-foreground/40\" style={{ animationDelay: \"300ms\" }} />\n </div>\n <span className=\"sr-only\">AI is generating a response...</span>\n </div>\n )}\n </div>\n </div>\n\n <div className=\"border-t border-border p-4\">\n <div className=\"mx-auto max-w-2xl\">\n <AiPrompt\n onSubmit={(value) => onSend?.(value)}\n disabled={loading}\n placeholder={promptPlaceholder}\n />\n </div>\n </div>\n </div>\n )\n }\n)\nAiChat.displayName = \"AiChat\"\n\nexport { AiChat }\n"
71
+ }
72
+ ]
73
+ },
74
+ {
75
+ "name": "ai-code-block",
76
+ "type": "components:ui",
77
+ "frameworks": [
78
+ "react",
79
+ "nextjs",
80
+ "vue",
81
+ "nuxt",
82
+ "solid",
83
+ "svelte",
84
+ "astro",
85
+ "remix"
86
+ ],
87
+ "dependencies": [
88
+ "@base-ui/react"
89
+ ],
90
+ "registryDependencies": [],
91
+ "files": [
92
+ {
93
+ "name": "ai-code-block.tsx",
94
+ "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { cn } from \"@/lib/utils\"\n\nexport interface AiCodeBlockProps extends React.HTMLAttributes<HTMLDivElement> {\n code: string\n language?: string\n showLineNumbers?: boolean\n}\n\nconst AiCodeBlock = React.forwardRef<HTMLDivElement, AiCodeBlockProps>(\n ({ className, code, language, showLineNumbers = false, ...props }, ref) => {\n const [copied, setCopied] = React.useState(false)\n\n const handleCopy = React.useCallback(async () => {\n try {\n await navigator.clipboard.writeText(code)\n setCopied(true)\n setTimeout(() => setCopied(false), 2000)\n } catch {\n // Clipboard API not available\n }\n }, [code])\n\n const lines = code.split(\"\\n\")\n\n return (\n <div\n ref={ref}\n className={cn(\"group relative rounded-lg border border-border overflow-hidden\", className)}\n role=\"region\"\n aria-label={language ? `${language} code block` : \"Code block\"}\n {...props}\n >\n <div className=\"flex items-center justify-between border-b border-border bg-muted/50 px-4 py-2\">\n <span className=\"text-xs text-muted-foreground font-mono\">\n {language || \"code\"}\n </span>\n <button\n type=\"button\"\n onClick={handleCopy}\n className={cn(\n \"flex items-center gap-1.5 rounded-md px-2 py-1 text-xs text-muted-foreground transition-colors\",\n \"hover:bg-muted hover:text-foreground\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n )}\n aria-label={copied ? \"Copied\" : \"Copy code\"}\n >\n {copied ? (\n <>\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"20 6 9 17 4 12\" />\n </svg>\n Copied\n </>\n ) : (\n <>\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\" ry=\"2\" />\n <path d=\"M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1\" />\n </svg>\n Copy\n </>\n )}\n </button>\n </div>\n <div className=\"overflow-x-auto p-4 text-sm\">\n <pre className=\"font-mono text-sm leading-relaxed\">\n <code>\n {showLineNumbers\n ? lines.map((line, i) => (\n <span key={i} className=\"table-row\">\n <span className=\"table-cell text-right text-muted-foreground/50 select-none pr-4 text-xs w-[1%]\">\n {i + 1}\n </span>\n <span className=\"table-cell text-foreground\">\n {line || \"\\u00A0\"}\n </span>\n </span>\n ))\n : code}\n </code>\n </pre>\n </div>\n </div>\n )\n }\n)\nAiCodeBlock.displayName = \"AiCodeBlock\"\n\nexport { AiCodeBlock }\n"
95
+ }
96
+ ]
97
+ },
98
+ {
99
+ "name": "ai-conversation",
100
+ "type": "components:ui",
101
+ "frameworks": [
102
+ "react",
103
+ "nextjs",
104
+ "vue",
105
+ "nuxt",
106
+ "solid",
107
+ "svelte",
108
+ "astro",
109
+ "remix"
110
+ ],
111
+ "dependencies": [
112
+ "@base-ui/react"
113
+ ],
114
+ "registryDependencies": [],
115
+ "files": [
116
+ {
117
+ "name": "ai-conversation.tsx",
118
+ "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { cn } from \"@/lib/utils\"\n\nexport interface AiConversationProps extends React.HTMLAttributes<HTMLDivElement> {\n title: string\n preview?: string\n timestamp?: string\n active?: boolean\n onClick?: () => void\n onDelete?: () => void\n}\n\nconst AiConversation = React.forwardRef<HTMLDivElement, AiConversationProps>(\n ({ className, title, preview, timestamp, active, onClick, onDelete, ...props }, ref) => {\n return (\n <div\n ref={ref}\n role=\"button\"\n tabIndex={0}\n onClick={onClick}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") onClick?.()\n }}\n className={cn(\n \"group flex cursor-pointer items-center gap-3 rounded-lg px-3 py-2.5 transition-colors\",\n active\n ? \"bg-primary/10 text-foreground\"\n : \"text-muted-foreground hover:bg-muted hover:text-foreground\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\",\n className\n )}\n aria-current={active ? \"page\" : undefined}\n {...props}\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"shrink-0\"\n aria-hidden=\"true\"\n >\n <path d=\"M21 15a2 2 0 01-2 2H7l-4 4V5a2 2 0 012-2h14a2 2 0 012 2z\" />\n </svg>\n <div className=\"flex min-w-0 flex-1 flex-col gap-0.5\">\n <span className=\"truncate text-sm font-medium leading-tight\">{title}</span>\n {preview && (\n <span className=\"truncate text-xs text-muted-foreground\">{preview}</span>\n )}\n </div>\n <div className=\"flex shrink-0 items-center gap-1.5\">\n {timestamp && (\n <span className=\"text-[10px] text-muted-foreground\">{timestamp}</span>\n )}\n {onDelete && (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation()\n onDelete()\n }}\n className=\"rounded-md p-1 opacity-0 group-hover:opacity-100 focus-visible:opacity-100 text-muted-foreground hover:text-destructive hover:bg-destructive/10 transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n aria-label={`Delete conversation: ${title}`}\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"3 6 5 6 21 6\" />\n <path d=\"M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6m3 0V4a2 2 0 012-2h4a2 2 0 012 2v2\" />\n </svg>\n </button>\n )}\n </div>\n </div>\n )\n }\n)\nAiConversation.displayName = \"AiConversation\"\n\nexport { AiConversation }\n"
119
+ }
120
+ ]
121
+ },
122
+ {
123
+ "name": "ai-file-upload",
124
+ "type": "components:ui",
125
+ "frameworks": [
126
+ "react",
127
+ "nextjs",
128
+ "vue",
129
+ "nuxt",
130
+ "solid",
131
+ "svelte",
132
+ "astro",
133
+ "remix"
134
+ ],
135
+ "dependencies": [
136
+ "@base-ui/react"
137
+ ],
138
+ "registryDependencies": [],
139
+ "files": [
140
+ {
141
+ "name": "ai-file-upload.tsx",
142
+ "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { cn } from \"@/lib/utils\"\n\nexport interface AiFileUploadProps extends React.HTMLAttributes<HTMLDivElement> {\n accept?: string\n maxSize?: number\n multiple?: boolean\n onUpload?: (files: File[]) => void\n}\n\ninterface FileEntry {\n file: File\n progress: number\n size: string\n}\n\nfunction formatSize(bytes: number): string {\n if (bytes < 1024) return bytes + \" B\"\n if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + \" KB\"\n return (bytes / (1024 * 1024)).toFixed(1) + \" MB\"\n}\n\nconst AiFileUpload = React.forwardRef<HTMLDivElement, AiFileUploadProps>(\n ({ className, accept, maxSize, multiple = true, onUpload, ...props }, ref) => {\n const [isDragging, setIsDragging] = React.useState(false)\n const [files, setFiles] = React.useState<FileEntry[]>([])\n const inputRef = React.useRef<HTMLInputElement>(null)\n\n const addFiles = React.useCallback(\n (incoming: FileList | File[]) => {\n const newFiles: FileEntry[] = Array.from(incoming).map((file) => ({\n file,\n progress: 0,\n size: formatSize(file.size),\n }))\n setFiles((prev) => (multiple ? [...prev, ...newFiles] : newFiles))\n onUpload?.(newFiles.map((f) => f.file))\n\n // Simulate upload progress\n newFiles.forEach((entry, i) => {\n let p = 0\n const interval = setInterval(() => {\n p += Math.random() * 30\n if (p >= 100) {\n p = 100\n clearInterval(interval)\n }\n setFiles((prev) => {\n const updated = [...prev]\n const idx = updated.indexOf(entry)\n if (idx !== -1) updated[idx] = { ...updated[idx], progress: p }\n return updated\n })\n }, 200 + i * 100)\n })\n },\n [multiple, onUpload]\n )\n\n const handleDragOver = (e: React.DragEvent) => {\n e.preventDefault()\n setIsDragging(true)\n }\n\n const handleDragLeave = (e: React.DragEvent) => {\n e.preventDefault()\n setIsDragging(false)\n }\n\n const handleDrop = (e: React.DragEvent) => {\n e.preventDefault()\n setIsDragging(false)\n if (e.dataTransfer.files.length > 0) {\n addFiles(e.dataTransfer.files)\n }\n }\n\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n if (e.target.files && e.target.files.length > 0) {\n addFiles(e.target.files)\n e.target.value = \"\"\n }\n }\n\n const removeFile = (index: number) => {\n setFiles((prev) => prev.filter((_, i) => i !== index))\n }\n\n return (\n <div\n ref={ref}\n className={cn(\"flex flex-col gap-3\", className)}\n {...props}\n >\n <div\n role=\"button\"\n tabIndex={0}\n onClick={() => inputRef.current?.click()}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") inputRef.current?.click()\n }}\n onDragOver={handleDragOver}\n onDragLeave={handleDragLeave}\n onDrop={handleDrop}\n aria-label=\"File upload zone\"\n className={cn(\n \"flex cursor-pointer flex-col items-center justify-center gap-2 rounded-xl border-2 border-dashed px-6 py-8 text-center transition-colors\",\n isDragging\n ? \"border-primary bg-primary/5\"\n : \"border-border hover:border-muted-foreground/30\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n )}\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"text-muted-foreground\"\n aria-hidden=\"true\"\n >\n <path d=\"M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z\" />\n <polyline points=\"14 2 14 8 20 8\" />\n <path d=\"M12 18v-6\" />\n <path d=\"M9 15l3-3 3 3\" />\n </svg>\n <div className=\"text-sm text-foreground\">\n <span className=\"font-medium\">Click to upload</span> or drag and drop\n </div>\n {accept && (\n <p className=\"text-xs text-muted-foreground\">\n Accepted: {accept}\n {maxSize && ` · Max: ${formatSize(maxSize)}`}\n </p>\n )}\n <input\n ref={inputRef}\n type=\"file\"\n accept={accept}\n multiple={multiple}\n onChange={handleInputChange}\n className=\"hidden\"\n aria-hidden=\"true\"\n />\n </div>\n\n {files.length > 0 && (\n <ul className=\"flex flex-col gap-2\" role=\"list\" aria-label=\"Uploaded files\">\n {files.map((entry, i) => (\n <li\n key={i}\n className=\"flex items-center gap-3 rounded-lg border border-border bg-background px-3 py-2.5\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"shrink-0 text-muted-foreground\"\n aria-hidden=\"true\"\n >\n <path d=\"M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z\" />\n <polyline points=\"14 2 14 8 20 8\" />\n </svg>\n <div className=\"flex min-w-0 flex-1 flex-col gap-1\">\n <div className=\"flex items-center justify-between gap-2\">\n <span className=\"truncate text-sm text-foreground\">\n {entry.file.name}\n </span>\n <span className=\"shrink-0 text-xs text-muted-foreground\">\n {entry.size}\n </span>\n </div>\n <div className=\"h-1.5 w-full overflow-hidden rounded-full bg-muted\">\n <div\n className={cn(\n \"h-full rounded-full transition-all duration-300\",\n entry.progress === 100 ? \"bg-primary\" : \"bg-primary/70\"\n )}\n style={{ width: `${entry.progress}%` }}\n />\n </div>\n </div>\n <button\n type=\"button\"\n onClick={() => removeFile(i)}\n className=\"shrink-0 rounded-md p-1 text-muted-foreground hover:text-foreground hover:bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n aria-label={`Remove ${entry.file.name}`}\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n </button>\n </li>\n ))}\n </ul>\n )}\n </div>\n )\n }\n)\nAiFileUpload.displayName = \"AiFileUpload\"\n\nexport { AiFileUpload }\n"
143
+ }
144
+ ]
145
+ },
146
+ {
147
+ "name": "ai-message",
148
+ "type": "components:ui",
149
+ "frameworks": [
150
+ "react",
151
+ "nextjs",
152
+ "vue",
153
+ "nuxt",
154
+ "solid",
155
+ "svelte",
156
+ "astro",
157
+ "remix"
158
+ ],
159
+ "dependencies": [
160
+ "@base-ui/react"
161
+ ],
162
+ "registryDependencies": [],
163
+ "files": [
164
+ {
165
+ "name": "ai-message.tsx",
166
+ "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { cn } from \"@/lib/utils\"\n\nexport interface AiMessageProps extends React.HTMLAttributes<HTMLDivElement> {\n role: \"user\" | \"assistant\"\n content: string\n timestamp?: string\n}\n\nconst AiMessage = React.forwardRef<HTMLDivElement, AiMessageProps>(\n ({ className, role, content, timestamp, ...props }, ref) => {\n const isUser = role === \"user\"\n\n return (\n <div\n ref={ref}\n className={cn(\n \"flex w-full gap-3\",\n isUser ? \"justify-end\" : \"justify-start\",\n className\n )}\n role=\"listitem\"\n {...props}\n >\n {!isUser && (\n <div className=\"flex size-8 shrink-0 items-center justify-center rounded-full bg-primary text-primary-foreground text-xs font-semibold\">\n AI\n </div>\n )}\n <div className={cn(\"flex max-w-[80%] flex-col gap-1\", isUser && \"items-end\")}>\n <div\n className={cn(\n \"rounded-2xl px-4 py-2.5 text-sm whitespace-pre-wrap\",\n isUser\n ? \"bg-primary text-primary-foreground rounded-br-md\"\n : \"bg-muted text-foreground rounded-bl-md\"\n )}\n >\n {content}\n </div>\n {timestamp && (\n <span className=\"text-[10px] text-muted-foreground px-1\">\n {timestamp}\n </span>\n )}\n </div>\n {isUser && (\n <div className=\"flex size-8 shrink-0 items-center justify-center rounded-full bg-muted text-muted-foreground text-xs font-semibold\">\n U\n </div>\n )}\n </div>\n )\n }\n)\nAiMessage.displayName = \"AiMessage\"\n\nexport { AiMessage }\n"
167
+ }
168
+ ]
169
+ },
170
+ {
171
+ "name": "ai-prompt",
172
+ "type": "components:ui",
173
+ "frameworks": [
174
+ "react",
175
+ "nextjs",
176
+ "vue",
177
+ "nuxt",
178
+ "solid",
179
+ "svelte",
180
+ "astro",
181
+ "remix"
182
+ ],
183
+ "dependencies": [
184
+ "@base-ui/react"
185
+ ],
186
+ "registryDependencies": [],
187
+ "files": [
188
+ {
189
+ "name": "ai-prompt.tsx",
190
+ "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { cn } from \"@/lib/utils\"\n\nexport interface AiPromptProps\n extends Omit<React.TextareaHTMLAttributes<HTMLTextAreaElement>, \"onSubmit\"> {\n onSubmit?: (value: string) => void\n disabled?: boolean\n maxLength?: number\n}\n\nconst AiPrompt = React.forwardRef<HTMLTextAreaElement, AiPromptProps>(\n ({ className, onSubmit, disabled, placeholder = \"Type a message...\", maxLength, ...props }, ref) => {\n const [value, setValue] = React.useState(\"\")\n const textareaRef = React.useRef<HTMLTextAreaElement>(null)\n const combinedRef = (node: HTMLTextAreaElement) => {\n (ref as React.RefCallback<HTMLTextAreaElement>)?.(node)\n ;(textareaRef as React.MutableRefObject<HTMLTextAreaElement | null>).current = node\n }\n\n const handleSubmit = React.useCallback(() => {\n const trimmed = value.trim()\n if (!trimmed || disabled) return\n onSubmit?.(trimmed)\n setValue(\"\")\n }, [value, disabled, onSubmit])\n\n const handleKeyDown = React.useCallback(\n (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === \"Enter\" && (e.metaKey || e.ctrlKey)) {\n e.preventDefault()\n handleSubmit()\n }\n if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault()\n handleSubmit()\n }\n },\n [handleSubmit]\n )\n\n const charCount = value.length\n\n return (\n <div className={cn(\"flex flex-col gap-2\", className)}>\n <div className=\"relative flex items-end gap-2\">\n <textarea\n ref={combinedRef}\n value={value}\n onChange={(e) => {\n if (maxLength && e.target.value.length > maxLength) return\n setValue(e.target.value)\n }}\n onKeyDown={handleKeyDown}\n placeholder={placeholder}\n disabled={disabled}\n rows={1}\n className={cn(\n \"min-h-[44px] w-full resize-none rounded-xl border border-border bg-background px-4 py-3 text-sm text-foreground placeholder:text-muted-foreground\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\",\n \"disabled:opacity-50 disabled:cursor-not-allowed\"\n )}\n aria-label=\"Chat input\"\n aria-disabled={disabled}\n {...props}\n />\n <button\n type=\"button\"\n onClick={handleSubmit}\n disabled={disabled || !value.trim()}\n aria-label=\"Send message\"\n className={cn(\n \"flex size-10 shrink-0 items-center justify-center rounded-xl bg-primary text-primary-foreground transition-colors\",\n \"hover:bg-primary/90\",\n \"disabled:opacity-50 disabled:cursor-not-allowed\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n )}\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M5 12h14\" />\n <path d=\"M12 5l7 7-7 7\" />\n </svg>\n </button>\n </div>\n <div className=\"flex justify-between px-1\">\n {maxLength && (\n <span className=\"text-[11px] text-muted-foreground\">\n {charCount}/{maxLength}\n </span>\n )}\n <span className=\"text-[11px] text-muted-foreground ml-auto opacity-60\">\n Enter to send · Shift+Enter for new line\n </span>\n </div>\n </div>\n )\n }\n)\nAiPrompt.displayName = \"AiPrompt\"\n\nexport { AiPrompt }\n"
191
+ }
192
+ ]
193
+ },
194
+ {
195
+ "name": "ai-sidebar",
196
+ "type": "components:ui",
197
+ "frameworks": [
198
+ "react",
199
+ "nextjs",
200
+ "vue",
201
+ "nuxt",
202
+ "solid",
203
+ "svelte",
204
+ "astro",
205
+ "remix"
206
+ ],
207
+ "dependencies": [
208
+ "@base-ui/react"
209
+ ],
210
+ "registryDependencies": [
211
+ "ai-conversation"
212
+ ],
213
+ "files": [
214
+ {
215
+ "name": "ai-sidebar.tsx",
216
+ "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { cn } from \"@/lib/utils\"\nimport { AiConversation } from \"./ai-conversation\"\n\nexport interface Conversation {\n id: string\n title: string\n preview?: string\n timestamp?: string\n}\n\nexport interface AiSidebarProps {\n className?: string\n conversations: Conversation[]\n activeId?: string\n onSelect?: (id: string) => void\n onNew?: () => void\n onDelete?: (id: string) => void\n}\n\nconst AiSidebar = React.forwardRef<HTMLDivElement, AiSidebarProps>(\n ({ className, conversations, activeId, onSelect, onNew, onDelete, ...props }, ref) => {\n const [search, setSearch] = React.useState(\"\")\n\n const filtered = React.useMemo(\n () =>\n conversations.filter((c) =>\n c.title.toLowerCase().includes(search.toLowerCase())\n ),\n [conversations, search]\n )\n\n return (\n <div\n ref={ref}\n className={cn(\"flex h-full flex-col gap-3\", className)}\n {...props}\n >\n <div className=\"flex items-center justify-between px-1\">\n <h2 className=\"text-sm font-semibold text-foreground\">Conversations</h2>\n <button\n type=\"button\"\n onClick={onNew}\n className={cn(\n \"flex items-center gap-1.5 rounded-lg px-3 py-1.5 text-xs font-medium text-foreground transition-colors\",\n \"hover:bg-muted\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n )}\n aria-label=\"New conversation\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\" />\n <line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\" />\n </svg>\n New\n </button>\n </div>\n\n <div className=\"relative\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground\"\n aria-hidden=\"true\"\n >\n <circle cx=\"11\" cy=\"11\" r=\"8\" />\n <line x1=\"21\" y1=\"21\" x2=\"16.65\" y2=\"16.65\" />\n </svg>\n <input\n type=\"text\"\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n placeholder=\"Search...\"\n aria-label=\"Search conversations\"\n className={cn(\n \"w-full rounded-lg border border-border bg-background py-2 pl-9 pr-3 text-sm text-foreground placeholder:text-muted-foreground\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n )}\n />\n </div>\n\n <div className=\"flex-1 overflow-y-auto\" role=\"list\" aria-label=\"Conversation list\">\n {filtered.length === 0 ? (\n <p className=\"px-1 text-xs text-muted-foreground py-4 text-center\">\n {search ? \"No conversations found\" : \"No conversations yet\"}\n </p>\n ) : (\n <div className=\"flex flex-col gap-0.5\">\n {filtered.map((conv) => (\n <AiConversation\n key={conv.id}\n title={conv.title}\n preview={conv.preview}\n timestamp={conv.timestamp}\n active={conv.id === activeId}\n onClick={() => onSelect?.(conv.id)}\n onDelete={onDelete ? () => onDelete(conv.id) : undefined}\n />\n ))}\n </div>\n )}\n </div>\n </div>\n )\n }\n)\nAiSidebar.displayName = \"AiSidebar\"\n\nexport { AiSidebar }\n"
11
217
  }
12
218
  ]
13
219
  },
14
220
  {
15
221
  "name": "alert-dialog",
222
+ "type": "components:ui",
223
+ "frameworks": [
224
+ "react",
225
+ "nextjs",
226
+ "remix"
227
+ ],
16
228
  "dependencies": [
17
229
  "@base-ui/react"
18
230
  ],
231
+ "registryDependencies": [],
19
232
  "files": [
20
233
  {
21
234
  "name": "alert-dialog.tsx",
22
- "content": "\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport { AlertDialog as BaseAlertDialog } from \"@base-ui/react/alert-dialog\"\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nconst AlertDialog = BaseAlertDialog.Root\r\n\r\nconst AlertDialogTrigger = BaseAlertDialog.Trigger\r\n\r\nconst AlertDialogPortal = BaseAlertDialog.Portal\r\n\r\nconst AlertDialogBackdrop = React.forwardRef<\r\n HTMLDivElement,\r\n React.ComponentPropsWithoutRef<typeof BaseAlertDialog.Backdrop>\r\n>(({ className, ...props }, ref) => (\r\n <BaseAlertDialog.Backdrop\r\n ref={ref}\r\n className={cn(\r\n \"fixed inset-0 min-h-dvh bg-black/40 backdrop-blur-xs transition-opacity duration-200\",\r\n \"data-[starting-style]:opacity-0 data-[ending-style]:opacity-0\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n))\r\nAlertDialogBackdrop.displayName = \"AlertDialogBackdrop\"\r\n\r\nconst AlertDialogPopup = React.forwardRef<\r\n HTMLDivElement,\r\n React.ComponentPropsWithoutRef<typeof BaseAlertDialog.Popup>\r\n>(({ className, ...props }, ref) => (\r\n <BaseAlertDialog.Popup\r\n ref={ref}\r\n className={cn(\r\n \"fixed top-1/2 left-1/2 w-full max-w-md -translate-x-1/2 -translate-y-1/2 rounded-xl border border-neutral-200 bg-white p-6 shadow-xl text-neutral-950 transition-all duration-200 ease-out\",\r\n \"data-[starting-style]:scale-95 data-[starting-style]:opacity-0\",\r\n \"data-[ending-style]:scale-95 data-[ending-style]:opacity-0\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n))\r\nAlertDialogPopup.displayName = \"AlertDialogPopup\"\r\n\r\nconst AlertDialogHeader = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (\r\n <div className={cn(\"flex flex-col gap-1 text-center sm:text-left mb-4\", className)} {...props} />\r\n)\r\nAlertDialogHeader.displayName = \"AlertDialogHeader\"\r\n\r\nconst AlertDialogFooter = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (\r\n <div className={cn(\"flex flex-col-reverse sm:flex-row sm:justify-end gap-2 mt-6\", className)} {...props} />\r\n)\r\nAlertDialogFooter.displayName = \"AlertDialogFooter\"\r\n\r\nconst AlertDialogTitle = React.forwardRef<\r\n HTMLHeadingElement,\r\n React.ComponentPropsWithoutRef<typeof BaseAlertDialog.Title>\r\n>(({ className, ...props }, ref) => (\r\n <BaseAlertDialog.Title\r\n ref={ref}\r\n className={cn(\"text-base font-semibold tracking-tight leading-none\", className)}\r\n {...props}\r\n />\r\n))\r\nAlertDialogTitle.displayName = \"AlertDialogTitle\"\r\n\r\nconst AlertDialogDescription = React.forwardRef<\r\n HTMLParagraphElement,\r\n React.ComponentPropsWithoutRef<typeof BaseAlertDialog.Description>\r\n>(({ className, ...props }, ref) => (\r\n <BaseAlertDialog.Description\r\n ref={ref}\r\n className={cn(\"text-sm text-neutral-500 leading-normal\", className)}\r\n {...props}\r\n />\r\n))\r\nAlertDialogDescription.displayName = \"AlertDialogDescription\"\r\n\r\nconst AlertDialogAction = BaseAlertDialog.Close\r\n\r\nconst AlertDialogCancel = BaseAlertDialog.Close\r\n\r\nexport {\r\n AlertDialog,\r\n AlertDialogTrigger,\r\n AlertDialogPortal,\r\n AlertDialogBackdrop,\r\n AlertDialogPopup,\r\n AlertDialogHeader,\r\n AlertDialogFooter,\r\n AlertDialogTitle,\r\n AlertDialogDescription,\r\n AlertDialogAction,\r\n AlertDialogCancel,\r\n}"
235
+ "content": "\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport { AlertDialog as AlertDialogPrimitive } from \"@base-ui/react/alert-dialog\"\r\n\r\nimport { cn } from \"@/lib/utils\"\r\nimport { Button } from \"@/button\"\r\n\r\nfunction AlertDialog({ ...props }: AlertDialogPrimitive.Root.Props) {\r\n return <AlertDialogPrimitive.Root data-slot=\"alert-dialog\" {...props} />\r\n}\r\n\r\nfunction AlertDialogTrigger({ ...props }: AlertDialogPrimitive.Trigger.Props) {\r\n return (\r\n <AlertDialogPrimitive.Trigger data-slot=\"alert-dialog-trigger\" {...props} />\r\n )\r\n}\r\n\r\nfunction AlertDialogPortal({ ...props }: AlertDialogPrimitive.Portal.Props) {\r\n return (\r\n <AlertDialogPrimitive.Portal data-slot=\"alert-dialog-portal\" {...props} />\r\n )\r\n}\r\n\r\nfunction AlertDialogOverlay({\r\n className,\r\n ...props\r\n}: AlertDialogPrimitive.Backdrop.Props) {\r\n return (\r\n <AlertDialogPrimitive.Backdrop\r\n data-slot=\"alert-dialog-overlay\"\r\n className={cn(\r\n \"fixed inset-0 isolate z-50 bg-black/10 duration-100 supports-backdrop-filter:backdrop-blur-xs data-open:animate-in data-open:fade-in-0 data-closed:animate-out data-closed:fade-out-0\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction AlertDialogContent({\r\n className,\r\n size = \"default\",\r\n ...props\r\n}: AlertDialogPrimitive.Popup.Props & {\r\n size?: \"default\" | \"sm\"\r\n}) {\r\n return (\r\n <AlertDialogPortal>\r\n <AlertDialogOverlay />\r\n <AlertDialogPrimitive.Popup\r\n data-slot=\"alert-dialog-content\"\r\n data-size={size}\r\n className={cn(\r\n \"group/alert-dialog-content fixed top-1/2 left-1/2 z-50 grid w-full -translate-x-1/2 -translate-y-1/2 gap-4 rounded-xl bg-popover p-4 text-popover-foreground ring-1 ring-foreground/10 duration-100 outline-none data-[size=default]:max-w-xs data-[size=sm]:max-w-xs data-[size=default]:sm:max-w-sm data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n </AlertDialogPortal>\r\n )\r\n}\r\n\r\nfunction AlertDialogHeader({\r\n className,\r\n ...props\r\n}: React.ComponentProps<\"div\">) {\r\n return (\r\n <div\r\n data-slot=\"alert-dialog-header\"\r\n className={cn(\r\n \"grid grid-rows-[auto_1fr] place-items-center gap-1.5 text-center has-data-[slot=alert-dialog-media]:grid-rows-[auto_auto_1fr] has-data-[slot=alert-dialog-media]:gap-x-4 sm:group-data-[size=default]/alert-dialog-content:place-items-start sm:group-data-[size=default]/alert-dialog-content:text-left sm:group-data-[size=default]/alert-dialog-content:has-data-[slot=alert-dialog-media]:grid-rows-[auto_1fr]\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction AlertDialogFooter({\r\n className,\r\n ...props\r\n}: React.ComponentProps<\"div\">) {\r\n return (\r\n <div\r\n data-slot=\"alert-dialog-footer\"\r\n className={cn(\r\n \"-mx-4 -mb-4 flex flex-col-reverse gap-2 rounded-b-xl border-t bg-muted/50 p-4 group-data-[size=sm]/alert-dialog-content:grid group-data-[size=sm]/alert-dialog-content:grid-cols-2 sm:flex-row sm:justify-end\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction AlertDialogMedia({\r\n className,\r\n ...props\r\n}: React.ComponentProps<\"div\">) {\r\n return (\r\n <div\r\n data-slot=\"alert-dialog-media\"\r\n className={cn(\r\n \"mb-2 inline-flex size-10 items-center justify-center rounded-md bg-muted sm:group-data-[size=default]/alert-dialog-content:row-span-2 *:[svg:not([class*='size-'])]:size-6\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction AlertDialogTitle({\r\n className,\r\n ...props\r\n}: React.ComponentProps<typeof AlertDialogPrimitive.Title>) {\r\n return (\r\n <AlertDialogPrimitive.Title\r\n data-slot=\"alert-dialog-title\"\r\n className={cn(\r\n \"cn-font-heading text-base font-medium sm:group-data-[size=default]/alert-dialog-content:group-has-data-[slot=alert-dialog-media]/alert-dialog-content:col-start-2\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction AlertDialogDescription({\r\n className,\r\n ...props\r\n}: React.ComponentProps<typeof AlertDialogPrimitive.Description>) {\r\n return (\r\n <AlertDialogPrimitive.Description\r\n data-slot=\"alert-dialog-description\"\r\n className={cn(\r\n \"text-sm text-balance text-muted-foreground md:text-pretty *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction AlertDialogAction({\r\n className,\r\n ...props\r\n}: React.ComponentProps<typeof Button>) {\r\n return (\r\n <Button\r\n data-slot=\"alert-dialog-action\"\r\n className={cn(className)}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction AlertDialogCancel({\r\n className,\r\n variant = \"outline\",\r\n size = \"default\",\r\n ...props\r\n}: AlertDialogPrimitive.Close.Props &\r\n Pick<React.ComponentProps<typeof Button>, \"variant\" | \"size\">) {\r\n return (\r\n <AlertDialogPrimitive.Close\r\n data-slot=\"alert-dialog-cancel\"\r\n className={cn(className)}\r\n render={<Button variant={variant} size={size} />}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nexport {\r\n AlertDialog,\r\n AlertDialogAction,\r\n AlertDialogCancel,\r\n AlertDialogContent,\r\n AlertDialogDescription,\r\n AlertDialogFooter,\r\n AlertDialogHeader,\r\n AlertDialogMedia,\r\n AlertDialogOverlay,\r\n AlertDialogPortal,\r\n AlertDialogTitle,\r\n AlertDialogTrigger,\r\n}\r\n"
23
236
  }
24
237
  ]
25
238
  },
26
239
  {
27
240
  "name": "alert",
241
+ "type": "components:ui",
242
+ "frameworks": [
243
+ "react",
244
+ "nextjs",
245
+ "vue",
246
+ "nuxt",
247
+ "solid",
248
+ "svelte",
249
+ "astro",
250
+ "remix"
251
+ ],
28
252
  "dependencies": [],
253
+ "registryDependencies": [],
29
254
  "files": [
30
255
  {
31
256
  "name": "alert.tsx",
32
- "content": "import * as React from \"react\"\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nconst Alert = React.forwardRef<\r\n HTMLDivElement,\r\n React.HTMLAttributes<HTMLDivElement> & { variant?: \"default\" | \"destructive\" }\r\n>(({ className, variant = \"default\", ...props }, ref) => (\r\n <div\r\n ref={ref}\r\n role=\"alert\"\r\n className={cn(\r\n \"relative w-full rounded-lg border p-4 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-neutral-950 [&>svg~*]:pl-7\",\r\n variant === \"default\" && \"bg-neutral-50 text-neutral-900 border-neutral-200 [&>svg]:text-neutral-600\",\r\n variant === \"destructive\" && \"border-red-500/50 bg-red-50 text-red-900 [&>svg]:text-red-600\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n))\r\nAlert.displayName = \"Alert\"\r\n\r\nconst AlertTitle = React.forwardRef<\r\n HTMLParagraphElement,\r\n React.HTMLAttributes<HTMLHeadingElement>\r\n>(({ className, ...props }, ref) => (\r\n <h5\r\n ref={ref}\r\n className={cn(\"mb-1 font-medium tracking-tight text-sm leading-none\", className)}\r\n {...props}\r\n />\r\n))\r\nAlertTitle.displayName = \"AlertTitle\"\r\n\r\nconst AlertDescription = React.forwardRef<\r\n HTMLParagraphElement,\r\n React.HTMLAttributes<HTMLParagraphElement>\r\n>(({ className, ...props }, ref) => (\r\n <div\r\n ref={ref}\r\n className={cn(\"text-xs text-neutral-500 [&_p]:leading-relaxed\", className)}\r\n {...props}\r\n />\r\n))\r\nAlertDescription.displayName = \"AlertDescription\"\r\n\r\nexport { Alert, AlertTitle, AlertDescription }"
257
+ "content": "import * as React from \"react\"\r\nimport { cva, type VariantProps } from \"class-variance-authority\"\r\n\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nconst alertVariants = cva(\r\n \"relative grid w-full grid-cols-[0_1fr] items-start gap-y-0.5 rounded-lg border px-4 py-3 text-sm has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] has-[>svg]:gap-x-3 [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current\",\r\n {\r\n variants: {\r\n variant: {\r\n default: \"bg-card text-card-foreground\",\r\n destructive:\r\n \"bg-card text-destructive *:data-[slot=alert-description]:text-destructive/90 [&>svg]:text-current\",\r\n },\r\n },\r\n defaultVariants: {\r\n variant: \"default\",\r\n },\r\n }\r\n)\r\n\r\nfunction Alert({\r\n className,\r\n variant,\r\n ...props\r\n}: React.ComponentProps<\"div\"> & VariantProps<typeof alertVariants>) {\r\n return (\r\n <div\r\n data-slot=\"alert\"\r\n role=\"alert\"\r\n className={cn(alertVariants({ variant }), className)}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction AlertTitle({ className, ...props }: React.ComponentProps<\"div\">) {\r\n return (\r\n <div\r\n data-slot=\"alert-title\"\r\n className={cn(\r\n \"col-start-2 line-clamp-1 min-h-4 font-medium tracking-tight\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction AlertDescription({\r\n className,\r\n ...props\r\n}: React.ComponentProps<\"div\">) {\r\n return (\r\n <div\r\n data-slot=\"alert-description\"\r\n className={cn(\r\n \"col-start-2 grid justify-items-start gap-1 text-sm text-muted-foreground [&_p]:leading-relaxed\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nexport { Alert, AlertTitle, AlertDescription }\r\n"
33
258
  }
34
259
  ]
35
260
  },
36
261
  {
37
262
  "name": "aspect-ratio",
263
+ "type": "components:ui",
264
+ "frameworks": [
265
+ "react",
266
+ "nextjs",
267
+ "vue",
268
+ "nuxt",
269
+ "solid",
270
+ "svelte",
271
+ "astro",
272
+ "remix"
273
+ ],
38
274
  "dependencies": [],
275
+ "registryDependencies": [],
39
276
  "files": [
40
277
  {
41
278
  "name": "aspect-ratio.tsx",
42
- "content": "import * as React from \"react\"\r\nimport { cn } from \"@/lib/utils\"\r\n\r\ninterface AspectRatioProps extends React.HTMLAttributes<HTMLDivElement> {\r\n ratio?: number\r\n}\r\n\r\nconst AspectRatio = React.forwardRef<HTMLDivElement, AspectRatioProps>(\r\n ({ className, ratio = 16 / 9, style, ...props }, ref) => (\r\n <div\r\n ref={ref}\r\n style={{\r\n position: \"relative\",\r\n width: \"100%\",\r\n aspectRatio: `${ratio}`,\r\n ...style,\r\n }}\r\n className={cn(\"[&>img]:absolute [&>img]:inset-0 [&>img]:h-full [&>img]:w-full [&>img]:object-cover\", className)}\r\n {...props}\r\n />\r\n )\r\n)\r\nAspectRatio.displayName = \"AspectRatio\"\r\n\r\nexport { AspectRatio }"
279
+ "content": "import { cn } from \"@/lib/utils\"\r\n\r\nfunction AspectRatio({\r\n ratio,\r\n className,\r\n ...props\r\n}: React.ComponentProps<\"div\"> & { ratio: number }) {\r\n return (\r\n <div\r\n data-slot=\"aspect-ratio\"\r\n style={\r\n {\r\n \"--ratio\": ratio,\r\n } as React.CSSProperties\r\n }\r\n className={cn(\"relative aspect-(--ratio)\", className)}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nexport { AspectRatio }\r\n"
43
280
  }
44
281
  ]
45
282
  },
46
283
  {
47
284
  "name": "avatar",
285
+ "type": "components:ui",
286
+ "frameworks": [
287
+ "react",
288
+ "nextjs",
289
+ "remix"
290
+ ],
48
291
  "dependencies": [
49
292
  "@base-ui/react"
50
293
  ],
294
+ "registryDependencies": [],
51
295
  "files": [
52
296
  {
53
297
  "name": "avatar.tsx",
54
- "content": "\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport { Avatar as BaseAvatar } from \"@base-ui/react/avatar\"\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nconst Avatar = React.forwardRef<\r\n HTMLSpanElement,\r\n React.ComponentPropsWithoutRef<typeof BaseAvatar.Root>\r\n>(({ className, ...props }, ref) => (\r\n <BaseAvatar.Root\r\n ref={ref}\r\n className={cn(\"relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full bg-neutral-100\", className)}\r\n {...props}\r\n />\r\n))\r\nAvatar.displayName = \"Avatar\"\r\n\r\nconst AvatarImage = React.forwardRef<\r\n HTMLImageElement,\r\n React.ComponentPropsWithoutRef<typeof BaseAvatar.Image>\r\n>(({ className, ...props }, ref) => (\r\n <BaseAvatar.Image\r\n ref={ref}\r\n className={cn(\"aspect-square h-full w-full object-cover transition-opacity duration-200 data-[status=loading]:opacity-0\", className)}\r\n {...props}\r\n />\r\n))\r\nAvatarImage.displayName = \"AvatarImage\"\r\n\r\nconst AvatarFallback = React.forwardRef<\r\n HTMLSpanElement,\r\n React.ComponentPropsWithoutRef<typeof BaseAvatar.Fallback>\r\n>(({ className, ...props }, ref) => (\r\n <BaseAvatar.Fallback\r\n ref={ref}\r\n className={cn(\r\n \"flex h-full w-full items-center justify-center rounded-full bg-neutral-100 font-medium text-sm text-neutral-600\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n))\r\nAvatarFallback.displayName = \"AvatarFallback\"\r\n\r\nexport { Avatar, AvatarImage, AvatarFallback }"
298
+ "content": "\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport { Avatar as AvatarPrimitive } from \"@base-ui/react/avatar\"\r\n\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nfunction Avatar({\r\n className,\r\n size = \"default\",\r\n ...props\r\n}: AvatarPrimitive.Root.Props & {\r\n size?: \"default\" | \"sm\" | \"lg\"\r\n}) {\r\n return (\r\n <AvatarPrimitive.Root\r\n data-slot=\"avatar\"\r\n data-size={size}\r\n className={cn(\r\n \"group/avatar relative flex size-8 shrink-0 rounded-full select-none after:absolute after:inset-0 after:rounded-full after:border after:border-border after:mix-blend-darken data-[size=lg]:size-10 data-[size=sm]:size-6 dark:after:mix-blend-lighten\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction AvatarImage({ className, ...props }: AvatarPrimitive.Image.Props) {\r\n return (\r\n <AvatarPrimitive.Image\r\n data-slot=\"avatar-image\"\r\n className={cn(\r\n \"aspect-square size-full rounded-full object-cover\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction AvatarFallback({\r\n className,\r\n ...props\r\n}: AvatarPrimitive.Fallback.Props) {\r\n return (\r\n <AvatarPrimitive.Fallback\r\n data-slot=\"avatar-fallback\"\r\n className={cn(\r\n \"flex size-full items-center justify-center rounded-full bg-muted text-sm text-muted-foreground group-data-[size=sm]/avatar:text-xs\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction AvatarBadge({ className, ...props }: React.ComponentProps<\"span\">) {\r\n return (\r\n <span\r\n data-slot=\"avatar-badge\"\r\n className={cn(\r\n \"absolute right-0 bottom-0 z-10 inline-flex items-center justify-center rounded-full bg-primary text-primary-foreground bg-blend-color ring-2 ring-background select-none\",\r\n \"group-data-[size=sm]/avatar:size-2 group-data-[size=sm]/avatar:[&>svg]:hidden\",\r\n \"group-data-[size=default]/avatar:size-2.5 group-data-[size=default]/avatar:[&>svg]:size-2\",\r\n \"group-data-[size=lg]/avatar:size-3 group-data-[size=lg]/avatar:[&>svg]:size-2\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction AvatarGroup({ className, ...props }: React.ComponentProps<\"div\">) {\r\n return (\r\n <div\r\n data-slot=\"avatar-group\"\r\n className={cn(\r\n \"group/avatar-group flex -space-x-2 *:data-[slot=avatar]:ring-2 *:data-[slot=avatar]:ring-background\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction AvatarGroupCount({\r\n className,\r\n ...props\r\n}: React.ComponentProps<\"div\">) {\r\n return (\r\n <div\r\n data-slot=\"avatar-group-count\"\r\n className={cn(\r\n \"relative flex size-8 shrink-0 items-center justify-center rounded-full bg-muted text-sm text-muted-foreground ring-2 ring-background group-has-data-[size=lg]/avatar-group:size-10 group-has-data-[size=sm]/avatar-group:size-6 [&>svg]:size-4 group-has-data-[size=lg]/avatar-group:[&>svg]:size-5 group-has-data-[size=sm]/avatar-group:[&>svg]:size-3\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nexport {\r\n Avatar,\r\n AvatarImage,\r\n AvatarFallback,\r\n AvatarGroup,\r\n AvatarGroupCount,\r\n AvatarBadge,\r\n}\r\n"
55
299
  }
56
300
  ]
57
301
  },
58
302
  {
59
303
  "name": "badge",
304
+ "type": "components:ui",
305
+ "frameworks": [
306
+ "react",
307
+ "nextjs",
308
+ "vue",
309
+ "nuxt",
310
+ "solid",
311
+ "svelte",
312
+ "astro",
313
+ "remix"
314
+ ],
60
315
  "dependencies": [
61
316
  "class-variance-authority"
62
317
  ],
318
+ "registryDependencies": [],
63
319
  "files": [
64
320
  {
65
321
  "name": "badge.tsx",
66
- "content": "import * as React from \"react\"\r\nimport { cva, type VariantProps } from \"class-variance-authority\"\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nconst badgeVariants = cva(\r\n \"inline-flex items-center rounded-md px-2.5 py-0.5 text-xs font-semibold transition-colors focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-neutral-950 focus-visible:ring-offset-2\",\r\n {\r\n variants: {\r\n variant: {\r\n default: \"border-transparent bg-neutral-900 text-neutral-50 shadow-sm hover:bg-neutral-900/80\",\r\n secondary: \"border-transparent bg-neutral-100 text-neutral-900 hover:bg-neutral-100/80\",\r\n destructive: \"border-transparent bg-red-500 text-neutral-50 shadow-sm hover:bg-red-500/80\",\r\n outline: \"text-neutral-950 border border-neutral-200\",\r\n },\r\n },\r\n defaultVariants: {\r\n variant: \"default\",\r\n },\r\n }\r\n)\r\n\r\nexport interface BadgeProps\r\n extends React.HTMLAttributes<HTMLDivElement>,\r\n VariantProps<typeof badgeVariants> {}\r\n\r\nconst Badge = React.forwardRef<HTMLDivElement, BadgeProps>(\r\n ({ className, variant, ...props }, ref) => {\r\n return (\r\n <div className={cn(badgeVariants({ variant }), className)} {...props} />\r\n )\r\n }\r\n)\r\n\r\nexport { Badge, badgeVariants }"
322
+ "content": "import { mergeProps } from \"@base-ui/react/merge-props\"\r\nimport { useRender } from \"@base-ui/react/use-render\"\r\nimport { cva, type VariantProps } from \"class-variance-authority\"\r\n\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nconst badgeVariants = cva(\r\n \"group/badge inline-flex h-5 w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-4xl border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-all focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3!\",\r\n {\r\n variants: {\r\n variant: {\r\n default: \"bg-primary text-primary-foreground [a]:hover:bg-primary/80\",\r\n secondary:\r\n \"bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80\",\r\n destructive:\r\n \"bg-destructive/10 text-destructive focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:focus-visible:ring-destructive/40 [a]:hover:bg-destructive/20\",\r\n outline:\r\n \"border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground\",\r\n ghost:\r\n \"hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50\",\r\n link: \"text-primary underline-offset-4 hover:underline\",\r\n },\r\n },\r\n defaultVariants: {\r\n variant: \"default\",\r\n },\r\n }\r\n)\r\n\r\nfunction Badge({\r\n className,\r\n variant = \"default\",\r\n render,\r\n ...props\r\n}: useRender.ComponentProps<\"span\"> & VariantProps<typeof badgeVariants>) {\r\n return useRender({\r\n defaultTagName: \"span\",\r\n props: mergeProps<\"span\">(\r\n {\r\n className: cn(badgeVariants({ variant }), className),\r\n },\r\n props\r\n ),\r\n render,\r\n state: {\r\n slot: \"badge\",\r\n variant,\r\n },\r\n })\r\n}\r\n\r\nexport { Badge, badgeVariants }\r\n"
67
323
  }
68
324
  ]
69
325
  },
70
326
  {
71
327
  "name": "breadcrumb",
328
+ "type": "components:ui",
329
+ "frameworks": [
330
+ "react",
331
+ "nextjs",
332
+ "vue",
333
+ "nuxt",
334
+ "solid",
335
+ "svelte",
336
+ "astro",
337
+ "remix"
338
+ ],
72
339
  "dependencies": [],
340
+ "registryDependencies": [],
73
341
  "files": [
74
342
  {
75
343
  "name": "breadcrumb.tsx",
76
- "content": "import * as React from \"react\"\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nconst Breadcrumb = React.forwardRef<\r\n HTMLElement,\r\n React.ComponentPropsWithoutRef<\"nav\"> & { separator?: React.ReactNode }\r\n>(({ className, ...props }, ref) => (\r\n <nav ref={ref} aria-label=\"breadcrumb\" className={cn(\"flex flex-wrap items-center gap-1.5 break-words text-sm text-neutral-500\", className)} {...props} />\r\n))\r\nBreadcrumb.displayName = \"Breadcrumb\"\r\n\r\nconst BreadcrumbList = React.forwardRef<\r\n HTMLOListElement,\r\n React.ComponentPropsWithoutRef<\"ol\">\r\n>(({ className, ...props }, ref) => (\r\n <ol ref={ref} className={cn(\"flex flex-wrap items-center gap-1.5 break-words text-sm text-neutral-500\", className)} {...props} />\r\n))\r\nBreadcrumbList.displayName = \"BreadcrumbList\"\r\n\r\nconst BreadcrumbItem = React.forwardRef<\r\n HTMLLIElement,\r\n React.ComponentPropsWithoutRef<\"li\">\r\n>(({ className, ...props }, ref) => (\r\n <li ref={ref} className={cn(\"inline-flex items-center gap-1.5\", className)} {...props} />\r\n))\r\nBreadcrumbItem.displayName = \"BreadcrumbItem\"\r\n\r\nconst BreadcrumbLink = React.forwardRef<\r\n HTMLAnchorElement,\r\n React.ComponentPropsWithoutRef<\"a\"> & { asChild?: boolean }\r\n>(({ className, ...props }, ref) => (\r\n <a ref={ref} className={cn(\"transition-colors hover:text-neutral-900 cursor-pointer\", className)} {...props} />\r\n))\r\nBreadcrumbLink.displayName = \"BreadcrumbLink\"\r\n\r\nconst BreadcrumbPage = React.forwardRef<\r\n HTMLSpanElement,\r\n React.ComponentPropsWithoutRef<\"span\">\r\n>(({ className, ...props }, ref) => (\r\n <span ref={ref} role=\"link\" aria-disabled=\"true\" aria-current=\"page\" className={cn(\"font-normal text-neutral-950\", className)} {...props} />\r\n))\r\nBreadcrumbPage.displayName = \"BreadcrumbPage\"\r\n\r\nconst BreadcrumbSeparator = ({ children, className, ...props }: React.ComponentProps<\"li\">) => (\r\n <li role=\"presentation\" aria-hidden=\"true\" className={cn(\"[&>svg]:h-3.5 [&>svg]:w-3.5 text-neutral-400\", className)} {...props}>\r\n {children ?? (\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\r\n <path d=\"m9 18 6-6-6-6\" />\r\n </svg>\r\n )}\r\n </li>\r\n)\r\nBreadcrumbSeparator.displayName = \"BreadcrumbSeparator\"\r\n\r\nexport { Breadcrumb, BreadcrumbList, BreadcrumbItem, BreadcrumbLink, BreadcrumbPage, BreadcrumbSeparator }"
344
+ "content": "import * as React from \"react\"\r\nimport { mergeProps } from \"@base-ui/react/merge-props\"\r\nimport { useRender } from \"@base-ui/react/use-render\"\r\nimport { ChevronRightIcon, MoreHorizontalIcon } from \"lucide-react\"\r\n\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nfunction Breadcrumb({ className, ...props }: React.ComponentProps<\"nav\">) {\r\n return (\r\n <nav\r\n aria-label=\"breadcrumb\"\r\n data-slot=\"breadcrumb\"\r\n className={cn(className)}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction BreadcrumbList({ className, ...props }: React.ComponentProps<\"ol\">) {\r\n return (\r\n <ol\r\n data-slot=\"breadcrumb-list\"\r\n className={cn(\r\n \"flex flex-wrap items-center gap-1.5 text-sm wrap-break-word text-muted-foreground\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction BreadcrumbItem({ className, ...props }: React.ComponentProps<\"li\">) {\r\n return (\r\n <li\r\n data-slot=\"breadcrumb-item\"\r\n className={cn(\"inline-flex items-center gap-1\", className)}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction BreadcrumbLink({\r\n className,\r\n render,\r\n ...props\r\n}: useRender.ComponentProps<\"a\">) {\r\n return useRender({\r\n defaultTagName: \"a\",\r\n props: mergeProps<\"a\">(\r\n {\r\n className: cn(\"transition-colors hover:text-foreground\", className),\r\n },\r\n props\r\n ),\r\n render,\r\n state: {\r\n slot: \"breadcrumb-link\",\r\n },\r\n })\r\n}\r\n\r\nfunction BreadcrumbPage({ className, ...props }: React.ComponentProps<\"span\">) {\r\n return (\r\n <span\r\n data-slot=\"breadcrumb-page\"\r\n role=\"link\"\r\n aria-disabled=\"true\"\r\n aria-current=\"page\"\r\n className={cn(\"font-normal text-foreground\", className)}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction BreadcrumbSeparator({\r\n children,\r\n className,\r\n ...props\r\n}: React.ComponentProps<\"li\">) {\r\n return (\r\n <li\r\n data-slot=\"breadcrumb-separator\"\r\n role=\"presentation\"\r\n aria-hidden=\"true\"\r\n className={cn(\"[&>svg]:size-3.5\", className)}\r\n {...props}\r\n >\r\n {children ?? <ChevronRightIcon className=\"cn-rtl-flip\" />}\r\n </li>\r\n )\r\n}\r\n\r\nfunction BreadcrumbEllipsis({\r\n className,\r\n ...props\r\n}: React.ComponentProps<\"span\">) {\r\n return (\r\n <span\r\n data-slot=\"breadcrumb-ellipsis\"\r\n role=\"presentation\"\r\n aria-hidden=\"true\"\r\n className={cn(\r\n \"flex size-5 items-center justify-center [&>svg]:size-4\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n <MoreHorizontalIcon />\r\n <span className=\"sr-only\">More</span>\r\n </span>\r\n )\r\n}\r\n\r\nexport {\r\n Breadcrumb,\r\n BreadcrumbList,\r\n BreadcrumbItem,\r\n BreadcrumbLink,\r\n BreadcrumbPage,\r\n BreadcrumbSeparator,\r\n BreadcrumbEllipsis,\r\n}\r\n"
77
345
  }
78
346
  ]
79
347
  },
80
348
  {
81
349
  "name": "button",
350
+ "type": "components:ui",
351
+ "frameworks": [
352
+ "react",
353
+ "nextjs",
354
+ "vue",
355
+ "nuxt",
356
+ "solid",
357
+ "svelte",
358
+ "astro",
359
+ "remix"
360
+ ],
82
361
  "dependencies": [
83
362
  "@base-ui/react",
84
363
  "class-variance-authority"
85
364
  ],
365
+ "registryDependencies": [],
86
366
  "files": [
87
367
  {
88
368
  "name": "button.tsx",
89
- "content": "import * as React from \"react\"\r\nimport { Button as BaseButton } from \"@base-ui/react/button\"\r\nimport { cva, type VariantProps } from \"class-variance-authority\"\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nconst buttonVariants = cva(\r\n \"inline-flex items-center justify-center font-medium rounded-md text-sm transition-colors focus-visible:outline-none disabled:pointer-events-none disabled:opacity-50 data-[focus-visible]:ring-2 data-[focus-visible]:ring-neutral-950 data-[focus-visible]:ring-offset-2\",\r\n {\r\n variants: {\r\n variant: {\r\n default: \"bg-neutral-900 text-neutral-50 hover:bg-neutral-900/90 data-[hover]:bg-neutral-800\",\r\n outline: \"border border-neutral-200 bg-white text-neutral-900 hover:bg-neutral-100 data-[hover]:bg-neutral-100\",\r\n destructive: \"bg-red-600 text-white hover:bg-red-600/90 data-[hover]:bg-red-700\",\r\n },\r\n size: {\r\n default: \"h-10 px-4 py-2\",\r\n sm: \"h-9 px-3\",\r\n lg: \"h-11 px-8\",\r\n },\r\n },\r\n defaultVariants: {\r\n variant: \"default\",\r\n size: \"default\",\r\n },\r\n }\r\n)\r\n\r\nexport interface ButtonProps\r\n extends React.ComponentPropsWithoutRef<typeof BaseButton>,\r\n VariantProps<typeof buttonVariants> {}\r\n\r\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\r\n ({ className, variant, size, ...props }, ref) => {\r\n return (\r\n <BaseButton\r\n ref={ref}\r\n className={cn(buttonVariants({ variant, size, className }))}\r\n {...props}\r\n />\r\n )\r\n }\r\n)\r\n\r\nButton.displayName = \"Button\"\r\n\r\nexport { Button, buttonVariants }"
369
+ "content": "import { Button as ButtonPrimitive } from \"@base-ui/react/button\"\r\nimport { cva, type VariantProps } from \"class-variance-authority\"\r\n\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nconst buttonVariants = cva(\r\n \"group/button inline-flex shrink-0 items-center justify-center rounded-lg border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\r\n {\r\n variants: {\r\n variant: {\r\n default: \"bg-primary text-primary-foreground hover:bg-primary/80\",\r\n outline:\r\n \"border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50\",\r\n secondary:\r\n \"bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground\",\r\n ghost:\r\n \"hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50\",\r\n destructive:\r\n \"bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40\",\r\n link: \"text-primary underline-offset-4 hover:underline\",\r\n },\r\n size: {\r\n default:\r\n \"h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2\",\r\n xs: \"h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3\",\r\n sm: \"h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5\",\r\n lg: \"h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2\",\r\n icon: \"size-8\",\r\n \"icon-xs\":\r\n \"size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3\",\r\n \"icon-sm\":\r\n \"size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg\",\r\n \"icon-lg\": \"size-9\",\r\n },\r\n },\r\n defaultVariants: {\r\n variant: \"default\",\r\n size: \"default\",\r\n },\r\n }\r\n)\r\n\r\nfunction Button({\r\n className,\r\n variant = \"default\",\r\n size = \"default\",\r\n ...props\r\n}: ButtonPrimitive.Props & VariantProps<typeof buttonVariants>) {\r\n return (\r\n <ButtonPrimitive\r\n data-slot=\"button\"\r\n className={cn(buttonVariants({ variant, size, className }))}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nexport { Button, buttonVariants }\r\n"
90
370
  }
91
371
  ]
92
372
  },
93
373
  {
94
374
  "name": "calendar",
375
+ "type": "components:ui",
376
+ "frameworks": [
377
+ "react",
378
+ "nextjs",
379
+ "vue",
380
+ "nuxt",
381
+ "solid",
382
+ "svelte",
383
+ "astro",
384
+ "remix"
385
+ ],
95
386
  "dependencies": [],
387
+ "registryDependencies": [],
96
388
  "files": [
97
389
  {
98
390
  "name": "calendar.tsx",
99
- "content": "\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nexport interface CalendarProps {\r\n className?: string\r\n value?: Date\r\n onChange?: (date: Date) => void\r\n}\r\n\r\nconst Calendar = React.forwardRef<HTMLDivElement, CalendarProps>(\r\n ({ className, value, onChange }, ref) => {\r\n const [currentDate, setCurrentDate] = React.useState(value || new Date())\r\n const selectedDate = value;\r\n\r\n const year = currentDate.getFullYear()\r\n const month = currentDate.getMonth()\r\n\r\n const monthNames = [\r\n \"January\", \"February\", \"March\", \"April\", \"May\", \"June\",\r\n \"July\", \"August\", \"September\", \"October\", \"November\", \"December\"\r\n ]\r\n\r\n const daysInMonth = new Date(year, month + 1, 0).getDate()\r\n const firstDayIndex = new Date(year, month, 1).getDay()\r\n\r\n const handlePrevMonth = () => {\r\n setCurrentDate(new Date(year, month - 1, 1))\r\n }\r\n\r\n const handleNextMonth = () => {\r\n setCurrentDate(new Date(year, month + 1, 1))\r\n }\r\n\r\n const handleDateClick = (day: number) => {\r\n const clickedDate = new Date(year, month, day)\r\n if (onChange) onChange(clickedDate)\r\n }\r\n\r\n const daysArray = Array.from({ length: daysInMonth }, (_, i) => i + 1)\r\n const blankDays = Array.from({ length: firstDayIndex }, (_, i) => i)\r\n\r\n const weekdays = [\"Su\", \"Mo\", \"Tu\", \"We\", \"Th\", \"Fr\", \"Sa\"]\r\n\r\n return (\r\n <div\r\n ref={ref}\r\n className={cn(\"p-4 bg-white border border-neutral-200 rounded-xl shadow-2xs max-w-[280px] w-full\", className)}\r\n >\r\n {/* Header section */}\r\n <div className=\"flex items-center justify-between pb-3\">\r\n <button\r\n type=\"button\"\r\n onClick={handlePrevMonth}\r\n className=\"inline-flex h-7 w-7 items-center justify-center rounded-md text-neutral-500 hover:bg-neutral-100 hover:text-neutral-900 cursor-pointer transition-colors\"\r\n >\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" fill=\"none\" viewBox=\"0 0 24 24\" strokeWidth=\"2\" stroke=\"currentColor\">\r\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M15.75 19.5L8.25 12l7.5-7.5\" />\r\n </svg>\r\n </button>\r\n <span className=\"text-sm font-semibold text-neutral-900 select-none\">\r\n {monthNames[month]} {year}\r\n </span>\r\n <button\r\n type=\"button\"\r\n onClick={handleNextMonth}\r\n className=\"inline-flex h-7 w-7 items-center justify-center rounded-md text-neutral-500 hover:bg-neutral-100 hover:text-neutral-900 cursor-pointer transition-colors\"\r\n >\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" fill=\"none\" viewBox=\"0 0 24 24\" strokeWidth=\"2\" stroke=\"currentColor\">\r\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M8.25 4.5l7.5 7.5-7.5 7.5\" />\r\n </svg>\r\n </button>\r\n </div>\r\n\r\n {/* Weekdays layout */}\r\n <div className=\"grid grid-cols-7 gap-1 text-center pb-1\">\r\n {weekdays.map((day) => (\r\n <span key={day} className=\"text-xs font-medium text-neutral-400 select-none h-6 w-6 flex items-center justify-center mx-auto\">\r\n {day}\r\n </span>\r\n ))}\r\n </div>\r\n\r\n {/* Month grid matrix */}\r\n <div className=\"grid grid-cols-7 gap-1 text-center\">\r\n {blankDays.map((blank) => (\r\n <div key={`blank-${blank}`} className=\"h-7 w-7\" />\r\n ))}\r\n {daysArray.map((day) => {\r\n const isSelected =\r\n selectedDate &&\r\n selectedDate.getDate() === day &&\r\n selectedDate.getMonth() === month &&\r\n selectedDate.getFullYear() === year\r\n\r\n return (\r\n <button\r\n key={day}\r\n type=\"button\"\r\n onClick={() => handleDateClick(day)}\r\n className={cn(\r\n \"h-7 w-7 text-xs font-normal rounded-md flex items-center justify-center mx-auto cursor-pointer transition-all select-none\",\r\n isSelected\r\n ? \"bg-neutral-900 text-white font-medium\"\r\n : \"text-neutral-800 hover:bg-neutral-100\"\r\n )}\r\n >\r\n {day}\r\n </button>\r\n )\r\n })}\r\n </div>\r\n </div>\r\n )\r\n }\r\n)\r\nCalendar.displayName = \"Calendar\"\r\n\r\nexport { Calendar }"
391
+ "content": "\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport {\r\n ChevronDownIcon,\r\n ChevronLeftIcon,\r\n ChevronRightIcon,\r\n} from \"lucide-react\"\r\nimport {\r\n DayPicker,\r\n getDefaultClassNames,\r\n type DayButton,\r\n type Locale,\r\n} from \"react-day-picker\"\r\n\r\nimport { cn } from \"@/lib/utils\"\r\nimport { Button, buttonVariants } from \"@/button\"\r\n\r\nfunction Calendar({\r\n className,\r\n classNames,\r\n showOutsideDays = true,\r\n captionLayout = \"label\",\r\n buttonVariant = \"ghost\",\r\n locale,\r\n formatters,\r\n components,\r\n ...props\r\n}: React.ComponentProps<typeof DayPicker> & {\r\n buttonVariant?: React.ComponentProps<typeof Button>[\"variant\"]\r\n}) {\r\n const defaultClassNames = getDefaultClassNames()\r\n\r\n return (\r\n <DayPicker\r\n showOutsideDays={showOutsideDays}\r\n className={cn(\r\n \"group/calendar bg-background p-2 [--cell-radius:var(--radius-md)] [--cell-size:--spacing(7)] in-data-[slot=card-content]:bg-transparent in-data-[slot=popover-content]:bg-transparent\",\r\n String.raw`rtl:**:[.rdp-button\\_next>svg]:rotate-180`,\r\n String.raw`rtl:**:[.rdp-button\\_previous>svg]:rotate-180`,\r\n className\r\n )}\r\n captionLayout={captionLayout}\r\n locale={locale}\r\n formatters={{\r\n formatMonthDropdown: (date) =>\r\n date.toLocaleString(locale?.code, { month: \"short\" }),\r\n ...formatters,\r\n }}\r\n classNames={{\r\n root: cn(\"w-fit\", defaultClassNames.root),\r\n months: cn(\r\n \"relative flex flex-col gap-4 md:flex-row\",\r\n defaultClassNames.months\r\n ),\r\n month: cn(\"flex w-full flex-col gap-4\", defaultClassNames.month),\r\n nav: cn(\r\n \"absolute inset-x-0 top-0 flex w-full items-center justify-between gap-1\",\r\n defaultClassNames.nav\r\n ),\r\n button_previous: cn(\r\n buttonVariants({ variant: buttonVariant }),\r\n \"size-(--cell-size) p-0 select-none aria-disabled:opacity-50\",\r\n defaultClassNames.button_previous\r\n ),\r\n button_next: cn(\r\n buttonVariants({ variant: buttonVariant }),\r\n \"size-(--cell-size) p-0 select-none aria-disabled:opacity-50\",\r\n defaultClassNames.button_next\r\n ),\r\n month_caption: cn(\r\n \"flex h-(--cell-size) w-full items-center justify-center px-(--cell-size)\",\r\n defaultClassNames.month_caption\r\n ),\r\n dropdowns: cn(\r\n \"flex h-(--cell-size) w-full items-center justify-center gap-1.5 text-sm font-medium\",\r\n defaultClassNames.dropdowns\r\n ),\r\n dropdown_root: cn(\r\n \"cn-calendar-dropdown-root relative rounded-(--cell-radius)\",\r\n defaultClassNames.dropdown_root\r\n ),\r\n dropdown: cn(\r\n \"absolute inset-0 bg-popover opacity-0\",\r\n defaultClassNames.dropdown\r\n ),\r\n caption_label: cn(\r\n \"font-medium select-none\",\r\n captionLayout === \"label\"\r\n ? \"cn-calendar-caption text-sm\"\r\n : \"cn-calendar-caption-label flex items-center gap-1 rounded-(--cell-radius) text-sm [&>svg]:size-3.5 [&>svg]:text-muted-foreground\",\r\n defaultClassNames.caption_label\r\n ),\r\n table: \"w-full border-collapse\",\r\n weekdays: cn(\"flex\", defaultClassNames.weekdays),\r\n weekday: cn(\r\n \"flex-1 rounded-(--cell-radius) text-[0.8rem] font-normal text-muted-foreground select-none\",\r\n defaultClassNames.weekday\r\n ),\r\n week: cn(\"mt-2 flex w-full\", defaultClassNames.week),\r\n week_number_header: cn(\r\n \"w-(--cell-size) select-none\",\r\n defaultClassNames.week_number_header\r\n ),\r\n week_number: cn(\r\n \"text-[0.8rem] text-muted-foreground select-none\",\r\n defaultClassNames.week_number\r\n ),\r\n day: cn(\r\n \"group/day relative aspect-square h-full w-full rounded-(--cell-radius) p-0 text-center select-none [&:last-child[data-selected=true]_button]:rounded-r-(--cell-radius)\",\r\n props.showWeekNumber\r\n ? \"[&:nth-child(2)[data-selected=true]_button]:rounded-l-(--cell-radius)\"\r\n : \"[&:first-child[data-selected=true]_button]:rounded-l-(--cell-radius)\",\r\n defaultClassNames.day\r\n ),\r\n range_start: cn(\r\n \"relative isolate z-0 rounded-l-(--cell-radius) bg-muted after:absolute after:inset-y-0 after:right-0 after:w-4 after:bg-muted\",\r\n defaultClassNames.range_start\r\n ),\r\n range_middle: cn(\"rounded-none\", defaultClassNames.range_middle),\r\n range_end: cn(\r\n \"relative isolate z-0 rounded-r-(--cell-radius) bg-muted after:absolute after:inset-y-0 after:left-0 after:w-4 after:bg-muted\",\r\n defaultClassNames.range_end\r\n ),\r\n today: cn(\r\n \"rounded-(--cell-radius) bg-muted text-foreground data-[selected=true]:rounded-none\",\r\n defaultClassNames.today\r\n ),\r\n outside: cn(\r\n \"text-muted-foreground aria-selected:text-muted-foreground\",\r\n defaultClassNames.outside\r\n ),\r\n disabled: cn(\r\n \"text-muted-foreground opacity-50\",\r\n defaultClassNames.disabled\r\n ),\r\n hidden: cn(\"invisible\", defaultClassNames.hidden),\r\n ...classNames,\r\n } as any}\r\n components={{\r\n Root: ({ className, rootRef, ...props }) => {\r\n return (\r\n <div\r\n data-slot=\"calendar\"\r\n ref={rootRef}\r\n className={cn(className)}\r\n {...props}\r\n />\r\n )\r\n },\r\n Chevron: ({ className, orientation, ...props }) => {\r\n if (orientation === \"left\") {\r\n return (\r\n <ChevronLeftIcon\r\n className={cn(\"cn-rtl-flip size-4\", className)}\r\n {...props}\r\n />\r\n )\r\n }\r\n\r\n if (orientation === \"right\") {\r\n return (\r\n <ChevronRightIcon\r\n className={cn(\"cn-rtl-flip size-4\", className)}\r\n {...props}\r\n />\r\n )\r\n }\r\n\r\n return (\r\n <ChevronDownIcon className={cn(\"size-4\", className)} {...props} />\r\n )\r\n },\r\n DayButton: ({ ...props }) => (\r\n <CalendarDayButton locale={locale} {...props} />\r\n ),\r\n WeekNumber: ({ children, ...props }) => {\r\n return (\r\n <td {...props}>\r\n <div className=\"flex size-(--cell-size) items-center justify-center text-center\">\r\n {children}\r\n </div>\r\n </td>\r\n )\r\n },\r\n ...components,\r\n }}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction CalendarDayButton({\r\n className,\r\n day,\r\n modifiers,\r\n locale,\r\n ...props\r\n}: React.ComponentProps<typeof DayButton> & { locale?: Partial<Locale> }) {\r\n const defaultClassNames = getDefaultClassNames()\r\n\r\n const ref = React.useRef<HTMLButtonElement>(null)\r\n React.useEffect(() => {\r\n if (modifiers.focused) ref.current?.focus()\r\n }, [modifiers.focused])\r\n\r\n return (\r\n <Button\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n data-day={day.date.toLocaleDateString(locale?.code)}\r\n data-selected-single={\r\n modifiers.selected &&\r\n !modifiers.range_start &&\r\n !modifiers.range_end &&\r\n !modifiers.range_middle\r\n }\r\n data-range-start={modifiers.range_start}\r\n data-range-end={modifiers.range_end}\r\n data-range-middle={modifiers.range_middle}\r\n className={cn(\r\n \"relative isolate z-10 flex aspect-square size-auto w-full min-w-(--cell-size) flex-col gap-1 border-0 leading-none font-normal group-data-[focused=true]/day:relative group-data-[focused=true]/day:z-10 group-data-[focused=true]/day:border-ring group-data-[focused=true]/day:ring-[3px] group-data-[focused=true]/day:ring-ring/50 data-[range-end=true]:rounded-(--cell-radius) data-[range-end=true]:rounded-r-(--cell-radius) data-[range-end=true]:bg-primary data-[range-end=true]:text-primary-foreground data-[range-middle=true]:rounded-none data-[range-middle=true]:bg-muted data-[range-middle=true]:text-foreground data-[range-start=true]:rounded-(--cell-radius) data-[range-start=true]:rounded-l-(--cell-radius) data-[range-start=true]:bg-primary data-[range-start=true]:text-primary-foreground data-[selected-single=true]:bg-primary data-[selected-single=true]:text-primary-foreground dark:hover:text-foreground [&>span]:text-xs [&>span]:opacity-70\",\r\n defaultClassNames.day,\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nexport { Calendar, CalendarDayButton }\r\n"
100
392
  }
101
393
  ]
102
394
  },
103
395
  {
104
396
  "name": "card",
397
+ "type": "components:ui",
398
+ "frameworks": [
399
+ "react",
400
+ "nextjs",
401
+ "vue",
402
+ "nuxt",
403
+ "solid",
404
+ "svelte",
405
+ "astro",
406
+ "remix"
407
+ ],
105
408
  "dependencies": [],
409
+ "registryDependencies": [],
106
410
  "files": [
107
411
  {
108
412
  "name": "card.tsx",
109
- "content": "import * as React from \"react\"\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nconst Card = React.forwardRef<\r\n HTMLDivElement,\r\n React.HTMLAttributes<HTMLDivElement>\r\n>(({ className, ...props }, ref) => (\r\n <div\r\n ref={ref}\r\n className={cn(\r\n \"rounded-xl border border-neutral-200 bg-white text-neutral-950 shadow-xs\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n))\r\nCard.displayName = \"Card\"\r\n\r\nconst CardHeader = React.forwardRef<\r\n HTMLDivElement,\r\n React.HTMLAttributes<HTMLDivElement>\r\n>(({ className, ...props }, ref) => (\r\n <div\r\n ref={ref}\r\n className={cn(\"flex flex-col space-y-1.5 p-6\", className)}\r\n {...props}\r\n />\r\n))\r\nCardHeader.displayName = \"CardHeader\"\r\n\r\nconst CardTitle = React.forwardRef<\r\n HTMLParagraphElement,\r\n React.HTMLAttributes<HTMLHeadingElement>\r\n>(({ className, ...props }, ref) => (\r\n <h3\r\n ref={ref}\r\n className={cn(\"font-semibold leading-none tracking-tight text-base\", className)}\r\n {...props}\r\n />\r\n))\r\nCardTitle.displayName = \"CardTitle\"\r\n\r\nconst CardDescription = React.forwardRef<\r\n HTMLParagraphElement,\r\n React.HTMLAttributes<HTMLParagraphElement>\r\n>(({ className, ...props }, ref) => (\r\n <p\r\n ref={ref}\r\n className={cn(\"text-sm text-neutral-500\", className)}\r\n {...props}\r\n />\r\n))\r\nCardDescription.displayName = \"CardDescription\"\r\n\r\nconst CardContent = React.forwardRef<\r\n HTMLDivElement,\r\n React.HTMLAttributes<HTMLDivElement>\r\n>(({ className, ...props }, ref) => (\r\n <div ref={ref} className={cn(\"p-6 pt-0\", className)} {...props} />\r\n))\r\nCardContent.displayName = \"CardContent\"\r\n\r\nconst CardFooter = React.forwardRef<\r\n HTMLDivElement,\r\n React.HTMLAttributes<HTMLDivElement>\r\n>(({ className, ...props }, ref) => (\r\n <div\r\n ref={ref}\r\n className={cn(\"flex items-center p-6 pt-0\", className)}\r\n {...props}\r\n />\r\n))\r\nCardFooter.displayName = \"CardFooter\"\r\n\r\nexport { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }"
413
+ "content": "import * as React from \"react\"\r\n\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nfunction Card({\r\n className,\r\n size = \"default\",\r\n ...props\r\n}: React.ComponentProps<\"div\"> & { size?: \"default\" | \"sm\" }) {\r\n return (\r\n <div\r\n data-slot=\"card\"\r\n data-size={size}\r\n className={cn(\r\n \"group/card flex flex-col gap-(--card-spacing) overflow-hidden rounded-xl bg-card py-(--card-spacing) text-sm text-card-foreground ring-1 ring-foreground/10 [--card-spacing:--spacing(4)] has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:[--card-spacing:--spacing(3)] data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction CardHeader({ className, ...props }: React.ComponentProps<\"div\">) {\r\n return (\r\n <div\r\n data-slot=\"card-header\"\r\n className={cn(\r\n \"group/card-header @container/card-header grid auto-rows-min items-start gap-1 rounded-t-xl px-(--card-spacing) has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-(--card-spacing)\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction CardTitle({ className, ...props }: React.ComponentProps<\"div\">) {\r\n return (\r\n <div\r\n data-slot=\"card-title\"\r\n className={cn(\r\n \"cn-font-heading text-base leading-snug font-medium group-data-[size=sm]/card:text-sm\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction CardDescription({ className, ...props }: React.ComponentProps<\"div\">) {\r\n return (\r\n <div\r\n data-slot=\"card-description\"\r\n className={cn(\"text-sm text-muted-foreground\", className)}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction CardAction({ className, ...props }: React.ComponentProps<\"div\">) {\r\n return (\r\n <div\r\n data-slot=\"card-action\"\r\n className={cn(\r\n \"col-start-2 row-span-2 row-start-1 self-start justify-self-end\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction CardContent({ className, ...props }: React.ComponentProps<\"div\">) {\r\n return (\r\n <div\r\n data-slot=\"card-content\"\r\n className={cn(\"px-(--card-spacing)\", className)}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction CardFooter({ className, ...props }: React.ComponentProps<\"div\">) {\r\n return (\r\n <div\r\n data-slot=\"card-footer\"\r\n className={cn(\r\n \"flex items-center rounded-b-xl border-t bg-muted/50 p-(--card-spacing)\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nexport {\r\n Card,\r\n CardHeader,\r\n CardFooter,\r\n CardTitle,\r\n CardAction,\r\n CardDescription,\r\n CardContent,\r\n}\r\n"
110
414
  }
111
415
  ]
112
416
  },
113
417
  {
114
418
  "name": "carousel",
419
+ "type": "components:ui",
420
+ "frameworks": [
421
+ "react",
422
+ "nextjs",
423
+ "vue",
424
+ "nuxt",
425
+ "solid",
426
+ "svelte",
427
+ "astro",
428
+ "remix"
429
+ ],
115
430
  "dependencies": [],
431
+ "registryDependencies": [],
116
432
  "files": [
117
433
  {
118
434
  "name": "carousel.tsx",
119
- "content": "\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport { cn } from \"@/lib/utils\"\r\n\r\ntype CarouselContextProps = {\r\n carouselRef: React.RefObject<HTMLDivElement | null>\r\n scrollPrev: () => void\r\n scrollNext: () => void\r\n canScrollPrev: boolean\r\n canScrollNext: boolean\r\n}\r\n\r\nconst CarouselContext = React.createContext<CarouselContextProps | null>(null)\r\n\r\nfunction useCarousel() {\r\n const context = React.useContext(CarouselContext)\r\n if (!context) throw new Error(\"useCarousel must be used within a CarouselProvider\")\r\n return context\r\n}\r\n\r\nconst Carousel = React.forwardRef<\r\n HTMLDivElement,\r\n React.HTMLAttributes<HTMLDivElement>\r\n>(({ className, children, ...props }, ref) => {\r\n const carouselRef = React.useRef<HTMLDivElement>(null)\r\n const [canScrollPrev, setCanScrollPrev] = React.useState(false)\r\n const [canScrollNext, setCanScrollNext] = React.useState(true)\r\n\r\n const checkScroll = React.useCallback(() => {\r\n if (!carouselRef.current) return\r\n const { scrollLeft, scrollWidth, clientWidth } = carouselRef.current\r\n setCanScrollPrev(scrollLeft > 0)\r\n setCanScrollNext(scrollLeft < scrollWidth - clientWidth - 1)\r\n }, [])\r\n\r\n React.useEffect(() => {\r\n const api = carouselRef.current\r\n if (!api) return\r\n api.addEventListener(\"scroll\", checkScroll, { passive: true })\r\n window.addEventListener(\"resize\", checkScroll)\r\n checkScroll()\r\n\r\n return () => {\r\n api.removeEventListener(\"scroll\", checkScroll)\r\n window.removeEventListener(\"resize\", checkScroll)\r\n }\r\n }, [checkScroll])\r\n\r\n const scrollPrev = React.useCallback(() => {\r\n carouselRef.current?.scrollBy({ left: -carouselRef.current.clientWidth, behavior: \"smooth\" })\r\n }, [])\r\n\r\n const scrollNext = React.useCallback(() => {\r\n carouselRef.current?.scrollBy({ left: carouselRef.current.clientWidth, behavior: \"smooth\" })\r\n }, [])\r\n\r\n return (\r\n <CarouselContext.Provider value={{ carouselRef, scrollPrev, scrollNext, canScrollPrev, canScrollNext }}>\r\n <div ref={ref} className={cn(\"relative w-full\", className)} role=\"region\" aria-roledescription=\"carousel\" {...props}>\r\n {children}\r\n </div>\r\n </CarouselContext.Provider>\r\n )\r\n})\r\nCarousel.displayName = \"Carousel\"\r\n\r\nconst CarouselContent = React.forwardRef<\r\n HTMLDivElement,\r\n React.HTMLAttributes<HTMLDivElement>\r\n>(({ className, ...props }, ref) => {\r\n const { carouselRef } = useCarousel()\r\n return (\r\n <div className=\"overflow-hidden\">\r\n <div\r\n ref={carouselRef}\r\n className={cn(\"flex snap-x snap-mandatory overflow-x-auto scrollbar-none gap-4 -ml-4\", className)}\r\n {...props}\r\n />\r\n </div>\r\n )\r\n})\r\nCarouselContent.displayName = \"CarouselContent\"\r\n\r\nconst CarouselItem = React.forwardRef<\r\n HTMLDivElement,\r\n React.HTMLAttributes<HTMLDivElement>\r\n>(({ className, ...props }, ref) => (\r\n <div\r\n ref={ref}\r\n role=\"group\"\r\n aria-roledescription=\"slide\"\r\n className={cn(\"min-w-0 shrink-0 grow-0 basis-full snap-start pl-4\", className)}\r\n {...props}\r\n />\r\n))\r\nCarouselItem.displayName = \"CarouselItem\"\r\n\r\nconst CarouselPrevious = React.forwardRef<\r\n HTMLButtonElement,\r\n React.ButtonHTMLAttributes<HTMLButtonElement>\r\n>(({ className, ...props }, ref) => {\r\n const { scrollPrev, canScrollPrev } = useCarousel()\r\n return (\r\n <button\r\n ref={ref}\r\n disabled={!canScrollPrev}\r\n onClick={scrollPrev}\r\n className={cn(\r\n \"absolute h-8 w-8 rounded-full border border-neutral-200 bg-white text-neutral-600 shadow-2xs inline-flex items-center justify-center left-4 top-1/2 -translate-y-1/2 disabled:opacity-30 cursor-pointer focus-visible:outline-hidden\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" fill=\"none\" viewBox=\"0 0 24 24\" strokeWidth=\"2\" stroke=\"currentColor\">\r\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M15.75 19.5L8.25 12l7.5-7.5\" />\r\n </svg>\r\n </button>\r\n )\r\n})\r\nCarouselPrevious.displayName = \"CarouselPrevious\"\r\n\r\nconst CarouselNext = React.forwardRef<\r\n HTMLButtonElement,\r\n React.ButtonHTMLAttributes<HTMLButtonElement>\r\n>(({ className, ...props }, ref) => {\r\n const { scrollNext, canScrollNext } = useCarousel()\r\n return (\r\n <button\r\n ref={ref}\r\n disabled={!canScrollNext}\r\n onClick={scrollNext}\r\n className={cn(\r\n \"absolute h-8 w-8 rounded-full border border-neutral-200 bg-white text-neutral-600 shadow-2xs inline-flex items-center justify-center right-4 top-1/2 -translate-y-1/2 disabled:opacity-30 cursor-pointer focus-visible:outline-hidden\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" fill=\"none\" viewBox=\"0 0 24 24\" strokeWidth=\"2\" stroke=\"currentColor\">\r\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M8.25 4.5l7.5 7.5-7.5 7.5\" />\r\n </svg>\r\n </button>\r\n )\r\n})\r\nCarouselNext.displayName = \"CarouselNext\"\r\n\r\nexport { Carousel, CarouselContent, CarouselItem, CarouselPrevious, CarouselNext }"
435
+ "content": "\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport useEmblaCarousel, {\r\n type UseEmblaCarouselType,\r\n} from \"embla-carousel-react\"\r\nimport { ChevronLeftIcon, ChevronRightIcon } from \"lucide-react\"\r\n\r\nimport { cn } from \"@/lib/utils\"\r\nimport { Button } from \"@/button\"\r\n\r\ntype CarouselApi = UseEmblaCarouselType[1]\r\ntype UseCarouselParameters = Parameters<typeof useEmblaCarousel>\r\ntype CarouselOptions = UseCarouselParameters[0]\r\ntype CarouselPlugin = UseCarouselParameters[1]\r\n\r\ntype CarouselProps = {\r\n opts?: CarouselOptions\r\n plugins?: CarouselPlugin\r\n orientation?: \"horizontal\" | \"vertical\"\r\n setApi?: (api: CarouselApi) => void\r\n}\r\n\r\ntype CarouselContextProps = {\r\n carouselRef: ReturnType<typeof useEmblaCarousel>[0]\r\n api: ReturnType<typeof useEmblaCarousel>[1]\r\n scrollPrev: () => void\r\n scrollNext: () => void\r\n canScrollPrev: boolean\r\n canScrollNext: boolean\r\n} & CarouselProps\r\n\r\nconst CarouselContext = React.createContext<CarouselContextProps | null>(null)\r\n\r\nfunction useCarousel() {\r\n const context = React.useContext(CarouselContext)\r\n\r\n if (!context) {\r\n throw new Error(\"useCarousel must be used within a <Carousel />\")\r\n }\r\n\r\n return context\r\n}\r\n\r\nfunction Carousel({\r\n orientation = \"horizontal\",\r\n opts,\r\n setApi,\r\n plugins,\r\n className,\r\n children,\r\n ...props\r\n}: React.ComponentProps<\"div\"> & CarouselProps) {\r\n const [carouselRef, api] = useEmblaCarousel(\r\n {\r\n ...opts,\r\n axis: orientation === \"horizontal\" ? \"x\" : \"y\",\r\n },\r\n plugins\r\n )\r\n const [canScrollPrev, setCanScrollPrev] = React.useState(false)\r\n const [canScrollNext, setCanScrollNext] = React.useState(false)\r\n\r\n const onSelect = React.useCallback((api: CarouselApi) => {\r\n if (!api) return\r\n setCanScrollPrev(api.canScrollPrev())\r\n setCanScrollNext(api.canScrollNext())\r\n }, [])\r\n\r\n const scrollPrev = React.useCallback(() => {\r\n api?.scrollPrev()\r\n }, [api])\r\n\r\n const scrollNext = React.useCallback(() => {\r\n api?.scrollNext()\r\n }, [api])\r\n\r\n const handleKeyDown = React.useCallback(\r\n (event: React.KeyboardEvent<HTMLDivElement>) => {\r\n if (event.key === \"ArrowLeft\") {\r\n event.preventDefault()\r\n scrollPrev()\r\n } else if (event.key === \"ArrowRight\") {\r\n event.preventDefault()\r\n scrollNext()\r\n }\r\n },\r\n [scrollPrev, scrollNext]\r\n )\r\n\r\n React.useEffect(() => {\r\n if (!api || !setApi) return\r\n setApi(api)\r\n }, [api, setApi])\r\n\r\n React.useEffect(() => {\r\n if (!api) return\r\n onSelect(api)\r\n api.on(\"reInit\", onSelect)\r\n api.on(\"select\", onSelect)\r\n\r\n return () => {\r\n api?.off(\"select\", onSelect)\r\n }\r\n }, [api, onSelect])\r\n\r\n return (\r\n <CarouselContext.Provider\r\n value={{\r\n carouselRef,\r\n api: api,\r\n opts,\r\n orientation:\r\n orientation || (opts?.axis === \"y\" ? \"vertical\" : \"horizontal\"),\r\n scrollPrev,\r\n scrollNext,\r\n canScrollPrev,\r\n canScrollNext,\r\n }}\r\n >\r\n <div\r\n onKeyDownCapture={handleKeyDown}\r\n className={cn(\"relative\", className)}\r\n role=\"region\"\r\n aria-roledescription=\"carousel\"\r\n data-slot=\"carousel\"\r\n {...props}\r\n >\r\n {children}\r\n </div>\r\n </CarouselContext.Provider>\r\n )\r\n}\r\n\r\nfunction CarouselContent({ className, ...props }: React.ComponentProps<\"div\">) {\r\n const { carouselRef, orientation } = useCarousel()\r\n\r\n return (\r\n <div\r\n ref={carouselRef}\r\n className=\"overflow-hidden\"\r\n data-slot=\"carousel-content\"\r\n >\r\n <div\r\n className={cn(\r\n \"flex\",\r\n orientation === \"horizontal\" ? \"-ml-4\" : \"-mt-4 flex-col\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n </div>\r\n )\r\n}\r\n\r\nfunction CarouselItem({ className, ...props }: React.ComponentProps<\"div\">) {\r\n const { orientation } = useCarousel()\r\n\r\n return (\r\n <div\r\n role=\"group\"\r\n aria-roledescription=\"slide\"\r\n data-slot=\"carousel-item\"\r\n className={cn(\r\n \"min-w-0 shrink-0 grow-0 basis-full\",\r\n orientation === \"horizontal\" ? \"pl-4\" : \"pt-4\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction CarouselPrevious({\r\n className,\r\n variant = \"outline\",\r\n size = \"icon-sm\",\r\n ...props\r\n}: React.ComponentProps<typeof Button>) {\r\n const { orientation, scrollPrev, canScrollPrev } = useCarousel()\r\n\r\n return (\r\n <Button\r\n data-slot=\"carousel-previous\"\r\n variant={variant}\r\n size={size}\r\n className={cn(\r\n \"absolute touch-manipulation rounded-full\",\r\n orientation === \"horizontal\"\r\n ? \"top-1/2 -left-12 -translate-y-1/2\"\r\n : \"-top-12 left-1/2 -translate-x-1/2 rotate-90\",\r\n className\r\n )}\r\n disabled={!canScrollPrev}\r\n onClick={scrollPrev}\r\n {...props}\r\n >\r\n <ChevronLeftIcon className=\"cn-rtl-flip\" />\r\n <span className=\"sr-only\">Previous slide</span>\r\n </Button>\r\n )\r\n}\r\n\r\nfunction CarouselNext({\r\n className,\r\n variant = \"outline\",\r\n size = \"icon-sm\",\r\n ...props\r\n}: React.ComponentProps<typeof Button>) {\r\n const { orientation, scrollNext, canScrollNext } = useCarousel()\r\n\r\n return (\r\n <Button\r\n data-slot=\"carousel-next\"\r\n variant={variant}\r\n size={size}\r\n className={cn(\r\n \"absolute touch-manipulation rounded-full\",\r\n orientation === \"horizontal\"\r\n ? \"top-1/2 -right-12 -translate-y-1/2\"\r\n : \"-bottom-12 left-1/2 -translate-x-1/2 rotate-90\",\r\n className\r\n )}\r\n disabled={!canScrollNext}\r\n onClick={scrollNext}\r\n {...props}\r\n >\r\n <ChevronRightIcon className=\"cn-rtl-flip\" />\r\n <span className=\"sr-only\">Next slide</span>\r\n </Button>\r\n )\r\n}\r\n\r\nexport {\r\n type CarouselApi,\r\n Carousel,\r\n CarouselContent,\r\n CarouselItem,\r\n CarouselPrevious,\r\n CarouselNext,\r\n useCarousel,\r\n}\r\n"
436
+ }
437
+ ]
438
+ },
439
+ {
440
+ "name": "chart",
441
+ "type": "components:ui",
442
+ "frameworks": [
443
+ "react",
444
+ "nextjs"
445
+ ],
446
+ "dependencies": [
447
+ "recharts",
448
+ "lucide-react"
449
+ ],
450
+ "registryDependencies": [],
451
+ "files": [
452
+ {
453
+ "name": "chart.tsx",
454
+ "content": "\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport * as RechartsPrimitive from \"recharts\"\r\nimport type { TooltipValueType } from \"recharts\"\r\n\r\nimport { cn } from \"@/lib/utils\"\r\n\r\n// Format: { THEME_NAME: CSS_SELECTOR }\r\nconst THEMES = { light: \"\", dark: \".dark\" } as const\r\n\r\nconst INITIAL_DIMENSION = { width: 320, height: 200 } as const\r\ntype TooltipNameType = number | string\r\n\r\nexport type ChartConfig = Record<\r\n string,\r\n {\r\n label?: React.ReactNode\r\n icon?: React.ComponentType\r\n } & (\r\n | { color?: string; theme?: never }\r\n | { color?: never; theme: Record<keyof typeof THEMES, string> }\r\n )\r\n>\r\n\r\ntype ChartContextProps = {\r\n config: ChartConfig\r\n}\r\n\r\nconst ChartContext = React.createContext<ChartContextProps | null>(null)\r\n\r\nfunction useChart() {\r\n const context = React.useContext(ChartContext)\r\n\r\n if (!context) {\r\n throw new Error(\"useChart must be used within a <ChartContainer />\")\r\n }\r\n\r\n return context\r\n}\r\n\r\nfunction ChartContainer({\r\n id,\r\n className,\r\n children,\r\n config,\r\n initialDimension = INITIAL_DIMENSION,\r\n ...props\r\n}: React.ComponentProps<\"div\"> & {\r\n config: ChartConfig\r\n children: React.ComponentProps<\r\n typeof RechartsPrimitive.ResponsiveContainer\r\n >[\"children\"]\r\n initialDimension?: {\r\n width: number\r\n height: number\r\n }\r\n}) {\r\n const uniqueId = React.useId()\r\n const chartId = `chart-${id ?? uniqueId.replace(/:/g, \"\")}`\r\n\r\n return (\r\n <ChartContext.Provider value={{ config }}>\r\n <div\r\n data-slot=\"chart\"\r\n data-chart={chartId}\r\n className={cn(\r\n \"flex aspect-video justify-center text-xs [&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-border/50 [&_.recharts-curve.recharts-tooltip-cursor]:stroke-border [&_.recharts-dot[stroke='#fff']]:stroke-transparent [&_.recharts-layer]:outline-hidden [&_.recharts-polar-grid_[stroke='#ccc']]:stroke-border [&_.recharts-radial-bar-background-sector]:fill-muted [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-muted [&_.recharts-reference-line_[stroke='#ccc']]:stroke-border [&_.recharts-sector]:outline-hidden [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-surface]:outline-hidden\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n <ChartStyle id={chartId} config={config} />\r\n <RechartsPrimitive.ResponsiveContainer\r\n initialDimension={initialDimension}\r\n >\r\n {children}\r\n </RechartsPrimitive.ResponsiveContainer>\r\n </div>\r\n </ChartContext.Provider>\r\n )\r\n}\r\n\r\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\r\n const colorConfig = Object.entries(config).filter(\r\n ([, config]) => config.theme ?? config.color\r\n )\r\n\r\n if (!colorConfig.length) {\r\n return null\r\n }\r\n\r\n return (\r\n <style\r\n dangerouslySetInnerHTML={{\r\n __html: Object.entries(THEMES)\r\n .map(\r\n ([theme, prefix]) => `\r\n${prefix} [data-chart=${id}] {\r\n${colorConfig\r\n .map(([key, itemConfig]) => {\r\n const color =\r\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??\r\n itemConfig.color\r\n return color ? ` --color-${key}: ${color};` : null\r\n })\r\n .join(\"\\n\")}\r\n}\r\n`\r\n )\r\n .join(\"\\n\"),\r\n }}\r\n />\r\n )\r\n}\r\n\r\nconst ChartTooltip = RechartsPrimitive.Tooltip\r\n\r\nfunction ChartTooltipContent({\r\n active,\r\n payload,\r\n className,\r\n indicator = \"dot\",\r\n hideLabel = false,\r\n hideIndicator = false,\r\n label,\r\n labelFormatter,\r\n labelClassName,\r\n formatter,\r\n color,\r\n nameKey,\r\n labelKey,\r\n}: React.ComponentProps<typeof RechartsPrimitive.Tooltip> &\r\n React.ComponentProps<\"div\"> & {\r\n hideLabel?: boolean\r\n hideIndicator?: boolean\r\n indicator?: \"line\" | \"dot\" | \"dashed\"\r\n nameKey?: string\r\n labelKey?: string\r\n } & Omit<\r\n RechartsPrimitive.DefaultTooltipContentProps<\r\n TooltipValueType,\r\n TooltipNameType\r\n >,\r\n \"accessibilityLayer\"\r\n >) {\r\n const { config } = useChart()\r\n\r\n const tooltipLabel = React.useMemo(() => {\r\n if (hideLabel || !payload?.length) {\r\n return null\r\n }\r\n\r\n const [item] = payload\r\n const key = `${labelKey ?? item?.dataKey ?? item?.name ?? \"value\"}`\r\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\r\n const value =\r\n !labelKey && typeof label === \"string\"\r\n ? (config[label]?.label ?? label)\r\n : itemConfig?.label\r\n\r\n if (labelFormatter) {\r\n return (\r\n <div className={cn(\"font-medium\", labelClassName)}>\r\n {labelFormatter(value, payload)}\r\n </div>\r\n )\r\n }\r\n\r\n if (!value) {\r\n return null\r\n }\r\n\r\n return <div className={cn(\"font-medium\", labelClassName)}>{value}</div>\r\n }, [\r\n label,\r\n labelFormatter,\r\n payload,\r\n hideLabel,\r\n labelClassName,\r\n config,\r\n labelKey,\r\n ])\r\n\r\n if (!active || !payload?.length) {\r\n return null\r\n }\r\n\r\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\r\n\r\n return (\r\n <div\r\n className={cn(\r\n \"grid min-w-32 items-start gap-1.5 rounded-lg border border-border/50 bg-background px-2.5 py-1.5 text-xs shadow-xl\",\r\n className\r\n )}\r\n >\r\n {!nestLabel ? tooltipLabel : null}\r\n <div className=\"grid gap-1.5\">\r\n {payload\r\n .filter((item) => item.type !== \"none\")\r\n .map((item, index) => {\r\n const key = `${nameKey ?? item.name ?? item.dataKey ?? \"value\"}`\r\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\r\n const indicatorColor = color ?? item.payload?.fill ?? item.color\r\n\r\n return (\r\n <div\r\n key={index}\r\n className={cn(\r\n \"flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\r\n indicator === \"dot\" && \"items-center\"\r\n )}\r\n >\r\n {formatter && item?.value !== undefined && item.name ? (\r\n formatter(item.value, item.name, item, index, item.payload)\r\n ) : (\r\n <>\r\n {itemConfig?.icon ? (\r\n <itemConfig.icon />\r\n ) : (\r\n !hideIndicator && (\r\n <div\r\n className={cn(\r\n \"shrink-0 rounded-[2px] border-(--color-border) bg-(--color-bg)\",\r\n {\r\n \"h-2.5 w-2.5\": indicator === \"dot\",\r\n \"w-1\": indicator === \"line\",\r\n \"w-0 border-[1.5px] border-dashed bg-transparent\":\r\n indicator === \"dashed\",\r\n \"my-0.5\": nestLabel && indicator === \"dashed\",\r\n }\r\n )}\r\n style={\r\n {\r\n \"--color-bg\": indicatorColor,\r\n \"--color-border\": indicatorColor,\r\n } as React.CSSProperties\r\n }\r\n />\r\n )\r\n )}\r\n <div\r\n className={cn(\r\n \"flex flex-1 justify-between leading-none\",\r\n nestLabel ? \"items-end\" : \"items-center\"\r\n )}\r\n >\r\n <div className=\"grid gap-1.5\">\r\n {nestLabel ? tooltipLabel : null}\r\n <span className=\"text-muted-foreground\">\r\n {itemConfig?.label ?? item.name}\r\n </span>\r\n </div>\r\n {item.value != null && (\r\n <span className=\"font-mono font-medium text-foreground tabular-nums\">\r\n {typeof item.value === \"number\"\r\n ? item.value.toLocaleString()\r\n : String(item.value)}\r\n </span>\r\n )}\r\n </div>\r\n </>\r\n )}\r\n </div>\r\n )\r\n })}\r\n </div>\r\n </div>\r\n )\r\n}\r\n\r\nconst ChartLegend = RechartsPrimitive.Legend\r\n\r\nfunction ChartLegendContent({\r\n className,\r\n hideIcon = false,\r\n payload,\r\n verticalAlign = \"bottom\",\r\n nameKey,\r\n}: React.ComponentProps<\"div\"> & {\r\n hideIcon?: boolean\r\n nameKey?: string\r\n} & RechartsPrimitive.DefaultLegendContentProps) {\r\n const { config } = useChart()\r\n\r\n if (!payload?.length) {\r\n return null\r\n }\r\n\r\n return (\r\n <div\r\n className={cn(\r\n \"flex items-center justify-center gap-4\",\r\n verticalAlign === \"top\" ? \"pb-3\" : \"pt-3\",\r\n className\r\n )}\r\n >\r\n {payload\r\n .filter((item) => item.type !== \"none\")\r\n .map((item, index) => {\r\n const key = `${nameKey ?? item.dataKey ?? \"value\"}`\r\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\r\n\r\n return (\r\n <div\r\n key={index}\r\n className={cn(\r\n \"flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\r\n )}\r\n >\r\n {itemConfig?.icon && !hideIcon ? (\r\n <itemConfig.icon />\r\n ) : (\r\n <div\r\n className=\"h-2 w-2 shrink-0 rounded-[2px]\"\r\n style={{\r\n backgroundColor: item.color,\r\n }}\r\n />\r\n )}\r\n {itemConfig?.label}\r\n </div>\r\n )\r\n })}\r\n </div>\r\n )\r\n}\r\n\r\nfunction getPayloadConfigFromPayload(\r\n config: ChartConfig,\r\n payload: unknown,\r\n key: string\r\n) {\r\n if (typeof payload !== \"object\" || payload === null) {\r\n return undefined\r\n }\r\n\r\n const payloadPayload =\r\n \"payload\" in payload &&\r\n typeof payload.payload === \"object\" &&\r\n payload.payload !== null\r\n ? payload.payload\r\n : undefined\r\n\r\n let configLabelKey: string = key\r\n\r\n if (\r\n key in payload &&\r\n typeof payload[key as keyof typeof payload] === \"string\"\r\n ) {\r\n configLabelKey = payload[key as keyof typeof payload] as string\r\n } else if (\r\n payloadPayload &&\r\n key in payloadPayload &&\r\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\r\n ) {\r\n configLabelKey = payloadPayload[\r\n key as keyof typeof payloadPayload\r\n ] as string\r\n }\r\n\r\n return configLabelKey in config ? config[configLabelKey] : config[key]\r\n}\r\n\r\nexport {\r\n ChartContainer,\r\n ChartTooltip,\r\n ChartTooltipContent,\r\n ChartLegend,\r\n ChartLegendContent,\r\n ChartStyle,\r\n}\r\n"
120
455
  }
121
456
  ]
122
457
  },
123
458
  {
124
459
  "name": "checkbox",
460
+ "type": "components:ui",
461
+ "frameworks": [
462
+ "react",
463
+ "nextjs",
464
+ "vue",
465
+ "nuxt",
466
+ "solid",
467
+ "svelte",
468
+ "astro",
469
+ "remix"
470
+ ],
125
471
  "dependencies": [
126
472
  "@base-ui/react"
127
473
  ],
474
+ "registryDependencies": [],
128
475
  "files": [
129
476
  {
130
477
  "name": "checkbox.tsx",
131
- "content": "\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport { Checkbox as BaseCheckbox } from \"@base-ui/react/checkbox\"\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nconst Checkbox = React.forwardRef<\r\n HTMLButtonElement,\r\n React.ComponentPropsWithoutRef<typeof BaseCheckbox.Root>\r\n>(({ className, ...props }, ref) => (\r\n <BaseCheckbox.Root\r\n ref={ref}\r\n className={cn(\r\n \"group peer h-4 w-4 shrink-0 rounded-sm border border-neutral-300 bg-white transition-all cursor-pointer\",\r\n \"focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-neutral-950 focus-visible:ring-offset-2\",\r\n \"disabled:cursor-not-allowed disabled:opacity-50\",\r\n \"data-[checked]:bg-neutral-900 data-[checked]:border-neutral-900\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n <BaseCheckbox.Indicator className=\"flex items-center justify-center text-white transition-transform duration-100 data-[starting-style]:scale-50\">\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n fill=\"none\"\r\n viewBox=\"0 0 24 24\"\r\n strokeWidth=\"3\"\r\n stroke=\"currentColor\"\r\n className=\"h-3 w-3\"\r\n >\r\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M4.5 12.75l6 6 9-13.5\" />\r\n </svg>\r\n </BaseCheckbox.Indicator>\r\n </BaseCheckbox.Root>\r\n))\r\nCheckbox.displayName = \"Checkbox\"\r\n\r\nexport { Checkbox }"
478
+ "content": "\"use client\"\r\n\r\nimport { Checkbox as CheckboxPrimitive } from \"@base-ui/react/checkbox\"\r\nimport { CheckIcon } from \"lucide-react\"\r\n\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nfunction Checkbox({ className, ...props }: CheckboxPrimitive.Root.Props) {\r\n return (\r\n <CheckboxPrimitive.Root\r\n data-slot=\"checkbox\"\r\n className={cn(\r\n \"peer relative flex size-4 shrink-0 items-center justify-center rounded-[4px] border border-input transition-colors outline-none group-has-disabled/field:opacity-50 after:absolute after:-inset-x-3 after:-inset-y-2 focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 aria-invalid:aria-checked:border-primary dark:bg-input/30 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 data-checked:border-primary data-checked:bg-primary data-checked:text-primary-foreground dark:data-checked:bg-primary\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n <CheckboxPrimitive.Indicator\r\n data-slot=\"checkbox-indicator\"\r\n className=\"grid place-content-center text-current transition-none [&>svg]:size-3.5\"\r\n >\r\n <CheckIcon />\r\n </CheckboxPrimitive.Indicator>\r\n </CheckboxPrimitive.Root>\r\n )\r\n}\r\n\r\nexport { Checkbox }\r\n"
132
479
  }
133
480
  ]
134
481
  },
135
482
  {
136
483
  "name": "collapsible",
484
+ "type": "components:ui",
485
+ "frameworks": [
486
+ "react",
487
+ "nextjs",
488
+ "vue",
489
+ "nuxt",
490
+ "solid",
491
+ "svelte",
492
+ "astro",
493
+ "remix"
494
+ ],
137
495
  "dependencies": [
138
496
  "@base-ui/react"
139
497
  ],
498
+ "registryDependencies": [],
140
499
  "files": [
141
500
  {
142
501
  "name": "collapsible.tsx",
143
- "content": "\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport { Collapsible as BaseCollapsible } from \"@base-ui/react/collapsible\"\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nconst Collapsible = BaseCollapsible.Root\r\n\r\nconst CollapsibleTrigger = BaseCollapsible.Trigger\r\n\r\nconst CollapsibleContent = React.forwardRef<\r\n HTMLDivElement,\r\n React.ComponentPropsWithoutRef<typeof BaseCollapsible.Panel>\r\n>(({ className, ...props }, ref) => (\r\n <BaseCollapsible.Panel\r\n ref={ref}\r\n className={cn(\r\n \"overflow-hidden transition-all animate-collapsible-up data-[open]:animate-collapsible-down\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n))\r\nCollapsibleContent.displayName = \"CollapsibleContent\"\r\n\r\nexport { Collapsible, CollapsibleTrigger, CollapsibleContent }"
502
+ "content": "\"use client\"\r\n\r\nimport { Collapsible as CollapsiblePrimitive } from \"@base-ui/react/collapsible\"\r\n\r\nfunction Collapsible({ ...props }: CollapsiblePrimitive.Root.Props) {\r\n return <CollapsiblePrimitive.Root data-slot=\"collapsible\" {...props} />\r\n}\r\n\r\nfunction CollapsibleTrigger({ ...props }: CollapsiblePrimitive.Trigger.Props) {\r\n return (\r\n <CollapsiblePrimitive.Trigger data-slot=\"collapsible-trigger\" {...props} />\r\n )\r\n}\r\n\r\nfunction CollapsibleContent({ ...props }: CollapsiblePrimitive.Panel.Props) {\r\n return (\r\n <CollapsiblePrimitive.Panel data-slot=\"collapsible-content\" {...props} />\r\n )\r\n}\r\n\r\nexport { Collapsible, CollapsibleTrigger, CollapsibleContent }\r\n"
144
503
  }
145
504
  ]
146
505
  },
147
506
  {
148
507
  "name": "context-menu",
508
+ "type": "components:ui",
509
+ "frameworks": [
510
+ "react",
511
+ "nextjs",
512
+ "vue",
513
+ "nuxt",
514
+ "solid",
515
+ "svelte",
516
+ "astro",
517
+ "remix"
518
+ ],
149
519
  "dependencies": [
150
520
  "@base-ui/react"
151
521
  ],
522
+ "registryDependencies": [],
152
523
  "files": [
153
524
  {
154
525
  "name": "context-menu.tsx",
155
- "content": "\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport { Menu as BaseMenu } from \"@base-ui/react/menu\"\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nconst ContextMenu = ({\r\n children,\r\n ...props\r\n}: React.ComponentPropsWithoutRef<typeof BaseMenu.Root>) => {\r\n const [open, setOpen] = React.useState(false)\r\n const [coords, setCoords] = React.useState({ x: 0, y: 0 })\r\n\r\n const handleContextMenu = React.useCallback((e: React.MouseEvent) => {\r\n e.preventDefault()\r\n setCoords({ x: e.clientX, y: e.clientY })\r\n setOpen(true)\r\n }, [])\r\n\r\n return (\r\n <div onContextMenu={handleContextMenu} className=\"w-full h-full\">\r\n <BaseMenu.Root open={open} onOpenChange={setOpen} {...props}>\r\n {/* Custom anchor positioning matrix matching right-click clients coordinates */}\r\n <BaseMenu.Anchor\r\n style={{\r\n position: \"fixed\",\r\n left: coords.x,\r\n top: coords.y,\r\n width: 1,\r\n height: 1,\r\n }}\r\n />\r\n {children}\r\n </BaseMenu.Root>\r\n </div>\r\n )\r\n}\r\n\r\nconst ContextMenuTrigger = ({ children }: { children: React.ReactNode }) => children\r\n\r\nconst ContextMenuPortal = BaseMenu.Portal\r\n\r\nconst ContextMenuContent = React.forwardRef<\r\n HTMLDivElement,\r\n React.ComponentPropsWithoutRef<typeof BaseMenu.Popup>\r\n>(({ className, ...props }, ref) => (\r\n <BaseMenu.Positioner side=\"bottom\" align=\"start\">\r\n <BaseMenu.Popup\r\n ref={ref}\r\n className={cn(\r\n \"z-50 min-w-[8rem] overflow-hidden rounded-lg border border-neutral-200 bg-white p-1 text-neutral-950 shadow-md outline-hidden transition-all duration-100 ease-out\",\r\n \"data-[starting-style]:scale-95 data-[starting-style]:opacity-0\",\r\n \"data-[ending-style]:scale-95 data-[ending-style]:opacity-0\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n </BaseMenu.Positioner>\r\n))\r\nContextMenuContent.displayName = \"ContextMenuContent\"\r\n\r\nconst ContextMenuItem = React.forwardRef<\r\n HTMLDivElement,\r\n React.ComponentPropsWithoutRef<typeof BaseMenu.Item>\r\n>(({ className, ...props }, ref) => (\r\n <BaseMenu.Item\r\n ref={ref}\r\n className={cn(\r\n \"relative flex cursor-default select-none items-center rounded-md px-2 py-1.5 text-sm outline-hidden transition-colors cursor-pointer\",\r\n \"data-[highlighted]:bg-neutral-100 data-[highlighted]:text-neutral-900\",\r\n \"data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n))\r\nContextMenuItem.displayName = \"ContextMenuItem\"\r\n\r\nexport {\r\n ContextMenu,\r\n ContextMenuTrigger,\r\n ContextMenuPortal,\r\n ContextMenuContent,\r\n ContextMenuItem,\r\n}"
526
+ "content": "\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport { ContextMenu as ContextMenuPrimitive } from \"@base-ui/react/context-menu\"\r\nimport { CheckIcon, ChevronRightIcon } from \"lucide-react\"\r\n\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nfunction ContextMenu({ ...props }: ContextMenuPrimitive.Root.Props) {\r\n return <ContextMenuPrimitive.Root data-slot=\"context-menu\" {...props} />\r\n}\r\n\r\nfunction ContextMenuPortal({ ...props }: ContextMenuPrimitive.Portal.Props) {\r\n return (\r\n <ContextMenuPrimitive.Portal data-slot=\"context-menu-portal\" {...props} />\r\n )\r\n}\r\n\r\nfunction ContextMenuTrigger({\r\n className,\r\n ...props\r\n}: ContextMenuPrimitive.Trigger.Props) {\r\n return (\r\n <ContextMenuPrimitive.Trigger\r\n data-slot=\"context-menu-trigger\"\r\n className={cn(\"select-none\", className)}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction ContextMenuContent({\r\n className,\r\n align = \"start\",\r\n alignOffset = 4,\r\n side = \"right\",\r\n sideOffset = 0,\r\n ...props\r\n}: ContextMenuPrimitive.Popup.Props &\r\n Pick<\r\n ContextMenuPrimitive.Positioner.Props,\r\n \"align\" | \"alignOffset\" | \"side\" | \"sideOffset\"\r\n >) {\r\n return (\r\n <ContextMenuPrimitive.Portal>\r\n <ContextMenuPrimitive.Positioner\r\n className=\"isolate z-50 outline-none\"\r\n align={align}\r\n alignOffset={alignOffset}\r\n side={side}\r\n sideOffset={sideOffset}\r\n >\r\n <ContextMenuPrimitive.Popup\r\n data-slot=\"context-menu-content\"\r\n className={cn(\"z-50 max-h-(--available-height) min-w-36 origin-(--transform-origin) overflow-x-hidden overflow-y-auto rounded-lg bg-popover p-1 text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 outline-none data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95\", className )}\r\n {...props}\r\n />\r\n </ContextMenuPrimitive.Positioner>\r\n </ContextMenuPrimitive.Portal>\r\n )\r\n}\r\n\r\nfunction ContextMenuGroup({ ...props }: ContextMenuPrimitive.Group.Props) {\r\n return (\r\n <ContextMenuPrimitive.Group data-slot=\"context-menu-group\" {...props} />\r\n )\r\n}\r\n\r\nfunction ContextMenuLabel({\r\n className,\r\n inset,\r\n ...props\r\n}: ContextMenuPrimitive.GroupLabel.Props & {\r\n inset?: boolean\r\n}) {\r\n return (\r\n <ContextMenuPrimitive.GroupLabel\r\n data-slot=\"context-menu-label\"\r\n data-inset={inset}\r\n className={cn(\r\n \"px-1.5 py-1 text-xs font-medium text-muted-foreground data-inset:pl-7\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction ContextMenuItem({\r\n className,\r\n inset,\r\n variant = \"default\",\r\n ...props\r\n}: ContextMenuPrimitive.Item.Props & {\r\n inset?: boolean\r\n variant?: \"default\" | \"destructive\"\r\n}) {\r\n return (\r\n <ContextMenuPrimitive.Item\r\n data-slot=\"context-menu-item\"\r\n data-inset={inset}\r\n data-variant={variant}\r\n className={cn(\r\n \"group/context-menu-item relative flex cursor-default items-center gap-1.5 rounded-md px-1.5 py-1 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-inset:pl-7 data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive dark:data-[variant=destructive]:focus:bg-destructive/20 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 focus:*:[svg]:text-accent-foreground data-[variant=destructive]:*:[svg]:text-destructive\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction ContextMenuSub({ ...props }: ContextMenuPrimitive.SubmenuRoot.Props) {\r\n return (\r\n <ContextMenuPrimitive.SubmenuRoot data-slot=\"context-menu-sub\" {...props} />\r\n )\r\n}\r\n\r\nfunction ContextMenuSubTrigger({\r\n className,\r\n inset,\r\n children,\r\n ...props\r\n}: ContextMenuPrimitive.SubmenuTrigger.Props & {\r\n inset?: boolean\r\n}) {\r\n return (\r\n <ContextMenuPrimitive.SubmenuTrigger\r\n data-slot=\"context-menu-sub-trigger\"\r\n data-inset={inset}\r\n className={cn(\r\n \"flex cursor-default items-center gap-1.5 rounded-md px-1.5 py-1 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-inset:pl-7 data-open:bg-accent data-open:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n {children}\r\n <ChevronRightIcon className=\"cn-rtl-flip ml-auto\" />\r\n </ContextMenuPrimitive.SubmenuTrigger>\r\n )\r\n}\r\n\r\nfunction ContextMenuSubContent({\r\n ...props\r\n}: React.ComponentProps<typeof ContextMenuContent>) {\r\n return (\r\n <ContextMenuContent\r\n data-slot=\"context-menu-sub-content\"\r\n className=\"shadow-lg\"\r\n side=\"right\"\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction ContextMenuCheckboxItem({\r\n className,\r\n children,\r\n checked,\r\n inset,\r\n ...props\r\n}: ContextMenuPrimitive.CheckboxItem.Props & {\r\n inset?: boolean\r\n}) {\r\n return (\r\n <ContextMenuPrimitive.CheckboxItem\r\n data-slot=\"context-menu-checkbox-item\"\r\n data-inset={inset}\r\n className={cn(\r\n \"relative flex cursor-default items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-inset:pl-7 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\r\n className\r\n )}\r\n checked={checked}\r\n {...props}\r\n >\r\n <span className=\"pointer-events-none absolute right-2\">\r\n <ContextMenuPrimitive.CheckboxItemIndicator>\r\n <CheckIcon />\r\n </ContextMenuPrimitive.CheckboxItemIndicator>\r\n </span>\r\n {children}\r\n </ContextMenuPrimitive.CheckboxItem>\r\n )\r\n}\r\n\r\nfunction ContextMenuRadioGroup({\r\n ...props\r\n}: ContextMenuPrimitive.RadioGroup.Props) {\r\n return (\r\n <ContextMenuPrimitive.RadioGroup\r\n data-slot=\"context-menu-radio-group\"\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction ContextMenuRadioItem({\r\n className,\r\n children,\r\n inset,\r\n ...props\r\n}: ContextMenuPrimitive.RadioItem.Props & {\r\n inset?: boolean\r\n}) {\r\n return (\r\n <ContextMenuPrimitive.RadioItem\r\n data-slot=\"context-menu-radio-item\"\r\n data-inset={inset}\r\n className={cn(\r\n \"relative flex cursor-default items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-inset:pl-7 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n <span className=\"pointer-events-none absolute right-2\">\r\n <ContextMenuPrimitive.RadioItemIndicator>\r\n <CheckIcon />\r\n </ContextMenuPrimitive.RadioItemIndicator>\r\n </span>\r\n {children}\r\n </ContextMenuPrimitive.RadioItem>\r\n )\r\n}\r\n\r\nfunction ContextMenuSeparator({\r\n className,\r\n ...props\r\n}: ContextMenuPrimitive.Separator.Props) {\r\n return (\r\n <ContextMenuPrimitive.Separator\r\n data-slot=\"context-menu-separator\"\r\n className={cn(\"-mx-1 my-1 h-px bg-border\", className)}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction ContextMenuShortcut({\r\n className,\r\n ...props\r\n}: React.ComponentProps<\"span\">) {\r\n return (\r\n <span\r\n data-slot=\"context-menu-shortcut\"\r\n className={cn(\r\n \"ml-auto text-xs tracking-widest text-muted-foreground group-focus/context-menu-item:text-accent-foreground\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nexport {\r\n ContextMenu,\r\n ContextMenuTrigger,\r\n ContextMenuContent,\r\n ContextMenuItem,\r\n ContextMenuCheckboxItem,\r\n ContextMenuRadioItem,\r\n ContextMenuLabel,\r\n ContextMenuSeparator,\r\n ContextMenuShortcut,\r\n ContextMenuGroup,\r\n ContextMenuPortal,\r\n ContextMenuSub,\r\n ContextMenuSubContent,\r\n ContextMenuSubTrigger,\r\n ContextMenuRadioGroup,\r\n}\r\n"
156
527
  }
157
528
  ]
158
529
  },
159
530
  {
160
531
  "name": "dialog",
532
+ "type": "components:ui",
533
+ "frameworks": [
534
+ "react",
535
+ "nextjs",
536
+ "vue",
537
+ "nuxt",
538
+ "solid",
539
+ "svelte",
540
+ "astro",
541
+ "remix"
542
+ ],
161
543
  "dependencies": [
162
544
  "@base-ui/react"
163
545
  ],
546
+ "registryDependencies": [],
164
547
  "files": [
165
548
  {
166
549
  "name": "dialog.tsx",
167
- "content": "\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport { Dialog as BaseDialog } from \"@base-ui/react/dialog\"\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nconst Dialog = BaseDialog.Root\r\n\r\nconst DialogTrigger = BaseDialog.Trigger\r\n\r\nconst DialogPortal = BaseDialog.Portal\r\n\r\nconst DialogBackdrop = React.forwardRef<\r\n HTMLDivElement,\r\n React.ComponentPropsWithoutRef<typeof BaseDialog.Backdrop>\r\n>(({ className, ...props }, ref) => (\r\n <BaseDialog.Backdrop\r\n ref={ref}\r\n className={cn(\r\n \"fixed inset-0 min-h-dvh bg-black/40 backdrop-blur-xs transition-opacity duration-200\",\r\n \"data-[starting-style]:opacity-0 data-[ending-style]:opacity-0\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n))\r\nDialogBackdrop.displayName = \"DialogBackdrop\"\r\n\r\nconst DialogPopup = React.forwardRef<\r\n HTMLDivElement,\r\n React.ComponentPropsWithoutRef<typeof BaseDialog.Popup>\r\n>(({ className, ...props }, ref) => (\r\n <BaseDialog.Popup\r\n ref={ref}\r\n className={cn(\r\n \"fixed top-1/2 left-1/2 w-full max-w-lg -translate-x-1/2 -translate-y-1/2 rounded-xl border border-neutral-200 bg-white p-6 shadow-xl text-neutral-950 transition-all duration-200 ease-out\",\r\n // Modern Base UI entry/exit animation attributes\r\n \"data-[starting-style]:scale-95 data-[starting-style]:opacity-0\",\r\n \"data-[ending-style]:scale-95 data-[ending-style]:opacity-0\",\r\n // Handle automatic visual scaling when nested inside another open modal\r\n \"scale-[calc(1-0.04*var(--nested-dialogs))]\",\r\n \"translate-y-[calc(-50%+1.25rem*var(--nested-dialogs))]\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n))\r\nDialogPopup.displayName = \"DialogPopup\"\r\n\r\nconst DialogHeader = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (\r\n <div className={cn(\"flex flex-col gap-1 text-center sm:text-left mb-4\", className)} {...props} />\r\n)\r\nDialogHeader.displayName = \"DialogHeader\"\r\n\r\nconst DialogFooter = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (\r\n <div className={cn(\"flex flex-col-reverse sm:flex-row sm:justify-end gap-2 mt-6\", className)} {...props} />\r\n)\r\nDialogFooter.displayName = \"DialogFooter\"\r\n\r\nconst DialogTitle = React.forwardRef<\r\n HTMLHeadingElement,\r\n React.ComponentPropsWithoutRef<typeof BaseDialog.Title>\r\n>(({ className, ...props }, ref) => (\r\n <BaseDialog.Title\r\n ref={ref}\r\n className={cn(\"text-lg font-semibold tracking-tight leading-none\", className)}\r\n {...props}\r\n />\r\n))\r\nDialogTitle.displayName = \"DialogTitle\"\r\n\r\nconst DialogDescription = React.forwardRef<\r\n HTMLParagraphElement,\r\n React.ComponentPropsWithoutRef<typeof BaseDialog.Description>\r\n>(({ className, ...props }, ref) => (\r\n <BaseDialog.Description\r\n ref={ref}\r\n className={cn(\"text-sm text-neutral-500\", className)}\r\n {...props}\r\n />\r\n))\r\nDialogDescription.displayName = \"DialogDescription\"\r\n\r\nconst DialogClose = BaseDialog.Close\r\n\r\nexport {\r\n Dialog,\r\n DialogTrigger,\r\n DialogPortal,\r\n DialogBackdrop,\r\n DialogPopup,\r\n DialogHeader,\r\n DialogFooter,\r\n DialogTitle,\r\n DialogDescription,\r\n DialogClose,\r\n}"
550
+ "content": "\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport { Dialog as DialogPrimitive } from \"@base-ui/react/dialog\"\r\nimport { XIcon } from \"lucide-react\"\r\n\r\nimport { cn } from \"@/lib/utils\"\r\nimport { Button } from \"@/button\"\r\n\r\nfunction Dialog({ ...props }: DialogPrimitive.Root.Props) {\r\n return <DialogPrimitive.Root data-slot=\"dialog\" {...props} />\r\n}\r\n\r\nfunction DialogTrigger({ ...props }: DialogPrimitive.Trigger.Props) {\r\n return <DialogPrimitive.Trigger data-slot=\"dialog-trigger\" {...props} />\r\n}\r\n\r\nfunction DialogPortal({ ...props }: DialogPrimitive.Portal.Props) {\r\n return <DialogPrimitive.Portal data-slot=\"dialog-portal\" {...props} />\r\n}\r\n\r\nfunction DialogClose({ ...props }: DialogPrimitive.Close.Props) {\r\n return <DialogPrimitive.Close data-slot=\"dialog-close\" {...props} />\r\n}\r\n\r\nfunction DialogOverlay({\r\n className,\r\n ...props\r\n}: DialogPrimitive.Backdrop.Props) {\r\n return (\r\n <DialogPrimitive.Backdrop\r\n data-slot=\"dialog-overlay\"\r\n className={cn(\r\n \"fixed inset-0 isolate z-50 bg-black/10 duration-100 supports-backdrop-filter:backdrop-blur-xs data-open:animate-in data-open:fade-in-0 data-closed:animate-out data-closed:fade-out-0\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction DialogContent({\r\n className,\r\n children,\r\n showCloseButton = true,\r\n ...props\r\n}: DialogPrimitive.Popup.Props & {\r\n showCloseButton?: boolean\r\n}) {\r\n return (\r\n <DialogPortal>\r\n <DialogOverlay />\r\n <DialogPrimitive.Popup\r\n data-slot=\"dialog-content\"\r\n className={cn(\r\n \"fixed top-1/2 left-1/2 z-50 grid w-full max-w-[calc(100%-2rem)] -translate-x-1/2 -translate-y-1/2 gap-4 rounded-xl bg-popover p-4 text-sm text-popover-foreground ring-1 ring-foreground/10 duration-100 outline-none sm:max-w-sm data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n {children}\r\n {showCloseButton && (\r\n <DialogPrimitive.Close data-slot=\"dialog-close\" render={<Button variant=\"ghost\" className=\"absolute top-2 right-2\" size=\"icon-sm\"><XIcon /><span className=\"sr-only\">Close</span></Button>} />\r\n )}\r\n </DialogPrimitive.Popup>\r\n </DialogPortal>\r\n )\r\n}\r\n\r\nfunction DialogHeader({ className, ...props }: React.ComponentProps<\"div\">) {\r\n return (\r\n <div\r\n data-slot=\"dialog-header\"\r\n className={cn(\"flex flex-col gap-2\", className)}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction DialogFooter({\r\n className,\r\n showCloseButton = false,\r\n children,\r\n ...props\r\n}: React.ComponentProps<\"div\"> & {\r\n showCloseButton?: boolean\r\n}) {\r\n return (\r\n <div\r\n data-slot=\"dialog-footer\"\r\n className={cn(\r\n \"-mx-4 -mb-4 flex flex-col-reverse gap-2 rounded-b-xl border-t bg-muted/50 p-4 sm:flex-row sm:justify-end\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n {children}\r\n {showCloseButton && (\r\n <DialogPrimitive.Close render={<Button variant=\"outline\">Close</Button>} />\r\n )}\r\n </div>\r\n )\r\n}\r\n\r\nfunction DialogTitle({ className, ...props }: DialogPrimitive.Title.Props) {\r\n return (\r\n <DialogPrimitive.Title\r\n data-slot=\"dialog-title\"\r\n className={cn(\r\n \"cn-font-heading text-base leading-none font-medium\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction DialogDescription({\r\n className,\r\n ...props\r\n}: DialogPrimitive.Description.Props) {\r\n return (\r\n <DialogPrimitive.Description\r\n data-slot=\"dialog-description\"\r\n className={cn(\r\n \"text-sm text-muted-foreground *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nexport {\r\n Dialog,\r\n DialogClose,\r\n DialogContent,\r\n DialogDescription,\r\n DialogFooter,\r\n DialogHeader,\r\n DialogOverlay,\r\n DialogPortal,\r\n DialogTitle,\r\n DialogTrigger,\r\n}\r\n"
168
551
  }
169
552
  ]
170
553
  },
171
554
  {
172
555
  "name": "drawer",
556
+ "type": "components:ui",
557
+ "frameworks": [
558
+ "react",
559
+ "nextjs",
560
+ "vue",
561
+ "nuxt",
562
+ "solid",
563
+ "svelte",
564
+ "astro",
565
+ "remix"
566
+ ],
173
567
  "dependencies": [
174
568
  "@base-ui/react"
175
569
  ],
570
+ "registryDependencies": [],
176
571
  "files": [
177
572
  {
178
573
  "name": "drawer.tsx",
179
- "content": "\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport { Dialog as BaseDialog } from \"@base-ui/react/dialog\"\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nconst Drawer = BaseDialog.Root\r\n\r\nconst DrawerTrigger = BaseDialog.Trigger\r\n\r\nconst DrawerPortal = BaseDialog.Portal\r\n\r\nconst DrawerBackdrop = React.forwardRef<\r\n HTMLDivElement,\r\n React.ComponentPropsWithoutRef<typeof BaseDialog.Backdrop>\r\n>(({ className, ...props }, ref) => (\r\n <BaseDialog.Backdrop\r\n ref={ref}\r\n className={cn(\r\n \"fixed inset-0 z-50 bg-black/40 backdrop-blur-xs transition-opacity duration-300\",\r\n \"data-[starting-style]:opacity-0 data-[ending-style]:opacity-0\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n))\r\nDrawerBackdrop.displayName = \"DrawerBackdrop\"\r\n\r\nconst DrawerContent = React.forwardRef<\r\n HTMLDivElement,\r\n React.ComponentPropsWithoutRef<typeof BaseDialog.Popup> & { side?: \"left\" | \"right\" }\r\n>(({ className, side = \"right\", ...props }, ref) => (\r\n <BaseDialog.Popup\r\n ref={ref}\r\n className={cn(\r\n \"fixed z-50 bg-white p-6 shadow-xl text-neutral-950 transition-transform duration-300 ease-in-out h-full w-full max-w-sm top-0 bottom-0\",\r\n side === \"right\" && \"right-0 data-[starting-style]:translate-x-full data-[ending-style]:translate-x-full border-l border-neutral-200\",\r\n side === \"left\" && \"left-0 data-[starting-style]:-translate-x-full data-[ending-style]:-translate-x-full border-r border-neutral-200\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n))\r\nDrawerContent.displayName = \"DrawerContent\"\r\n\r\nconst DrawerClose = BaseDialog.Close\r\n\r\nexport { Drawer, DrawerTrigger, DrawerPortal, DrawerBackdrop, DrawerContent, DrawerClose }"
574
+ "content": "\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport { Drawer as DrawerPrimitive } from \"vaul\"\r\n\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nfunction Drawer({\r\n ...props\r\n}: React.ComponentProps<typeof DrawerPrimitive.Root>) {\r\n return <DrawerPrimitive.Root data-slot=\"drawer\" {...props} />\r\n}\r\n\r\nfunction DrawerTrigger({\r\n ...props\r\n}: React.ComponentProps<typeof DrawerPrimitive.Trigger>) {\r\n return <DrawerPrimitive.Trigger data-slot=\"drawer-trigger\" {...props} />\r\n}\r\n\r\nfunction DrawerPortal({\r\n ...props\r\n}: React.ComponentProps<typeof DrawerPrimitive.Portal>) {\r\n return <DrawerPrimitive.Portal data-slot=\"drawer-portal\" {...props} />\r\n}\r\n\r\nfunction DrawerClose({\r\n ...props\r\n}: React.ComponentProps<typeof DrawerPrimitive.Close>) {\r\n return <DrawerPrimitive.Close data-slot=\"drawer-close\" {...props} />\r\n}\r\n\r\nfunction DrawerOverlay({\r\n className,\r\n ...props\r\n}: React.ComponentProps<typeof DrawerPrimitive.Overlay>) {\r\n return (\r\n <DrawerPrimitive.Overlay\r\n data-slot=\"drawer-overlay\"\r\n className={cn(\r\n \"fixed inset-0 z-50 bg-black/10 supports-backdrop-filter:backdrop-blur-xs data-open:animate-in data-open:fade-in-0 data-closed:animate-out data-closed:fade-out-0\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction DrawerContent({\r\n className,\r\n children,\r\n ...props\r\n}: React.ComponentProps<typeof DrawerPrimitive.Content>) {\r\n return (\r\n <DrawerPortal data-slot=\"drawer-portal\">\r\n <DrawerOverlay />\r\n <DrawerPrimitive.Content\r\n data-slot=\"drawer-content\"\r\n className={cn(\r\n \"group/drawer-content fixed z-50 flex h-auto flex-col bg-popover text-sm text-popover-foreground data-[vaul-drawer-direction=bottom]:inset-x-0 data-[vaul-drawer-direction=bottom]:bottom-0 data-[vaul-drawer-direction=bottom]:mt-24 data-[vaul-drawer-direction=bottom]:max-h-[80vh] data-[vaul-drawer-direction=bottom]:rounded-t-xl data-[vaul-drawer-direction=bottom]:border-t data-[vaul-drawer-direction=left]:inset-y-0 data-[vaul-drawer-direction=left]:left-0 data-[vaul-drawer-direction=left]:w-3/4 data-[vaul-drawer-direction=left]:rounded-r-xl data-[vaul-drawer-direction=left]:border-r data-[vaul-drawer-direction=right]:inset-y-0 data-[vaul-drawer-direction=right]:right-0 data-[vaul-drawer-direction=right]:w-3/4 data-[vaul-drawer-direction=right]:rounded-l-xl data-[vaul-drawer-direction=right]:border-l data-[vaul-drawer-direction=top]:inset-x-0 data-[vaul-drawer-direction=top]:top-0 data-[vaul-drawer-direction=top]:mb-24 data-[vaul-drawer-direction=top]:max-h-[80vh] data-[vaul-drawer-direction=top]:rounded-b-xl data-[vaul-drawer-direction=top]:border-b data-[vaul-drawer-direction=left]:sm:max-w-sm data-[vaul-drawer-direction=right]:sm:max-w-sm\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n <div className=\"mx-auto mt-4 hidden h-1 w-[100px] shrink-0 rounded-full bg-muted group-data-[vaul-drawer-direction=bottom]/drawer-content:block\" />\r\n {children}\r\n </DrawerPrimitive.Content>\r\n </DrawerPortal>\r\n )\r\n}\r\n\r\nfunction DrawerHeader({ className, ...props }: React.ComponentProps<\"div\">) {\r\n return (\r\n <div\r\n data-slot=\"drawer-header\"\r\n className={cn(\r\n \"flex flex-col gap-0.5 p-4 group-data-[vaul-drawer-direction=bottom]/drawer-content:text-center group-data-[vaul-drawer-direction=top]/drawer-content:text-center md:gap-0.5 md:text-left\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction DrawerFooter({ className, ...props }: React.ComponentProps<\"div\">) {\r\n return (\r\n <div\r\n data-slot=\"drawer-footer\"\r\n className={cn(\"mt-auto flex flex-col gap-2 p-4\", className)}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction DrawerTitle({\r\n className,\r\n ...props\r\n}: React.ComponentProps<typeof DrawerPrimitive.Title>) {\r\n return (\r\n <DrawerPrimitive.Title\r\n data-slot=\"drawer-title\"\r\n className={cn(\r\n \"cn-font-heading text-base font-medium text-foreground\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction DrawerDescription({\r\n className,\r\n ...props\r\n}: React.ComponentProps<typeof DrawerPrimitive.Description>) {\r\n return (\r\n <DrawerPrimitive.Description\r\n data-slot=\"drawer-description\"\r\n className={cn(\"text-sm text-muted-foreground\", className)}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nexport {\r\n Drawer,\r\n DrawerPortal,\r\n DrawerOverlay,\r\n DrawerTrigger,\r\n DrawerClose,\r\n DrawerContent,\r\n DrawerHeader,\r\n DrawerFooter,\r\n DrawerTitle,\r\n DrawerDescription,\r\n}\r\n"
180
575
  }
181
576
  ]
182
577
  },
183
578
  {
184
579
  "name": "dropdown-menu",
580
+ "type": "components:ui",
581
+ "frameworks": [
582
+ "react",
583
+ "nextjs",
584
+ "vue",
585
+ "nuxt",
586
+ "solid",
587
+ "svelte",
588
+ "astro",
589
+ "remix"
590
+ ],
185
591
  "dependencies": [
186
592
  "@base-ui/react"
187
593
  ],
594
+ "registryDependencies": [],
188
595
  "files": [
189
596
  {
190
597
  "name": "dropdown-menu.tsx",
191
- "content": "\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport { Menu as BaseMenu } from \"@base-ui/react/menu\"\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nconst DropdownMenu = BaseMenu.Root\r\n\r\nconst DropdownMenuTrigger = BaseMenu.Trigger\r\n\r\nconst DropdownMenuPortal = BaseMenu.Portal\r\n\r\ntype DropdownMenuContentProps = React.ComponentPropsWithoutRef<typeof BaseMenu.Popup> & {\r\n sideOffset?: number\r\n}\r\n\r\nconst DropdownMenuContent = React.forwardRef<\r\n HTMLDivElement,\r\n DropdownMenuContentProps\r\n>(({ className, sideOffset = 4, ...props }, ref) => (\r\n <BaseMenu.Positioner sideOffset={sideOffset}>\r\n <BaseMenu.Popup\r\n ref={ref}\r\n className={cn(\r\n \"z-50 min-w-[8rem] overflow-hidden rounded-lg border border-neutral-200 bg-white p-1 text-neutral-950 shadow-md outline-hidden transition-all duration-100 ease-out\",\r\n \"data-[starting-style]:scale-95 data-[starting-style]:opacity-0\",\r\n \"data-[ending-style]:scale-95 data-[ending-style]:opacity-0\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n </BaseMenu.Positioner>\r\n))\r\nDropdownMenuContent.displayName = \"DropdownMenuContent\"\r\n\r\nconst DropdownMenuItem = React.forwardRef<\r\n HTMLDivElement,\r\n React.ComponentPropsWithoutRef<typeof BaseMenu.Item>\r\n>(({ className, ...props }, ref) => (\r\n <BaseMenu.Item\r\n ref={ref}\r\n className={cn(\r\n \"relative flex cursor-default select-none items-center rounded-md px-2 py-1.5 text-sm outline-hidden transition-colors cursor-pointer\",\r\n \"data-[highlighted]:bg-neutral-100 data-[highlighted]:text-neutral-900\",\r\n \"data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n))\r\nDropdownMenuItem.displayName = \"DropdownMenuItem\"\r\n\r\nexport {\r\n DropdownMenu,\r\n DropdownMenuTrigger,\r\n DropdownMenuPortal,\r\n DropdownMenuContent,\r\n DropdownMenuItem,\r\n}"
598
+ "content": "\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport { Menu as MenuPrimitive } from \"@base-ui/react/menu\"\r\nimport { CheckIcon, ChevronRightIcon } from \"lucide-react\"\r\n\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nfunction DropdownMenu({ ...props }: MenuPrimitive.Root.Props) {\r\n return <MenuPrimitive.Root data-slot=\"dropdown-menu\" {...props} />\r\n}\r\n\r\nfunction DropdownMenuPortal({ ...props }: MenuPrimitive.Portal.Props) {\r\n return <MenuPrimitive.Portal data-slot=\"dropdown-menu-portal\" {...props} />\r\n}\r\n\r\nfunction DropdownMenuTrigger({ ...props }: MenuPrimitive.Trigger.Props) {\r\n return <MenuPrimitive.Trigger data-slot=\"dropdown-menu-trigger\" {...props} />\r\n}\r\n\r\nfunction DropdownMenuContent({\r\n align = \"start\",\r\n alignOffset = 0,\r\n side = \"bottom\",\r\n sideOffset = 4,\r\n className,\r\n ...props\r\n}: MenuPrimitive.Popup.Props &\r\n Pick<\r\n MenuPrimitive.Positioner.Props,\r\n \"align\" | \"alignOffset\" | \"side\" | \"sideOffset\"\r\n >) {\r\n return (\r\n <MenuPrimitive.Portal>\r\n <MenuPrimitive.Positioner\r\n className=\"isolate z-50 outline-none\"\r\n align={align}\r\n alignOffset={alignOffset}\r\n side={side}\r\n sideOffset={sideOffset}\r\n >\r\n <MenuPrimitive.Popup\r\n data-slot=\"dropdown-menu-content\"\r\n className={cn(\"z-50 max-h-(--available-height) w-(--anchor-width) min-w-32 origin-(--transform-origin) overflow-x-hidden overflow-y-auto rounded-lg bg-popover p-1 text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 outline-none data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:overflow-hidden data-closed:fade-out-0 data-closed:zoom-out-95\", className )}\r\n {...props}\r\n />\r\n </MenuPrimitive.Positioner>\r\n </MenuPrimitive.Portal>\r\n )\r\n}\r\n\r\nfunction DropdownMenuGroup({ ...props }: MenuPrimitive.Group.Props) {\r\n return <MenuPrimitive.Group data-slot=\"dropdown-menu-group\" {...props} />\r\n}\r\n\r\nfunction DropdownMenuLabel({\r\n className,\r\n inset,\r\n ...props\r\n}: MenuPrimitive.GroupLabel.Props & {\r\n inset?: boolean\r\n}) {\r\n return (\r\n <MenuPrimitive.GroupLabel\r\n data-slot=\"dropdown-menu-label\"\r\n data-inset={inset}\r\n className={cn(\r\n \"px-1.5 py-1 text-xs font-medium text-muted-foreground data-inset:pl-7\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction DropdownMenuItem({\r\n className,\r\n inset,\r\n variant = \"default\",\r\n ...props\r\n}: MenuPrimitive.Item.Props & {\r\n inset?: boolean\r\n variant?: \"default\" | \"destructive\"\r\n}) {\r\n return (\r\n <MenuPrimitive.Item\r\n data-slot=\"dropdown-menu-item\"\r\n data-inset={inset}\r\n data-variant={variant}\r\n className={cn(\r\n \"group/dropdown-menu-item relative flex cursor-default items-center gap-1.5 rounded-md px-1.5 py-1 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-inset:pl-7 data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive dark:data-[variant=destructive]:focus:bg-destructive/20 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 data-[variant=destructive]:*:[svg]:text-destructive\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction DropdownMenuSub({ ...props }: MenuPrimitive.SubmenuRoot.Props) {\r\n return <MenuPrimitive.SubmenuRoot data-slot=\"dropdown-menu-sub\" {...props} />\r\n}\r\n\r\nfunction DropdownMenuSubTrigger({\r\n className,\r\n inset,\r\n children,\r\n ...props\r\n}: MenuPrimitive.SubmenuTrigger.Props & {\r\n inset?: boolean\r\n}) {\r\n return (\r\n <MenuPrimitive.SubmenuTrigger\r\n data-slot=\"dropdown-menu-sub-trigger\"\r\n data-inset={inset}\r\n className={cn(\r\n \"flex cursor-default items-center gap-1.5 rounded-md px-1.5 py-1 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-inset:pl-7 data-popup-open:bg-accent data-popup-open:text-accent-foreground data-open:bg-accent data-open:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n {children}\r\n <ChevronRightIcon className=\"cn-rtl-flip ml-auto\" />\r\n </MenuPrimitive.SubmenuTrigger>\r\n )\r\n}\r\n\r\nfunction DropdownMenuSubContent({\r\n align = \"start\",\r\n alignOffset = -3,\r\n side = \"right\",\r\n sideOffset = 0,\r\n className,\r\n ...props\r\n}: React.ComponentProps<typeof DropdownMenuContent>) {\r\n return (\r\n <DropdownMenuContent\r\n data-slot=\"dropdown-menu-sub-content\"\r\n className={cn(\"w-auto min-w-[96px] rounded-lg bg-popover p-1 text-popover-foreground shadow-lg ring-1 ring-foreground/10 duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95\", className )}\r\n align={align}\r\n alignOffset={alignOffset}\r\n side={side}\r\n sideOffset={sideOffset}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction DropdownMenuCheckboxItem({\r\n className,\r\n children,\r\n checked,\r\n inset,\r\n ...props\r\n}: MenuPrimitive.CheckboxItem.Props & {\r\n inset?: boolean\r\n}) {\r\n return (\r\n <MenuPrimitive.CheckboxItem\r\n data-slot=\"dropdown-menu-checkbox-item\"\r\n data-inset={inset}\r\n className={cn(\r\n \"relative flex cursor-default items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground data-inset:pl-7 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\r\n className\r\n )}\r\n checked={checked}\r\n {...props}\r\n >\r\n <span\r\n className=\"pointer-events-none absolute right-2 flex items-center justify-center\"\r\n data-slot=\"dropdown-menu-checkbox-item-indicator\"\r\n >\r\n <MenuPrimitive.CheckboxItemIndicator>\r\n <CheckIcon />\r\n </MenuPrimitive.CheckboxItemIndicator>\r\n </span>\r\n {children}\r\n </MenuPrimitive.CheckboxItem>\r\n )\r\n}\r\n\r\nfunction DropdownMenuRadioGroup({ ...props }: MenuPrimitive.RadioGroup.Props) {\r\n return (\r\n <MenuPrimitive.RadioGroup\r\n data-slot=\"dropdown-menu-radio-group\"\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction DropdownMenuRadioItem({\r\n className,\r\n children,\r\n inset,\r\n ...props\r\n}: MenuPrimitive.RadioItem.Props & {\r\n inset?: boolean\r\n}) {\r\n return (\r\n <MenuPrimitive.RadioItem\r\n data-slot=\"dropdown-menu-radio-item\"\r\n data-inset={inset}\r\n className={cn(\r\n \"relative flex cursor-default items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground data-inset:pl-7 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n <span\r\n className=\"pointer-events-none absolute right-2 flex items-center justify-center\"\r\n data-slot=\"dropdown-menu-radio-item-indicator\"\r\n >\r\n <MenuPrimitive.RadioItemIndicator>\r\n <CheckIcon />\r\n </MenuPrimitive.RadioItemIndicator>\r\n </span>\r\n {children}\r\n </MenuPrimitive.RadioItem>\r\n )\r\n}\r\n\r\nfunction DropdownMenuSeparator({\r\n className,\r\n ...props\r\n}: MenuPrimitive.Separator.Props) {\r\n return (\r\n <MenuPrimitive.Separator\r\n data-slot=\"dropdown-menu-separator\"\r\n className={cn(\"-mx-1 my-1 h-px bg-border\", className)}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction DropdownMenuShortcut({\r\n className,\r\n ...props\r\n}: React.ComponentProps<\"span\">) {\r\n return (\r\n <span\r\n data-slot=\"dropdown-menu-shortcut\"\r\n className={cn(\r\n \"ml-auto text-xs tracking-widest text-muted-foreground group-focus/dropdown-menu-item:text-accent-foreground\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nexport {\r\n DropdownMenu,\r\n DropdownMenuPortal,\r\n DropdownMenuTrigger,\r\n DropdownMenuContent,\r\n DropdownMenuGroup,\r\n DropdownMenuLabel,\r\n DropdownMenuItem,\r\n DropdownMenuCheckboxItem,\r\n DropdownMenuRadioGroup,\r\n DropdownMenuRadioItem,\r\n DropdownMenuSeparator,\r\n DropdownMenuShortcut,\r\n DropdownMenuSub,\r\n DropdownMenuSubTrigger,\r\n DropdownMenuSubContent,\r\n}\r\n"
192
599
  }
193
600
  ]
194
601
  },
195
602
  {
196
603
  "name": "hover-card",
604
+ "type": "components:ui",
605
+ "frameworks": [
606
+ "react",
607
+ "nextjs",
608
+ "vue",
609
+ "nuxt",
610
+ "solid",
611
+ "svelte",
612
+ "astro",
613
+ "remix"
614
+ ],
197
615
  "dependencies": [
198
616
  "@base-ui/react"
199
617
  ],
618
+ "registryDependencies": [],
200
619
  "files": [
201
620
  {
202
621
  "name": "hover-card.tsx",
203
- "content": "\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport { Popover as BasePopover } from \"@base-ui/react/popover\"\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nconst HoverCard = ({\r\n children,\r\n openDelay = 200,\r\n closeDelay = 200,\r\n ...props\r\n}: React.ComponentPropsWithoutRef<typeof BasePopover.Root> & {\r\n openDelay?: number\r\n closeDelay?: number\r\n}) => {\r\n const [open, setOpen] = React.useState(false)\r\n const openTimeout = React.useRef<ReturnType<typeof setTimeout> | null>(null)\r\n const closeTimeout = React.useRef<ReturnType<typeof setTimeout> | null>(null)\r\n\r\n const handleOpen = React.useCallback(() => {\r\n if (closeTimeout.current) clearTimeout(closeTimeout.current)\r\n openTimeout.current = setTimeout(() => setOpen(true), openDelay)\r\n }, [openDelay])\r\n\r\n const handleClose = React.useCallback(() => {\r\n if (openTimeout.current) clearTimeout(openTimeout.current)\r\n closeTimeout.current = setTimeout(() => setOpen(false), closeDelay)\r\n }, [closeDelay])\r\n\r\n React.useEffect(() => {\r\n return () => {\r\n if (openTimeout.current) clearTimeout(openTimeout.current)\r\n if (closeTimeout.current) clearTimeout(closeTimeout.current)\r\n }\r\n }, [])\r\n\r\n return (\r\n <BasePopover.Root open={open} onOpenChange={setOpen} {...props}>\r\n {React.isValidElement(children)\r\n ? React.cloneElement(children, {\r\n onMouseEnter: handleOpen,\r\n onMouseLeave: handleClose,\r\n } as React.HTMLAttributes<HTMLElement>)\r\n : children}\r\n </BasePopover.Root>\r\n )\r\n}\r\n\r\nconst HoverCardTrigger = React.forwardRef<\r\n HTMLButtonElement,\r\n React.ComponentPropsWithoutRef<typeof BasePopover.Trigger>\r\n>(({ className, ...props }, ref) => (\r\n <BasePopover.Trigger\r\n ref={ref}\r\n className={cn(\"inline-block cursor-pointer\", className)}\r\n {...props}\r\n />\r\n))\r\nHoverCardTrigger.displayName = \"HoverCardTrigger\"\r\n\r\nconst HoverCardPortal = BasePopover.Portal\r\n\r\ninterface HoverCardContentProps extends React.ComponentPropsWithoutRef<typeof BasePopover.Popup> {\r\n sideOffset?: number\r\n align?: \"start\" | \"center\" | \"end\"\r\n}\r\n\r\nconst HoverCardContent = React.forwardRef<\r\n HTMLDivElement,\r\n HoverCardContentProps\r\n>(({ className, align = \"center\", sideOffset = 8, ...props }, ref) => (\r\n <BasePopover.Positioner sideOffset={sideOffset} align={align}>\r\n <BasePopover.Popup\r\n ref={ref}\r\n className={cn(\r\n // Stylized to mirror our clean standalone Card architecture\r\n \"z-50 w-64 rounded-xl border border-neutral-200 bg-white p-4 text-neutral-950 shadow-md outline-hidden transition-all duration-150 ease-out pointer-events-auto\",\r\n \"data-[starting-style]:scale-95 data-[starting-style]:opacity-0\",\r\n \"data-[ending-style]:scale-95 data-[ending-style]:opacity-0\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n </BasePopover.Positioner>\r\n))\r\nHoverCardContent.displayName = \"HoverCardContent\"\r\n\r\nexport { HoverCard, HoverCardTrigger, HoverCardPortal, HoverCardContent }"
622
+ "content": "\"use client\"\r\n\r\nimport { PreviewCard as PreviewCardPrimitive } from \"@base-ui/react/preview-card\"\r\n\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nfunction HoverCard({ ...props }: PreviewCardPrimitive.Root.Props) {\r\n return <PreviewCardPrimitive.Root data-slot=\"hover-card\" {...props} />\r\n}\r\n\r\nfunction HoverCardTrigger({ ...props }: PreviewCardPrimitive.Trigger.Props) {\r\n return (\r\n <PreviewCardPrimitive.Trigger data-slot=\"hover-card-trigger\" {...props} />\r\n )\r\n}\r\n\r\nfunction HoverCardContent({\r\n className,\r\n side = \"bottom\",\r\n sideOffset = 4,\r\n align = \"center\",\r\n alignOffset = 4,\r\n ...props\r\n}: PreviewCardPrimitive.Popup.Props &\r\n Pick<\r\n PreviewCardPrimitive.Positioner.Props,\r\n \"align\" | \"alignOffset\" | \"side\" | \"sideOffset\"\r\n >) {\r\n return (\r\n <PreviewCardPrimitive.Portal data-slot=\"hover-card-portal\">\r\n <PreviewCardPrimitive.Positioner\r\n align={align}\r\n alignOffset={alignOffset}\r\n side={side}\r\n sideOffset={sideOffset}\r\n className=\"isolate z-50\"\r\n >\r\n <PreviewCardPrimitive.Popup\r\n data-slot=\"hover-card-content\"\r\n className={cn(\r\n \"z-50 w-64 origin-(--transform-origin) rounded-lg bg-popover p-2.5 text-sm text-popover-foreground shadow-md ring-1 ring-foreground/10 outline-hidden duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n </PreviewCardPrimitive.Positioner>\r\n </PreviewCardPrimitive.Portal>\r\n )\r\n}\r\n\r\nexport { HoverCard, HoverCardTrigger, HoverCardContent }\r\n"
204
623
  }
205
624
  ]
206
625
  },
207
626
  {
208
627
  "name": "input-group",
628
+ "type": "components:ui",
629
+ "frameworks": [
630
+ "react",
631
+ "nextjs",
632
+ "vue",
633
+ "nuxt",
634
+ "solid",
635
+ "svelte",
636
+ "astro",
637
+ "remix"
638
+ ],
209
639
  "dependencies": [],
640
+ "registryDependencies": [],
210
641
  "files": [
211
642
  {
212
643
  "name": "input-group.tsx",
213
- "content": "import * as React from \"react\"\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nconst InputGroup = React.forwardRef<\r\n HTMLDivElement,\r\n React.HTMLAttributes<HTMLDivElement>\r\n>(({ className, ...props }, ref) => (\r\n <div\r\n ref={ref}\r\n className={cn(\r\n \"relative flex items-center w-full shadow-2xs rounded-md border border-neutral-200 bg-white focus-within:border-neutral-900 focus-within:ring-1 focus-within:ring-neutral-900 transition-all\",\r\n \"[&>input]:border-0 [&>input]:focus-visible:ring-0 [&>input]:shadow-none\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n))\r\nInputGroup.displayName = \"InputGroup\"\r\n\r\nconst InputGroupText = React.forwardRef<\r\n HTMLSpanElement,\r\n React.HTMLAttributes<HTMLSpanElement>\r\n>(({ className, ...props }, ref) => (\r\n <span\r\n ref={ref}\r\n className={cn(\r\n \"flex items-center px-3 text-sm text-neutral-500 bg-neutral-50 border-r border-neutral-200 h-10 select-none font-medium\",\r\n \"first:rounded-l-md last:rounded-r-md last:border-r-0\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n))\r\nInputGroupText.displayName = \"InputGroupText\"\r\n\r\nexport { InputGroup, InputGroupText }"
644
+ "content": "\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport { cva, type VariantProps } from \"class-variance-authority\"\r\n\r\nimport { cn } from \"@/lib/utils\"\r\nimport { Button } from \"@/button\"\r\nimport { Input } from \"@/input\"\r\nimport { Textarea } from \"@/textarea\"\r\n\r\nfunction InputGroup({ className, ...props }: React.ComponentProps<\"div\">) {\r\n return (\r\n <div\r\n data-slot=\"input-group\"\r\n role=\"group\"\r\n className={cn(\r\n \"group/input-group relative flex h-8 w-full min-w-0 items-center rounded-lg border border-input transition-colors outline-none in-data-[slot=combobox-content]:focus-within:border-inherit in-data-[slot=combobox-content]:focus-within:ring-0 has-disabled:bg-input/50 has-disabled:opacity-50 has-[[data-slot=input-group-control]:focus-visible]:border-ring has-[[data-slot=input-group-control]:focus-visible]:ring-3 has-[[data-slot=input-group-control]:focus-visible]:ring-ring/50 has-[[data-slot][aria-invalid=true]]:border-destructive has-[[data-slot][aria-invalid=true]]:ring-3 has-[[data-slot][aria-invalid=true]]:ring-destructive/20 has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>textarea]:h-auto dark:bg-input/30 dark:has-disabled:bg-input/80 dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40 has-[>[data-align=block-end]]:[&>input]:pt-3 has-[>[data-align=block-start]]:[&>input]:pb-3 has-[>[data-align=inline-end]]:[&>input]:pr-1.5 has-[>[data-align=inline-start]]:[&>input]:pl-1.5\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nconst inputGroupAddonVariants = cva(\r\n \"flex h-auto cursor-text items-center justify-center gap-2 py-1.5 text-sm font-medium text-muted-foreground select-none group-data-[disabled=true]/input-group:opacity-50 [&>kbd]:rounded-[calc(var(--radius)-5px)] [&>svg:not([class*='size-'])]:size-4\",\r\n {\r\n variants: {\r\n align: {\r\n \"inline-start\":\r\n \"order-first pl-2 has-[>button]:ml-[-0.3rem] has-[>kbd]:ml-[-0.15rem]\",\r\n \"inline-end\":\r\n \"order-last pr-2 has-[>button]:mr-[-0.3rem] has-[>kbd]:mr-[-0.15rem]\",\r\n \"block-start\":\r\n \"order-first w-full justify-start px-2.5 pt-2 group-has-[>input]/input-group:pt-2 [.border-b]:pb-2\",\r\n \"block-end\":\r\n \"order-last w-full justify-start px-2.5 pb-2 group-has-[>input]/input-group:pb-2 [.border-t]:pt-2\",\r\n },\r\n },\r\n defaultVariants: {\r\n align: \"inline-start\",\r\n },\r\n }\r\n)\r\n\r\nfunction InputGroupAddon({\r\n className,\r\n align = \"inline-start\",\r\n ...props\r\n}: React.ComponentProps<\"div\"> & VariantProps<typeof inputGroupAddonVariants>) {\r\n return (\r\n <div\r\n role=\"group\"\r\n data-slot=\"input-group-addon\"\r\n data-align={align}\r\n className={cn(inputGroupAddonVariants({ align }), className)}\r\n onClick={(e) => {\r\n if ((e.target as HTMLElement).closest(\"button\")) {\r\n return\r\n }\r\n e.currentTarget.parentElement?.querySelector(\"input\")?.focus()\r\n }}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nconst inputGroupButtonVariants = cva(\r\n \"flex items-center gap-2 text-sm shadow-none\",\r\n {\r\n variants: {\r\n size: {\r\n xs: \"h-6 gap-1 rounded-[calc(var(--radius)-3px)] px-1.5 [&>svg:not([class*='size-'])]:size-3.5\",\r\n sm: \"\",\r\n \"icon-xs\":\r\n \"size-6 rounded-[calc(var(--radius)-3px)] p-0 has-[>svg]:p-0\",\r\n \"icon-sm\": \"size-8 p-0 has-[>svg]:p-0\",\r\n },\r\n },\r\n defaultVariants: {\r\n size: \"xs\",\r\n },\r\n }\r\n)\r\n\r\nfunction InputGroupButton({\r\n className,\r\n type = \"button\",\r\n variant = \"ghost\",\r\n size = \"xs\",\r\n ...props\r\n}: Omit<React.ComponentProps<typeof Button>, \"size\" | \"type\"> &\r\n VariantProps<typeof inputGroupButtonVariants> & {\r\n type?: \"button\" | \"submit\" | \"reset\"\r\n }) {\r\n return (\r\n <Button\r\n type={type}\r\n data-size={size}\r\n variant={variant}\r\n className={cn(inputGroupButtonVariants({ size }), className)}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction InputGroupText({ className, ...props }: React.ComponentProps<\"span\">) {\r\n return (\r\n <span\r\n className={cn(\r\n \"flex items-center gap-2 text-sm text-muted-foreground [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction InputGroupInput({\r\n className,\r\n ...props\r\n}: React.ComponentProps<\"input\">) {\r\n return (\r\n <Input\r\n data-slot=\"input-group-control\"\r\n className={cn(\r\n \"flex-1 rounded-none border-0 bg-transparent shadow-none ring-0 focus-visible:ring-0 disabled:bg-transparent aria-invalid:ring-0 dark:bg-transparent dark:disabled:bg-transparent\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction InputGroupTextarea({\r\n className,\r\n ...props\r\n}: React.ComponentProps<\"textarea\">) {\r\n return (\r\n <Textarea\r\n data-slot=\"input-group-control\"\r\n className={cn(\r\n \"flex-1 resize-none rounded-none border-0 bg-transparent py-2 shadow-none ring-0 focus-visible:ring-0 disabled:bg-transparent aria-invalid:ring-0 dark:bg-transparent dark:disabled:bg-transparent\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nexport {\r\n InputGroup,\r\n InputGroupAddon,\r\n InputGroupButton,\r\n InputGroupText,\r\n InputGroupInput,\r\n InputGroupTextarea,\r\n}\r\n"
214
645
  }
215
646
  ]
216
647
  },
217
648
  {
218
649
  "name": "input-otp",
650
+ "type": "components:ui",
651
+ "frameworks": [
652
+ "react",
653
+ "nextjs",
654
+ "vue",
655
+ "nuxt",
656
+ "solid",
657
+ "svelte",
658
+ "astro",
659
+ "remix"
660
+ ],
219
661
  "dependencies": [],
662
+ "registryDependencies": [],
220
663
  "files": [
221
664
  {
222
665
  "name": "input-otp.tsx",
223
- "content": "\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport { cn } from \"@/lib/utils\"\r\n\r\ninterface InputOTPProps extends React.InputHTMLAttributes<HTMLInputElement> {\r\n maxLength: number\r\n onCodeComplete?: (code: string) => void\r\n}\r\n\r\nconst InputOTP = React.forwardRef<HTMLInputElement, InputOTPProps>(\r\n ({ className, maxLength = 6, onCodeComplete, value, onChange, ...props }, ref) => {\r\n const [code, setCode] = React.useState<string[]>((value as string || \"\").split(\"\").slice(0, maxLength))\r\n const inputRefs = React.useRef<HTMLInputElement[]>([])\r\n\r\n React.useEffect(() => {\r\n if (value !== undefined) {\r\n setCode((value as string).split(\"\").slice(0, maxLength))\r\n }\r\n }, [value, maxLength])\r\n\r\n const handleTextChange = (text: string, index: number) => {\r\n const cleanDigit = text.replace(/[^0-9]/g, \"\").slice(-1)\r\n const newCode = [...code]\r\n newCode[index] = cleanDigit\r\n \r\n setCode(newCode)\r\n if (onChange) {\r\n const joined = newCode.join(\"\")\r\n onChange({ target: { value: joined } } as React.ChangeEvent<HTMLInputElement>)\r\n if (joined.length === maxLength && onCodeComplete) onCodeComplete(joined)\r\n }\r\n\r\n if (cleanDigit && index < maxLength - 1) {\r\n inputRefs.current[index + 1]?.focus()\r\n }\r\n }\r\n\r\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>, index: number) => {\r\n if (e.key === \"Backspace\" && !code[index] && index > 0) {\r\n inputRefs.current[index - 1]?.focus()\r\n }\r\n }\r\n\r\n return (\r\n <div className={cn(\"flex items-center gap-2\", className)}>\r\n {Array.from({ length: maxLength }).map((_, index) => (\r\n <input\r\n key={index}\r\n ref={(el) => { if (el) inputRefs.current[index] = el }}\r\n type=\"text\"\r\n inputMode=\"numeric\"\r\n pattern=\"[0-9]*\"\r\n maxLength={1}\r\n value={code[index] || \"\"}\r\n onChange={(e) => handleTextChange(e.target.value, index)}\r\n onKeyDown={(e) => handleKeyDown(e, index)}\r\n className=\"w-10 h-12 text-center text-lg font-semibold border border-neutral-200 bg-white rounded-md shadow-2xs focus:outline-hidden focus:border-neutral-900 focus:ring-1 focus:ring-neutral-900 transition-all\"\r\n {...props}\r\n />\r\n ))}\r\n </div>\r\n )\r\n }\r\n)\r\nInputOTP.displayName = \"InputOTP\"\r\n\r\nexport { InputOTP }"
666
+ "content": "\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport { OTPInput, OTPInputContext } from \"input-otp\"\r\nimport { MinusIcon } from \"lucide-react\"\r\n\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nfunction InputOTP({\r\n className,\r\n containerClassName,\r\n ...props\r\n}: React.ComponentProps<typeof OTPInput> & {\r\n containerClassName?: string\r\n}) {\r\n return (\r\n <OTPInput\r\n data-slot=\"input-otp\"\r\n containerClassName={cn(\r\n \"cn-input-otp flex items-center has-disabled:opacity-50\",\r\n containerClassName\r\n )}\r\n spellCheck={false}\r\n className={cn(\"disabled:cursor-not-allowed\", className)}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction InputOTPGroup({ className, ...props }: React.ComponentProps<\"div\">) {\r\n return (\r\n <div\r\n data-slot=\"input-otp-group\"\r\n className={cn(\r\n \"flex items-center rounded-lg has-aria-invalid:border-destructive has-aria-invalid:ring-3 has-aria-invalid:ring-destructive/20 dark:has-aria-invalid:ring-destructive/40\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction InputOTPSlot({\r\n index,\r\n className,\r\n ...props\r\n}: React.ComponentProps<\"div\"> & {\r\n index: number\r\n}) {\r\n const inputOTPContext = React.useContext(OTPInputContext)\r\n const { char, hasFakeCaret, isActive } = inputOTPContext?.slots[index] ?? {}\r\n\r\n return (\r\n <div\r\n data-slot=\"input-otp-slot\"\r\n data-active={isActive}\r\n className={cn(\r\n \"relative flex size-8 items-center justify-center border-y border-r border-input text-sm transition-all outline-none first:rounded-l-lg first:border-l last:rounded-r-lg aria-invalid:border-destructive data-[active=true]:z-10 data-[active=true]:border-ring data-[active=true]:ring-3 data-[active=true]:ring-ring/50 data-[active=true]:aria-invalid:border-destructive data-[active=true]:aria-invalid:ring-destructive/20 dark:bg-input/30 dark:data-[active=true]:aria-invalid:ring-destructive/40\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n {char}\r\n {hasFakeCaret && (\r\n <div className=\"pointer-events-none absolute inset-0 flex items-center justify-center\">\r\n <div className=\"h-4 w-px animate-caret-blink bg-foreground duration-1000\" />\r\n </div>\r\n )}\r\n </div>\r\n )\r\n}\r\n\r\nfunction InputOTPSeparator({ ...props }: React.ComponentProps<\"div\">) {\r\n return (\r\n <div\r\n data-slot=\"input-otp-separator\"\r\n className=\"flex items-center [&_svg:not([class*='size-'])]:size-4\"\r\n role=\"separator\"\r\n {...props}\r\n >\r\n <MinusIcon />\r\n </div>\r\n )\r\n}\r\n\r\nexport { InputOTP, InputOTPGroup, InputOTPSlot, InputOTPSeparator }\r\n"
224
667
  }
225
668
  ]
226
669
  },
227
670
  {
228
671
  "name": "input",
672
+ "type": "components:ui",
673
+ "frameworks": [
674
+ "react",
675
+ "nextjs",
676
+ "vue",
677
+ "nuxt",
678
+ "solid",
679
+ "svelte",
680
+ "astro",
681
+ "remix"
682
+ ],
229
683
  "dependencies": [],
684
+ "registryDependencies": [],
230
685
  "files": [
231
686
  {
232
687
  "name": "input.tsx",
233
- "content": "import * as React from \"react\"\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nexport interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {}\r\n\r\nconst Input = React.forwardRef<HTMLInputElement, InputProps>(\r\n ({ className, type = \"text\", ...props }, ref) => {\r\n return (\r\n <input\r\n type={type}\r\n className={cn(\r\n \"flex h-10 w-full rounded-md border border-neutral-200 bg-white px-3 py-2 text-sm text-neutral-950 file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-neutral-400 shadow-2xs transition-all\",\r\n \"focus-visible:outline-hidden focus-visible:border-neutral-900 focus-visible:ring-1 focus-visible:ring-neutral-900\",\r\n \"disabled:cursor-not-allowed disabled:opacity-50 disabled:bg-neutral-50/50\",\r\n className\r\n )}\r\n ref={ref}\r\n {...props}\r\n />\r\n )\r\n }\r\n)\r\nInput.displayName = \"Input\"\r\n\r\nexport { Input }"
688
+ "content": "import * as React from \"react\"\r\nimport { Input as InputPrimitive } from \"@base-ui/react/input\"\r\n\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nfunction Input({ className, type, ...props }: React.ComponentProps<\"input\">) {\r\n return (\r\n <InputPrimitive\r\n type={type}\r\n data-slot=\"input\"\r\n className={cn(\r\n \"h-8 w-full min-w-0 rounded-lg border border-input bg-transparent px-2.5 py-1 text-base transition-colors outline-none file:inline-flex file:h-6 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:cursor-not-allowed disabled:bg-input/50 disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:disabled:bg-input/80 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nexport { Input }\r\n"
234
689
  }
235
690
  ]
236
691
  },
237
692
  {
238
693
  "name": "kbd",
239
- "dependencies": [
240
- "@base-ui/react"
694
+ "type": "components:ui",
695
+ "frameworks": [
696
+ "react",
697
+ "nextjs",
698
+ "vue",
699
+ "nuxt",
700
+ "solid",
701
+ "svelte",
702
+ "astro",
703
+ "remix"
241
704
  ],
705
+ "dependencies": [],
706
+ "registryDependencies": [],
242
707
  "files": [
243
708
  {
244
709
  "name": "kbd.tsx",
245
- "content": "import * as React from \"react\"\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nconst Kbd = React.forwardRef<HTMLElement, React.HTMLAttributes<HTMLElement>>(\r\n ({ className, ...props }, ref) => (\r\n <kbd\r\n ref={ref}\r\n className={cn(\r\n \"pointer-events-none inline-flex h-5 select-none items-center gap-1 rounded border border-neutral-200 bg-neutral-100 px-1.5 font-mono text-[10px] font-medium text-neutral-500 shadow-xs\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n)\r\nKbd.displayName = \"Kbd\"\r\n\r\nexport { Kbd }"
710
+ "content": "import { cn } from \"@/lib/utils\"\r\n\r\nfunction Kbd({ className, ...props }: React.ComponentProps<\"kbd\">) {\r\n return (\r\n <kbd\r\n data-slot=\"kbd\"\r\n className={cn(\r\n \"pointer-events-none inline-flex h-5 w-fit min-w-5 items-center justify-center gap-1 rounded-sm bg-muted px-1 font-sans text-xs font-medium text-muted-foreground select-none in-data-[slot=tooltip-content]:bg-background/20 in-data-[slot=tooltip-content]:text-background dark:in-data-[slot=tooltip-content]:bg-background/10 [&_svg:not([class*='size-'])]:size-3\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction KbdGroup({ className, ...props }: React.ComponentProps<\"div\">) {\r\n return (\r\n <kbd\r\n data-slot=\"kbd-group\"\r\n className={cn(\"inline-flex items-center gap-1\", className)}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nexport { Kbd, KbdGroup }\r\n"
246
711
  }
247
712
  ]
248
713
  },
249
714
  {
250
715
  "name": "label",
716
+ "type": "components:ui",
717
+ "frameworks": [
718
+ "react",
719
+ "nextjs",
720
+ "vue",
721
+ "nuxt",
722
+ "solid",
723
+ "svelte",
724
+ "astro",
725
+ "remix"
726
+ ],
251
727
  "dependencies": [],
728
+ "registryDependencies": [],
252
729
  "files": [
253
730
  {
254
731
  "name": "label.tsx",
255
- "content": "import * as React from \"react\"\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nconst Label = React.forwardRef<\r\n HTMLLabelElement,\r\n React.LabelHTMLAttributes<HTMLLabelElement>\r\n>(({ className, ...props }, ref) => (\r\n <label\r\n ref={ref}\r\n className={cn(\r\n \"text-sm font-medium leading-none text-neutral-900 select-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n))\r\nLabel.displayName = \"Label\"\r\n\r\nexport { Label }"
256
- }
257
- ]
258
- },
259
- {
260
- "name": "number-field",
261
- "dependencies": [
262
- "@base-ui/react"
263
- ],
264
- "files": [
265
- {
266
- "name": "number-field.tsx",
267
- "content": "\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport { NumberField as BaseNumberField } from \"@base-ui/react/number-field\"\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nexport interface NumberFieldProps extends React.ComponentPropsWithoutRef<typeof BaseNumberField.Root> {\r\n label?: string\r\n}\r\n\r\nconst NumberField = React.forwardRef<HTMLDivElement, NumberFieldProps>(\r\n ({ className, label, ...props }, ref) => {\r\n return (\r\n <BaseNumberField.Root ref={ref} className={cn(\"flex flex-col gap-1.5 w-full max-w-[200px]\", className)} {...props}>\r\n {label && <label className=\"text-sm font-medium text-neutral-700\">{label}</label>}\r\n \r\n <div className=\"relative flex items-center border border-neutral-200 rounded-md bg-white shadow-sm focus-within:ring-2 focus-within:ring-neutral-950\">\r\n {/* Decrement Button */}\r\n <BaseNumberField.Decrement className=\"flex items-center justify-center h-9 w-9 text-neutral-500 transition-colors hover:bg-neutral-50 data-[disabled]:opacity-30 border-r border-neutral-200\">\r\n −\r\n </BaseNumberField.Decrement>\r\n\r\n {/* Core Input Element */}\r\n <BaseNumberField.Input className=\"w-full text-center bg-transparent text-sm font-medium text-neutral-900 outline-none placeholder:text-neutral-400 py-1.5\" />\r\n\r\n {/* Increment Button */}\r\n <BaseNumberField.Increment className=\"flex items-center justify-center h-9 w-9 text-neutral-500 transition-colors hover:bg-neutral-50 data-[disabled]:opacity-30 border-l border-neutral-200\">\r\n +\r\n </BaseNumberField.Increment>\r\n </div>\r\n </BaseNumberField.Root>\r\n )\r\n }\r\n)\r\n\r\nNumberField.displayName = \"NumberField\"\r\n\r\nexport { NumberField }"
732
+ "content": "\"use client\"\r\n\r\nimport * as React from \"react\"\r\n\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nfunction Label({ className, ...props }: React.ComponentProps<\"label\">) {\r\n return (\r\n <label\r\n data-slot=\"label\"\r\n className={cn(\r\n \"flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nexport { Label }\r\n"
268
733
  }
269
734
  ]
270
735
  },
271
736
  {
272
737
  "name": "pagination",
738
+ "type": "components:ui",
739
+ "frameworks": [
740
+ "react",
741
+ "nextjs",
742
+ "vue",
743
+ "nuxt",
744
+ "solid",
745
+ "svelte",
746
+ "astro",
747
+ "remix"
748
+ ],
273
749
  "dependencies": [],
750
+ "registryDependencies": [],
274
751
  "files": [
275
752
  {
276
753
  "name": "pagination.tsx",
277
- "content": "import * as React from \"react\"\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nconst Pagination = ({ className, ...props }: React.ComponentProps<\"nav\">) => (\r\n <nav role=\"navigation\" aria-label=\"pagination\" className={cn(\"mx-auto flex w-full justify-center\", className)} {...props} />\r\n)\r\nPagination.displayName = \"Pagination\"\r\n\r\nconst PaginationContent = React.forwardRef<\r\n HTMLUListElement,\r\n React.ComponentPropsWithoutRef<\"ul\">\r\n>(({ className, ...props }, ref) => (\r\n <ul ref={ref} className={cn(\"flex flex-row items-center gap-1\", className)} {...props} />\r\n))\r\nPaginationContent.displayName = \"PaginationContent\"\r\n\r\nconst PaginationItem = React.forwardRef<\r\n HTMLLIElement,\r\n React.ComponentPropsWithoutRef<\"li\">\r\n>(({ className, ...props }, ref) => (\r\n <li ref={ref} className={cn(\"\", className)} {...props} />\r\n))\r\nPaginationItem.displayName = \"PaginationItem\"\r\n\r\nconst PaginationLink = ({ className, isActive, ...props }: React.ComponentProps<\"a\"> & { isActive?: boolean }) => (\r\n <a\r\n aria-current={isActive ? \"page\" : undefined}\r\n className={cn(\r\n \"flex h-9 w-9 items-center justify-center rounded-md text-sm font-medium transition-colors cursor-pointer select-none border border-transparent\",\r\n isActive ? \"bg-neutral-900 text-neutral-50 border-neutral-900\" : \"hover:bg-neutral-100 text-neutral-900\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n)\r\nPaginationLink.displayName = \"PaginationLink\"\r\n\r\nconst PaginationPrevious = ({ className, ...props }: React.ComponentProps<typeof PaginationLink>) => (\r\n <PaginationLink aria-label=\"Go to previous page\" className={cn(\"gap-1 pl-2.5 pr-3.5 w-auto\", className)} {...props}>\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\"><polyline points=\"15 18 9 12 15 6\" /></svg>\r\n <span>Previous</span>\r\n </PaginationLink>\r\n)\r\nPaginationPrevious.displayName = \"PaginationPrevious\"\r\n\r\nconst PaginationNext = ({ className, ...props }: React.ComponentProps<typeof PaginationLink>) => (\r\n <PaginationLink aria-label=\"Go to next page\" className={cn(\"gap-1 pl-3.5 pr-2.5 w-auto\", className)} {...props}>\r\n <span>Next</span>\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\"><polyline points=\"9 18 15 12 9 6\" /></svg>\r\n </PaginationLink>\r\n)\r\nPaginationNext.displayName = \"PaginationNext\"\r\n\r\nconst PaginationEllipsis = ({ className, ...props }: React.ComponentProps<\"span\">) => (\r\n <span aria-hidden=\"true\" className={cn(\"flex h-9 w-9 items-center justify-center text-neutral-400\", className)} {...props}>\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\"><circle cx=\"12\" cy=\"12\" r=\"1\" /><circle cx=\"19\" cy=\"12\" r=\"1\" /><circle cx=\"5\" cy=\"12\" r=\"1\" /></svg>\r\n </span>\r\n)\r\nPaginationEllipsis.displayName = \"PaginationEllipsis\"\r\n\r\nexport { Pagination, PaginationContent, PaginationItem, PaginationLink, PaginationPrevious, PaginationNext, PaginationEllipsis }"
754
+ "content": "import * as React from \"react\"\r\nimport {\r\n ChevronLeftIcon,\r\n ChevronRightIcon,\r\n MoreHorizontalIcon,\r\n} from \"lucide-react\"\r\n\r\nimport { cn } from \"@/lib/utils\"\r\nimport { Button } from \"@/button\"\r\n\r\nfunction Pagination({ className, ...props }: React.ComponentProps<\"nav\">) {\r\n return (\r\n <nav\r\n role=\"navigation\"\r\n aria-label=\"pagination\"\r\n data-slot=\"pagination\"\r\n className={cn(\"mx-auto flex w-full justify-center\", className)}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction PaginationContent({\r\n className,\r\n ...props\r\n}: React.ComponentProps<\"ul\">) {\r\n return (\r\n <ul\r\n data-slot=\"pagination-content\"\r\n className={cn(\"flex items-center gap-0.5\", className)}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction PaginationItem({ ...props }: React.ComponentProps<\"li\">) {\r\n return <li data-slot=\"pagination-item\" {...props} />\r\n}\r\n\r\ntype PaginationLinkProps = {\r\n isActive?: boolean\r\n} & Pick<React.ComponentProps<typeof Button>, \"size\"> &\r\n React.ComponentProps<\"a\">\r\n\r\nfunction PaginationLink({\r\n className,\r\n isActive,\r\n size = \"icon\",\r\n ...props\r\n}: PaginationLinkProps) {\r\n return (\r\n <Button\r\n variant={isActive ? \"outline\" : \"ghost\"}\r\n size={size}\r\n className={cn(className)}\r\n nativeButton={false}\r\n render={\r\n <a\r\n aria-current={isActive ? \"page\" : undefined}\r\n data-slot=\"pagination-link\"\r\n data-active={isActive}\r\n {...props}\r\n />\r\n }\r\n />\r\n )\r\n}\r\n\r\nfunction PaginationPrevious({\r\n className,\r\n text = \"Previous\",\r\n ...props\r\n}: React.ComponentProps<typeof PaginationLink> & { text?: string }) {\r\n return (\r\n <PaginationLink\r\n aria-label=\"Go to previous page\"\r\n size=\"default\"\r\n className={cn(\"pl-1.5!\", className)}\r\n {...props}\r\n >\r\n <ChevronLeftIcon data-icon=\"inline-start\" className=\"cn-rtl-flip\" />\r\n <span className=\"hidden sm:block\">{text}</span>\r\n </PaginationLink>\r\n )\r\n}\r\n\r\nfunction PaginationNext({\r\n className,\r\n text = \"Next\",\r\n ...props\r\n}: React.ComponentProps<typeof PaginationLink> & { text?: string }) {\r\n return (\r\n <PaginationLink\r\n aria-label=\"Go to next page\"\r\n size=\"default\"\r\n className={cn(\"pr-1.5!\", className)}\r\n {...props}\r\n >\r\n <span className=\"hidden sm:block\">{text}</span>\r\n <ChevronRightIcon data-icon=\"inline-end\" className=\"cn-rtl-flip\" />\r\n </PaginationLink>\r\n )\r\n}\r\n\r\nfunction PaginationEllipsis({\r\n className,\r\n ...props\r\n}: React.ComponentProps<\"span\">) {\r\n return (\r\n <span\r\n aria-hidden\r\n data-slot=\"pagination-ellipsis\"\r\n className={cn(\r\n \"flex size-8 items-center justify-center [&_svg:not([class*='size-'])]:size-4\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n <MoreHorizontalIcon />\r\n <span className=\"sr-only\">More pages</span>\r\n </span>\r\n )\r\n}\r\n\r\nexport {\r\n Pagination,\r\n PaginationContent,\r\n PaginationEllipsis,\r\n PaginationItem,\r\n PaginationLink,\r\n PaginationNext,\r\n PaginationPrevious,\r\n}\r\n"
278
755
  }
279
756
  ]
280
757
  },
281
758
  {
282
759
  "name": "popover",
760
+ "type": "components:ui",
761
+ "frameworks": [
762
+ "react",
763
+ "nextjs",
764
+ "vue",
765
+ "nuxt",
766
+ "solid",
767
+ "svelte",
768
+ "astro",
769
+ "remix"
770
+ ],
283
771
  "dependencies": [
284
772
  "@base-ui/react"
285
773
  ],
774
+ "registryDependencies": [],
286
775
  "files": [
287
776
  {
288
777
  "name": "popover.tsx",
289
- "content": "\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport { Popover as BasePopover } from \"@base-ui/react/popover\"\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nconst Popover = BasePopover.Root\r\n\r\nconst PopoverTrigger = BasePopover.Trigger\r\n\r\nconst PopoverPortal = BasePopover.Portal\r\n\r\nconst PopoverContent = React.forwardRef<\r\n HTMLDivElement,\r\n React.ComponentPropsWithoutRef<typeof BasePopover.Popup> & { sideOffset?: number; align?: \"start\" | \"center\" | \"end\" }\r\n>(({ className, align = \"center\", sideOffset = 8, ...props }, ref) => (\r\n <BasePopover.Positioner sideOffset={sideOffset} align={align}>\r\n <BasePopover.Popup\r\n ref={ref}\r\n className={cn(\r\n \"z-50 w-72 rounded-xl border border-neutral-200 bg-white p-4 text-neutral-950 shadow-md outline-hidden transition-all duration-150 ease-out\",\r\n \"data-[starting-style]:scale-95 data-[starting-style]:opacity-0\",\r\n \"data-[ending-style]:scale-95 data-[ending-style]:opacity-0\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n </BasePopover.Positioner>\r\n))\r\nPopoverContent.displayName = \"PopoverContent\"\r\n\r\nexport { Popover, PopoverTrigger, PopoverPortal, PopoverContent }"
778
+ "content": "\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport { Popover as PopoverPrimitive } from \"@base-ui/react/popover\"\r\n\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nfunction Popover({ ...props }: PopoverPrimitive.Root.Props) {\r\n return <PopoverPrimitive.Root data-slot=\"popover\" {...props} />\r\n}\r\n\r\nfunction PopoverTrigger({ ...props }: PopoverPrimitive.Trigger.Props) {\r\n return <PopoverPrimitive.Trigger data-slot=\"popover-trigger\" {...props} />\r\n}\r\n\r\nfunction PopoverContent({\r\n className,\r\n align = \"center\",\r\n alignOffset = 0,\r\n side = \"bottom\",\r\n sideOffset = 4,\r\n ...props\r\n}: PopoverPrimitive.Popup.Props &\r\n Pick<\r\n PopoverPrimitive.Positioner.Props,\r\n \"align\" | \"alignOffset\" | \"side\" | \"sideOffset\"\r\n >) {\r\n return (\r\n <PopoverPrimitive.Portal>\r\n <PopoverPrimitive.Positioner\r\n align={align}\r\n alignOffset={alignOffset}\r\n side={side}\r\n sideOffset={sideOffset}\r\n className=\"isolate z-50\"\r\n >\r\n <PopoverPrimitive.Popup\r\n data-slot=\"popover-content\"\r\n className={cn(\r\n \"z-50 flex w-72 origin-(--transform-origin) flex-col gap-2.5 rounded-lg bg-popover p-2.5 text-sm text-popover-foreground shadow-md ring-1 ring-foreground/10 outline-hidden duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n </PopoverPrimitive.Positioner>\r\n </PopoverPrimitive.Portal>\r\n )\r\n}\r\n\r\nfunction PopoverHeader({ className, ...props }: React.ComponentProps<\"div\">) {\r\n return (\r\n <div\r\n data-slot=\"popover-header\"\r\n className={cn(\"flex flex-col gap-0.5 text-sm\", className)}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction PopoverTitle({ className, ...props }: PopoverPrimitive.Title.Props) {\r\n return (\r\n <PopoverPrimitive.Title\r\n data-slot=\"popover-title\"\r\n className={cn(\"font-medium\", className)}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction PopoverDescription({\r\n className,\r\n ...props\r\n}: PopoverPrimitive.Description.Props) {\r\n return (\r\n <PopoverPrimitive.Description\r\n data-slot=\"popover-description\"\r\n className={cn(\"text-muted-foreground\", className)}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nexport {\r\n Popover,\r\n PopoverContent,\r\n PopoverDescription,\r\n PopoverHeader,\r\n PopoverTitle,\r\n PopoverTrigger,\r\n}\r\n"
290
779
  }
291
780
  ]
292
781
  },
293
782
  {
294
783
  "name": "progress",
784
+ "type": "components:ui",
785
+ "frameworks": [
786
+ "react",
787
+ "nextjs",
788
+ "vue",
789
+ "nuxt",
790
+ "solid",
791
+ "svelte",
792
+ "astro",
793
+ "remix"
794
+ ],
295
795
  "dependencies": [
296
796
  "@base-ui/react"
297
797
  ],
798
+ "registryDependencies": [],
298
799
  "files": [
299
800
  {
300
801
  "name": "progress.tsx",
301
- "content": "\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport { Progress as BaseProgress } from \"@base-ui/react/progress\"\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nconst Progress = React.forwardRef<\r\n HTMLDivElement,\r\n React.ComponentPropsWithoutRef<typeof BaseProgress.Root>\r\n>(({ className, value = 0, ...props }, ref) => (\r\n <BaseProgress.Root\r\n ref={ref}\r\n value={value}\r\n className={cn(\r\n \"relative h-2 w-full overflow-hidden rounded-full bg-neutral-100\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n <BaseProgress.Track className=\"h-full w-full bg-neutral-100\">\r\n <BaseProgress.Indicator\r\n className=\"h-full bg-neutral-900 transition-all duration-300 ease-in-out\"\r\n style={{ transform: `translateX(-${100 - (value || 0)}%)` }}\r\n />\r\n </BaseProgress.Track>\r\n </BaseProgress.Root>\r\n))\r\nProgress.displayName = \"Progress\"\r\n\r\nexport { Progress }"
802
+ "content": "\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport { Popover as PopoverPrimitive } from \"@base-ui/react/popover\"\r\n\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nfunction Popover({ ...props }: PopoverPrimitive.Root.Props) {\r\n return <PopoverPrimitive.Root data-slot=\"popover\" {...props} />\r\n}\r\n\r\nfunction PopoverTrigger({ ...props }: PopoverPrimitive.Trigger.Props) {\r\n return <PopoverPrimitive.Trigger data-slot=\"popover-trigger\" {...props} />\r\n}\r\n\r\nfunction PopoverContent({\r\n className,\r\n align = \"center\",\r\n alignOffset = 0,\r\n side = \"bottom\",\r\n sideOffset = 4,\r\n ...props\r\n}: PopoverPrimitive.Popup.Props &\r\n Pick<\r\n PopoverPrimitive.Positioner.Props,\r\n \"align\" | \"alignOffset\" | \"side\" | \"sideOffset\"\r\n >) {\r\n return (\r\n <PopoverPrimitive.Portal>\r\n <PopoverPrimitive.Positioner\r\n align={align}\r\n alignOffset={alignOffset}\r\n side={side}\r\n sideOffset={sideOffset}\r\n className=\"isolate z-50\"\r\n >\r\n <PopoverPrimitive.Popup\r\n data-slot=\"popover-content\"\r\n className={cn(\r\n \"z-50 flex w-72 origin-(--transform-origin) flex-col gap-2.5 rounded-lg bg-popover p-2.5 text-sm text-popover-foreground shadow-md ring-1 ring-foreground/10 outline-hidden duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n </PopoverPrimitive.Positioner>\r\n </PopoverPrimitive.Portal>\r\n )\r\n}\r\n\r\nfunction PopoverHeader({ className, ...props }: React.ComponentProps<\"div\">) {\r\n return (\r\n <div\r\n data-slot=\"popover-header\"\r\n className={cn(\"flex flex-col gap-0.5 text-sm\", className)}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction PopoverTitle({ className, ...props }: PopoverPrimitive.Title.Props) {\r\n return (\r\n <PopoverPrimitive.Title\r\n data-slot=\"popover-title\"\r\n className={cn(\"font-medium\", className)}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction PopoverDescription({\r\n className,\r\n ...props\r\n}: PopoverPrimitive.Description.Props) {\r\n return (\r\n <PopoverPrimitive.Description\r\n data-slot=\"popover-description\"\r\n className={cn(\"text-muted-foreground\", className)}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nexport {\r\n Popover,\r\n PopoverContent,\r\n PopoverDescription,\r\n PopoverHeader,\r\n PopoverTitle,\r\n PopoverTrigger,\r\n}\r\n"
302
803
  }
303
804
  ]
304
805
  },
305
806
  {
306
807
  "name": "radio-group",
808
+ "type": "components:ui",
809
+ "frameworks": [
810
+ "react",
811
+ "nextjs",
812
+ "vue",
813
+ "nuxt",
814
+ "solid",
815
+ "svelte",
816
+ "astro",
817
+ "remix"
818
+ ],
307
819
  "dependencies": [
308
820
  "@base-ui/react"
309
821
  ],
822
+ "registryDependencies": [],
310
823
  "files": [
311
824
  {
312
825
  "name": "radio-group.tsx",
313
- "content": "\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport { RadioGroup as BaseRadioGroup } from \"@base-ui/react/radio-group\"\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nconst RadioGroup = React.forwardRef<\r\n HTMLDivElement,\r\n React.ComponentPropsWithoutRef<typeof BaseRadioGroup.Root>\r\n>(({ className, ...props }, ref) => (\r\n <BaseRadioGroup.Root ref={ref} className={cn(\"grid gap-2.5\", className)} {...props} />\r\n))\r\nRadioGroup.displayName = \"RadioGroup\"\r\n\r\nconst RadioGroupItem = React.forwardRef<\r\n HTMLButtonElement,\r\n React.ComponentPropsWithoutRef<typeof BaseRadioGroup.Item>\r\n>(({ className, ...props }, ref) => (\r\n <BaseRadioGroup.Item\r\n ref={ref}\r\n className={cn(\r\n \"group aspect-square h-4 w-4 shrink-0 rounded-full border border-neutral-300 bg-white transition-all cursor-pointer flex items-center justify-center\",\r\n \"focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-neutral-950 focus-visible:ring-offset-2\",\r\n \"disabled:cursor-not-allowed disabled:opacity-50\",\r\n \"data-[checked]:border-neutral-900 data-[checked]:bg-neutral-900\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n <BaseRadioGroup.Indicator className=\"h-1.5 w-1.5 rounded-full bg-white transition-transform duration-100 data-[starting-style]:scale-50\" />\r\n </BaseRadioGroup.Item>\r\n))\r\nRadioGroupItem.displayName = \"RadioGroupItem\"\r\n\r\nexport { RadioGroup, RadioGroupItem }"
826
+ "content": "\"use client\"\n\nimport { Radio as RadioPrimitive } from \"@base-ui/react/radio\"\nimport { RadioGroup as RadioGroupPrimitive } from \"@base-ui/react/radio-group\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction RadioGroup({ className, ...props }: RadioGroupPrimitive.Props) {\n return (\n <RadioGroupPrimitive\n data-slot=\"radio-group\"\n className={cn(\"grid w-full gap-2\", className)}\n {...props}\n />\n )\n}\n\nfunction RadioGroupItem({ className, ...props }: RadioPrimitive.Root.Props) {\n return (\n <RadioPrimitive.Root\n data-slot=\"radio-group-item\"\n className={cn(\n \"group/radio-group-item peer relative flex aspect-square size-4 shrink-0 rounded-full border border-input outline-none after:absolute after:-inset-x-3 after:-inset-y-2 focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 aria-invalid:aria-checked:border-primary dark:bg-input/30 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 data-checked:border-primary data-checked:bg-primary data-checked:text-primary-foreground dark:data-checked:bg-primary\",\n className\n )}\n {...props}\n >\n <RadioPrimitive.Indicator\n data-slot=\"radio-group-indicator\"\n className=\"flex size-4 items-center justify-center\"\n >\n <span className=\"absolute top-1/2 left-1/2 size-2 -translate-x-1/2 -translate-y-1/2 rounded-full bg-primary-foreground\" />\n </RadioPrimitive.Indicator>\n </RadioPrimitive.Root>\n )\n}\n\nexport { RadioGroup, RadioGroupItem }\n"
314
827
  }
315
828
  ]
316
829
  },
317
830
  {
318
831
  "name": "scroll-area",
832
+ "type": "components:ui",
833
+ "frameworks": [
834
+ "react",
835
+ "nextjs",
836
+ "vue",
837
+ "nuxt",
838
+ "solid",
839
+ "svelte",
840
+ "astro",
841
+ "remix"
842
+ ],
319
843
  "dependencies": [
320
844
  "@base-ui/react"
321
845
  ],
846
+ "registryDependencies": [],
322
847
  "files": [
323
848
  {
324
849
  "name": "scroll-area.tsx",
325
- "content": "\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport { ScrollArea as BaseScrollArea } from \"@base-ui/react/scroll-area\"\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nconst ScrollArea = React.forwardRef<\r\n HTMLDivElement,\r\n React.ComponentPropsWithoutRef<typeof BaseScrollArea.Root>\r\n>(({ className, children, ...props }, ref) => (\r\n <BaseScrollArea.Root\r\n ref={ref}\r\n className={cn(\"relative overflow-hidden group/scroll\", className)}\r\n {...props}\r\n >\r\n <BaseScrollArea.Viewport className=\"h-full w-full rounded-[inherit] overscroll-contain outline-hidden\">\r\n <BaseScrollArea.Content>{children}</BaseScrollArea.Content>\r\n </BaseScrollArea.Viewport>\r\n \r\n <BaseScrollArea.Scrollbar\r\n orientation=\"vertical\"\r\n className=\"absolute right-0 top-0 bottom-0 z-50 flex w-2.5 touch-none select-none p-px bg-transparent transition-opacity duration-150 opacity-0 group-hover/scroll:opacity-100 data-[scrolling]:opacity-100 data-[hovering]:opacity-100\"\r\n >\r\n <BaseScrollArea.Thumb className=\"relative flex-1 rounded-full bg-neutral-300 transition-colors hover:bg-neutral-400\" />\r\n </BaseScrollArea.Scrollbar>\r\n\r\n <BaseScrollArea.Scrollbar\r\n orientation=\"horizontal\"\r\n className=\"absolute bottom-0 left-0 right-0 z-50 flex h-2.5 touch-none select-none flex-col p-px bg-transparent transition-opacity duration-150 opacity-0 group-hover/scroll:opacity-100 data-[scrolling]:opacity-100 data-[hovering]:opacity-100\"\r\n >\r\n <BaseScrollArea.Thumb className=\"relative flex-1 rounded-full bg-neutral-300 transition-colors hover:bg-neutral-400\" />\r\n </BaseScrollArea.Scrollbar>\r\n </BaseScrollArea.Root>\r\n))\r\nScrollArea.displayName = \"ScrollArea\"\r\n\r\nexport { ScrollArea }"
850
+ "content": "\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport { ScrollArea as ScrollAreaPrimitive } from \"@base-ui/react/scroll-area\"\r\n\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nfunction ScrollArea({\r\n className,\r\n children,\r\n ...props\r\n}: ScrollAreaPrimitive.Root.Props) {\r\n return (\r\n <ScrollAreaPrimitive.Root\r\n data-slot=\"scroll-area\"\r\n className={cn(\"relative\", className)}\r\n {...props}\r\n >\r\n <ScrollAreaPrimitive.Viewport\r\n data-slot=\"scroll-area-viewport\"\r\n className=\"size-full rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:outline-1\"\r\n >\r\n {children}\r\n </ScrollAreaPrimitive.Viewport>\r\n <ScrollBar />\r\n <ScrollAreaPrimitive.Corner />\r\n </ScrollAreaPrimitive.Root>\r\n )\r\n}\r\n\r\nfunction ScrollBar({\r\n className,\r\n orientation = \"vertical\",\r\n ...props\r\n}: ScrollAreaPrimitive.Scrollbar.Props) {\r\n return (\r\n <ScrollAreaPrimitive.Scrollbar\r\n data-slot=\"scroll-area-scrollbar\"\r\n data-orientation={orientation}\r\n orientation={orientation}\r\n className={cn(\r\n \"flex touch-none p-px transition-colors select-none data-horizontal:h-2.5 data-horizontal:flex-col data-horizontal:border-t data-horizontal:border-t-transparent data-vertical:h-full data-vertical:w-2.5 data-vertical:border-l data-vertical:border-l-transparent\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n <ScrollAreaPrimitive.Thumb\r\n data-slot=\"scroll-area-thumb\"\r\n className=\"relative flex-1 rounded-full bg-border\"\r\n />\r\n </ScrollAreaPrimitive.Scrollbar>\r\n )\r\n}\r\n\r\nexport { ScrollArea, ScrollBar }\r\n"
326
851
  }
327
852
  ]
328
853
  },
329
854
  {
330
855
  "name": "select",
856
+ "type": "components:ui",
857
+ "frameworks": [
858
+ "react",
859
+ "nextjs",
860
+ "vue",
861
+ "nuxt",
862
+ "solid",
863
+ "svelte",
864
+ "astro",
865
+ "remix"
866
+ ],
331
867
  "dependencies": [
332
868
  "@base-ui/react"
333
869
  ],
870
+ "registryDependencies": [],
334
871
  "files": [
335
872
  {
336
873
  "name": "select.tsx",
337
- "content": "\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport { Select as BaseSelect } from \"@base-ui/react/select\"\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nconst Select = BaseSelect.Root\r\n\r\nconst SelectGroup = BaseSelect.Group\r\n\r\nconst SelectValue = BaseSelect.Value\r\n\r\nconst SelectTrigger = React.forwardRef<\r\n HTMLButtonElement,\r\n React.ComponentPropsWithoutRef<typeof BaseSelect.Trigger>\r\n>(({ className, children, ...props }, ref) => (\r\n <BaseSelect.Trigger\r\n ref={ref}\r\n className={cn(\r\n \"flex h-10 w-full items-center justify-between rounded-md border border-neutral-200 bg-white px-3 py-2 text-sm text-neutral-950 shadow-2xs transition-all cursor-pointer select-none\",\r\n \"focus:outline-hidden focus:border-neutral-900 focus:ring-1 focus:ring-neutral-900\",\r\n \"disabled:cursor-not-allowed disabled:opacity-50 disabled:bg-neutral-50/50\",\r\n \"group text-left\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n {children}\r\n <BaseSelect.Icon className=\"h-4 w-4 opacity-50 transition-transform duration-200 group-data-[popup-open]:rotate-180\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" strokeWidth=\"2\" stroke=\"currentColor\">\r\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M19.5 8.25l-7.5 7.5-7.5-7.5\" />\r\n </svg>\r\n </BaseSelect.Icon>\r\n </BaseSelect.Trigger>\r\n))\r\nSelectTrigger.displayName = \"SelectTrigger\"\r\n\r\nconst SelectPortal = BaseSelect.Portal\r\n\r\nconst SelectContent = React.forwardRef<\r\n HTMLDivElement,\r\n React.ComponentPropsWithoutRef<typeof BaseSelect.Popup>\r\n>(({ className, sideOffset = 4, ...props }, ref) => (\r\n <BaseSelect.Positioner sideOffset={sideOffset}>\r\n <BaseSelect.Popup\r\n ref={ref}\r\n className={cn(\r\n \"z-50 min-w-[8rem] overflow-hidden rounded-lg border border-neutral-200 bg-white p-1 text-neutral-950 shadow-md outline-hidden transition-all duration-100 ease-out\",\r\n \"data-[starting-style]:scale-95 data-[starting-style]:opacity-0\",\r\n \"data-[ending-style]:scale-95 data-[ending-style]:opacity-0\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n </BaseSelect.Positioner>\r\n))\r\nSelectContent.displayName = \"SelectContent\"\r\n\r\nconst SelectItem = React.forwardRef<\r\n HTMLDivElement,\r\n React.ComponentPropsWithoutRef<typeof BaseSelect.Item>\r\n>(({ className, children, ...props }, ref) => (\r\n <BaseSelect.Item\r\n ref={ref}\r\n className={cn(\r\n \"relative flex w-full cursor-default select-none items-center rounded-md py-1.5 pl-8 pr-2 text-sm text-neutral-900 outline-hidden cursor-pointer group\",\r\n \"data-[highlighted]:bg-neutral-100 data-[highlighted]:text-neutral-900\",\r\n \"data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n <span className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center opacity-0 group-data-[selected]:opacity-100 transition-opacity duration-700\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" strokeWidth=\"3\" stroke=\"currentColor\" className=\"h-3 w-3\">\r\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M4.5 12.75l6 6 9-13.5\" />\r\n </svg>\r\n </span>\r\n <BaseSelect.ItemText>{children}</BaseSelect.ItemText>\r\n </BaseSelect.Item>\r\n))\r\nSelectItem.displayName = \"SelectItem\"\r\n\r\nconst SelectLabel = React.forwardRef<\r\n HTMLDivElement,\r\n React.ComponentPropsWithoutRef<typeof BaseSelect.Label>\r\n>(({ className, ...props }, ref) => (\r\n <BaseSelect.Label\r\n ref={ref}\r\n className={cn(\"px-2 py-1.5 text-xs font-semibold text-neutral-400 uppercase tracking-wider select-none\", className)}\r\n {...props}\r\n />\r\n))\r\nSelectLabel.displayName = \"SelectLabel\"\r\n\r\nexport {\r\n Select,\r\n SelectGroup,\r\n SelectValue,\r\n SelectTrigger,\r\n SelectPortal,\r\n SelectContent,\r\n SelectItem,\r\n SelectLabel,\r\n}"
874
+ "content": "\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport { Select as SelectPrimitive } from \"@base-ui/react/select\"\r\nimport { CheckIcon, ChevronDownIcon, ChevronUpIcon } from \"lucide-react\"\r\n\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nconst Select = SelectPrimitive.Root\r\n\r\nfunction SelectGroup({ className, ...props }: SelectPrimitive.Group.Props) {\r\n return (\r\n <SelectPrimitive.Group\r\n data-slot=\"select-group\"\r\n className={cn(\"scroll-my-1 p-1\", className)}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction SelectValue({ className, ...props }: SelectPrimitive.Value.Props) {\r\n return (\r\n <SelectPrimitive.Value\r\n data-slot=\"select-value\"\r\n className={cn(\"flex flex-1 text-left\", className)}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction SelectTrigger({\r\n className,\r\n size = \"default\",\r\n children,\r\n ...props\r\n}: SelectPrimitive.Trigger.Props & {\r\n size?: \"sm\" | \"default\"\r\n}) {\r\n return (\r\n <SelectPrimitive.Trigger\r\n data-slot=\"select-trigger\"\r\n data-size={size}\r\n className={cn(\r\n \"flex w-fit items-center justify-between gap-1.5 rounded-lg border border-input bg-transparent py-2 pr-2 pl-2.5 text-sm whitespace-nowrap transition-colors outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 data-placeholder:text-muted-foreground data-[size=default]:h-8 data-[size=sm]:h-7 data-[size=sm]:rounded-[min(var(--radius-md),10px)] *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-1.5 dark:bg-input/30 dark:hover:bg-input/50 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n {children}\r\n <SelectPrimitive.Icon\r\n render={\r\n <ChevronDownIcon className=\"pointer-events-none size-4 text-muted-foreground\" />\r\n }\r\n />\r\n </SelectPrimitive.Trigger>\r\n )\r\n}\r\n\r\nfunction SelectContent({\r\n className,\r\n children,\r\n side = \"bottom\",\r\n sideOffset = 4,\r\n align = \"center\",\r\n alignOffset = 0,\r\n alignItemWithTrigger = true,\r\n ...props\r\n}: SelectPrimitive.Popup.Props &\r\n Pick<\r\n SelectPrimitive.Positioner.Props,\r\n \"align\" | \"alignOffset\" | \"side\" | \"sideOffset\" | \"alignItemWithTrigger\"\r\n >) {\r\n return (\r\n <SelectPrimitive.Portal>\r\n <SelectPrimitive.Positioner\r\n side={side}\r\n sideOffset={sideOffset}\r\n align={align}\r\n alignOffset={alignOffset}\r\n alignItemWithTrigger={alignItemWithTrigger}\r\n className=\"isolate z-50\"\r\n >\r\n <SelectPrimitive.Popup\r\n data-slot=\"select-content\"\r\n data-align-trigger={alignItemWithTrigger}\r\n className={cn(\"relative isolate z-50 max-h-(--available-height) w-(--anchor-width) min-w-36 origin-(--transform-origin) overflow-x-hidden overflow-y-auto rounded-lg bg-popover text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 data-[align-trigger=true]:animate-none data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95\", className )}\r\n {...props}\r\n >\r\n <SelectScrollUpButton />\r\n <SelectPrimitive.List>{children}</SelectPrimitive.List>\r\n <SelectScrollDownButton />\r\n </SelectPrimitive.Popup>\r\n </SelectPrimitive.Positioner>\r\n </SelectPrimitive.Portal>\r\n )\r\n}\r\n\r\nfunction SelectLabel({\r\n className,\r\n ...props\r\n}: SelectPrimitive.GroupLabel.Props) {\r\n return (\r\n <SelectPrimitive.GroupLabel\r\n data-slot=\"select-label\"\r\n className={cn(\"px-1.5 py-1 text-xs text-muted-foreground\", className)}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction SelectItem({\r\n className,\r\n children,\r\n ...props\r\n}: SelectPrimitive.Item.Props) {\r\n return (\r\n <SelectPrimitive.Item\r\n data-slot=\"select-item\"\r\n className={cn(\r\n \"relative flex w-full cursor-default items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n <SelectPrimitive.ItemText className=\"flex flex-1 shrink-0 gap-2 whitespace-nowrap\">\r\n {children}\r\n </SelectPrimitive.ItemText>\r\n <SelectPrimitive.ItemIndicator render={<span className=\"pointer-events-none absolute right-2 flex size-4 items-center justify-center\"><CheckIcon className=\"pointer-events-none\" /></span>} />\r\n </SelectPrimitive.Item>\r\n )\r\n}\r\n\r\nfunction SelectSeparator({\r\n className,\r\n ...props\r\n}: SelectPrimitive.Separator.Props) {\r\n return (\r\n <SelectPrimitive.Separator\r\n data-slot=\"select-separator\"\r\n className={cn(\"pointer-events-none -mx-1 my-1 h-px bg-border\", className)}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction SelectScrollUpButton({\r\n className,\r\n ...props\r\n}: React.ComponentProps<typeof SelectPrimitive.ScrollUpArrow>) {\r\n return (\r\n <SelectPrimitive.ScrollUpArrow\r\n data-slot=\"select-scroll-up-button\"\r\n className={cn(\r\n \"top-0 z-10 flex w-full cursor-default items-center justify-center bg-popover py-1 [&_svg:not([class*='size-'])]:size-4\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n <ChevronUpIcon />\r\n </SelectPrimitive.ScrollUpArrow>\r\n )\r\n}\r\n\r\nfunction SelectScrollDownButton({\r\n className,\r\n ...props\r\n}: React.ComponentProps<typeof SelectPrimitive.ScrollDownArrow>) {\r\n return (\r\n <SelectPrimitive.ScrollDownArrow\r\n data-slot=\"select-scroll-down-button\"\r\n className={cn(\r\n \"bottom-0 z-10 flex w-full cursor-default items-center justify-center bg-popover py-1 [&_svg:not([class*='size-'])]:size-4\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n <ChevronDownIcon />\r\n </SelectPrimitive.ScrollDownArrow>\r\n )\r\n}\r\n\r\nexport {\r\n Select,\r\n SelectContent,\r\n SelectGroup,\r\n SelectItem,\r\n SelectLabel,\r\n SelectScrollDownButton,\r\n SelectScrollUpButton,\r\n SelectSeparator,\r\n SelectTrigger,\r\n SelectValue,\r\n}\r\n"
338
875
  }
339
876
  ]
340
877
  },
341
878
  {
342
879
  "name": "separator",
880
+ "type": "components:ui",
881
+ "frameworks": [
882
+ "react",
883
+ "nextjs",
884
+ "vue",
885
+ "nuxt",
886
+ "solid",
887
+ "svelte",
888
+ "astro",
889
+ "remix"
890
+ ],
891
+ "dependencies": [],
892
+ "registryDependencies": [],
893
+ "files": [
894
+ {
895
+ "name": "separator.tsx",
896
+ "content": "\"use client\"\r\n\r\nimport { Separator as SeparatorPrimitive } from \"@base-ui/react/separator\"\r\n\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nfunction Separator({\r\n className,\r\n orientation = \"horizontal\",\r\n ...props\r\n}: SeparatorPrimitive.Props) {\r\n return (\r\n <SeparatorPrimitive\r\n data-slot=\"separator\"\r\n orientation={orientation}\r\n className={cn(\r\n \"shrink-0 bg-border data-horizontal:h-px data-horizontal:w-full data-vertical:w-px data-vertical:self-stretch\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nexport { Separator }\r\n"
897
+ }
898
+ ]
899
+ },
900
+ {
901
+ "name": "sheet",
902
+ "type": "components:ui",
903
+ "frameworks": [
904
+ "react",
905
+ "nextjs",
906
+ "remix"
907
+ ],
343
908
  "dependencies": [
344
909
  "@base-ui/react"
345
910
  ],
911
+ "registryDependencies": [],
346
912
  "files": [
347
913
  {
348
- "name": "separator.tsx",
349
- "content": "import * as React from \"react\"\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nconst Separator = React.forwardRef<\r\n HTMLDivElement,\r\n React.HTMLAttributes<HTMLDivElement> & { orientation?: \"horizontal\" | \"vertical\" }\r\n>(({ className, orientation = \"horizontal\", ...props }, ref) => (\r\n <div\r\n ref={ref}\r\n role=\"none\"\r\n className={cn(\r\n \"shrink-0 bg-neutral-200\",\r\n orientation === \"horizontal\" ? \"h-[1px] w-full\" : \"h-full w-[1px]\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n))\r\nSeparator.displayName = \"Separator\"\r\n\r\nexport { Separator }"
914
+ "name": "sheet.tsx",
915
+ "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { Dialog as SheetPrimitive } from \"@base-ui/react/dialog\"\nimport { XIcon } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst Sheet = SheetPrimitive.Root\nconst SheetTrigger = SheetPrimitive.Trigger\nconst SheetClose = SheetPrimitive.Close\nconst SheetPortal = SheetPrimitive.Portal\n\nfunction SheetOverlay({\n className,\n ...props\n}: SheetPrimitive.Backdrop.Props) {\n return (\n <SheetPrimitive.Backdrop\n data-slot=\"sheet-overlay\"\n className={cn(\n \"fixed inset-0 z-50 bg-black/10 supports-backdrop-filter:backdrop-blur-xs data-open:animate-in data-open:fade-in-0 data-closed:animate-out data-closed:fade-out-0\",\n className\n )}\n {...props}\n />\n )\n}\n\nconst SHEET_SIDES = [\"top\", \"right\", \"bottom\", \"left\"] as const\ntype SheetSide = (typeof SHEET_SIDES)[number]\n\nfunction SheetContent({\n className,\n children,\n side = \"right\",\n ...props\n}: SheetPrimitive.Popup.Props & {\n side?: SheetSide\n}) {\n return (\n <SheetPortal>\n <SheetOverlay />\n <SheetPrimitive.Popup\n data-slot=\"sheet-content\"\n className={cn(\n \"fixed z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-open:animate-in data-closed:animate-out\",\n side === \"right\" &&\n \"inset-y-0 right-0 h-full w-3/4 border-l data-open:slide-in-from-right-full data-closed:slide-out-to-right-full sm:max-w-sm\",\n side === \"left\" &&\n \"inset-y-0 left-0 h-full w-3/4 border-r data-open:slide-in-from-left-full data-closed:slide-out-to-left-full sm:max-w-sm\",\n side === \"top\" &&\n \"inset-x-0 top-0 border-b data-open:slide-in-from-top-full data-closed:slide-out-to-top-full\",\n side === \"bottom\" &&\n \"inset-x-0 bottom-0 border-t data-open:slide-in-from-bottom-full data-closed:slide-out-to-bottom-full\",\n className\n )}\n {...props}\n >\n {children}\n <SheetPrimitive.Close\n data-slot=\"sheet-close\"\n className=\"absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-hidden focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary\"\n >\n <XIcon className=\"h-4 w-4\" />\n <span className=\"sr-only\">Close</span>\n </SheetPrimitive.Close>\n </SheetPrimitive.Popup>\n </SheetPortal>\n )\n}\n\nfunction SheetHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"sheet-header\"\n className={cn(\n \"flex flex-col gap-2 text-center sm:text-left\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction SheetFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"sheet-footer\"\n className={cn(\n \"flex flex-col-reverse sm:flex-row sm:justify-end sm:gap-2\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction SheetTitle({\n className,\n ...props\n}: SheetPrimitive.Title.Props) {\n return (\n <SheetPrimitive.Title\n data-slot=\"sheet-title\"\n className={cn(\n \"cn-font-heading text-lg font-semibold text-foreground\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction SheetDescription({\n className,\n ...props\n}: SheetPrimitive.Description.Props) {\n return (\n <SheetPrimitive.Description\n data-slot=\"sheet-description\"\n className={cn(\"text-sm text-muted-foreground\", className)}\n {...props}\n />\n )\n}\n\nexport {\n Sheet,\n SheetPortal,\n SheetOverlay,\n SheetTrigger,\n SheetClose,\n SheetContent,\n SheetHeader,\n SheetFooter,\n SheetTitle,\n SheetDescription,\n}\n"
350
916
  }
351
917
  ]
352
918
  },
353
919
  {
354
920
  "name": "sidebar",
921
+ "type": "components:ui",
922
+ "frameworks": [
923
+ "react",
924
+ "nextjs",
925
+ "vue",
926
+ "nuxt",
927
+ "solid",
928
+ "svelte",
929
+ "astro",
930
+ "remix"
931
+ ],
355
932
  "dependencies": [],
933
+ "registryDependencies": [],
356
934
  "files": [
357
935
  {
358
936
  "name": "sidebar.tsx",
359
- "content": "\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nconst SidebarContext = React.createContext<{\r\n isCollapsed: boolean\r\n setIsCollapsed: React.Dispatch<React.SetStateAction<boolean>>\r\n} | null>(null)\r\n\r\nfunction useSidebar() {\r\n const context = React.useContext(SidebarContext)\r\n if (!context) throw new Error(\"useSidebar must be used within a SidebarProvider\")\r\n return context\r\n}\r\n\r\nconst SidebarProvider = ({\r\n children,\r\n className,\r\n ...props\r\n}: React.HTMLAttributes<HTMLDivElement>) => {\r\n const [isCollapsed, setIsCollapsed] = React.useState(false)\r\n\r\n return (\r\n <SidebarContext.Provider value={{ isCollapsed, setIsCollapsed }}>\r\n <div\r\n className={cn(\r\n \"flex min-h-screen w-full bg-neutral-50/50 text-neutral-950\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n {children}\r\n </div>\r\n </SidebarContext.Provider>\r\n )\r\n}\r\nSidebarProvider.displayName = \"SidebarProvider\"\r\n\r\nconst Sidebar = React.forwardRef<\r\n HTMLDivElement,\r\n React.HTMLAttributes<HTMLDivElement>\r\n>(({ className, children, ...props }, ref) => {\r\n const { isCollapsed } = useSidebar()\r\n\r\n return (\r\n <aside\r\n ref={ref}\r\n className={cn(\r\n \"h-screen border-r border-neutral-200 bg-white transition-all duration-300 ease-in-out flex flex-col shrink-0 sticky top-0 z-20\",\r\n isCollapsed ? \"w-16\" : \"w-64\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n {children}\r\n </aside>\r\n )\r\n})\r\nSidebar.displayName = \"Sidebar\"\r\n\r\nconst SidebarTrigger = React.forwardRef<\r\n HTMLButtonElement,\r\n React.ButtonHTMLAttributes<HTMLButtonElement>\r\n>(({ className, ...props }, ref) => {\r\n const { isCollapsed, setIsCollapsed } = useSidebar()\r\n\r\n return (\r\n <button\r\n ref={ref}\r\n onClick={() => setIsCollapsed(!isCollapsed)}\r\n className={cn(\r\n \"inline-flex h-8 w-8 items-center justify-center rounded-md border border-neutral-200 bg-white text-neutral-500 hover:text-neutral-900 shadow-2xs cursor-pointer focus-visible:outline-hidden\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n width=\"16\"\r\n height=\"16\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n strokeWidth=\"2\"\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n className={cn(\"transition-transform duration-200\", isCollapsed && \"rotate-180\")}\r\n >\r\n <rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" />\r\n <path d=\"M9 3v18\" />\r\n </svg>\r\n </button>\r\n )\r\n})\r\nSidebarTrigger.displayName = \"SidebarTrigger\"\r\n\r\nconst SidebarContent = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (\r\n <div className={cn(\"flex-1 overflow-y-auto p-3 space-y-1.5\", className)} {...props} />\r\n)\r\nSidebarContent.displayName = \"SidebarContent\"\r\n\r\nconst SidebarGroup = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (\r\n <div className={cn(\"flex flex-col space-y-1\", className)} {...props} />\r\n)\r\nSidebarGroup.displayName = \"SidebarGroup\"\r\n\r\nconst SidebarGroupLabel = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => {\r\n const { isCollapsed } = useSidebar()\r\n if (isCollapsed) return null\r\n return (\r\n <div\r\n className={cn(\r\n \"px-2 py-1.5 text-xs font-semibold uppercase tracking-wider text-neutral-400 select-none\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\nSidebarGroupLabel.displayName = \"SidebarGroupLabel\"\r\n\r\nconst SidebarItem = React.forwardRef<\r\n HTMLButtonElement,\r\n React.ButtonHTMLAttributes<HTMLButtonElement> & { isActive?: boolean }\r\n>(({ className, isActive, children, ...props }, ref) => {\r\n const { isCollapsed } = useSidebar()\r\n\r\n return (\r\n <button\r\n ref={ref}\r\n className={cn(\r\n \"flex w-full items-center rounded-lg px-3 py-2 text-sm font-medium transition-all cursor-pointer group text-left select-none relative\",\r\n isActive\r\n ? \"bg-neutral-900 text-neutral-50 shadow-xs\"\r\n : \"text-neutral-600 hover:bg-neutral-100 hover:text-neutral-900\",\r\n isCollapsed && \"justify-center px-0 h-10\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n {children}\r\n </button>\r\n )\r\n})\r\nSidebarItem.displayName = \"SidebarItem\"\r\n\r\nexport {\r\n SidebarProvider,\r\n Sidebar,\r\n SidebarTrigger,\r\n SidebarContent,\r\n SidebarGroup,\r\n SidebarGroupLabel,\r\n SidebarItem,\r\n useSidebar,\r\n}"
937
+ "content": "\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport { mergeProps } from \"@base-ui/react/merge-props\"\r\nimport { useRender } from \"@base-ui/react/use-render\"\r\nimport { cva, type VariantProps } from \"class-variance-authority\"\r\nimport { PanelLeftIcon } from \"lucide-react\"\r\n\r\nimport { cn } from \"@/lib/utils\"\r\nimport { useIsMobile } from \"@/hooks/use-mobile\"\r\nimport { Button } from \"@/components/ui/button\"\r\nimport { Input } from \"@/components/ui/input\"\r\nimport { Separator } from \"@/components/ui/separator\"\r\nimport {\r\n Sheet,\r\n SheetContent,\r\n SheetDescription,\r\n SheetHeader,\r\n SheetTitle,\r\n} from \"@/components/ui/sheet\"\r\nimport { Skeleton } from \"@/components/ui/skeleton\"\r\nimport {\r\n Tooltip,\r\n TooltipContent,\r\n TooltipTrigger,\r\n} from \"@/components/ui/tooltip\"\r\n\r\nconst SIDEBAR_COOKIE_NAME = \"sidebar_state\"\r\nconst SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7\r\nconst SIDEBAR_WIDTH = \"16rem\"\r\nconst SIDEBAR_WIDTH_MOBILE = \"18rem\"\r\nconst SIDEBAR_WIDTH_ICON = \"3rem\"\r\nconst SIDEBAR_KEYBOARD_SHORTCUT = \"b\"\r\n\r\ntype SidebarContextProps = {\r\n state: \"expanded\" | \"collapsed\"\r\n open: boolean\r\n setOpen: (open: boolean) => void\r\n openMobile: boolean\r\n setOpenMobile: (open: boolean) => void\r\n isMobile: boolean\r\n toggleSidebar: () => void\r\n}\r\n\r\nconst SidebarContext = React.createContext<SidebarContextProps | null>(null)\r\n\r\nfunction useSidebar() {\r\n const context = React.useContext(SidebarContext)\r\n if (!context) {\r\n throw new Error(\"useSidebar must be used within a SidebarProvider.\")\r\n }\r\n\r\n return context\r\n}\r\n\r\nfunction SidebarProvider({\r\n defaultOpen = true,\r\n open: openProp,\r\n onOpenChange: setOpenProp,\r\n className,\r\n style,\r\n children,\r\n ...props\r\n}: React.ComponentProps<\"div\"> & {\r\n defaultOpen?: boolean\r\n open?: boolean\r\n onOpenChange?: (open: boolean) => void\r\n}) {\r\n const isMobile = useIsMobile()\r\n const [openMobile, setOpenMobile] = React.useState(false)\r\n\r\n // This is the internal state of the sidebar.\r\n // We use openProp and setOpenProp for control from outside the component.\r\n const [_open, _setOpen] = React.useState(defaultOpen)\r\n const open = openProp ?? _open\r\n const setOpen = React.useCallback(\r\n (value: boolean | ((value: boolean) => boolean)) => {\r\n const openState = typeof value === \"function\" ? value(open) : value\r\n if (setOpenProp) {\r\n setOpenProp(openState)\r\n } else {\r\n _setOpen(openState)\r\n }\r\n\r\n // This sets the cookie to keep the sidebar state.\r\n document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`\r\n },\r\n [setOpenProp, open]\r\n )\r\n\r\n // Helper to toggle the sidebar.\r\n const toggleSidebar = React.useCallback(() => {\r\n return isMobile ? setOpenMobile((open) => !open) : setOpen((open) => !open)\r\n }, [isMobile, setOpen, setOpenMobile])\r\n\r\n // Adds a keyboard shortcut to toggle the sidebar.\r\n React.useEffect(() => {\r\n const handleKeyDown = (event: KeyboardEvent) => {\r\n if (\r\n event.key === SIDEBAR_KEYBOARD_SHORTCUT &&\r\n (event.metaKey || event.ctrlKey)\r\n ) {\r\n event.preventDefault()\r\n toggleSidebar()\r\n }\r\n }\r\n\r\n window.addEventListener(\"keydown\", handleKeyDown)\r\n return () => window.removeEventListener(\"keydown\", handleKeyDown)\r\n }, [toggleSidebar])\r\n\r\n // We add a state so that we can do data-state=\"expanded\" or \"collapsed\".\r\n // This makes it easier to style the sidebar with Tailwind classes.\r\n const state = open ? \"expanded\" : \"collapsed\"\r\n\r\n const contextValue = React.useMemo<SidebarContextProps>(\r\n () => ({\r\n state,\r\n open,\r\n setOpen,\r\n isMobile,\r\n openMobile,\r\n setOpenMobile,\r\n toggleSidebar,\r\n }),\r\n [state, open, setOpen, isMobile, openMobile, setOpenMobile, toggleSidebar]\r\n )\r\n\r\n return (\r\n <SidebarContext.Provider value={contextValue}>\r\n <div\r\n data-slot=\"sidebar-wrapper\"\r\n style={\r\n {\r\n \"--sidebar-width\": SIDEBAR_WIDTH,\r\n \"--sidebar-width-icon\": SIDEBAR_WIDTH_ICON,\r\n ...style,\r\n } as React.CSSProperties\r\n }\r\n className={cn(\r\n \"group/sidebar-wrapper flex min-h-svh w-full has-data-[variant=inset]:bg-sidebar\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n {children}\r\n </div>\r\n </SidebarContext.Provider>\r\n )\r\n}\r\n\r\nfunction Sidebar({\r\n side = \"left\",\r\n variant = \"sidebar\",\r\n collapsible = \"offcanvas\",\r\n className,\r\n children,\r\n dir,\r\n ...props\r\n}: React.ComponentProps<\"div\"> & {\r\n side?: \"left\" | \"right\"\r\n variant?: \"sidebar\" | \"floating\" | \"inset\"\r\n collapsible?: \"offcanvas\" | \"icon\" | \"none\"\r\n}) {\r\n const { isMobile, state, openMobile, setOpenMobile } = useSidebar()\r\n\r\n if (collapsible === \"none\") {\r\n return (\r\n <div\r\n data-slot=\"sidebar\"\r\n className={cn(\r\n \"flex h-full w-(--sidebar-width) flex-col bg-sidebar text-sidebar-foreground\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n {children}\r\n </div>\r\n )\r\n }\r\n\r\n if (isMobile) {\r\n return (\r\n <Sheet open={openMobile} onOpenChange={setOpenMobile} {...props}>\r\n <SheetContent\r\n dir={dir}\r\n data-sidebar=\"sidebar\"\r\n data-slot=\"sidebar\"\r\n data-mobile=\"true\"\r\n className=\"w-(--sidebar-width) bg-sidebar p-0 text-sidebar-foreground [&>button]:hidden\"\r\n style={\r\n {\r\n \"--sidebar-width\": SIDEBAR_WIDTH_MOBILE,\r\n } as React.CSSProperties\r\n }\r\n side={side}\r\n >\r\n <SheetHeader className=\"sr-only\">\r\n <SheetTitle>Sidebar</SheetTitle>\r\n <SheetDescription>Displays the mobile sidebar.</SheetDescription>\r\n </SheetHeader>\r\n <div className=\"flex h-full w-full flex-col\">{children}</div>\r\n </SheetContent>\r\n </Sheet>\r\n )\r\n }\r\n\r\n return (\r\n <div\r\n className=\"group peer hidden text-sidebar-foreground md:block\"\r\n data-state={state}\r\n data-collapsible={state === \"collapsed\" ? collapsible : \"\"}\r\n data-variant={variant}\r\n data-side={side}\r\n data-slot=\"sidebar\"\r\n >\r\n {/* This is what handles the sidebar gap on desktop */}\r\n <div\r\n data-slot=\"sidebar-gap\"\r\n className={cn(\r\n \"relative w-(--sidebar-width) bg-transparent transition-[width] duration-200 ease-linear\",\r\n \"group-data-[collapsible=offcanvas]:w-0\",\r\n \"group-data-[side=right]:rotate-180\",\r\n variant === \"floating\" || variant === \"inset\"\r\n ? \"group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4)))]\"\r\n : \"group-data-[collapsible=icon]:w-(--sidebar-width-icon)\"\r\n )}\r\n />\r\n <div\r\n data-slot=\"sidebar-container\"\r\n data-side={side}\r\n className={cn(\r\n \"fixed inset-y-0 z-10 hidden h-svh w-(--sidebar-width) transition-[left,right,width] duration-200 ease-linear data-[side=left]:left-0 data-[side=left]:group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)] data-[side=right]:right-0 data-[side=right]:group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)] md:flex\",\r\n // Adjust the padding for floating and inset variants.\r\n variant === \"floating\" || variant === \"inset\"\r\n ? \"p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4))+2px)]\"\r\n : \"group-data-[collapsible=icon]:w-(--sidebar-width-icon) group-data-[side=left]:border-r group-data-[side=right]:border-l\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n <div\r\n data-sidebar=\"sidebar\"\r\n data-slot=\"sidebar-inner\"\r\n className=\"flex size-full flex-col bg-sidebar group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:shadow-sm group-data-[variant=floating]:ring-1 group-data-[variant=floating]:ring-sidebar-border\"\r\n >\r\n {children}\r\n </div>\r\n </div>\r\n </div>\r\n )\r\n}\r\n\r\nfunction SidebarTrigger({\r\n className,\r\n onClick,\r\n ...props\r\n}: React.ComponentProps<typeof Button>) {\r\n const { toggleSidebar } = useSidebar()\r\n\r\n return (\r\n <Button\r\n data-sidebar=\"trigger\"\r\n data-slot=\"sidebar-trigger\"\r\n variant=\"ghost\"\r\n size=\"icon-sm\"\r\n className={cn(className)}\r\n onClick={(event) => {\r\n onClick?.(event)\r\n toggleSidebar()\r\n }}\r\n {...props}\r\n >\r\n <PanelLeftIcon className=\"cn-rtl-flip\" />\r\n <span className=\"sr-only\">Toggle Sidebar</span>\r\n </Button>\r\n )\r\n}\r\n\r\nfunction SidebarRail({ className, ...props }: React.ComponentProps<\"button\">) {\r\n const { toggleSidebar } = useSidebar()\r\n\r\n return (\r\n <button\r\n data-sidebar=\"rail\"\r\n data-slot=\"sidebar-rail\"\r\n aria-label=\"Toggle Sidebar\"\r\n tabIndex={-1}\r\n onClick={toggleSidebar}\r\n title=\"Toggle Sidebar\"\r\n className={cn(\r\n \"absolute inset-y-0 z-20 hidden w-4 transition-all ease-linear group-data-[side=left]:-right-4 group-data-[side=right]:left-0 after:absolute after:inset-y-0 after:start-1/2 after:w-[2px] hover:after:bg-sidebar-border sm:flex ltr:-translate-x-1/2 rtl:-translate-x-1/2\",\r\n \"in-data-[side=left]:cursor-w-resize in-data-[side=right]:cursor-e-resize\",\r\n \"[[data-side=left][data-state=collapsed]_&]:cursor-e-resize [[data-side=right][data-state=collapsed]_&]:cursor-w-resize\",\r\n \"group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full hover:group-data-[collapsible=offcanvas]:bg-sidebar\",\r\n \"[[data-side=left][data-collapsible=offcanvas]_&]:-right-2\",\r\n \"[[data-side=right][data-collapsible=offcanvas]_&]:-left-2\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction SidebarInset({ className, ...props }: React.ComponentProps<\"main\">) {\r\n return (\r\n <main\r\n data-slot=\"sidebar-inset\"\r\n className={cn(\r\n \"relative flex w-full flex-1 flex-col bg-background md:peer-data-[variant=inset]:m-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow-sm md:peer-data-[variant=inset]:peer-data-[state=collapsed]:ml-2\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction SidebarInput({\r\n className,\r\n ...props\r\n}: React.ComponentProps<typeof Input>) {\r\n return (\r\n <Input\r\n data-slot=\"sidebar-input\"\r\n data-sidebar=\"input\"\r\n className={cn(\"h-8 w-full bg-background shadow-none\", className)}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction SidebarHeader({ className, ...props }: React.ComponentProps<\"div\">) {\r\n return (\r\n <div\r\n data-slot=\"sidebar-header\"\r\n data-sidebar=\"header\"\r\n className={cn(\"flex flex-col gap-2 p-2\", className)}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction SidebarFooter({ className, ...props }: React.ComponentProps<\"div\">) {\r\n return (\r\n <div\r\n data-slot=\"sidebar-footer\"\r\n data-sidebar=\"footer\"\r\n className={cn(\"flex flex-col gap-2 p-2\", className)}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction SidebarSeparator({\r\n className,\r\n ...props\r\n}: React.ComponentProps<typeof Separator>) {\r\n return (\r\n <Separator\r\n data-slot=\"sidebar-separator\"\r\n data-sidebar=\"separator\"\r\n className={cn(\"mx-2 w-auto bg-sidebar-border\", className)}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction SidebarContent({ className, ...props }: React.ComponentProps<\"div\">) {\r\n return (\r\n <div\r\n data-slot=\"sidebar-content\"\r\n data-sidebar=\"content\"\r\n className={cn(\r\n \"no-scrollbar flex min-h-0 flex-1 flex-col gap-0 overflow-auto group-data-[collapsible=icon]:overflow-hidden\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction SidebarGroup({ className, ...props }: React.ComponentProps<\"div\">) {\r\n return (\r\n <div\r\n data-slot=\"sidebar-group\"\r\n data-sidebar=\"group\"\r\n className={cn(\"relative flex w-full min-w-0 flex-col p-2\", className)}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction SidebarGroupLabel({\r\n className,\r\n render,\r\n ...props\r\n}: useRender.ComponentProps<\"div\"> & React.ComponentProps<\"div\">) {\r\n return useRender({\r\n defaultTagName: \"div\",\r\n props: mergeProps<\"div\">(\r\n {\r\n className: cn(\r\n \"flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium text-sidebar-foreground/70 ring-sidebar-ring outline-hidden transition-[margin,opacity] duration-200 ease-linear group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0 focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0\",\r\n className\r\n ),\r\n },\r\n props\r\n ),\r\n render,\r\n state: {\r\n slot: \"sidebar-group-label\",\r\n sidebar: \"group-label\",\r\n },\r\n })\r\n}\r\n\r\nfunction SidebarGroupAction({\r\n className,\r\n render,\r\n ...props\r\n}: useRender.ComponentProps<\"button\"> & React.ComponentProps<\"button\">) {\r\n return useRender({\r\n defaultTagName: \"button\",\r\n props: mergeProps<\"button\">(\r\n {\r\n className: cn(\r\n \"absolute top-3.5 right-3 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-sidebar-foreground ring-sidebar-ring outline-hidden transition-transform group-data-[collapsible=icon]:hidden after:absolute after:-inset-2 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 md:after:hidden [&>svg]:size-4 [&>svg]:shrink-0\",\r\n className\r\n ),\r\n },\r\n props\r\n ),\r\n render,\r\n state: {\r\n slot: \"sidebar-group-action\",\r\n sidebar: \"group-action\",\r\n },\r\n })\r\n}\r\n\r\nfunction SidebarGroupContent({\r\n className,\r\n ...props\r\n}: React.ComponentProps<\"div\">) {\r\n return (\r\n <div\r\n data-slot=\"sidebar-group-content\"\r\n data-sidebar=\"group-content\"\r\n className={cn(\"w-full text-sm\", className)}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction SidebarMenu({ className, ...props }: React.ComponentProps<\"ul\">) {\r\n return (\r\n <ul\r\n data-slot=\"sidebar-menu\"\r\n data-sidebar=\"menu\"\r\n className={cn(\"flex w-full min-w-0 flex-col gap-0\", className)}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction SidebarMenuItem({ className, ...props }: React.ComponentProps<\"li\">) {\r\n return (\r\n <li\r\n data-slot=\"sidebar-menu-item\"\r\n data-sidebar=\"menu-item\"\r\n className={cn(\"group/menu-item relative\", className)}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nconst sidebarMenuButtonVariants = cva(\r\n \"peer/menu-button group/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm ring-sidebar-ring outline-hidden transition-[width,height,padding] group-has-data-[sidebar=menu-action]/menu-item:pr-8 group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-open:hover:bg-sidebar-accent data-open:hover:text-sidebar-accent-foreground data-active:bg-sidebar-accent data-active:font-medium data-active:text-sidebar-accent-foreground [&_svg]:size-4 [&_svg]:shrink-0 [&>span:last-child]:truncate\",\r\n {\r\n variants: {\r\n variant: {\r\n default: \"hover:bg-sidebar-accent hover:text-sidebar-accent-foreground\",\r\n outline:\r\n \"bg-background shadow-[0_0_0_1px_var(--sidebar-border)] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground hover:shadow-[0_0_0_1px_var(--sidebar-accent)]\",\r\n },\r\n size: {\r\n default: \"h-8 text-sm\",\r\n sm: \"h-7 text-xs\",\r\n lg: \"h-12 text-sm group-data-[collapsible=icon]:p-0!\",\r\n },\r\n },\r\n defaultVariants: {\r\n variant: \"default\",\r\n size: \"default\",\r\n },\r\n }\r\n)\r\n\r\nfunction SidebarMenuButton({\r\n render,\r\n isActive = false,\r\n variant = \"default\",\r\n size = \"default\",\r\n tooltip,\r\n className,\r\n ...props\r\n}: useRender.ComponentProps<\"button\"> &\r\n React.ComponentProps<\"button\"> & {\r\n isActive?: boolean\r\n tooltip?: string | React.ComponentProps<typeof TooltipContent>\r\n } & VariantProps<typeof sidebarMenuButtonVariants>) {\r\n const { isMobile, state } = useSidebar()\r\n const comp = useRender({\r\n defaultTagName: \"button\",\r\n props: mergeProps<\"button\">(\r\n {\r\n className: cn(sidebarMenuButtonVariants({ variant, size }), className),\r\n },\r\n props\r\n ),\r\n render: !tooltip ? render : <TooltipTrigger render={render} />,\r\n state: {\r\n slot: \"sidebar-menu-button\",\r\n sidebar: \"menu-button\",\r\n size,\r\n active: isActive,\r\n },\r\n })\r\n\r\n if (!tooltip) {\r\n return comp\r\n }\r\n\r\n if (typeof tooltip === \"string\") {\r\n tooltip = {\r\n children: tooltip,\r\n }\r\n }\r\n\r\n return (\r\n <Tooltip>\r\n {comp}\r\n <TooltipContent\r\n side=\"right\"\r\n align=\"center\"\r\n hidden={state !== \"collapsed\" || isMobile}\r\n {...tooltip}\r\n />\r\n </Tooltip>\r\n )\r\n}\r\n\r\nfunction SidebarMenuAction({\r\n className,\r\n render,\r\n showOnHover = false,\r\n ...props\r\n}: useRender.ComponentProps<\"button\"> &\r\n React.ComponentProps<\"button\"> & {\r\n showOnHover?: boolean\r\n }) {\r\n return useRender({\r\n defaultTagName: \"button\",\r\n props: mergeProps<\"button\">(\r\n {\r\n className: cn(\r\n \"absolute top-1.5 right-1 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-sidebar-foreground ring-sidebar-ring outline-hidden transition-transform group-data-[collapsible=icon]:hidden peer-hover/menu-button:text-sidebar-accent-foreground peer-data-[size=default]/menu-button:top-1.5 peer-data-[size=lg]/menu-button:top-2.5 peer-data-[size=sm]/menu-button:top-1 after:absolute after:-inset-2 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 md:after:hidden [&>svg]:size-4 [&>svg]:shrink-0\",\r\n showOnHover &&\r\n \"group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 peer-data-active/menu-button:text-sidebar-accent-foreground aria-expanded:opacity-100 md:opacity-0\",\r\n className\r\n ),\r\n },\r\n props\r\n ),\r\n render,\r\n state: {\r\n slot: \"sidebar-menu-action\",\r\n sidebar: \"menu-action\",\r\n },\r\n })\r\n}\r\n\r\nfunction SidebarMenuBadge({\r\n className,\r\n ...props\r\n}: React.ComponentProps<\"div\">) {\r\n return (\r\n <div\r\n data-slot=\"sidebar-menu-badge\"\r\n data-sidebar=\"menu-badge\"\r\n className={cn(\r\n \"pointer-events-none absolute right-1 flex h-5 min-w-5 items-center justify-center rounded-md px-1 text-xs font-medium text-sidebar-foreground tabular-nums select-none group-data-[collapsible=icon]:hidden peer-hover/menu-button:text-sidebar-accent-foreground peer-data-[size=default]/menu-button:top-1.5 peer-data-[size=lg]/menu-button:top-2.5 peer-data-[size=sm]/menu-button:top-1 peer-data-active/menu-button:text-sidebar-accent-foreground\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction SidebarMenuSkeleton({\r\n className,\r\n showIcon = false,\r\n ...props\r\n}: React.ComponentProps<\"div\"> & {\r\n showIcon?: boolean\r\n}) {\r\n // Random width between 50 to 90%.\r\n const [width] = React.useState(() => {\r\n return `${Math.floor(Math.random() * 40) + 50}%`\r\n })\r\n\r\n return (\r\n <div\r\n data-slot=\"sidebar-menu-skeleton\"\r\n data-sidebar=\"menu-skeleton\"\r\n className={cn(\"flex h-8 items-center gap-2 rounded-md px-2\", className)}\r\n {...props}\r\n >\r\n {showIcon && (\r\n <Skeleton\r\n className=\"size-4 rounded-md\"\r\n data-sidebar=\"menu-skeleton-icon\"\r\n />\r\n )}\r\n <Skeleton\r\n className=\"h-4 max-w-(--skeleton-width) flex-1\"\r\n data-sidebar=\"menu-skeleton-text\"\r\n style={\r\n {\r\n \"--skeleton-width\": width,\r\n } as React.CSSProperties\r\n }\r\n />\r\n </div>\r\n )\r\n}\r\n\r\nfunction SidebarMenuSub({ className, ...props }: React.ComponentProps<\"ul\">) {\r\n return (\r\n <ul\r\n data-slot=\"sidebar-menu-sub\"\r\n data-sidebar=\"menu-sub\"\r\n className={cn(\r\n \"mx-3.5 flex min-w-0 translate-x-px flex-col gap-1 border-l border-sidebar-border px-2.5 py-0.5 group-data-[collapsible=icon]:hidden\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction SidebarMenuSubItem({\r\n className,\r\n ...props\r\n}: React.ComponentProps<\"li\">) {\r\n return (\r\n <li\r\n data-slot=\"sidebar-menu-sub-item\"\r\n data-sidebar=\"menu-sub-item\"\r\n className={cn(\"group/menu-sub-item relative\", className)}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction SidebarMenuSubButton({\r\n render,\r\n size = \"md\",\r\n isActive = false,\r\n className,\r\n ...props\r\n}: useRender.ComponentProps<\"a\"> &\r\n React.ComponentProps<\"a\"> & {\r\n size?: \"sm\" | \"md\"\r\n isActive?: boolean\r\n }) {\r\n return useRender({\r\n defaultTagName: \"a\",\r\n props: mergeProps<\"a\">(\r\n {\r\n className: cn(\r\n \"flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 text-sidebar-foreground ring-sidebar-ring outline-hidden group-data-[collapsible=icon]:hidden hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[size=md]:text-sm data-[size=sm]:text-xs data-active:bg-sidebar-accent data-active:text-sidebar-accent-foreground [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0 [&>svg]:text-sidebar-accent-foreground\",\r\n className\r\n ),\r\n },\r\n props\r\n ),\r\n render,\r\n state: {\r\n slot: \"sidebar-menu-sub-button\",\r\n sidebar: \"menu-sub-button\",\r\n size,\r\n active: isActive,\r\n },\r\n })\r\n}\r\n\r\nexport {\r\n Sidebar,\r\n SidebarContent,\r\n SidebarFooter,\r\n SidebarGroup,\r\n SidebarGroupAction,\r\n SidebarGroupContent,\r\n SidebarGroupLabel,\r\n SidebarHeader,\r\n SidebarInput,\r\n SidebarInset,\r\n SidebarMenu,\r\n SidebarMenuAction,\r\n SidebarMenuBadge,\r\n SidebarMenuButton,\r\n SidebarMenuItem,\r\n SidebarMenuSkeleton,\r\n SidebarMenuSub,\r\n SidebarMenuSubButton,\r\n SidebarMenuSubItem,\r\n SidebarProvider,\r\n SidebarRail,\r\n SidebarSeparator,\r\n SidebarTrigger,\r\n useSidebar,\r\n}\r\n"
360
938
  }
361
939
  ]
362
940
  },
363
941
  {
364
942
  "name": "skeleton",
943
+ "type": "components:ui",
944
+ "frameworks": [
945
+ "react",
946
+ "nextjs",
947
+ "vue",
948
+ "nuxt",
949
+ "solid",
950
+ "svelte",
951
+ "astro",
952
+ "remix"
953
+ ],
365
954
  "dependencies": [],
955
+ "registryDependencies": [],
366
956
  "files": [
367
957
  {
368
958
  "name": "skeleton.tsx",
369
- "content": "import * as React from \"react\"\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nfunction Skeleton({\r\n className,\r\n ...props\r\n}: React.HTMLAttributes<HTMLDivElement>) {\r\n return (\r\n <div\r\n className={cn(\r\n \"animate-pulse rounded-md bg-neutral-200/60\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nexport { Skeleton }"
959
+ "content": "import { cn } from \"@/lib/utils\"\r\n\r\nfunction Skeleton({ className, ...props }: React.ComponentProps<\"div\">) {\r\n return (\r\n <div\r\n data-slot=\"skeleton\"\r\n className={cn(\"animate-pulse rounded-md bg-muted\", className)}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nexport { Skeleton }\r\n"
370
960
  }
371
961
  ]
372
962
  },
373
963
  {
374
964
  "name": "slider",
965
+ "type": "components:ui",
966
+ "frameworks": [
967
+ "react",
968
+ "nextjs",
969
+ "vue",
970
+ "nuxt",
971
+ "solid",
972
+ "svelte",
973
+ "astro",
974
+ "remix"
975
+ ],
375
976
  "dependencies": [
376
977
  "@base-ui/react"
377
978
  ],
979
+ "registryDependencies": [],
378
980
  "files": [
379
981
  {
380
982
  "name": "slider.tsx",
381
- "content": "\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport { Slider as BaseSlider } from \"@base-ui/react/slider\"\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nconst Slider = React.forwardRef<\r\n HTMLDivElement,\r\n React.ComponentPropsWithoutRef<typeof BaseSlider.Root>\r\n>(({ className, ...props }, ref) => (\r\n <BaseSlider.Root\r\n ref={ref}\r\n className={cn(\"relative flex w-full touch-none select-none items-center group py-4\", className)}\r\n {...props}\r\n >\r\n <BaseSlider.Track className=\"relative h-2 w-full grow overflow-hidden rounded-full bg-neutral-100\">\r\n <BaseSlider.Indicator className=\"absolute h-full bg-neutral-900\" />\r\n </BaseSlider.Track>\r\n <BaseSlider.Thumb \r\n className={cn(\r\n \"block h-5 w-5 rounded-full border border-neutral-200 bg-white shadow-sm transition-colors\",\r\n \"focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-neutral-950\",\r\n \"disabled:pointer-events-none disabled:opacity-50 cursor-grab active:cursor-grabbing\"\r\n )} \r\n />\r\n </BaseSlider.Root>\r\n))\r\nSlider.displayName = \"Slider\"\r\n\r\nexport { Slider }"
983
+ "content": "import { Slider as SliderPrimitive } from \"@base-ui/react/slider\"\r\n\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nfunction Slider({\r\n className,\r\n defaultValue,\r\n value,\r\n min = 0,\r\n max = 100,\r\n ...props\r\n}: SliderPrimitive.Root.Props) {\r\n const _values = Array.isArray(value)\r\n ? value\r\n : Array.isArray(defaultValue)\r\n ? defaultValue\r\n : [min, max]\r\n\r\n return (\r\n <SliderPrimitive.Root\r\n className={cn(\"data-horizontal:w-full data-vertical:h-full\", className)}\r\n data-slot=\"slider\"\r\n defaultValue={defaultValue}\r\n value={value}\r\n min={min}\r\n max={max}\r\n thumbAlignment=\"edge\"\r\n {...props}\r\n >\r\n <SliderPrimitive.Control className=\"relative flex w-full touch-none items-center select-none data-disabled:opacity-50 data-vertical:h-full data-vertical:min-h-40 data-vertical:w-auto data-vertical:flex-col\">\r\n <SliderPrimitive.Track\r\n data-slot=\"slider-track\"\r\n className=\"relative grow overflow-hidden rounded-full bg-muted select-none data-horizontal:h-1 data-horizontal:w-full data-vertical:h-full data-vertical:w-1\"\r\n >\r\n <SliderPrimitive.Indicator\r\n data-slot=\"slider-range\"\r\n className=\"bg-primary select-none data-horizontal:h-full data-vertical:w-full\"\r\n />\r\n </SliderPrimitive.Track>\r\n {Array.from({ length: _values.length }, (_, index) => (\r\n <SliderPrimitive.Thumb\r\n data-slot=\"slider-thumb\"\r\n key={index}\r\n className=\"relative block size-3 shrink-0 rounded-full border border-ring bg-white ring-ring/50 transition-[color,box-shadow] select-none after:absolute after:-inset-2 hover:ring-3 focus-visible:ring-3 focus-visible:outline-hidden active:ring-3 disabled:pointer-events-none disabled:opacity-50\"\r\n />\r\n ))}\r\n </SliderPrimitive.Control>\r\n </SliderPrimitive.Root>\r\n )\r\n}\r\n\r\nexport { Slider }\r\n"
382
984
  }
383
985
  ]
384
986
  },
385
987
  {
386
988
  "name": "sonner",
989
+ "type": "components:ui",
990
+ "frameworks": [
991
+ "react",
992
+ "nextjs",
993
+ "vue",
994
+ "nuxt",
995
+ "solid",
996
+ "svelte",
997
+ "astro",
998
+ "remix"
999
+ ],
387
1000
  "dependencies": [],
1001
+ "registryDependencies": [],
388
1002
  "files": [
389
1003
  {
390
1004
  "name": "sonner.tsx",
391
- "content": "\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport { cn } from \"@/lib/utils\"\r\n\r\ninterface SonnerMessage {\r\n id: string\r\n message: string\r\n description?: string\r\n}\r\n\r\nconst SonnerContext = React.createContext<{\r\n toast: (message: string, description?: string) => void\r\n} | null>(null)\r\n\r\nexport function useSonner() {\r\n const context = React.useContext(SonnerContext)\r\n if (!context) throw new Error(\"useSonner must be used within a SonnerProvider\")\r\n return context\r\n}\r\n\r\nexport const SonnerProvider = ({ children }: { children: React.ReactNode }) => {\r\n const [items, setItems] = React.useState<SonnerMessage[]>([])\r\n\r\n const toast = React.useCallback((message: string, description?: string) => {\r\n const id = Math.random().toString(36).substring(2, 9)\r\n setItems((prev) => [...prev, { id, message, description }].slice(-3)) // Keeps a max stack of 3 on screen\r\n\r\n setTimeout(() => {\r\n setItems((prev) => prev.filter((item) => item.id !== id))\r\n }, 4000)\r\n }, [])\r\n\r\n return (\r\n <SonnerContext.Provider value={{ toast }}>\r\n {children}\r\n <div className=\"fixed bottom-4 right-4 z-50 flex flex-col gap-2 pointer-events-none w-full max-w-sm\">\r\n {items.map((item, index) => {\r\n const isBottom = items.length - 1 - index\r\n return (\r\n <div\r\n key={item.id}\r\n style={{\r\n transform: `scale(${1 - isBottom * 0.05}) translateY(${isBottom * 10}px)`,\r\n zIndex: items.length - isBottom,\r\n opacity: 1 - isBottom * 0.3,\r\n }}\r\n className={cn(\r\n \"pointer-events-auto w-full rounded-xl border border-neutral-200 bg-white p-4 text-neutral-950 shadow-md transition-all duration-300 flex flex-col gap-1 origin-bottom\",\r\n isBottom > 0 ? \"absolute bottom-0\" : \"relative\"\r\n )}\r\n >\r\n <div className=\"text-sm font-semibold tracking-tight\">{item.message}</div>\r\n {item.description && <div className=\"text-xs text-neutral-500\">{item.description}</div>}\r\n </div>\r\n )\r\n })}\r\n </div>\r\n </SonnerContext.Provider>\r\n )\r\n}"
1005
+ "content": "\"use client\"\r\n\r\nimport {\r\n CircleCheckIcon,\r\n InfoIcon,\r\n Loader2Icon,\r\n OctagonXIcon,\r\n TriangleAlertIcon,\r\n} from \"lucide-react\"\r\nimport { useTheme } from \"next-themes\"\r\nimport { Toaster as Sonner, type ToasterProps } from \"sonner\"\r\n\r\nconst Toaster = ({ ...props }: ToasterProps) => {\r\n const { theme = \"system\" } = useTheme()\r\n\r\n return (\r\n <Sonner\r\n theme={theme as ToasterProps[\"theme\"]}\r\n className=\"toaster group\"\r\n icons={{\r\n success: <CircleCheckIcon className=\"size-4\" />,\r\n info: <InfoIcon className=\"size-4\" />,\r\n warning: <TriangleAlertIcon className=\"size-4\" />,\r\n error: <OctagonXIcon className=\"size-4\" />,\r\n loading: <Loader2Icon className=\"size-4 animate-spin\" />,\r\n }}\r\n style={\r\n {\r\n \"--normal-bg\": \"var(--popover)\",\r\n \"--normal-text\": \"var(--popover-foreground)\",\r\n \"--normal-border\": \"var(--border)\",\r\n \"--border-radius\": \"var(--radius)\",\r\n } as React.CSSProperties\r\n }\r\n toastOptions={{\r\n classNames: {\r\n toast: \"cn-toast\",\r\n },\r\n }}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nexport { Toaster }\r\n"
392
1006
  }
393
1007
  ]
394
1008
  },
395
1009
  {
396
1010
  "name": "spinner",
1011
+ "type": "components:ui",
1012
+ "frameworks": [
1013
+ "react",
1014
+ "nextjs",
1015
+ "vue",
1016
+ "nuxt",
1017
+ "solid",
1018
+ "svelte",
1019
+ "astro",
1020
+ "remix"
1021
+ ],
397
1022
  "dependencies": [],
1023
+ "registryDependencies": [],
398
1024
  "files": [
399
1025
  {
400
1026
  "name": "spinner.tsx",
401
- "content": "import * as React from \"react\"\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nconst Spinner = React.forwardRef<\r\n SVGSVGElement,\r\n React.ComponentPropsWithoutRef<\"svg\">\r\n>(({ className, ...props }, ref) => (\r\n <svg\r\n ref={ref}\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n stroke=\"currentColor\"\r\n className={cn(\"h-4 w-4 animate-spin text-neutral-500\", className)}\r\n fill=\"none\"\r\n viewBox=\"0 0 24 24\"\r\n {...props}\r\n >\r\n <circle\r\n className=\"opacity-25\"\r\n cx=\"12\"\r\n cy=\"12\"\r\n r=\"10\"\r\n stroke=\"currentColor\"\r\n strokeWidth=\"4\"\r\n />\r\n <path\r\n className=\"opacity-75\"\r\n fill=\"currentColor\"\r\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\r\n />\r\n </svg>\r\n))\r\nSpinner.displayName = \"Spinner\"\r\n\r\nexport { Spinner }"
1027
+ "content": "import { Loader2Icon } from \"lucide-react\"\r\n\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nfunction Spinner({ className, ...props }: React.ComponentProps<\"svg\">) {\r\n return (\r\n <Loader2Icon\r\n role=\"status\"\r\n aria-label=\"Loading\"\r\n className={cn(\"size-4 animate-spin\", className)}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nexport { Spinner }\r\n"
402
1028
  }
403
1029
  ]
404
1030
  },
405
1031
  {
406
1032
  "name": "switch",
1033
+ "type": "components:ui",
1034
+ "frameworks": [
1035
+ "react",
1036
+ "nextjs",
1037
+ "vue",
1038
+ "nuxt",
1039
+ "solid",
1040
+ "svelte",
1041
+ "astro",
1042
+ "remix"
1043
+ ],
407
1044
  "dependencies": [
408
1045
  "@base-ui/react"
409
1046
  ],
1047
+ "registryDependencies": [],
410
1048
  "files": [
411
1049
  {
412
1050
  "name": "switch.tsx",
413
- "content": "\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport { Switch as BaseSwitch } from \"@base-ui/react/switch\"\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nconst Switch = React.forwardRef<\r\n HTMLButtonElement,\r\n React.ComponentPropsWithoutRef<typeof BaseSwitch.Root>\r\n>(({ className, ...props }, ref) => (\r\n <BaseSwitch.Root\r\n ref={ref}\r\n className={cn(\r\n \"group inline-flex h-6 w-11 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out\",\r\n \"focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-neutral-950 focus-visible:ring-offset-2\",\r\n \"disabled:cursor-not-allowed disabled:opacity-50\",\r\n \"bg-neutral-200 data-[checked]:bg-neutral-900\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n <BaseSwitch.Thumb\r\n className={cn(\r\n \"pointer-events-none block h-5 w-5 rounded-full bg-white shadow-lg ring-0 transition-transform duration-200 ease-in-out\",\r\n \"translate-x-0 data-[checked]:translate-x-5\"\r\n )}\r\n />\r\n </BaseSwitch.Root>\r\n))\r\nSwitch.displayName = \"Switch\"\r\n\r\nexport { Switch }"
1051
+ "content": "\"use client\"\r\n\r\nimport { Switch as SwitchPrimitive } from \"@base-ui/react/switch\"\r\n\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nfunction Switch({\r\n className,\r\n size = \"default\",\r\n ...props\r\n}: SwitchPrimitive.Root.Props & {\r\n size?: \"sm\" | \"default\"\r\n}) {\r\n return (\r\n <SwitchPrimitive.Root\r\n data-slot=\"switch\"\r\n data-size={size}\r\n className={cn(\r\n \"peer group/switch relative inline-flex shrink-0 items-center rounded-full border border-transparent transition-all outline-none after:absolute after:-inset-x-3 after:-inset-y-2 focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 data-[size=default]:h-[18.4px] data-[size=default]:w-[32px] data-[size=sm]:h-[14px] data-[size=sm]:w-[24px] dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 data-checked:bg-primary data-unchecked:bg-input dark:data-unchecked:bg-input/80 data-disabled:cursor-not-allowed data-disabled:opacity-50\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n <SwitchPrimitive.Thumb\r\n data-slot=\"switch-thumb\"\r\n className=\"pointer-events-none block rounded-full bg-background ring-0 transition-transform group-data-[size=default]/switch:size-4 group-data-[size=sm]/switch:size-3 group-data-[size=default]/switch:data-checked:translate-x-[calc(100%-2px)] group-data-[size=sm]/switch:data-checked:translate-x-[calc(100%-2px)] dark:data-checked:bg-primary-foreground group-data-[size=default]/switch:data-unchecked:translate-x-0 group-data-[size=sm]/switch:data-unchecked:translate-x-0 dark:data-unchecked:bg-foreground\"\r\n />\r\n </SwitchPrimitive.Root>\r\n )\r\n}\r\n\r\nexport { Switch }\r\n"
414
1052
  }
415
1053
  ]
416
1054
  },
417
1055
  {
418
1056
  "name": "table",
1057
+ "type": "components:ui",
1058
+ "frameworks": [
1059
+ "react",
1060
+ "nextjs",
1061
+ "vue",
1062
+ "nuxt",
1063
+ "solid",
1064
+ "svelte",
1065
+ "astro",
1066
+ "remix"
1067
+ ],
419
1068
  "dependencies": [],
1069
+ "registryDependencies": [],
420
1070
  "files": [
421
1071
  {
422
1072
  "name": "table.tsx",
423
- "content": "import * as React from \"react\"\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nconst Table = React.forwardRef<\r\n HTMLTableElement,\r\n React.HTMLAttributes<HTMLTableElement>\r\n>(({ className, ...props }, ref) => (\r\n <div className=\"relative w-full overflow-auto\">\r\n <table\r\n ref={ref}\r\n className={cn(\"w-full caption-bottom text-sm border-collapse\", className)}\r\n {...props}\r\n />\r\n </div>\r\n))\r\nTable.displayName = \"Table\"\r\n\r\nconst TableHeader = React.forwardRef<\r\n HTMLTableSectionElement,\r\n React.HTMLAttributes<HTMLTableSectionElement>\r\n>(({ className, ...props }, ref) => (\r\n <thead ref={ref} className={cn(\"[&_tr]:border-b bg-neutral-50/70 border-neutral-200\", className)} {...props} />\r\n))\r\nTableHeader.displayName = \"TableHeader\"\r\n\r\nconst TableBody = React.forwardRef<\r\n HTMLTableSectionElement,\r\n React.HTMLAttributes<HTMLTableSectionElement>\r\n>(({ className, ...props }, ref) => (\r\n <tbody\r\n ref={ref}\r\n className={cn(\"[&_tr:last-child]:border-0\", className)}\r\n {...props}\r\n />\r\n))\r\nTableBody.displayName = \"TableBody\"\r\n\r\nconst TableFooter = React.forwardRef<\r\n HTMLTableSectionElement,\r\n React.HTMLAttributes<HTMLTableSectionElement>\r\n>(({ className, ...props }, ref) => (\r\n <tfoot\r\n ref={ref}\r\n className={cn(\"border-t bg-neutral-50 font-medium [&_tr]:last-child:border-0 border-neutral-200\", className)}\r\n {...props}\r\n />\r\n))\r\nTableFooter.displayName = \"TableFooter\"\r\n\r\nconst TableRow = React.forwardRef<\r\n HTMLTableRowElement,\r\n React.HTMLAttributes<HTMLTableRowElement>\r\n>(({ className, ...props }, ref) => (\r\n <tr\r\n ref={ref}\r\n className={cn(\r\n \"border-b border-neutral-200 transition-colors hover:bg-neutral-50/50 data-[state=selected]:bg-neutral-50\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n))\r\nTableRow.displayName = \"TableRow\"\r\n\r\nconst TableHead = React.forwardRef<\r\n HTMLTableCellElement,\r\n React.ThHTMLAttributes<HTMLTableCellElement>\r\n>(({ className, ...props }, ref) => (\r\n <th\r\n ref={ref}\r\n className={cn(\r\n \"h-10 px-4 text-left align-middle font-medium text-neutral-500 [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n))\r\nTableHead.displayName = \"TableHead\"\r\n\r\nconst TableCell = React.forwardRef<\r\n HTMLTableCellElement,\r\n React.TdHTMLAttributes<HTMLTableCellElement>\r\n>(({ className, ...props }, ref) => (\r\n <td\r\n ref={ref}\r\n className={cn(\r\n \"p-4 align-middle [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n))\r\nTableCell.displayName = \"TableCell\"\r\n\r\nexport {\r\n Table,\r\n TableHeader,\r\n TableBody,\r\n TableFooter,\r\n TableRow,\r\n TableHead,\r\n TableCell,\r\n}"
1073
+ "content": "\"use client\"\r\n\r\nimport * as React from \"react\"\r\n\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nfunction Table({ className, ...props }: React.ComponentProps<\"table\">) {\r\n return (\r\n <div\r\n data-slot=\"table-container\"\r\n className=\"relative w-full overflow-x-auto\"\r\n >\r\n <table\r\n data-slot=\"table\"\r\n className={cn(\"w-full caption-bottom text-sm\", className)}\r\n {...props}\r\n />\r\n </div>\r\n )\r\n}\r\n\r\nfunction TableHeader({ className, ...props }: React.ComponentProps<\"thead\">) {\r\n return (\r\n <thead\r\n data-slot=\"table-header\"\r\n className={cn(\"[&_tr]:border-b\", className)}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction TableBody({ className, ...props }: React.ComponentProps<\"tbody\">) {\r\n return (\r\n <tbody\r\n data-slot=\"table-body\"\r\n className={cn(\"[&_tr:last-child]:border-0\", className)}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction TableFooter({ className, ...props }: React.ComponentProps<\"tfoot\">) {\r\n return (\r\n <tfoot\r\n data-slot=\"table-footer\"\r\n className={cn(\r\n \"border-t bg-muted/50 font-medium [&>tr]:last:border-b-0\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction TableRow({ className, ...props }: React.ComponentProps<\"tr\">) {\r\n return (\r\n <tr\r\n data-slot=\"table-row\"\r\n className={cn(\r\n \"border-b transition-colors hover:bg-muted/50 has-aria-expanded:bg-muted/50 data-[state=selected]:bg-muted\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction TableHead({ className, ...props }: React.ComponentProps<\"th\">) {\r\n return (\r\n <th\r\n data-slot=\"table-head\"\r\n className={cn(\r\n \"h-10 px-2 text-left align-middle font-medium whitespace-nowrap text-foreground [&:has([role=checkbox])]:pr-0\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction TableCell({ className, ...props }: React.ComponentProps<\"td\">) {\r\n return (\r\n <td\r\n data-slot=\"table-cell\"\r\n className={cn(\r\n \"p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction TableCaption({\r\n className,\r\n ...props\r\n}: React.ComponentProps<\"caption\">) {\r\n return (\r\n <caption\r\n data-slot=\"table-caption\"\r\n className={cn(\"mt-4 text-sm text-muted-foreground\", className)}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nexport {\r\n Table,\r\n TableHeader,\r\n TableBody,\r\n TableFooter,\r\n TableHead,\r\n TableRow,\r\n TableCell,\r\n TableCaption,\r\n}\r\n"
424
1074
  }
425
1075
  ]
426
1076
  },
427
1077
  {
428
1078
  "name": "tabs",
1079
+ "type": "components:ui",
1080
+ "frameworks": [
1081
+ "react",
1082
+ "nextjs",
1083
+ "vue",
1084
+ "nuxt",
1085
+ "solid",
1086
+ "svelte",
1087
+ "astro",
1088
+ "remix"
1089
+ ],
429
1090
  "dependencies": [
430
1091
  "@base-ui/react"
431
1092
  ],
1093
+ "registryDependencies": [],
432
1094
  "files": [
433
1095
  {
434
1096
  "name": "tabs.tsx",
435
- "content": "\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport { Tabs as BaseTabs } from \"@base-ui/react/tabs\"\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nconst Tabs = BaseTabs.Root\r\n\r\nconst TabsList = React.forwardRef<\r\n HTMLDivElement,\r\n React.ComponentPropsWithoutRef<typeof BaseTabs.List>\r\n>(({ className, ...props }, ref) => (\r\n <BaseTabs.List\r\n ref={ref}\r\n className={cn(\r\n \"inline-flex h-10 items-center justify-center rounded-lg bg-neutral-100 p-1 text-neutral-500\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n))\r\nTabsList.displayName = \"TabsList\"\r\n\r\nconst TabsTrigger = React.forwardRef<\r\n HTMLButtonElement,\r\n React.ComponentPropsWithoutRef<typeof BaseTabs.Trigger>\r\n>(({ className, ...props }, ref) => (\r\n <BaseTabs.Trigger\r\n ref={ref}\r\n className={cn(\r\n \"inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1.5 text-sm font-medium transition-all cursor-pointer select-none\",\r\n \"focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-neutral-950 focus-visible:ring-offset-2\",\r\n \"disabled:pointer-events-none disabled:opacity-50\",\r\n \"data-[selected]:bg-white data-[selected]:text-neutral-950 data-[selected]:shadow-xs\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n))\r\nTabsTrigger.displayName = \"TabsTrigger\"\r\n\r\nconst TabsContent = React.forwardRef<\r\n HTMLDivElement,\r\n React.ComponentPropsWithoutRef<typeof BaseTabs.Panel>\r\n>(({ className, ...props }, ref) => (\r\n <BaseTabs.Panel\r\n ref={ref}\r\n className={cn(\r\n \"mt-2 outline-hidden focus-visible:ring-2 focus-visible:ring-neutral-950 focus-visible:ring-offset-2\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n))\r\nTabsContent.displayName = \"TabsContent\"\r\n\r\nexport { Tabs, TabsList, TabsTrigger, TabsContent }"
1097
+ "content": "\"use client\"\r\n\r\nimport { Tabs as TabsPrimitive } from \"@base-ui/react/tabs\"\r\nimport { cva, type VariantProps } from \"class-variance-authority\"\r\n\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nfunction Tabs({\r\n className,\r\n orientation = \"horizontal\",\r\n ...props\r\n}: TabsPrimitive.Root.Props) {\r\n return (\r\n <TabsPrimitive.Root\r\n data-slot=\"tabs\"\r\n data-orientation={orientation}\r\n className={cn(\r\n \"group/tabs flex gap-2 data-horizontal:flex-col\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nconst tabsListVariants = cva(\r\n \"group/tabs-list inline-flex w-fit items-center justify-center rounded-lg p-[3px] text-muted-foreground group-data-horizontal/tabs:h-8 group-data-vertical/tabs:h-fit group-data-vertical/tabs:flex-col data-[variant=line]:rounded-none\",\r\n {\r\n variants: {\r\n variant: {\r\n default: \"bg-muted\",\r\n line: \"gap-1 bg-transparent\",\r\n },\r\n },\r\n defaultVariants: {\r\n variant: \"default\",\r\n },\r\n }\r\n)\r\n\r\nfunction TabsList({\r\n className,\r\n variant = \"default\",\r\n ...props\r\n}: TabsPrimitive.List.Props & VariantProps<typeof tabsListVariants>) {\r\n return (\r\n <TabsPrimitive.List\r\n data-slot=\"tabs-list\"\r\n data-variant={variant}\r\n className={cn(tabsListVariants({ variant }), className)}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction TabsTrigger({ className, ...props }: TabsPrimitive.Tab.Props) {\r\n return (\r\n <TabsPrimitive.Tab\r\n data-slot=\"tabs-trigger\"\r\n className={cn(\r\n \"relative inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-1.5 py-0.5 text-sm font-medium whitespace-nowrap text-foreground/60 transition-all group-data-vertical/tabs:w-full group-data-vertical/tabs:justify-start hover:text-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:outline-1 focus-visible:outline-ring disabled:pointer-events-none disabled:opacity-50 has-data-[icon=inline-end]:pr-1 has-data-[icon=inline-start]:pl-1 aria-disabled:pointer-events-none aria-disabled:opacity-50 dark:text-muted-foreground dark:hover:text-foreground group-data-[variant=default]/tabs-list:data-active:shadow-sm group-data-[variant=line]/tabs-list:data-active:shadow-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\r\n \"group-data-[variant=line]/tabs-list:bg-transparent group-data-[variant=line]/tabs-list:data-active:bg-transparent dark:group-data-[variant=line]/tabs-list:data-active:border-transparent dark:group-data-[variant=line]/tabs-list:data-active:bg-transparent\",\r\n \"data-active:bg-background data-active:text-foreground dark:data-active:border-input dark:data-active:bg-input/30 dark:data-active:text-foreground\",\r\n \"after:absolute after:bg-foreground after:opacity-0 after:transition-opacity group-data-horizontal/tabs:after:inset-x-0 group-data-horizontal/tabs:after:bottom-[-5px] group-data-horizontal/tabs:after:h-0.5 group-data-vertical/tabs:after:inset-y-0 group-data-vertical/tabs:after:-right-1 group-data-vertical/tabs:after:w-0.5 group-data-[variant=line]/tabs-list:data-active:after:opacity-100\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction TabsContent({ className, ...props }: TabsPrimitive.Panel.Props) {\r\n return (\r\n <TabsPrimitive.Panel\r\n data-slot=\"tabs-content\"\r\n className={cn(\"flex-1 text-sm outline-none\", className)}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nexport { Tabs, TabsList, TabsTrigger, TabsContent, tabsListVariants }\r\n"
436
1098
  }
437
1099
  ]
438
1100
  },
439
1101
  {
440
1102
  "name": "textarea",
1103
+ "type": "components:ui",
1104
+ "frameworks": [
1105
+ "react",
1106
+ "nextjs",
1107
+ "vue",
1108
+ "nuxt",
1109
+ "solid",
1110
+ "svelte",
1111
+ "astro",
1112
+ "remix"
1113
+ ],
441
1114
  "dependencies": [],
1115
+ "registryDependencies": [],
442
1116
  "files": [
443
1117
  {
444
1118
  "name": "textarea.tsx",
445
- "content": "import * as React from \"react\"\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nexport interface TextareaProps extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {}\r\n\r\nconst Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(\r\n ({ className, ...props }, ref) => {\r\n return (\r\n <textarea\r\n className={cn(\r\n \"flex min-h-[80px] w-full rounded-md border border-neutral-200 bg-white px-3 py-2 text-sm text-neutral-950 placeholder:text-neutral-400 shadow-2xs transition-all\",\r\n \"focus-visible:outline-hidden focus-visible:border-neutral-900 focus-visible:ring-1 focus-visible:ring-neutral-900\",\r\n \"disabled:cursor-not-allowed disabled:opacity-50 disabled:bg-neutral-50/50\",\r\n className\r\n )}\r\n ref={ref}\r\n {...props}\r\n />\r\n )\r\n }\r\n)\r\nTextarea.displayName = \"Textarea\"\r\n\r\nexport { Textarea }"
446
- }
447
- ]
448
- },
449
- {
450
- "name": "toast",
451
- "dependencies": [],
452
- "files": [
453
- {
454
- "name": "toast.tsx",
455
- "content": "\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport { cn } from \"@/lib/utils\"\r\n\r\ninterface ToastMessage {\r\n id: string\r\n title?: string\r\n description?: string\r\n variant?: \"default\" | \"destructive\"\r\n}\r\n\r\nconst ToastContext = React.createContext<{\r\n toast: (props: Omit<ToastMessage, \"id\">) => void\r\n} | null>(null)\r\n\r\nexport function useToast() {\r\n const context = React.useContext(ToastContext)\r\n if (!context) throw new Error(\"useToast must be used within a ToastProvider\")\r\n return context\r\n}\r\n\r\nexport const ToastProvider = ({ children }: { children: React.ReactNode }) => {\r\n const [toasts, setToasts] = React.useState<ToastMessage[]>([])\r\n\r\n const toast = React.useCallback(({ title, description, variant = \"default\" }: Omit<ToastMessage, \"id\">) => {\r\n const id = Math.random().toString(36).substring(2, 9)\r\n setToasts((prev) => [...prev, { id, title, description, variant }])\r\n\r\n setTimeout(() => {\r\n setToasts((prev) => prev.filter((t) => t.id !== id))\r\n }, 4000)\r\n }, [])\r\n\r\n return (\r\n <ToastContext.Provider value={{ toast }}>\r\n {children}\r\n <div className=\"fixed bottom-0 right-0 z-50 flex max-h-screen w-full flex-col-reverse p-4 sm:bottom-0 sm:right-0 sm:top-auto sm:flex-col md:max-w-[420px] gap-2\">\r\n {toasts.map((t) => (\r\n <div\r\n key={t.id}\r\n className={cn(\r\n \"group relative flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md border p-4 pr-8 shadow-lg transition-all duration-300 ease-out\",\r\n t.variant === \"default\" && \"bg-white border-neutral-200 text-neutral-950\",\r\n t.variant === \"destructive\" && \"destructive group border-red-500 bg-red-600 text-white\"\r\n )}\r\n >\r\n <div className=\"grid gap-1\">\r\n {t.title && <div className=\"text-sm font-semibold\">{t.title}</div>}\r\n {t.description && <div className={cn(\"text-xs opacity-90\", t.variant === \"default\" ? \"text-neutral-500\" : \"text-white\")}>{t.description}</div>}\r\n </div>\r\n </div>\r\n ))}\r\n </div>\r\n </ToastContext.Provider>\r\n )\r\n}"
1119
+ "content": "import * as React from \"react\"\r\n\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nfunction Textarea({ className, ...props }: React.ComponentProps<\"textarea\">) {\r\n return (\r\n <textarea\r\n data-slot=\"textarea\"\r\n className={cn(\r\n \"flex field-sizing-content min-h-16 w-full rounded-lg border border-input bg-transparent px-2.5 py-2 text-base transition-colors outline-none placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:bg-input/50 disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:disabled:bg-input/80 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nexport { Textarea }\r\n"
456
1120
  }
457
1121
  ]
458
1122
  },
459
1123
  {
460
1124
  "name": "toggle-group",
1125
+ "type": "components:ui",
1126
+ "frameworks": [
1127
+ "react",
1128
+ "nextjs",
1129
+ "vue",
1130
+ "nuxt",
1131
+ "solid",
1132
+ "svelte",
1133
+ "astro",
1134
+ "remix"
1135
+ ],
461
1136
  "dependencies": [
462
1137
  "@base-ui/react"
463
1138
  ],
1139
+ "registryDependencies": [],
464
1140
  "files": [
465
1141
  {
466
1142
  "name": "toggle-group.tsx",
467
- "content": "\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport { ToggleGroup as BaseToggleGroup } from \"@base-ui/react/toggle-group\"\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nconst ToggleGroupContext = React.createContext<{\r\n size?: \"default\" | \"sm\" | \"lg\"\r\n variant?: \"default\" | \"outline\"\r\n} | null>(null)\r\n\r\nconst ToggleGroup = React.forwardRef<\r\n HTMLDivElement,\r\n React.ComponentPropsWithoutRef<typeof BaseToggleGroup.Root> & {\r\n size?: \"default\" | \"sm\" | \"lg\"\r\n variant?: \"default\" | \"outline\"\r\n }\r\n>(({ className, variant, size, children, ...props }, ref) => (\r\n <BaseToggleGroup.Root\r\n ref={ref}\r\n className={cn(\"flex items-center justify-center gap-1\", className)}\r\n {...props}\r\n >\r\n <ToggleGroupContext.Provider value={{ variant, size }}>\r\n {children}\r\n </ToggleGroupContext.Provider>\r\n </BaseToggleGroup.Root>\r\n))\r\n\r\nToggleGroup.displayName = \"ToggleGroup\"\r\n\r\nconst ToggleGroupItem = React.forwardRef<\r\n HTMLButtonElement,\r\n React.ComponentPropsWithoutRef<typeof BaseToggleGroup.Item> & {\r\n size?: \"default\" | \"sm\" | \"lg\"\r\n variant?: \"default\" | \"outline\"\r\n }\r\n>(({ className, children, variant, size, ...props }, ref) => {\r\n const context = React.useContext(ToggleGroupContext)\r\n \r\n // Toggle layout variant overrides based on group setup mappings\r\n const itemVariant = variant || context?.variant || \"default\"\r\n const itemSize = size || context?.size || \"default\"\r\n\r\n return (\r\n <BaseToggleGroup.Item\r\n ref={ref}\r\n className={cn(\r\n \"inline-flex items-center justify-center text-sm font-medium transition-colors hover:bg-neutral-100 hover:text-neutral-500 cursor-pointer select-none focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-neutral-950 disabled:pointer-events-none disabled:opacity-50 data-[pressed]:bg-neutral-900 data-[pressed]:text-neutral-50 rounded-none first:rounded-l-md last:rounded-r-md border-r last:border-r-0 border-neutral-200/60 shadow-2xs\",\r\n itemVariant === \"outline\" ? \"border border-neutral-200\" : \"bg-transparent\",\r\n itemSize === \"default\" && \"h-9 px-3\",\r\n itemSize === \"sm\" && \"h-8 px-2\",\r\n itemSize === \"lg\" && \"h-10 px-3\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n {children}\r\n </BaseToggleGroup.Item>\r\n )\r\n})\r\n\r\nToggleGroupItem.displayName = \"ToggleGroupItem\"\r\n\r\nexport { ToggleGroup, ToggleGroupItem }"
1143
+ "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { Toggle as TogglePrimitive } from \"@base-ui/react/toggle\"\nimport { ToggleGroup as ToggleGroupPrimitive } from \"@base-ui/react/toggle-group\"\nimport { type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\nimport { toggleVariants } from \"@/toggle\"\n\nconst ToggleGroupContext = React.createContext<\n VariantProps<typeof toggleVariants> & {\n spacing?: number\n orientation?: \"horizontal\" | \"vertical\"\n }\n>({\n size: \"default\",\n variant: \"default\",\n spacing: 2,\n orientation: \"horizontal\",\n})\n\nfunction ToggleGroup({\n className,\n variant,\n size,\n spacing = 2,\n orientation = \"horizontal\",\n children,\n ...props\n}: ToggleGroupPrimitive.Props &\n VariantProps<typeof toggleVariants> & {\n spacing?: number\n orientation?: \"horizontal\" | \"vertical\"\n }) {\n return (\n <ToggleGroupPrimitive\n data-slot=\"toggle-group\"\n data-variant={variant}\n data-size={size}\n data-spacing={spacing}\n data-orientation={orientation}\n style={{ \"--gap\": spacing } as React.CSSProperties}\n className={cn(\n \"group/toggle-group flex w-fit flex-row items-center gap-[--spacing(var(--gap))] rounded-lg data-[size=sm]:rounded-[min(var(--radius-md),10px)] data-vertical:flex-col data-vertical:items-stretch\",\n className\n )}\n {...props}\n >\n <ToggleGroupContext.Provider\n value={{ variant, size, spacing, orientation }}\n >\n {children}\n </ToggleGroupContext.Provider>\n </ToggleGroupPrimitive>\n )\n}\n\nfunction ToggleGroupItem({\n className,\n children,\n variant = \"default\",\n size = \"default\",\n ...props\n}: TogglePrimitive.Props & VariantProps<typeof toggleVariants>) {\n const context = React.useContext(ToggleGroupContext)\n\n return (\n <TogglePrimitive\n data-slot=\"toggle-group-item\"\n data-variant={context.variant || variant}\n data-size={context.size || size}\n data-spacing={context.spacing}\n className={cn(\n \"shrink-0 group-data-[spacing=0]/toggle-group:rounded-none group-data-[spacing=0]/toggle-group:px-2 focus:z-10 focus-visible:z-10 group-data-[spacing=0]/toggle-group:has-data-[icon=inline-end]:pr-1.5 group-data-[spacing=0]/toggle-group:has-data-[icon=inline-start]:pl-1.5 group-data-horizontal/toggle-group:data-[spacing=0]:first:rounded-l-lg group-data-vertical/toggle-group:data-[spacing=0]:first:rounded-t-lg group-data-horizontal/toggle-group:data-[spacing=0]:last:rounded-r-lg group-data-vertical/toggle-group:data-[spacing=0]:last:rounded-b-lg group-data-horizontal/toggle-group:data-[spacing=0]:data-[variant=outline]:border-l-0 group-data-vertical/toggle-group:data-[spacing=0]:data-[variant=outline]:border-t-0 group-data-horizontal/toggle-group:data-[spacing=0]:data-[variant=outline]:first:border-l group-data-vertical/toggle-group:data-[spacing=0]:data-[variant=outline]:first:border-t\",\n toggleVariants({\n variant: context.variant || variant,\n size: context.size || size,\n }),\n className\n )}\n {...props}\n >\n {children}\n </TogglePrimitive>\n )\n}\n\nexport { ToggleGroup, ToggleGroupItem }\n"
468
1144
  }
469
1145
  ]
470
1146
  },
471
1147
  {
472
1148
  "name": "toggle",
1149
+ "type": "components:ui",
1150
+ "frameworks": [
1151
+ "react",
1152
+ "nextjs",
1153
+ "vue",
1154
+ "nuxt",
1155
+ "solid",
1156
+ "svelte",
1157
+ "astro",
1158
+ "remix"
1159
+ ],
473
1160
  "dependencies": [
474
1161
  "@base-ui/react",
475
1162
  "class-variance-authority"
476
1163
  ],
1164
+ "registryDependencies": [],
477
1165
  "files": [
478
1166
  {
479
1167
  "name": "toggle.tsx",
480
- "content": "\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport { Toggle as BaseToggle } from \"@base-ui/react/toggle\"\r\nimport { cva, type VariantProps } from \"class-variance-authority\"\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nconst toggleVariants = cva(\r\n \"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors hover:bg-neutral-100 hover:text-neutral-500 cursor-pointer select-none focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-neutral-950 disabled:pointer-events-none disabled:opacity-50 data-[pressed]:bg-neutral-900 data-[pressed]:text-neutral-50 shadow-2xs\",\r\n {\r\n variants: {\r\n variant: {\r\n default: \"bg-transparent\",\r\n outline: \"border border-neutral-200 bg-transparent hover:bg-neutral-100 hover:text-neutral-900\",\r\n },\r\n size: {\r\n default: \"h-9 px-3\",\r\n sm: \"h-8 px-2\",\r\n lg: \"h-10 px-3\",\r\n },\r\n },\r\n defaultVariants: {\r\n variant: \"default\",\r\n size: \"default\",\r\n },\r\n }\r\n)\r\n\r\nexport interface ToggleProps\r\n extends React.ComponentPropsWithoutRef<typeof BaseToggle>,\r\n VariantProps<typeof toggleVariants> {}\r\n\r\nconst Toggle = React.forwardRef<HTMLButtonElement, ToggleProps>(\r\n ({ className, variant, size, ...props }, ref) => (\r\n <BaseToggle\r\n ref={ref}\r\n className={cn(toggleVariants({ variant, size, className }))}\r\n {...props}\r\n />\r\n )\r\n)\r\n\r\nToggle.displayName = \"Toggle\"\r\n\r\nexport { Toggle, toggleVariants }"
1168
+ "content": "\"use client\"\r\n\r\nimport { Toggle as TogglePrimitive } from \"@base-ui/react/toggle\"\r\nimport { cva, type VariantProps } from \"class-variance-authority\"\r\n\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nconst toggleVariants = cva(\r\n \"group/toggle inline-flex items-center justify-center gap-1 rounded-lg text-sm font-medium whitespace-nowrap transition-all outline-none hover:bg-muted hover:text-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 aria-pressed:bg-muted data-[state=on]:bg-muted dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\r\n {\r\n variants: {\r\n variant: {\r\n default: \"bg-transparent\",\r\n outline: \"border border-input bg-transparent hover:bg-muted\",\r\n },\r\n size: {\r\n default:\r\n \"h-8 min-w-8 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2\",\r\n sm: \"h-7 min-w-7 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5\",\r\n lg: \"h-9 min-w-9 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2\",\r\n },\r\n },\r\n defaultVariants: {\r\n variant: \"default\",\r\n size: \"default\",\r\n },\r\n }\r\n)\r\n\r\nfunction Toggle({\r\n className,\r\n variant = \"default\",\r\n size = \"default\",\r\n ...props\r\n}: TogglePrimitive.Props & VariantProps<typeof toggleVariants>) {\r\n return (\r\n <TogglePrimitive\r\n data-slot=\"toggle\"\r\n className={cn(toggleVariants({ variant, size, className }))}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nexport { Toggle, toggleVariants }\r\n"
481
1169
  }
482
1170
  ]
483
1171
  },
484
1172
  {
485
1173
  "name": "tooltip",
1174
+ "type": "components:ui",
1175
+ "frameworks": [
1176
+ "react",
1177
+ "nextjs",
1178
+ "vue",
1179
+ "nuxt",
1180
+ "solid",
1181
+ "svelte",
1182
+ "astro",
1183
+ "remix"
1184
+ ],
486
1185
  "dependencies": [
487
1186
  "@base-ui/react"
488
1187
  ],
1188
+ "registryDependencies": [],
489
1189
  "files": [
490
1190
  {
491
1191
  "name": "tooltip.tsx",
492
- "content": "\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport { Tooltip as BaseTooltip } from \"@base-ui/react/tooltip\"\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nconst TooltipProvider = BaseTooltip.Provider\r\n\r\nconst Tooltip = BaseTooltip.Root\r\n\r\nconst TooltipTrigger = BaseTooltip.Trigger\r\n\r\nconst TooltipPortal = BaseTooltip.Portal\r\n\r\nconst TooltipContent = React.forwardRef<\r\n HTMLDivElement,\r\n React.ComponentPropsWithoutRef<typeof BaseTooltip.Popup>\r\n>(({ className, sideOffset = 4, ...props }, ref) => (\r\n <BaseTooltip.Positioner sideOffset={sideOffset}>\r\n <BaseTooltip.Popup\r\n ref={ref}\r\n className={cn(\r\n \"z-50 overflow-hidden rounded-md bg-neutral-900 px-3 py-1.5 text-xs text-neutral-50 shadow-md transition-all duration-100 ease-out\",\r\n \"data-[starting-style]:opacity-0 data-[starting-style]:scale-95\",\r\n \"data-[ending-style]:opacity-0 data-[ending-style]:scale-95\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n </BaseTooltip.Positioner>\r\n))\r\nTooltipContent.displayName = \"TooltipContent\"\r\n\r\nexport { Tooltip, TooltipTrigger, TooltipContent, TooltipPortal, TooltipProvider }"
1192
+ "content": "\"use client\"\r\n\r\nimport { Tooltip as TooltipPrimitive } from \"@base-ui/react/tooltip\"\r\n\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nfunction TooltipProvider({\r\n delay = 0,\r\n ...props\r\n}: TooltipPrimitive.Provider.Props) {\r\n return (\r\n <TooltipPrimitive.Provider\r\n data-slot=\"tooltip-provider\"\r\n delay={delay}\r\n {...props}\r\n />\r\n )\r\n}\r\n\r\nfunction Tooltip({ ...props }: TooltipPrimitive.Root.Props) {\r\n return <TooltipPrimitive.Root data-slot=\"tooltip\" {...props} />\r\n}\r\n\r\nfunction TooltipTrigger({ ...props }: TooltipPrimitive.Trigger.Props) {\r\n return <TooltipPrimitive.Trigger data-slot=\"tooltip-trigger\" {...props} />\r\n}\r\n\r\nfunction TooltipContent({\r\n className,\r\n side = \"top\",\r\n sideOffset = 4,\r\n align = \"center\",\r\n alignOffset = 0,\r\n children,\r\n ...props\r\n}: TooltipPrimitive.Popup.Props &\r\n Pick<\r\n TooltipPrimitive.Positioner.Props,\r\n \"align\" | \"alignOffset\" | \"side\" | \"sideOffset\"\r\n >) {\r\n return (\r\n <TooltipPrimitive.Portal>\r\n <TooltipPrimitive.Positioner\r\n align={align}\r\n alignOffset={alignOffset}\r\n side={side}\r\n sideOffset={sideOffset}\r\n className=\"isolate z-50\"\r\n >\r\n <TooltipPrimitive.Popup\r\n data-slot=\"tooltip-content\"\r\n className={cn(\r\n \"z-50 inline-flex w-fit max-w-xs origin-(--transform-origin) items-center gap-1.5 rounded-md bg-foreground px-3 py-1.5 text-xs text-background has-data-[slot=kbd]:pr-1.5 data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 **:data-[slot=kbd]:relative **:data-[slot=kbd]:isolate **:data-[slot=kbd]:z-50 **:data-[slot=kbd]:rounded-sm data-[state=delayed-open]:animate-in data-[state=delayed-open]:fade-in-0 data-[state=delayed-open]:zoom-in-95 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n {children}\r\n <TooltipPrimitive.Arrow className=\"z-50 size-2.5 translate-y-[calc(-50%-2px)] rotate-45 rounded-[2px] bg-foreground fill-foreground data-[side=bottom]:top-1 data-[side=inline-end]:top-1/2! data-[side=inline-end]:-left-1 data-[side=inline-end]:-translate-y-1/2 data-[side=inline-start]:top-1/2! data-[side=inline-start]:-right-1 data-[side=inline-start]:-translate-y-1/2 data-[side=left]:top-1/2! data-[side=left]:-right-1 data-[side=left]:-translate-y-1/2 data-[side=right]:top-1/2! data-[side=right]:-left-1 data-[side=right]:-translate-y-1/2 data-[side=top]:-bottom-2.5\" />\r\n </TooltipPrimitive.Popup>\r\n </TooltipPrimitive.Positioner>\r\n </TooltipPrimitive.Portal>\r\n )\r\n}\r\n\r\nexport { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }\r\n"
493
1193
  }
494
1194
  ]
495
1195
  },
496
1196
  {
497
1197
  "name": "typography",
1198
+ "type": "components:ui",
1199
+ "frameworks": [
1200
+ "react",
1201
+ "nextjs",
1202
+ "vue",
1203
+ "nuxt",
1204
+ "solid",
1205
+ "svelte",
1206
+ "astro",
1207
+ "remix"
1208
+ ],
498
1209
  "dependencies": [],
1210
+ "registryDependencies": [],
499
1211
  "files": [
500
1212
  {
501
1213
  "name": "typography.tsx",
502
- "content": "import * as React from \"react\"\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nconst TypographyH1 = React.forwardRef<HTMLHeadingElement, React.HTMLAttributes<HTMLHeadingElement>>(\r\n ({ className, ...props }, ref) => (\r\n <h1 ref={ref} className={cn(\"scroll-m-20 text-4xl font-extrabold tracking-tight lg:text-5xl text-neutral-950\", className)} {...props} />\r\n )\r\n)\r\nTypographyH1.displayName = \"TypographyH1\"\r\n\r\nconst TypographyH2 = React.forwardRef<HTMLHeadingElement, React.HTMLAttributes<HTMLHeadingElement>>(\r\n ({ className, ...props }, ref) => (\r\n <h2 ref={ref} className={cn(\"scroll-m-20 border-b border-neutral-200 pb-2 text-3xl font-semibold tracking-tight first:mt-0 text-neutral-950\", className)} {...props} />\r\n )\r\n)\r\nTypographyH2.displayName = \"TypographyH2\"\r\n\r\nconst TypographyH3 = React.forwardRef<HTMLHeadingElement, React.HTMLAttributes<HTMLHeadingElement>>(\r\n ({ className, ...props }, ref) => (\r\n <h3 ref={ref} className={cn(\"scroll-m-20 text-2xl font-semibold tracking-tight text-neutral-950\", className)} {...props} />\r\n )\r\n)\r\nTypographyH3.displayName = \"TypographyH3\"\r\n\r\nconst TypographyLead = React.forwardRef<HTMLParagraphElement, React.HTMLAttributes<HTMLParagraphElement>>(\r\n ({ className, ...props }, ref) => (\r\n <p ref={ref} className={cn(\"text-xl text-neutral-500\", className)} {...props} />\r\n )\r\n)\r\nTypographyLead.displayName = \"TypographyLead\"\r\n\r\nconst TypographyMuted = React.forwardRef<HTMLSpanElement, React.HTMLAttributes<HTMLSpanElement>>(\r\n ({ className, ...props }, ref) => (\r\n <span ref={ref} className={cn(\"text-sm text-neutral-500\", className)} {...props} />\r\n )\r\n)\r\nTypographyMuted.displayName = \"TypographyMuted\"\r\n\r\nexport { TypographyH1, TypographyH2, TypographyH3, TypographyLead, TypographyMuted }"
1214
+ "content": "import * as React from \"react\"\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nexport function TypographyH1() {\r\n return (\r\n <h1 className=\"scroll-m-20 text-center text-4xl font-extrabold tracking-tight text-balance\">\r\n Taxing Laughter: The Joke Tax Chronicles\r\n </h1>\r\n )\r\n}\r\n\r\n\r\nexport function TypographyH2() {\r\n return (\r\n <h2 className=\"scroll-m-20 border-b pb-2 text-3xl font-semibold tracking-tight first:mt-0\">\r\n The People of the Kingdom\r\n </h2>\r\n )\r\n}\r\n\r\n\r\nexport function TypographyH3() {\r\n return (\r\n <h3 className=\"scroll-m-20 text-2xl font-semibold tracking-tight\">\r\n The Joke Tax\r\n </h3>\r\n )\r\n}\r\n\r\nexport function TypographyH4() {\r\n return (\r\n <h4 className=\"scroll-m-20 text-xl font-semibold tracking-tight\">\r\n People stopped telling jokes\r\n </h4>\r\n )\r\n}\r\n\r\nexport function TypographyP() {\r\n return (\r\n <p className=\"leading-7 [&:not(:first-child)]:mt-6\">\r\n The king, seeing how much happier his subjects were, realized the error of\r\n his ways and repealed the joke tax.\r\n </p>\r\n )\r\n}\r\n\r\nexport function TypographyBlockquote() {\r\n return (\r\n <blockquote className=\"mt-6 border-l-2 pl-6 italic\">\r\n &quot;After all,&quot; he said, &quot;everyone enjoys a good joke, so\r\n it&apos;s only fair that they should pay for the privilege.&quot;\r\n </blockquote>\r\n )\r\n}\r\n\r\nexport function TypographyTable() {\r\n return (\r\n <div className=\"my-6 w-full overflow-y-auto\">\r\n <table className=\"w-full\">\r\n <thead>\r\n <tr className=\"m-0 border-t p-0 even:bg-muted\">\r\n <th className=\"border px-4 py-2 text-left font-bold [&[align=center]]:text-center [&[align=right]]:text-right\">\r\n King&apos;s Treasury\r\n </th>\r\n <th className=\"border px-4 py-2 text-left font-bold [&[align=center]]:text-center [&[align=right]]:text-right\">\r\n People&apos;s happiness\r\n </th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n <tr className=\"m-0 border-t p-0 even:bg-muted\">\r\n <td className=\"border px-4 py-2 text-left [&[align=center]]:text-center [&[align=right]]:text-right\">\r\n Empty\r\n </td>\r\n <td className=\"border px-4 py-2 text-left [&[align=center]]:text-center [&[align=right]]:text-right\">\r\n Overflowing\r\n </td>\r\n </tr>\r\n <tr className=\"m-0 border-t p-0 even:bg-muted\">\r\n <td className=\"border px-4 py-2 text-left [&[align=center]]:text-center [&[align=right]]:text-right\">\r\n Modest\r\n </td>\r\n <td className=\"border px-4 py-2 text-left [&[align=center]]:text-center [&[align=right]]:text-right\">\r\n Satisfied\r\n </td>\r\n </tr>\r\n <tr className=\"m-0 border-t p-0 even:bg-muted\">\r\n <td className=\"border px-4 py-2 text-left [&[align=center]]:text-center [&[align=right]]:text-right\">\r\n Full\r\n </td>\r\n <td className=\"border px-4 py-2 text-left [&[align=center]]:text-center [&[align=right]]:text-right\">\r\n Ecstatic\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n )\r\n}\r\n\r\nexport function TypographyList() {\r\n return (\r\n <ul className=\"my-6 ml-6 list-disc [&>li]:mt-2\">\r\n <li>1st level of puns: 5 gold coins</li>\r\n <li>2nd level of jokes: 10 gold coins</li>\r\n <li>3rd level of one-liners : 20 gold coins</li>\r\n </ul>\r\n )\r\n}\r\n\r\nexport function TypographyInlineCode() {\r\n return (\r\n <code className=\"relative rounded bg-muted px-[0.3rem] py-[0.2rem] font-mono text-sm font-semibold\">\r\n @radix-ui/react-alert-dialog\r\n </code>\r\n )\r\n}\r\n\r\n\r\nexport function TypographyLead() {\r\n return (\r\n <p className=\"text-xl text-muted-foreground\">\r\n A modal dialog that interrupts the user with important content and expects\r\n a response.\r\n </p>\r\n )\r\n}\r\n\r\nexport function TypographyLarge() {\r\n return <div className=\"text-lg font-semibold\">Are you absolutely sure?</div>\r\n}\r\n\r\nexport function TypographySmall() {\r\n return (\r\n <small className=\"text-sm leading-none font-medium\">Email address</small>\r\n )\r\n}\r\n\r\n\r\nexport function TypographyMuted() {\r\n return (\r\n <p className=\"text-sm text-muted-foreground\">Enter your email address.</p>\r\n )\r\n}\r\n\r\n\r\n"
1215
+ }
1216
+ ]
1217
+ },
1218
+ {
1219
+ "name": "use-mobile",
1220
+ "type": "components:hook",
1221
+ "frameworks": [
1222
+ "react",
1223
+ "nextjs",
1224
+ "vue",
1225
+ "nuxt",
1226
+ "solid",
1227
+ "svelte",
1228
+ "astro",
1229
+ "remix"
1230
+ ],
1231
+ "dependencies": [],
1232
+ "registryDependencies": [],
1233
+ "files": [
1234
+ {
1235
+ "name": "hooks/use-mobile.ts",
1236
+ "content": "import * as React from \"react\"\n\nconst MOBILE_BREAKPOINT = 768\n\nexport function useIsMobile() {\n const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined)\n\n React.useEffect(() => {\n const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`)\n const onChange = () => {\n setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)\n }\n mql.addEventListener(\"change\", onChange)\n setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)\n return () => mql.removeEventListener(\"change\", onChange)\n }, [])\n\n return !!isMobile\n}\n"
1237
+ }
1238
+ ]
1239
+ },
1240
+ {
1241
+ "name": "dashboard-01",
1242
+ "type": "components:block",
1243
+ "frameworks": [
1244
+ "react",
1245
+ "nextjs",
1246
+ "vue",
1247
+ "nuxt",
1248
+ "solid",
1249
+ "svelte",
1250
+ "astro",
1251
+ "remix"
1252
+ ],
1253
+ "dependencies": [
1254
+ "@base-ui/react",
1255
+ "lucide-react"
1256
+ ],
1257
+ "registryDependencies": [
1258
+ "sidebar",
1259
+ "card",
1260
+ "button",
1261
+ "avatar"
1262
+ ],
1263
+ "files": [
1264
+ {
1265
+ "name": "blocks/dashboard-01.tsx",
1266
+ "content": "\"use client\"\n\nimport * as React from \"react\"\n\nexport function Dashboard01() {\n return (\n <div className=\"flex min-h-screen\">\n <aside className=\"w-64 border-r border-border bg-background p-4\">\n <div className=\"text-lg font-bold text-foreground mb-8\">Static UI</div>\n <nav className=\"space-y-1\">\n {[\"Overview\", \"Analytics\", \"Customers\", \"Settings\"].map((item) => (\n <a key={item} href=\"#\" className=\"block rounded-md px-3 py-2 text-sm font-medium text-muted-foreground hover:bg-accent hover:text-accent-foreground transition-colors\">{item}</a>\n ))}\n </nav>\n </aside>\n <main className=\"flex-1 p-6\">\n <header className=\"mb-6\">\n <h1 className=\"text-2xl font-bold text-foreground\">Dashboard</h1>\n <p className=\"text-sm text-muted-foreground\">Welcome back, here is your overview.</p>\n </header>\n <div className=\"grid grid-cols-1 md:grid-cols-3 gap-4 mb-6\">\n {[\n { label: \"Total Revenue\", value: \"$45,231\", change: \"+20.1%\" },\n { label: \"Active Users\", value: \"2,350\", change: \"+180.1%\" },\n { label: \"Sales\", value: \"12,234\", change: \"+19%\" },\n ].map((stat) => (\n <div key={stat.label} className=\"rounded-xl border border-border bg-card p-4 text-card-foreground shadow-xs\">\n <p className=\"text-sm text-muted-foreground\">{stat.label}</p>\n <p className=\"text-2xl font-bold text-foreground\">{stat.value}</p>\n <p className=\"text-xs text-green-500\">{stat.change}</p>\n </div>\n ))}\n </div>\n </main>\n </div>\n )\n}\n"
1267
+ }
1268
+ ]
1269
+ },
1270
+ {
1271
+ "name": "dashboard-02",
1272
+ "type": "components:block",
1273
+ "frameworks": [
1274
+ "react",
1275
+ "nextjs",
1276
+ "vue",
1277
+ "nuxt",
1278
+ "solid",
1279
+ "svelte",
1280
+ "astro",
1281
+ "remix"
1282
+ ],
1283
+ "dependencies": [
1284
+ "@base-ui/react",
1285
+ "lucide-react"
1286
+ ],
1287
+ "registryDependencies": [
1288
+ "sidebar",
1289
+ "card",
1290
+ "tabs",
1291
+ "select",
1292
+ "button"
1293
+ ],
1294
+ "files": [
1295
+ {
1296
+ "name": "blocks/dashboard-02.tsx",
1297
+ "content": "\"use client\"\n\nimport * as React from \"react\"\n\nexport function Dashboard02() {\n return (\n <div className=\"flex min-h-screen\">\n <aside className=\"w-64 border-r border-border bg-background p-4\">\n <div className=\"text-lg font-bold text-foreground mb-8\">Static UI</div>\n <nav className=\"space-y-1\">\n {[\"Overview\", \"Analytics\", \"Reports\", \"Settings\"].map((item) => (\n <a key={item} href=\"#\" className=\"block rounded-md px-3 py-2 text-sm font-medium text-muted-foreground hover:bg-accent hover:text-accent-foreground transition-colors\">{item}</a>\n ))}\n </nav>\n </aside>\n <main className=\"flex-1 p-6\">\n <header className=\"flex items-center justify-between mb-6\">\n <div>\n <h1 className=\"text-2xl font-bold text-foreground\">Analytics</h1>\n <p className=\"text-sm text-muted-foreground\">Track your performance metrics.</p>\n </div>\n <select className=\"h-9 rounded-md border border-border bg-background px-3 text-sm text-foreground\">\n <option>Last 7 days</option>\n <option>Last 30 days</option>\n <option>Last 90 days</option>\n </select>\n </header>\n <div className=\"grid grid-cols-1 lg:grid-cols-2 gap-4 mb-6\">\n <div className=\"rounded-xl border border-border bg-card p-4 text-card-foreground shadow-xs\">\n <p className=\"text-sm text-muted-foreground mb-2\">Page Views</p>\n <p className=\"text-3xl font-bold text-foreground\">54,321</p>\n <div className=\"mt-4 h-32 flex items-end gap-2\">\n {[40, 65, 45, 80, 55, 90, 70].map((h, i) => (\n <div key={i} className=\"flex-1 bg-primary/20 rounded-t-sm\" style={{ height: `${h}%` }} />\n ))}\n </div>\n </div>\n <div className=\"rounded-xl border border-border bg-card p-4 text-card-foreground shadow-xs\">\n <p className=\"text-sm text-muted-foreground mb-2\">Conversion Rate</p>\n <p className=\"text-3xl font-bold text-foreground\">3.24%</p>\n <div className=\"mt-4 h-32 flex items-end gap-2\">\n {[30, 50, 35, 60, 45, 70, 55].map((h, i) => (\n <div key={i} className=\"flex-1 bg-green-500/20 rounded-t-sm\" style={{ height: `${h}%` }} />\n ))}\n </div>\n </div>\n </div>\n </main>\n </div>\n )\n}\n"
1298
+ }
1299
+ ]
1300
+ },
1301
+ {
1302
+ "name": "feature-01",
1303
+ "type": "components:block",
1304
+ "frameworks": [
1305
+ "react",
1306
+ "nextjs",
1307
+ "vue",
1308
+ "nuxt",
1309
+ "solid",
1310
+ "svelte",
1311
+ "astro",
1312
+ "remix"
1313
+ ],
1314
+ "dependencies": [
1315
+ "@base-ui/react",
1316
+ "lucide-react"
1317
+ ],
1318
+ "registryDependencies": [
1319
+ "card"
1320
+ ],
1321
+ "files": [
1322
+ {
1323
+ "name": "blocks/feature-01.tsx",
1324
+ "content": "\"use client\"\n\nimport * as React from \"react\"\n\nexport function Feature01() {\n const features = [\n { title: \"Accessible\", description: \"Built on Base UI with full ARIA support and keyboard navigation out of the box.\" },\n { title: \"Customizable\", description: \"Style with Tailwind CSS v4 classes. No opinionated themes to override.\" },\n { title: \"Lightweight\", description: \"Copy what you need. Zero unnecessary dependencies in your bundle.\" },\n ]\n return (\n <section className=\"py-16 px-4 bg-muted/30\">\n <div className=\"max-w-4xl mx-auto\">\n <div className=\"text-center mb-10\">\n <h2 className=\"text-3xl font-bold text-foreground\">Why Static UI?</h2>\n <p className=\"text-muted-foreground mt-2\">Everything you need to build modern interfaces</p>\n </div>\n <div className=\"grid grid-cols-1 md:grid-cols-3 gap-6\">\n {features.map((f) => (\n <div key={f.title} className=\"rounded-xl border border-border bg-card p-6 text-card-foreground shadow-xs\">\n <h3 className=\"font-semibold text-foreground\">{f.title}</h3>\n <p className=\"mt-2 text-sm text-muted-foreground\">{f.description}</p>\n </div>\n ))}\n </div>\n </div>\n </section>\n )\n}\n"
1325
+ }
1326
+ ]
1327
+ },
1328
+ {
1329
+ "name": "feature-02",
1330
+ "type": "components:block",
1331
+ "frameworks": [
1332
+ "react",
1333
+ "nextjs",
1334
+ "vue",
1335
+ "nuxt",
1336
+ "solid",
1337
+ "svelte",
1338
+ "astro",
1339
+ "remix"
1340
+ ],
1341
+ "dependencies": [
1342
+ "@base-ui/react",
1343
+ "lucide-react"
1344
+ ],
1345
+ "registryDependencies": [
1346
+ "card"
1347
+ ],
1348
+ "files": [
1349
+ {
1350
+ "name": "blocks/feature-02.tsx",
1351
+ "content": "\"use client\"\n\nimport * as React from \"react\"\n\nexport function Feature02() {\n const features = [\n { title: \"Seamless integration\", description: \"Drop into any Next.js, Vite, or Remix project. No build tool configuration needed.\" },\n { title: \"Consistent design\", description: \"Every component uses the same Tailwind CSS variable tokens for a unified look.\" },\n { title: \"Community driven\", description: \"Open source and free. Contributions, issues, and feedback are always welcome.\" },\n ]\n return (\n <section className=\"py-16 px-4\">\n <div className=\"max-w-4xl mx-auto space-y-12\">\n {features.map((f, i) => (\n <div key={f.title} className={`flex flex-col ${i % 2 === 0 ? \"md:flex-row\" : \"md:flex-row-reverse\"} gap-6 items-center`}>\n <div className=\"flex-1\">\n <h3 className=\"text-xl font-semibold text-foreground\">{f.title}</h3>\n <p className=\"mt-2 text-muted-foreground\">{f.description}</p>\n </div>\n <div className=\"flex-1 rounded-xl border border-border bg-card p-8 text-card-foreground shadow-xs aspect-video flex items-center justify-center\">\n <p className=\"text-muted-foreground text-sm\">Illustration</p>\n </div>\n </div>\n ))}\n </div>\n </section>\n )\n}\n"
1352
+ }
1353
+ ]
1354
+ },
1355
+ {
1356
+ "name": "hero-01",
1357
+ "type": "components:block",
1358
+ "frameworks": [
1359
+ "react",
1360
+ "nextjs",
1361
+ "vue",
1362
+ "nuxt",
1363
+ "solid",
1364
+ "svelte",
1365
+ "astro",
1366
+ "remix"
1367
+ ],
1368
+ "dependencies": [
1369
+ "@base-ui/react",
1370
+ "lucide-react"
1371
+ ],
1372
+ "registryDependencies": [
1373
+ "button",
1374
+ "badge"
1375
+ ],
1376
+ "files": [
1377
+ {
1378
+ "name": "blocks/hero-01.tsx",
1379
+ "content": "\"use client\"\n\nimport * as React from \"react\"\n\nexport function Hero01() {\n return (\n <section className=\"py-24 px-4 text-center\">\n <div className=\"max-w-2xl mx-auto\">\n <span className=\"inline-flex items-center rounded-full border border-border bg-background px-2.5 py-0.5 text-xs font-semibold text-foreground mb-4\">New release v2.0</span>\n <h1 className=\"text-4xl font-bold tracking-tight text-foreground sm:text-5xl\">Build beautiful interfaces with Static UI</h1>\n <p className=\"mt-4 text-lg text-muted-foreground\">A modern component library built on Base UI and Tailwind CSS v4. Open source and ready to use.</p>\n <div className=\"mt-8 flex items-center justify-center gap-4\">\n <button className=\"inline-flex h-10 items-center justify-center rounded-md bg-primary px-6 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90 transition-colors\">Get started</button>\n <button className=\"inline-flex h-10 items-center justify-center rounded-md border border-border bg-background px-6 py-2 text-sm font-medium text-foreground hover:bg-muted transition-colors\">Learn more</button>\n </div>\n </div>\n </section>\n )\n}\n"
1380
+ }
1381
+ ]
1382
+ },
1383
+ {
1384
+ "name": "hero-02",
1385
+ "type": "components:block",
1386
+ "frameworks": [
1387
+ "react",
1388
+ "nextjs",
1389
+ "vue",
1390
+ "nuxt",
1391
+ "solid",
1392
+ "svelte",
1393
+ "astro",
1394
+ "remix"
1395
+ ],
1396
+ "dependencies": [
1397
+ "@base-ui/react",
1398
+ "lucide-react"
1399
+ ],
1400
+ "registryDependencies": [
1401
+ "button",
1402
+ "badge"
1403
+ ],
1404
+ "files": [
1405
+ {
1406
+ "name": "blocks/hero-02.tsx",
1407
+ "content": "\"use client\"\n\nimport * as React from \"react\"\n\nexport function Hero02() {\n return (\n <section className=\"py-16 px-4\">\n <div className=\"max-w-5xl mx-auto grid md:grid-cols-2 gap-8 items-center\">\n <div>\n <span className=\"inline-flex items-center rounded-full border border-border bg-background px-2.5 py-0.5 text-xs font-semibold text-foreground mb-4\">Featured</span>\n <h1 className=\"text-3xl font-bold tracking-tight text-foreground sm:text-4xl\">Design faster with pre-built components</h1>\n <p className=\"mt-4 text-muted-foreground\">Stop writing repetitive UI code. Static UI gives you accessible, customizable components that you can copy and paste into your projects.</p>\n <div className=\"mt-6 flex gap-3\">\n <button className=\"inline-flex h-10 items-center justify-center rounded-md bg-primary px-6 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90 transition-colors\">Browse components</button>\n <button className=\"inline-flex h-10 items-center justify-center rounded-md border border-border bg-background px-6 py-2 text-sm font-medium text-foreground hover:bg-muted transition-colors\">View on GitHub</button>\n </div>\n </div>\n <div className=\"rounded-xl border border-border bg-card p-8 text-card-foreground shadow-xs aspect-[4/3] flex items-center justify-center\">\n <p className=\"text-muted-foreground\">Preview</p>\n </div>\n </div>\n </section>\n )\n}\n"
1408
+ }
1409
+ ]
1410
+ },
1411
+ {
1412
+ "name": "login-01",
1413
+ "type": "components:block",
1414
+ "frameworks": [
1415
+ "react",
1416
+ "nextjs",
1417
+ "vue",
1418
+ "nuxt",
1419
+ "solid",
1420
+ "svelte",
1421
+ "astro",
1422
+ "remix"
1423
+ ],
1424
+ "dependencies": [
1425
+ "@base-ui/react",
1426
+ "lucide-react"
1427
+ ],
1428
+ "registryDependencies": [
1429
+ "button",
1430
+ "input",
1431
+ "label",
1432
+ "card"
1433
+ ],
1434
+ "files": [
1435
+ {
1436
+ "name": "blocks/login-01.tsx",
1437
+ "content": "\"use client\"\n\nimport * as React from \"react\"\n\nexport function Login01() {\n return (\n <div className=\"flex min-h-screen items-center justify-center bg-muted/50 p-4\">\n <div className=\"w-full max-w-sm rounded-xl border border-border bg-card p-6 text-card-foreground shadow-xs\">\n <div className=\"text-center mb-6\">\n <h1 className=\"text-2xl font-bold text-foreground\">Welcome back</h1>\n <p className=\"text-sm text-muted-foreground\">Sign in to your account</p>\n </div>\n <form onSubmit={(e) => e.preventDefault()} className=\"space-y-4\">\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium text-foreground\">Email</label>\n <input type=\"email\" placeholder=\"m@example.com\" className=\"flex h-10 w-full rounded-md border border-border bg-background px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground shadow-xs\" />\n </div>\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium text-foreground\">Password</label>\n <input type=\"password\" placeholder=\"Enter your password\" className=\"flex h-10 w-full rounded-md border border-border bg-background px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground shadow-xs\" />\n </div>\n <button type=\"submit\" className=\"inline-flex h-10 w-full items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90 transition-colors\">Sign in</button>\n </form>\n </div>\n </div>\n )\n}\n"
1438
+ }
1439
+ ]
1440
+ },
1441
+ {
1442
+ "name": "login-02",
1443
+ "type": "components:block",
1444
+ "frameworks": [
1445
+ "react",
1446
+ "nextjs",
1447
+ "vue",
1448
+ "nuxt",
1449
+ "solid",
1450
+ "svelte",
1451
+ "astro",
1452
+ "remix"
1453
+ ],
1454
+ "dependencies": [
1455
+ "@base-ui/react",
1456
+ "lucide-react"
1457
+ ],
1458
+ "registryDependencies": [
1459
+ "button",
1460
+ "input",
1461
+ "label",
1462
+ "card",
1463
+ "separator"
1464
+ ],
1465
+ "files": [
1466
+ {
1467
+ "name": "blocks/login-02.tsx",
1468
+ "content": "\"use client\"\n\nimport * as React from \"react\"\n\nexport function Login02() {\n return (\n <div className=\"flex min-h-screen items-center justify-center bg-muted/50 p-4\">\n <div className=\"w-full max-w-sm rounded-xl border border-border bg-card p-6 text-card-foreground shadow-xs\">\n <div className=\"text-center mb-6\">\n <h1 className=\"text-2xl font-bold text-foreground\">Create an account</h1>\n <p className=\"text-sm text-muted-foreground\">Choose your sign up method</p>\n </div>\n <div className=\"space-y-3\">\n <button className=\"inline-flex h-10 w-full items-center justify-center rounded-md border border-border bg-background px-4 py-2 text-sm font-medium text-foreground hover:bg-muted transition-colors\">\n <svg className=\"w-4 h-4 mr-2\" viewBox=\"0 0 24 24\"><path fill=\"currentColor\" d=\"M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92a5.06 5.06 0 0 1-2.2 3.32v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.1z\"/><path fill=\"currentColor\" d=\"M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z\"/><path fill=\"currentColor\" d=\"M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z\"/><path fill=\"currentColor\" d=\"M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z\"/></svg>\n Continue with Google\n </button>\n <button className=\"inline-flex h-10 w-full items-center justify-center rounded-md border border-border bg-background px-4 py-2 text-sm font-medium text-foreground hover:bg-muted transition-colors\">\n <svg className=\"w-4 h-4 mr-2\" viewBox=\"0 0 24 24\"><path fill=\"currentColor\" d=\"M12 0C5.37 0 0 5.37 0 12c0 5.3 3.44 9.8 8.2 11.39.6.11.82-.26.82-.58v-2.05c-3.34.72-4.04-1.61-4.04-1.61-.55-1.39-1.34-1.76-1.34-1.76-1.09-.74.08-.73.08-.73 1.2.09 1.84 1.24 1.84 1.24 1.07 1.84 2.81 1.31 3.5 1 .1-.77.42-1.31.76-1.61-2.66-.3-5.47-1.33-5.47-5.93 0-1.31.47-2.38 1.24-3.22-.14-.3-.54-1.52.1-3.18 0 0 1-.33 3.3 1.23.96-.27 2-.4 3.02-.4s2.06.13 3.02.4c2.3-1.56 3.3-1.23 3.3-1.23.64 1.66.24 2.88.12 3.18.77.84 1.24 1.91 1.24 3.22 0 4.61-2.8 5.63-5.48 5.92.42.36.81 1.09.81 2.2v3.27c0 .32.22.7.83.58C20.56 21.8 24 17.3 24 12 24 5.37 18.63 0 12 0z\"/></svg>\n Continue with GitHub\n </button>\n <div className=\"relative my-4\">\n <div className=\"absolute inset-0 flex items-center\"><span className=\"w-full border-t border-border\" /></div>\n <div className=\"relative flex justify-center text-xs\"><span className=\"bg-card px-2 text-muted-foreground\">or</span></div>\n </div>\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium text-foreground\">Email</label>\n <input type=\"email\" placeholder=\"m@example.com\" className=\"flex h-10 w-full rounded-md border border-border bg-background px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground shadow-xs\" />\n </div>\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium text-foreground\">Password</label>\n <input type=\"password\" placeholder=\"Create a password\" className=\"flex h-10 w-full rounded-md border border-border bg-background px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground shadow-xs\" />\n </div>\n <button type=\"submit\" className=\"inline-flex h-10 w-full items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90 transition-colors\">Create account</button>\n </div>\n </div>\n </div>\n )\n}\n"
1469
+ }
1470
+ ]
1471
+ },
1472
+ {
1473
+ "name": "pricing-01",
1474
+ "type": "components:block",
1475
+ "frameworks": [
1476
+ "react",
1477
+ "nextjs",
1478
+ "vue",
1479
+ "nuxt",
1480
+ "solid",
1481
+ "svelte",
1482
+ "astro",
1483
+ "remix"
1484
+ ],
1485
+ "dependencies": [
1486
+ "@base-ui/react",
1487
+ "lucide-react"
1488
+ ],
1489
+ "registryDependencies": [
1490
+ "card",
1491
+ "button",
1492
+ "badge"
1493
+ ],
1494
+ "files": [
1495
+ {
1496
+ "name": "blocks/pricing-01.tsx",
1497
+ "content": "\"use client\"\n\nimport * as React from \"react\"\n\nexport function Pricing01() {\n const tiers = [\n { name: \"Starter\", price: \"$9\", description: \"Perfect for getting started\", popular: false },\n { name: \"Pro\", price: \"$29\", description: \"Best for growing teams\", popular: true },\n { name: \"Enterprise\", price: \"$99\", description: \"For large organizations\", popular: false },\n ]\n return (\n <section className=\"py-16 px-4\">\n <div className=\"text-center mb-10\">\n <h2 className=\"text-3xl font-bold text-foreground\">Simple pricing</h2>\n <p className=\"text-muted-foreground mt-2\">Choose the plan that fits your needs</p>\n </div>\n <div className=\"grid grid-cols-1 md:grid-cols-3 gap-6 max-w-4xl mx-auto\">\n {tiers.map((tier) => (\n <div key={tier.name} className={`rounded-xl border ${tier.popular ? \"border-primary\" : \"border-border\"} bg-card p-6 text-card-foreground shadow-xs relative`}>\n {tier.popular && <span className=\"absolute -top-2.5 left-1/2 -translate-x-1/2 inline-flex items-center rounded-full border border-border bg-background px-2.5 py-0.5 text-xs font-semibold text-foreground\">Most Popular</span>}\n <h3 className=\"text-lg font-semibold text-foreground\">{tier.name}</h3>\n <p className=\"text-sm text-muted-foreground mt-1\">{tier.description}</p>\n <p className=\"mt-4\"><span className=\"text-4xl font-bold text-foreground\">{tier.price}</span><span className=\"text-sm text-muted-foreground\">/month</span></p>\n <button className=\"mt-6 inline-flex h-10 w-full items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90 transition-colors\">Get started</button>\n </div>\n ))}\n </div>\n </section>\n )\n}\n"
1498
+ }
1499
+ ]
1500
+ },
1501
+ {
1502
+ "name": "pricing-02",
1503
+ "type": "components:block",
1504
+ "frameworks": [
1505
+ "react",
1506
+ "nextjs",
1507
+ "vue",
1508
+ "nuxt",
1509
+ "solid",
1510
+ "svelte",
1511
+ "astro",
1512
+ "remix"
1513
+ ],
1514
+ "dependencies": [
1515
+ "@base-ui/react",
1516
+ "lucide-react"
1517
+ ],
1518
+ "registryDependencies": [
1519
+ "card",
1520
+ "button",
1521
+ "badge",
1522
+ "table"
1523
+ ],
1524
+ "files": [
1525
+ {
1526
+ "name": "blocks/pricing-02.tsx",
1527
+ "content": "\"use client\"\n\nimport * as React from \"react\"\n\nexport function Pricing02() {\n const features = [\"Unlimited projects\", \"Team collaboration\", \"API access\", \"Priority support\", \"Custom domains\", \"Analytics dashboard\"]\n const plans = [\n { name: \"Free\", price: \"$0\", features: [true, true, false, false, false, false] },\n { name: \"Pro\", price: \"$29\", features: [true, true, true, true, false, false] },\n { name: \"Business\", price: \"$79\", features: [true, true, true, true, true, true] },\n ]\n return (\n <section className=\"py-16 px-4\">\n <div className=\"text-center mb-10\">\n <h2 className=\"text-3xl font-bold text-foreground\">Compare plans</h2>\n <p className=\"text-muted-foreground mt-2\">Find the right plan for your team</p>\n </div>\n <div className=\"overflow-x-auto max-w-4xl mx-auto\">\n <table className=\"w-full border-collapse\">\n <thead>\n <tr className=\"border-b border-border\">\n <th className=\"text-left py-3 px-4 text-sm font-medium text-muted-foreground\">Feature</th>\n {plans.map((p) => <th key={p.name} className=\"py-3 px-4 text-sm font-semibold text-foreground text-center\">{p.name}<div className=\"text-lg font-bold\">{p.price}<span className=\"text-xs font-normal text-muted-foreground\">/mo</span></div></th>)}\n </tr>\n </thead>\n <tbody>\n {features.map((feature, idx) => (\n <tr key={feature} className=\"border-b border-border\">\n <td className=\"py-3 px-4 text-sm text-foreground\">{feature}</td>\n {plans.map((p) => (\n <td key={p.name} className=\"py-3 px-4 text-center\">\n {p.features[idx] ? <svg className=\"w-4 h-4 mx-auto text-green-500\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth=\"3\"><path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M4.5 12.75l6 6 9-13.5\" /></svg> : <svg className=\"w-4 h-4 mx-auto text-muted-foreground/40\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth=\"2\"><path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M6 18L18 6M6 6l12 12\" /></svg>}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </section>\n )\n}\n"
1528
+ }
1529
+ ]
1530
+ },
1531
+ {
1532
+ "name": "auth",
1533
+ "type": "components:template",
1534
+ "frameworks": [
1535
+ "react",
1536
+ "nextjs",
1537
+ "vue",
1538
+ "nuxt",
1539
+ "solid",
1540
+ "svelte",
1541
+ "astro",
1542
+ "remix"
1543
+ ],
1544
+ "dependencies": [
1545
+ "@base-ui/react",
1546
+ "lucide-react",
1547
+ "next"
1548
+ ],
1549
+ "registryDependencies": [
1550
+ "login-01",
1551
+ "login-02"
1552
+ ],
1553
+ "files": [
1554
+ {
1555
+ "name": "templates/auth.tsx",
1556
+ "content": "\"use client\"\n\nimport * as React from \"react\"\n\nexport function AuthPage() {\n const [mode, setMode] = React.useState<\"login\" | \"register\">(\"login\")\n return (\n <div className=\"flex min-h-screen items-center justify-center bg-muted/50 p-4\">\n <div className=\"w-full max-w-sm rounded-xl border border-border bg-card p-6 text-card-foreground shadow-xs\">\n <div className=\"flex mb-6 rounded-md border border-border p-1 bg-muted/50\">\n <button onClick={() => setMode(\"login\")} className={`flex-1 rounded-md px-3 py-1.5 text-sm font-medium transition-colors ${mode === \"login\" ? \"bg-background text-foreground shadow-xs\" : \"text-muted-foreground hover:text-foreground\"}`}>Sign in</button>\n <button onClick={() => setMode(\"register\")} className={`flex-1 rounded-md px-3 py-1.5 text-sm font-medium transition-colors ${mode === \"register\" ? \"bg-background text-foreground shadow-xs\" : \"text-muted-foreground hover:text-foreground\"}`}>Register</button>\n </div>\n {mode === \"login\" ? (\n <form onSubmit={(e) => e.preventDefault()} className=\"space-y-4\">\n <div className=\"text-center mb-2\">\n <h1 className=\"text-xl font-bold text-foreground\">Welcome back</h1>\n <p className=\"text-sm text-muted-foreground\">Sign in to your account</p>\n </div>\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium text-foreground\">Email</label>\n <input type=\"email\" placeholder=\"m@example.com\" className=\"flex h-10 w-full rounded-md border border-border bg-background px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground shadow-xs\" />\n </div>\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium text-foreground\">Password</label>\n <input type=\"password\" placeholder=\"Enter your password\" className=\"flex h-10 w-full rounded-md border border-border bg-background px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground shadow-xs\" />\n </div>\n <button type=\"submit\" className=\"inline-flex h-10 w-full items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90 transition-colors\">Sign in</button>\n </form>\n ) : (\n <form onSubmit={(e) => e.preventDefault()} className=\"space-y-4\">\n <div className=\"text-center mb-2\">\n <h1 className=\"text-xl font-bold text-foreground\">Create account</h1>\n <p className=\"text-sm text-muted-foreground\">Enter your details to get started</p>\n </div>\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium text-foreground\">Name</label>\n <input type=\"text\" placeholder=\"John Doe\" className=\"flex h-10 w-full rounded-md border border-border bg-background px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground shadow-xs\" />\n </div>\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium text-foreground\">Email</label>\n <input type=\"email\" placeholder=\"m@example.com\" className=\"flex h-10 w-full rounded-md border border-border bg-background px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground shadow-xs\" />\n </div>\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium text-foreground\">Password</label>\n <input type=\"password\" placeholder=\"Create a password\" className=\"flex h-10 w-full rounded-md border border-border bg-background px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground shadow-xs\" />\n </div>\n <button type=\"submit\" className=\"inline-flex h-10 w-full items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90 transition-colors\">Create account</button>\n </form>\n )}\n </div>\n </div>\n )\n}\n"
1557
+ }
1558
+ ]
1559
+ },
1560
+ {
1561
+ "name": "dashboard",
1562
+ "type": "components:template",
1563
+ "frameworks": [
1564
+ "react",
1565
+ "nextjs",
1566
+ "vue",
1567
+ "nuxt",
1568
+ "solid",
1569
+ "svelte",
1570
+ "astro",
1571
+ "remix"
1572
+ ],
1573
+ "dependencies": [
1574
+ "@base-ui/react",
1575
+ "lucide-react",
1576
+ "next"
1577
+ ],
1578
+ "registryDependencies": [
1579
+ "dashboard-01",
1580
+ "sidebar",
1581
+ "button",
1582
+ "card"
1583
+ ],
1584
+ "files": [
1585
+ {
1586
+ "name": "templates/dashboard.tsx",
1587
+ "content": "\"use client\"\n\nimport * as React from \"react\"\n\nexport function DashboardPage() {\n return (\n <div className=\"flex min-h-screen bg-muted/50\">\n <aside className=\"w-64 border-r border-border bg-background p-4\">\n <div className=\"text-lg font-bold text-foreground mb-8\">Static UI</div>\n <nav className=\"space-y-1\">\n {[\"Overview\", \"Analytics\", \"Customers\", \"Settings\"].map((item) => (\n <a key={item} href=\"#\" className=\"block rounded-md px-3 py-2 text-sm font-medium text-muted-foreground hover:bg-accent hover:text-accent-foreground transition-colors\">{item}</a>\n ))}\n </nav>\n </aside>\n <main className=\"flex-1 p-6\">\n <header className=\"mb-6\">\n <h1 className=\"text-2xl font-bold text-foreground\">Dashboard</h1>\n <p className=\"text-sm text-muted-foreground\">Welcome back, here is your overview.</p>\n </header>\n <div className=\"grid grid-cols-1 md:grid-cols-3 gap-4 mb-6\">\n {[\n { label: \"Total Revenue\", value: \"$45,231\", change: \"+20.1%\" },\n { label: \"Active Users\", value: \"2,350\", change: \"+180.1%\" },\n { label: \"Sales\", value: \"12,234\", change: \"+19%\" },\n ].map((stat) => (\n <div key={stat.label} className=\"rounded-xl border border-border bg-card p-4 text-card-foreground shadow-xs\">\n <p className=\"text-sm text-muted-foreground\">{stat.label}</p>\n <p className=\"text-2xl font-bold text-foreground\">{stat.value}</p>\n <p className=\"text-xs text-green-500\">{stat.change}</p>\n </div>\n ))}\n </div>\n <div className=\"rounded-xl border border-border bg-card p-4 text-card-foreground shadow-xs\">\n <p className=\"text-sm text-muted-foreground mb-2\">Recent Activity</p>\n <div className=\"text-sm text-foreground\">No recent activity to show.</div>\n </div>\n </main>\n </div>\n )\n}\n"
1588
+ }
1589
+ ]
1590
+ },
1591
+ {
1592
+ "name": "marketing",
1593
+ "type": "components:template",
1594
+ "frameworks": [
1595
+ "react",
1596
+ "nextjs",
1597
+ "vue",
1598
+ "nuxt",
1599
+ "solid",
1600
+ "svelte",
1601
+ "astro",
1602
+ "remix"
1603
+ ],
1604
+ "dependencies": [
1605
+ "@base-ui/react",
1606
+ "lucide-react",
1607
+ "next"
1608
+ ],
1609
+ "registryDependencies": [
1610
+ "hero-01",
1611
+ "feature-01",
1612
+ "pricing-01",
1613
+ "button"
1614
+ ],
1615
+ "files": [
1616
+ {
1617
+ "name": "templates/marketing.tsx",
1618
+ "content": "\"use client\"\n\nimport * as React from \"react\"\n\nexport function MarketingPage() {\n return (\n <div className=\"flex min-h-screen flex-col bg-background text-foreground\">\n <header className=\"border-b border-border\">\n <div className=\"max-w-5xl mx-auto flex h-14 items-center justify-between px-4\">\n <span className=\"text-lg font-bold\">Static UI</span>\n <nav className=\"hidden md:flex items-center gap-6 text-sm font-medium text-muted-foreground\">\n <a href=\"#\" className=\"hover:text-foreground transition-colors\">Features</a>\n <a href=\"#\" className=\"hover:text-foreground transition-colors\">Pricing</a>\n <a href=\"#\" className=\"hover:text-foreground transition-colors\">Docs</a>\n </nav>\n <button className=\"inline-flex h-9 items-center justify-center rounded-md bg-primary px-4 text-sm font-medium text-primary-foreground hover:bg-primary/90 transition-colors\">Get started</button>\n </div>\n </header>\n <main className=\"flex-1\">\n <section className=\"py-24 px-4 text-center\">\n <div className=\"max-w-2xl mx-auto\">\n <span className=\"inline-flex items-center rounded-full border border-border bg-background px-2.5 py-0.5 text-xs font-semibold text-foreground mb-4\">New release v2.0</span>\n <h1 className=\"text-4xl font-bold tracking-tight sm:text-5xl\">Build beautiful interfaces with Static UI</h1>\n <p className=\"mt-4 text-lg text-muted-foreground\">A modern component library built on Base UI and Tailwind CSS v4.</p>\n <div className=\"mt-8 flex items-center justify-center gap-4\">\n <button className=\"inline-flex h-10 items-center justify-center rounded-md bg-primary px-6 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90 transition-colors\">Get started</button>\n <button className=\"inline-flex h-10 items-center justify-center rounded-md border border-border bg-background px-6 py-2 text-sm font-medium text-foreground hover:bg-muted transition-colors\">Learn more</button>\n </div>\n </div>\n </section>\n <section className=\"py-16 px-4 bg-muted/30\">\n <div className=\"max-w-4xl mx-auto\">\n <div className=\"text-center mb-10\">\n <h2 className=\"text-3xl font-bold\">Why Static UI?</h2>\n <p className=\"text-muted-foreground mt-2\">Everything you need to build modern interfaces</p>\n </div>\n <div className=\"grid grid-cols-1 md:grid-cols-3 gap-6\">\n {[{ title: \"Accessible\", desc: \"Built on Base UI with full ARIA support.\" }, { title: \"Customizable\", desc: \"Style with Tailwind CSS v4. No themes to override.\" }, { title: \"Lightweight\", desc: \"Copy what you need. Zero unnecessary deps.\" }].map((f) => (\n <div key={f.title} className=\"rounded-xl border border-border bg-card p-6 text-card-foreground shadow-xs\">\n <h3 className=\"font-semibold\">{f.title}</h3>\n <p className=\"mt-2 text-sm text-muted-foreground\">{f.desc}</p>\n </div>\n ))}\n </div>\n </div>\n </section>\n <section className=\"py-16 px-4\">\n <div className=\"text-center mb-10\">\n <h2 className=\"text-3xl font-bold\">Simple pricing</h2>\n <p className=\"text-muted-foreground mt-2\">Choose the plan that fits your needs</p>\n </div>\n <div className=\"grid grid-cols-1 md:grid-cols-3 gap-6 max-w-4xl mx-auto\">\n {[{ name: \"Starter\", price: \"$9\" }, { name: \"Pro\", price: \"$29\" }, { name: \"Enterprise\", price: \"$99\" }].map((tier) => (\n <div key={tier.name} className=\"rounded-xl border border-border bg-card p-6 text-card-foreground shadow-xs\">\n <h3 className=\"text-lg font-semibold\">{tier.name}</h3>\n <p className=\"mt-4\"><span className=\"text-4xl font-bold\">{tier.price}</span><span className=\"text-sm text-muted-foreground\">/month</span></p>\n <button className=\"mt-6 inline-flex h-10 w-full items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90 transition-colors\">Get started</button>\n </div>\n ))}\n </div>\n </section>\n </main>\n <footer className=\"border-t border-border py-6 text-center text-sm text-muted-foreground\">\n &copy; 2026 Static UI. All rights reserved.\n </footer>\n </div>\n )\n}\n"
503
1619
  }
504
1620
  ]
505
1621
  }