{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "comp-553",
  "type": "registry:component",
  "title": "Comp 553",
  "description": "Comp 553",
  "files": [
    {
      "path": "registry/ui-basic/comp-553.tsx",
      "content": "\"use client\";\n\nimport { useState } from \"react\";\n\nimport { Button } from \"@/components/ui/button\";\nimport {\n\tAlertCircleIcon,\n\tFileArchiveIcon,\n\tFileIcon,\n\tFileSpreadsheetIcon,\n\tFileTextIcon,\n\tHeadphonesIcon,\n\tImageIcon,\n\tTrash2Icon,\n\tUploadIcon,\n\tVideoIcon,\n\tXIcon,\n} from \"lucide-react\";\n\nimport {\n\tformatBytes,\n\tuseFileUpload,\n\ttype FileWithPreview,\n} from \"../utilities/usefileUpload\";\n\n// Create some dummy initial files\nconst initialFiles = [\n\t{\n\t\tname: \"intro.zip\",\n\t\tsize: 252873,\n\t\ttype: \"application/zip\",\n\t\turl: \"https://example.com/intro.zip\",\n\t\tid: \"intro.zip-1744638436563-8u5xuls\",\n\t},\n\t{\n\t\tname: \"image-01.jpg\",\n\t\tsize: 1528737,\n\t\ttype: \"image/jpeg\",\n\t\turl: \"https://picsum.photos/1000/800?grayscale&random=1\",\n\t\tid: \"image-01-123456789\",\n\t},\n\t{\n\t\tname: \"audio.mp3\",\n\t\tsize: 1528737,\n\t\ttype: \"audio/mpeg\",\n\t\turl: \"https://example.com/audio.mp3\",\n\t\tid: \"audio-123456789\",\n\t},\n];\n\nconst getFileIcon = (file: { file: File | { type: string; name: string } }) => {\n\tconst fileType = file.file instanceof File ? file.file.type : file.file.type;\n\tconst fileName = file.file instanceof File ? file.file.name : file.file.name;\n\n\tconst iconMap = {\n\t\tpdf: {\n\t\t\ticon: FileTextIcon,\n\t\t\tconditions: (type: string, name: string) =>\n\t\t\t\ttype.includes(\"pdf\") ||\n\t\t\t\tname.endsWith(\".pdf\") ||\n\t\t\t\ttype.includes(\"word\") ||\n\t\t\t\tname.endsWith(\".doc\") ||\n\t\t\t\tname.endsWith(\".docx\"),\n\t\t},\n\t\tarchive: {\n\t\t\ticon: FileArchiveIcon,\n\t\t\tconditions: (type: string, name: string) =>\n\t\t\t\ttype.includes(\"zip\") ||\n\t\t\t\ttype.includes(\"archive\") ||\n\t\t\t\tname.endsWith(\".zip\") ||\n\t\t\t\tname.endsWith(\".rar\"),\n\t\t},\n\t\texcel: {\n\t\t\ticon: FileSpreadsheetIcon,\n\t\t\tconditions: (type: string, name: string) =>\n\t\t\t\ttype.includes(\"excel\") ||\n\t\t\t\tname.endsWith(\".xls\") ||\n\t\t\t\tname.endsWith(\".xlsx\"),\n\t\t},\n\t\tvideo: {\n\t\t\ticon: VideoIcon,\n\t\t\tconditions: (type: string) => type.includes(\"video/\"),\n\t\t},\n\t\taudio: {\n\t\t\ticon: HeadphonesIcon,\n\t\t\tconditions: (type: string) => type.includes(\"audio/\"),\n\t\t},\n\t\timage: {\n\t\t\ticon: ImageIcon,\n\t\t\tconditions: (type: string) => type.startsWith(\"image/\"),\n\t\t},\n\t};\n\n\tfor (const { icon: Icon, conditions } of Object.values(iconMap)) {\n\t\tif (conditions(fileType, fileName)) {\n\t\t\treturn <Icon className=\"size-5 opacity-60\" />;\n\t\t}\n\t}\n\n\treturn <FileIcon className=\"size-5 opacity-60\" />;\n};\n\nconst getFilePreview = (file: {\n\tfile: File | { type: string; name: string; url?: string };\n}) => {\n\tconst fileType = file.file instanceof File ? file.file.type : file.file.type;\n\tconst fileName = file.file instanceof File ? file.file.name : file.file.name;\n\n\tconst renderImage = (src: string) => (\n\t\t<img\n\t\t\tsrc={src}\n\t\t\talt={fileName}\n\t\t\tclassName=\"size-full rounded-t-[inherit] object-cover\"\n\t\t/>\n\t);\n\n\treturn (\n\t\t<div className=\"bg-accent flex aspect-square items-center justify-center overflow-hidden rounded-t-[inherit]\">\n\t\t\t{fileType.startsWith(\"image/\") ? (\n\t\t\t\tfile.file instanceof File ? (\n\t\t\t\t\t(() => {\n\t\t\t\t\t\tconst previewUrl = URL.createObjectURL(file.file);\n\t\t\t\t\t\treturn renderImage(previewUrl);\n\t\t\t\t\t})()\n\t\t\t\t) : file.file.url ? (\n\t\t\t\t\trenderImage(file.file.url)\n\t\t\t\t) : (\n\t\t\t\t\t<ImageIcon className=\"size-5 opacity-60\" />\n\t\t\t\t)\n\t\t\t) : (\n\t\t\t\tgetFileIcon(file)\n\t\t\t)}\n\t\t</div>\n\t);\n};\n\n// Type for tracking upload progress\ntype UploadProgress = {\n\tfileId: string;\n\tprogress: number;\n\tcompleted: boolean;\n};\n\n// Function to simulate file upload with more realistic timing and progress\nconst simulateUpload = (\n\ttotalBytes: number,\n\tonProgress: (progress: number) => void,\n\tonComplete: () => void\n) => {\n\tlet timeoutId: NodeJS.Timeout;\n\tlet uploadedBytes = 0;\n\tlet lastProgressReport = 0;\n\n\tconst simulateChunk = () => {\n\t\t// Simulate variable network conditions with random chunk sizes\n\t\tconst chunkSize = Math.floor(Math.random() * 300000) + 2000;\n\t\tuploadedBytes = Math.min(totalBytes, uploadedBytes + chunkSize);\n\n\t\t// Calculate progress percentage (0-100)\n\t\tconst progressPercent = Math.floor((uploadedBytes / totalBytes) * 100);\n\n\t\t// Only report progress if it's changed by at least 1%\n\t\tif (progressPercent > lastProgressReport) {\n\t\t\tlastProgressReport = progressPercent;\n\t\t\tonProgress(progressPercent);\n\t\t}\n\n\t\t// Continue simulation if not complete\n\t\tif (uploadedBytes < totalBytes) {\n\t\t\t// Variable delay between 50ms and 500ms to simulate network fluctuations (reduced for faster uploads)\n\t\t\tconst delay = Math.floor(Math.random() * 450) + 50;\n\n\t\t\t// Occasionally add a longer pause to simulate network congestion (5% chance, shorter duration)\n\t\t\tconst extraDelay = Math.random() < 0.05 ? 500 : 0;\n\n\t\t\ttimeoutId = setTimeout(simulateChunk, delay + extraDelay);\n\t\t} else {\n\t\t\t// Upload complete\n\t\t\tonComplete();\n\t\t}\n\t};\n\n\t// Start the simulation\n\ttimeoutId = setTimeout(simulateChunk, 100);\n\n\t// Return a cleanup function to cancel the simulation\n\treturn () => {\n\t\tif (timeoutId) {\n\t\t\tclearTimeout(timeoutId);\n\t\t}\n\t};\n};\n\nexport default function Component() {\n\tconst maxSizeMB = 5;\n\tconst maxSize = maxSizeMB * 1024 * 1024; // 5MB default\n\tconst maxFiles = 6;\n\n\t// State to track upload progress for each file\n\tconst [uploadProgress, setUploadProgress] = useState<UploadProgress[]>([]);\n\n\t// Function to handle newly added files\n\tconst handleFilesAdded = (addedFiles: FileWithPreview[]) => {\n\t\t// Initialize progress tracking for each new file\n\t\tconst newProgressItems = addedFiles.map((file) => ({\n\t\t\tfileId: file.id,\n\t\t\tprogress: 0,\n\t\t\tcompleted: false,\n\t\t}));\n\n\t\t// Add new progress items to state\n\t\tsetUploadProgress((prev) => [...prev, ...newProgressItems]);\n\n\t\t// Store cleanup functions\n\t\tconst cleanupFunctions: Array<() => void> = [];\n\n\t\t// Start simulated upload for each file\n\t\taddedFiles.forEach((file) => {\n\t\t\tconst fileSize =\n\t\t\t\tfile.file instanceof File ? file.file.size : file.file.size;\n\n\t\t\t// Start the upload simulation and store the cleanup function\n\t\t\tconst cleanup = simulateUpload(\n\t\t\t\tfileSize,\n\t\t\t\t// Progress callback\n\t\t\t\t(progress) => {\n\t\t\t\t\tsetUploadProgress((prev) =>\n\t\t\t\t\t\tprev.map((item) =>\n\t\t\t\t\t\t\titem.fileId === file.id ? { ...item, progress } : item\n\t\t\t\t\t\t)\n\t\t\t\t\t);\n\t\t\t\t},\n\t\t\t\t// Complete callback\n\t\t\t\t() => {\n\t\t\t\t\tsetUploadProgress((prev) =>\n\t\t\t\t\t\tprev.map((item) =>\n\t\t\t\t\t\t\titem.fileId === file.id\n\t\t\t\t\t\t\t\t? { ...item, completed: true }\n\t\t\t\t\t\t\t\t: item\n\t\t\t\t\t\t)\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t);\n\n\t\t\tcleanupFunctions.push(cleanup);\n\t\t});\n\n\t\t// Return a cleanup function that cancels all animations\n\t\treturn () => {\n\t\t\tcleanupFunctions.forEach((cleanup) => cleanup());\n\t\t};\n\t};\n\n\t// Remove the progress tracking for the file\n\tconst handleFileRemoved = (fileId: string) => {\n\t\tsetUploadProgress((prev) =>\n\t\t\tprev.filter((item) => item.fileId !== fileId)\n\t\t);\n\t};\n\n\tconst [\n\t\t{ files, isDragging, errors },\n\t\t{\n\t\t\thandleDragEnter,\n\t\t\thandleDragLeave,\n\t\t\thandleDragOver,\n\t\t\thandleDrop,\n\t\t\topenFileDialog,\n\t\t\tremoveFile,\n\t\t\tclearFiles,\n\t\t\tgetInputProps,\n\t\t},\n\t] = useFileUpload({\n\t\tmultiple: true,\n\t\tmaxFiles,\n\t\tmaxSize,\n\t\tinitialFiles,\n\t\tonFilesAdded: handleFilesAdded,\n\t});\n\n\treturn (\n\t\t<div className=\"flex flex-col gap-2\">\n\t\t\t{/* Drop area */}\n\t\t\t<div\n\t\t\t\tonDragEnter={handleDragEnter}\n\t\t\t\tonDragLeave={handleDragLeave}\n\t\t\t\tonDragOver={handleDragOver}\n\t\t\t\tonDrop={handleDrop}\n\t\t\t\tdata-dragging={isDragging || undefined}\n\t\t\t\tdata-files={files.length > 0 || undefined}\n\t\t\t\tclassName=\"border-input data-[dragging=true]:bg-accent/50 has-[input:focus]:border-ring has-[input:focus]:ring-ring/50 relative flex min-h-52 flex-col items-center overflow-hidden rounded-xl border border-dashed p-4 transition-colors not-data-files:justify-center has-[input:focus]:ring-[3px]\"\n\t\t\t>\n\t\t\t\t<input\n\t\t\t\t\t{...getInputProps()}\n\t\t\t\t\tclassName=\"sr-only\"\n\t\t\t\t\taria-label=\"Upload image file\"\n\t\t\t\t/>\n\t\t\t\t{files.length > 0 ? (\n\t\t\t\t\t<div className=\"flex w-full flex-col gap-3\">\n\t\t\t\t\t\t<div className=\"flex items-center justify-between gap-2\">\n\t\t\t\t\t\t\t<h3 className=\"truncate text-sm font-medium\">\n\t\t\t\t\t\t\t\tFiles ({files.length})\n\t\t\t\t\t\t\t</h3>\n\t\t\t\t\t\t\t<div className=\"flex gap-2\">\n\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\t\t\tonClick={openFileDialog}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<UploadIcon\n\t\t\t\t\t\t\t\t\t\tclassName=\"-ms-0.5 size-3.5 opacity-60\"\n\t\t\t\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\tAdd files\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\t\t// Clear all progress tracking\n\t\t\t\t\t\t\t\t\t\tsetUploadProgress([]);\n\t\t\t\t\t\t\t\t\t\tclearFiles();\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<Trash2Icon\n\t\t\t\t\t\t\t\t\t\tclassName=\"-ms-0.5 size-3.5 opacity-60\"\n\t\t\t\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\tRemove all\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t<div className=\"w-full space-y-2\">\n\t\t\t\t\t\t\t{files.map((file) => {\n\t\t\t\t\t\t\t\t// Find the upload progress for this file once to avoid repeated lookups\n\t\t\t\t\t\t\t\tconst fileProgress = uploadProgress.find(\n\t\t\t\t\t\t\t\t\t(p) => p.fileId === file.id\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\tconst isUploading =\n\t\t\t\t\t\t\t\t\tfileProgress && !fileProgress.completed;\n\n\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\tkey={file.id}\n\t\t\t\t\t\t\t\t\t\tdata-uploading={isUploading || undefined}\n\t\t\t\t\t\t\t\t\t\tclassName=\"bg-background flex flex-col gap-1 rounded-lg border p-2 pe-3 transition-opacity duration-300\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<div className=\"flex items-center justify-between gap-2\">\n\t\t\t\t\t\t\t\t\t\t\t<div className=\"flex items-center gap-3 overflow-hidden in-data-[uploading=true]:opacity-50\">\n\t\t\t\t\t\t\t\t\t\t\t\t<div className=\"flex aspect-square size-10 shrink-0 items-center justify-center rounded border\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t{getFileIcon(file)}\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\t<div className=\"flex min-w-0 flex-col gap-0.5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<p className=\"truncate text-[13px] font-medium\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{file.file instanceof File\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t? file.file.name\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t: file.file.name}\n\t\t\t\t\t\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<p className=\"text-muted-foreground text-xs\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{formatBytes(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tfile.file instanceof File\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t? file.file.size\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t: file.file.size\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"text-muted-foreground/80 hover:text-foreground -me-2 size-8 hover:bg-transparent\"\n\t\t\t\t\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\t\t\t\t\thandleFileRemoved(file.id);\n\t\t\t\t\t\t\t\t\t\t\t\t\tremoveFile(file.id);\n\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t\taria-label=\"Remove file\"\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t<XIcon\n\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"size-4\"\n\t\t\t\t\t\t\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t\t\t{/* Upload progress bar */}\n\t\t\t\t\t\t\t\t\t\t{fileProgress &&\n\t\t\t\t\t\t\t\t\t\t\t(() => {\n\t\t\t\t\t\t\t\t\t\t\t\tconst progress = fileProgress.progress || 0;\n\t\t\t\t\t\t\t\t\t\t\t\tconst completed =\n\t\t\t\t\t\t\t\t\t\t\t\t\tfileProgress.completed || false;\n\n\t\t\t\t\t\t\t\t\t\t\t\tif (completed) return null;\n\n\t\t\t\t\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t\t\t\t\t<div className=\"mt-1 flex items-center gap-2\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<div className=\"h-1.5 w-full overflow-hidden rounded-full bg-gray-100\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"bg-primary h-full transition-all duration-300 ease-out\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\twidth: `${progress}%`,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<span className=\"text-muted-foreground w-10 text-xs tabular-nums\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{progress}%\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t\t})()}\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t) : (\n\t\t\t\t\t<div className=\"flex flex-col items-center justify-center px-4 py-3 text-center\">\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tclassName=\"bg-background mb-2 flex size-11 shrink-0 items-center justify-center rounded-full border\"\n\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<ImageIcon className=\"size-4 opacity-60\" />\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<p className=\"mb-1.5 text-sm font-medium\">\n\t\t\t\t\t\t\tDrop your files here\n\t\t\t\t\t\t</p>\n\t\t\t\t\t\t<p className=\"text-muted-foreground text-xs\">\n\t\t\t\t\t\t\tMax {maxFiles} files ∙ Up to {maxSizeMB}MB\n\t\t\t\t\t\t</p>\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\t\tclassName=\"mt-4\"\n\t\t\t\t\t\t\tonClick={openFileDialog}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<UploadIcon\n\t\t\t\t\t\t\t\tclassName=\"-ms-1 opacity-60\"\n\t\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\tSelect images\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</div>\n\n\t\t\t{errors.length > 0 && (\n\t\t\t\t<div\n\t\t\t\t\tclassName=\"text-destructive flex items-center gap-1 text-xs\"\n\t\t\t\t\trole=\"alert\"\n\t\t\t\t>\n\t\t\t\t\t<AlertCircleIcon className=\"size-3 shrink-0\" />\n\t\t\t\t\t<span>{errors[0]}</span>\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t<p\n\t\t\t\taria-live=\"polite\"\n\t\t\t\trole=\"region\"\n\t\t\t\tclassName=\"text-muted-foreground mt-2 text-center text-xs\"\n\t\t\t>\n\t\t\t\tWith simulated progress track ∙{\" \"}\n\t\t\t\t<a\n\t\t\t\t\thref=\"https://github.com/origin-space/originui/tree/main/docs/use-file-upload.md\"\n\t\t\t\t\tclassName=\"hover:text-foreground underline\"\n\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t>\n\t\t\t\t\tAPI\n\t\t\t\t</a>\n\t\t\t</p>\n\t\t</div>\n\t);\n}\n",
      "type": "registry:ui"
    },
    {
      "path": "components/ui/button.tsx",
      "content": "import * as React from \"react\";\r\n\r\nimport { cn } from \"@/registry/utilities/cn\";\r\nimport { Slot } from \"@radix-ui/react-slot\";\r\nimport { cva, type VariantProps } from \"class-variance-authority\";\r\n\r\nconst buttonVariants = cva(\r\n\t\"inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm text-white hover:text-gray-400 font-medium ring-offset-background transition-colors focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50\",\r\n\t{\r\n\t\tvariants: {\r\n\t\t\tvariant: {\r\n\t\t\t\tsimple:\r\n\t\t\t\t\t\"bg-secondary relative z-10 bg-transparent hover:border-secondary hover:bg-secondary/50  border border-transparent dark:text-white text-sm md:text-sm transition font-medium duration-200  rounded-md px-4 py-2  flex items-center justify-center\",\r\n\t\t\t\tdefault: \"bg-primary text-primary-foreground hover:bg-primary/90\",\r\n\t\t\t\tdestructive:\r\n\t\t\t\t\t\"bg-destructive text-destructive-foreground hover:bg-destructive/90\",\r\n\t\t\t\toutline:\r\n\t\t\t\t\t\"border border-input bg-background hover:bg-accent hover:text-accent-foreground\",\r\n\t\t\t\tsecondary:\r\n\t\t\t\t\t\"bg-secondary text-secondary-foreground hover:bg-secondary/80\",\r\n\t\t\t\tghost: \"hover:bg-accent hover:text-black hover:stroke-black dark:text-white text-black\",\r\n\t\t\t\tlink: \"text-primary underline-offset-4 hover:underline\",\r\n\t\t\t},\r\n\t\t\tsize: {\r\n\t\t\t\tdefault: \"h-10 px-4 py-2\",\r\n\t\t\t\tsm: \"h-9 rounded-md px-3\",\r\n\t\t\t\tlg: \"h-11 rounded-md px-8\",\r\n\t\t\t\ticon: \"h-10 w-10\",\r\n\t\t\t},\r\n\t\t},\r\n\t\tdefaultVariants: {\r\n\t\t\tvariant: \"default\",\r\n\t\t\tsize: \"default\",\r\n\t\t},\r\n\t}\r\n);\r\n\r\nexport interface ButtonProps\r\n\textends React.ButtonHTMLAttributes<HTMLButtonElement>,\r\n\t\tVariantProps<typeof buttonVariants> {\r\n\tasChild?: boolean;\r\n}\r\n\r\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\r\n\t({ className, variant, size, asChild = false, ...props }, ref) => {\r\n\t\tconst Comp = asChild ? Slot : \"button\";\r\n\t\treturn (\r\n\t\t\t<Comp\r\n\t\t\t\tclassName={cn(buttonVariants({ variant, size, className }))}\r\n\t\t\t\tref={ref}\r\n\t\t\t\t{...props}\r\n\t\t\t/>\r\n\t\t);\r\n\t}\r\n);\r\nButton.displayName = \"Button\";\r\n\r\nexport { Button, buttonVariants };\r\n",
      "type": "registry:ui"
    },
    {
      "path": "registry/utilities/cn.ts",
      "content": "import { ClassValue, clsx } from \"clsx\";\r\nimport { twMerge } from \"tailwind-merge\";\r\n\r\nexport function cn(...inputs: ClassValue[]) {\r\n\treturn twMerge(clsx(inputs));\r\n}\r\n",
      "type": "registry:ui"
    }
  ]
}