{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "settings-storage",
  "title": "Settings Storage",
  "description": "Manage storage usage and quotas by category.",
  "registryDependencies": [
    "alert-dialog",
    "button",
    "card",
    "field",
    "progress",
    "separator"
  ],
  "files": [
    {
      "path": "registry/new-york/blocks/settings/settings-storage.tsx",
      "content": "\"use client\";\n\nimport {\n  Database,\n  Loader2,\n  type LucideIcon,\n  Trash2,\n  TrendingDown,\n} from \"lucide-react\";\nimport { useState } from \"react\";\nimport { cn } from \"@/lib/utils\";\nimport {\n  AlertDialog,\n  AlertDialogAction,\n  AlertDialogCancel,\n  AlertDialogContent,\n  AlertDialogDescription,\n  AlertDialogFooter,\n  AlertDialogHeader,\n  AlertDialogTitle,\n  AlertDialogTrigger,\n} from \"@/registry/new-york/ui/alert-dialog\";\nimport { Button } from \"@/registry/new-york/ui/button\";\nimport {\n  Card,\n  CardContent,\n  CardDescription,\n  CardHeader,\n  CardTitle,\n} from \"@/registry/new-york/ui/card\";\nimport { FieldDescription, FieldLabel } from \"@/registry/new-york/ui/field\";\nimport { Progress } from \"@/registry/new-york/ui/progress\";\nimport { Separator } from \"@/registry/new-york/ui/separator\";\n\nexport interface StorageCategory {\n  id: string;\n  name: string;\n  icon: LucideIcon;\n  used: number;\n  total?: number;\n  color: string;\n}\n\nexport interface SettingsStorageProps {\n  totalUsed?: number;\n  totalLimit?: number;\n  categories?: StorageCategory[];\n  onCleanup?: (categoryId?: string) => Promise<void>;\n  className?: string;\n}\n\nfunction formatBytes(bytes: number): string {\n  if (bytes === 0) return \"0 Bytes\";\n  const k = 1024;\n  const sizes = [\"Bytes\", \"KB\", \"MB\", \"GB\", \"TB\"];\n  const i = Math.floor(Math.log(bytes) / Math.log(k));\n  return `${Math.round((bytes / k ** i) * 100) / 100} ${sizes[i]}`;\n}\n\nexport default function SettingsStorage({\n  totalUsed = 0,\n  totalLimit = 100 * 1024 * 1024 * 1024, // 100 GB default\n  categories = [],\n  onCleanup,\n  className,\n}: SettingsStorageProps) {\n  const [isCleaning, setIsCleaning] = useState<string | null>(null);\n\n  const usagePercentage = (totalUsed / totalLimit) * 100;\n  const remaining = totalLimit - totalUsed;\n\n  const handleCleanup = async (categoryId?: string) => {\n    setIsCleaning(categoryId || \"all\");\n    try {\n      await onCleanup?.(categoryId);\n    } finally {\n      setIsCleaning(null);\n    }\n  };\n\n  return (\n    <Card className={cn(\"w-full shadow-xs\", className)}>\n      <CardHeader>\n        <div className=\"flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between\">\n          <div className=\"flex min-w-0 flex-1 flex-col gap-2\">\n            <CardTitle className=\"wrap-break-word\">Storage</CardTitle>\n            <CardDescription className=\"wrap-break-word\">\n              Manage your storage usage and quotas\n            </CardDescription>\n          </div>\n        </div>\n      </CardHeader>\n      <CardContent>\n        <div className=\"flex flex-col gap-6\">\n          {/* Overall Usage */}\n          <div className=\"flex flex-col gap-4 rounded-lg border p-4\">\n            <div className=\"flex items-center gap-2\">\n              <div className=\"flex size-8 items-center justify-center rounded-lg bg-muted\">\n                <Database className=\"size-4\" />\n              </div>\n              <FieldLabel className=\"mb-0\">Storage Usage</FieldLabel>\n            </div>\n            <div className=\"flex flex-col gap-3\">\n              <div className=\"flex items-center justify-between\">\n                <span className=\"text-muted-foreground text-sm\">\n                  {formatBytes(totalUsed)} of {formatBytes(totalLimit)} used\n                </span>\n                <span className=\"font-medium text-sm\">\n                  {usagePercentage.toFixed(1)}%\n                </span>\n              </div>\n              <Progress value={usagePercentage} />\n              <p className=\"text-muted-foreground text-xs\">\n                {formatBytes(remaining)} remaining\n              </p>\n            </div>\n          </div>\n\n          <Separator />\n\n          {/* Storage by Category */}\n          <div className=\"flex flex-col gap-4\">\n            <h3 className=\"font-semibold text-base\">Storage by Category</h3>\n            {categories.length === 0 ? (\n              <p className=\"text-muted-foreground text-sm\">\n                No storage data available\n              </p>\n            ) : (\n              <div className=\"grid gap-4 md:grid-cols-2\">\n                {categories.map((category) => {\n                  const Icon = category.icon;\n                  const categoryPercentage = category.total\n                    ? (category.used / category.total) * 100\n                    : 0;\n\n                  return (\n                    <div\n                      className=\"flex flex-col gap-4 rounded-lg border p-4\"\n                      key={category.id}\n                    >\n                      <div className=\"flex items-center justify-between\">\n                        <div className=\"flex items-center gap-2\">\n                          <div\n                            className={cn(\n                              \"flex size-8 items-center justify-center rounded-lg\",\n                              category.color\n                            )}\n                          >\n                            <Icon className=\"size-4\" />\n                          </div>\n                          <FieldLabel className=\"mb-0\">\n                            {category.name}\n                          </FieldLabel>\n                        </div>\n                        {category.total && (\n                          <span className=\"font-medium text-sm\">\n                            {categoryPercentage.toFixed(1)}%\n                          </span>\n                        )}\n                      </div>\n                      <div className=\"flex flex-col gap-2\">\n                        <div className=\"flex items-center justify-between text-muted-foreground text-xs\">\n                          <span>{formatBytes(category.used)}</span>\n                          {category.total && (\n                            <span>of {formatBytes(category.total)}</span>\n                          )}\n                        </div>\n                        {category.total && (\n                          <Progress value={categoryPercentage} />\n                        )}\n                      </div>\n                      <AlertDialog>\n                        <AlertDialogTrigger asChild>\n                          <Button\n                            className=\"w-full\"\n                            disabled={isCleaning === category.id}\n                            type=\"button\"\n                            variant=\"outline\"\n                          >\n                            {isCleaning === category.id ? (\n                              <>\n                                <Loader2 className=\"size-4 animate-spin\" />\n                                Cleaning…\n                              </>\n                            ) : (\n                              <>\n                                <Trash2 className=\"size-4\" />\n                                Clean Up\n                              </>\n                            )}\n                          </Button>\n                        </AlertDialogTrigger>\n                        <AlertDialogContent>\n                          <AlertDialogHeader>\n                            <AlertDialogTitle>\n                              Clean Up {category.name}?\n                            </AlertDialogTitle>\n                            <AlertDialogDescription>\n                              This will delete old and unused files from{\" \"}\n                              {category.name}. This action cannot be undone.\n                            </AlertDialogDescription>\n                          </AlertDialogHeader>\n                          <AlertDialogFooter>\n                            <AlertDialogCancel>Cancel</AlertDialogCancel>\n                            <AlertDialogAction\n                              onClick={() => handleCleanup(category.id)}\n                            >\n                              Clean Up\n                            </AlertDialogAction>\n                          </AlertDialogFooter>\n                        </AlertDialogContent>\n                      </AlertDialog>\n                    </div>\n                  );\n                })}\n              </div>\n            )}\n          </div>\n\n          <Separator />\n\n          {/* Cleanup Actions */}\n          <div className=\"flex flex-col gap-4 rounded-lg border p-4\">\n            <div className=\"flex items-center gap-2\">\n              <div className=\"flex size-8 items-center justify-center rounded-lg bg-muted\">\n                <TrendingDown className=\"size-4\" />\n              </div>\n              <FieldLabel className=\"mb-0\">Storage Optimization</FieldLabel>\n            </div>\n            <div className=\"flex flex-col gap-3\">\n              <AlertDialog>\n                <AlertDialogTrigger asChild>\n                  <Button\n                    className=\"w-full sm:w-auto\"\n                    disabled={isCleaning === \"all\"}\n                    type=\"button\"\n                    variant=\"outline\"\n                  >\n                    {isCleaning === \"all\" ? (\n                      <>\n                        <Loader2 className=\"size-4 animate-spin\" />\n                        Cleaning…\n                      </>\n                    ) : (\n                      <>\n                        <Trash2 className=\"size-4\" />\n                        Empty Trash\n                      </>\n                    )}\n                  </Button>\n                </AlertDialogTrigger>\n                <AlertDialogContent>\n                  <AlertDialogHeader>\n                    <AlertDialogTitle>Empty Trash?</AlertDialogTitle>\n                    <AlertDialogDescription>\n                      This will permanently delete all files in your trash. This\n                      action cannot be undone.\n                    </AlertDialogDescription>\n                  </AlertDialogHeader>\n                  <AlertDialogFooter>\n                    <AlertDialogCancel>Cancel</AlertDialogCancel>\n                    <AlertDialogAction onClick={() => handleCleanup()}>\n                      Empty Trash\n                    </AlertDialogAction>\n                  </AlertDialogFooter>\n                </AlertDialogContent>\n              </AlertDialog>\n              <FieldDescription>\n                Remove old and unused files to free up storage space\n              </FieldDescription>\n            </div>\n          </div>\n        </div>\n      </CardContent>\n    </Card>\n  );\n}\n",
      "type": "registry:ui"
    }
  ],
  "categories": [
    "block",
    "settings"
  ],
  "type": "registry:ui"
}