{
  "name": "file-upload-uploadthing-demo",
  "type": "registry:example",
  "dependencies": [
    "lucide-react",
    "uploadthing",
    "@uploadthing/react"
  ],
  "registryDependencies": [
    "button",
    "file-upload"
  ],
  "files": [
    {
      "path": "examples/file-upload-uploadthing-demo.tsx",
      "type": "registry:example",
      "content": "\"use client\";\n\nimport { Upload, X } from \"lucide-react\";\nimport * as React from \"react\";\nimport { toast } from \"sonner\";\nimport { UploadThingError } from \"uploadthing/server\";\n\nimport { uploadFiles } from \"@/lib/uploadthing\";\nimport { Button } from \"@/registry/bases/radix/ui/button\";\nimport {\n  FileUpload,\n  FileUploadDropzone,\n  FileUploadItem,\n  FileUploadItemDelete,\n  FileUploadItemMetadata,\n  FileUploadItemPreview,\n  FileUploadItemProgress,\n  FileUploadList,\n  type FileUploadProps,\n  FileUploadTrigger,\n} from \"@/registry/bases/radix/ui/file-upload\";\n\nexport default function FileUploadUploadThingDemo() {\n  const [isUploading, setIsUploading] = React.useState(false);\n  const [files, setFiles] = React.useState<File[]>([]);\n\n  const onUpload: NonNullable<FileUploadProps[\"onUpload\"]> = React.useCallback(\n    async (files, { onProgress }) => {\n      try {\n        setIsUploading(true);\n        const res = await uploadFiles(\"imageUploader\", {\n          files,\n          onUploadProgress: ({ file, progress }) => {\n            onProgress(file, progress);\n          },\n        });\n\n        toast.success(\"Uploaded files:\", {\n          description: (\n            <pre className=\"mt-2 w-80 rounded-md bg-accent/30 p-4 text-accent-foreground\">\n              <code>\n                {JSON.stringify(\n                  res.map((file) =>\n                    file.name.length > 25\n                      ? `${file.name.slice(0, 25)}...`\n                      : file.name,\n                  ),\n                  null,\n                  2,\n                )}\n              </code>\n            </pre>\n          ),\n        });\n      } catch (error) {\n        setIsUploading(false);\n\n        if (error instanceof UploadThingError) {\n          const errorMessage =\n            error.data && \"error\" in error.data\n              ? error.data.error\n              : \"Upload failed\";\n          toast.error(errorMessage);\n          return;\n        }\n\n        toast.error(\n          error instanceof Error ? error.message : \"An unknown error occurred\",\n        );\n      } finally {\n        setIsUploading(false);\n      }\n    },\n    [],\n  );\n\n  const onFileReject = React.useCallback((file: File, message: string) => {\n    toast(message, {\n      description: `\"${file.name.length > 20 ? `${file.name.slice(0, 20)}...` : file.name}\" has been rejected`,\n    });\n  }, []);\n\n  return (\n    <FileUpload\n      accept=\"image/*\"\n      maxFiles={2}\n      maxSize={4 * 1024 * 1024}\n      className=\"w-full max-w-md\"\n      onAccept={(files) => setFiles(files)}\n      onUpload={onUpload}\n      onFileReject={onFileReject}\n      multiple\n      disabled={isUploading}\n    >\n      <FileUploadDropzone>\n        <div className=\"flex flex-col items-center gap-1 text-center\">\n          <div className=\"flex items-center justify-center rounded-full border p-2.5\">\n            <Upload className=\"size-6 text-muted-foreground\" />\n          </div>\n          <p className=\"text-sm font-medium\">Drag & drop images here</p>\n          <p className=\"text-xs text-muted-foreground\">\n            Or click to browse (max 2 files, up to 4MB each)\n          </p>\n        </div>\n        <FileUploadTrigger asChild>\n          <Button variant=\"outline\" size=\"sm\" className=\"mt-2 w-fit\">\n            Browse files\n          </Button>\n        </FileUploadTrigger>\n      </FileUploadDropzone>\n      <FileUploadList>\n        {files.map((file, index) => (\n          <FileUploadItem key={index} value={file}>\n            <div className=\"flex w-full items-center gap-2\">\n              <FileUploadItemPreview />\n              <FileUploadItemMetadata />\n              <FileUploadItemDelete asChild>\n                <Button variant=\"ghost\" size=\"icon\" className=\"size-7\">\n                  <X />\n                </Button>\n              </FileUploadItemDelete>\n            </div>\n            <FileUploadItemProgress />\n          </FileUploadItem>\n        ))}\n      </FileUploadList>\n    </FileUpload>\n  );\n}\n",
      "target": ""
    }
  ]
}