{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "custom-toast",
  "type": "registry:ui",
  "title": "Custom Toast",
  "description": "Beautiful toast with progress bar and colored variants.",
  "dependencies": [
    "sonner",
    "lucide-react"
  ],
  "registryDependencies": [
    "button"
  ],
  "files": [
    {
      "path": "registry/new-york/ui/custom-toast.tsx",
      "content": "\"use client\"\n\nimport {\n  CircleCheckIcon,\n  InfoIcon,\n  OctagonXIcon,\n  TriangleAlertIcon,\n  XIcon,\n} from \"lucide-react\"\nimport { useEffect, useState } from \"react\"\nimport { toast } from \"sonner\"\nimport { Button } from \"@/components/ui/button\"\nimport { cn } from \"@/lib/utils\"\n\ntype ToastType = \"success\" | \"error\" | \"warning\" | \"info\"\n\ninterface CustomToastProps {\n  id: string | number\n  type: ToastType\n  message: string\n  description?: string\n  duration?: number\n}\n\nconst config: Record<\n  ToastType,\n  { icon: React.ElementType; progressColor: string; iconColor: string }\n> = {\n  success: {\n    icon: CircleCheckIcon,\n    progressColor: \"bg-green-500\",\n    iconColor: \"text-green-500\",\n  },\n  error: {\n    icon: OctagonXIcon,\n    progressColor: \"bg-red-500\",\n    iconColor: \"text-red-500\",\n  },\n  warning: {\n    icon: TriangleAlertIcon,\n    progressColor: \"bg-amber-500\",\n    iconColor: \"text-amber-500\",\n  },\n  info: {\n    icon: InfoIcon,\n    progressColor: \"bg-blue-500\",\n    iconColor: \"text-blue-500\",\n  },\n}\n\nexport function CustomToast({\n  id,\n  type,\n  message,\n  description,\n  duration = 4000,\n}: CustomToastProps) {\n  const [progress, setProgress] = useState(100)\n  const { icon: Icon, progressColor, iconColor } = config[type]\n\n  useEffect(() => {\n    const startTime = Date.now()\n\n    const interval = setInterval(() => {\n      const elapsed = Date.now() - startTime\n      const remaining = Math.max(0, 100 - (elapsed / duration) * 100)\n      setProgress(remaining)\n\n      if (remaining === 0) {\n        clearInterval(interval)\n        toast.dismiss(id)\n      }\n    }, 16)\n\n    return () => clearInterval(interval)\n  }, [duration, id])\n\n  return (\n    <div\n      className={cn(\n        \"relative flex w-full items-start gap-3 overflow-hidden rounded-lg border bg-popover p-4 text-popover-foreground shadow-lg\",\n        \"border-l-4\",\n        type === \"success\" && \"border-l-green-500\",\n        type === \"error\" && \"border-l-red-500\",\n        type === \"warning\" && \"border-l-amber-500\",\n        type === \"info\" && \"border-l-blue-500\",\n      )}\n    >\n      <Icon className={cn(\"mt-0.5 size-5 shrink-0\", iconColor)} />\n\n      <div className=\"flex-1 space-y-1\">\n        <p className=\"text-base font-medium leading-tight\">{message}</p>\n        {description && (\n          <p className=\"text-sm text-muted-foreground whitespace-pre-line\">\n            {description}\n          </p>\n        )}\n      </div>\n\n      <Button\n        variant=\"ghost\"\n        size=\"icon\"\n        onClick={() => toast.dismiss(id)}\n        className=\"size-6 shrink-0 opacity-70 hover:opacity-100\"\n      >\n        <XIcon className=\"size-4\" />\n      </Button>\n\n      {/* Progress bar */}\n      <div className=\"absolute bottom-0 left-0 right-0 h-0.5 bg-muted/50\">\n        <div\n          className={cn(\n            \"h-full transition-all duration-[16ms] ease-linear\",\n            progressColor,\n          )}\n          style={{ width: `${progress}%` }}\n        />\n      </div>\n    </div>\n  )\n}\n",
      "type": "registry:ui"
    }
  ]
}