{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "settings-domains",
  "title": "Settings Domains",
  "description": "Manage custom domains and SSL certificates.",
  "registryDependencies": [
    "alert-dialog",
    "badge",
    "button",
    "card",
    "dialog",
    "field",
    "input-group"
  ],
  "files": [
    {
      "path": "registry/new-york/blocks/settings/settings-domains.tsx",
      "content": "\"use client\";\n\nimport { Check, Copy, Globe, Plus, RefreshCw, Trash2, X } 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 { Badge } from \"@/registry/new-york/ui/badge\";\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 {\n  Dialog,\n  DialogContent,\n  DialogDescription,\n  DialogFooter,\n  DialogHeader,\n  DialogTitle,\n  DialogTrigger,\n} from \"@/registry/new-york/ui/dialog\";\nimport {\n  Field,\n  FieldContent,\n  FieldDescription,\n  FieldError,\n  FieldLabel,\n} from \"@/registry/new-york/ui/field\";\nimport {\n  InputGroup,\n  InputGroupInput,\n} from \"@/registry/new-york/ui/input-group\";\n\nexport interface Domain {\n  id: string;\n  domain: string;\n  status: \"verified\" | \"pending\" | \"failed\";\n  sslEnabled: boolean;\n  verifiedAt?: Date;\n  dnsRecords?: {\n    type: string;\n    name: string;\n    value: string;\n  }[];\n}\n\nexport interface SettingsDomainsProps {\n  domains?: Domain[];\n  onCreate?: (domain: string) => Promise<Domain>;\n  onDelete?: (id: string) => Promise<void>;\n  onVerify?: (id: string) => Promise<void>;\n  onToggleSSL?: (id: string) => Promise<void>;\n  className?: string;\n}\n\nfunction formatDate(date: Date): string {\n  return new Intl.DateTimeFormat(\"en-US\", {\n    month: \"short\",\n    day: \"numeric\",\n    year: \"numeric\",\n  }).format(date);\n}\n\nexport default function SettingsDomains({\n  domains = [],\n  onCreate,\n  onDelete,\n  onVerify,\n  onToggleSSL,\n  className,\n}: SettingsDomainsProps) {\n  const [createDialogOpen, setCreateDialogOpen] = useState(false);\n  const [newDomain, setNewDomain] = useState(\"\");\n  const [errors, setErrors] = useState<Record<string, string>>({});\n  const [copiedDomain, setCopiedDomain] = useState<string | null>(null);\n\n  const handleCreate = async () => {\n    setErrors({});\n\n    if (!newDomain.trim()) {\n      setErrors({ domain: \"Domain is required\" });\n      return;\n    }\n\n    try {\n      await onCreate?.(newDomain.trim());\n      setNewDomain(\"\");\n      setCreateDialogOpen(false);\n    } catch (error) {\n      setErrors({\n        domain: error instanceof Error ? error.message : \"Failed to add domain\",\n      });\n    }\n  };\n\n  const copyToClipboard = async (text: string) => {\n    await navigator.clipboard.writeText(text);\n    setCopiedDomain(text);\n    setTimeout(() => setCopiedDomain(null), 2000);\n  };\n\n  const getStatusBadge = (status: Domain[\"status\"]) => {\n    switch (status) {\n      case \"verified\":\n        return (\n          <Badge className=\"flex items-center gap-1 text-xs\" variant=\"default\">\n            <Check className=\"size-3\" />\n            <span>Verified</span>\n          </Badge>\n        );\n      case \"pending\":\n        return (\n          <Badge className=\"text-xs\" variant=\"secondary\">\n            Pending\n          </Badge>\n        );\n      case \"failed\":\n        return (\n          <Badge className=\"text-xs\" variant=\"destructive\">\n            Failed\n          </Badge>\n        );\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\">Custom Domains</CardTitle>\n            <CardDescription className=\"wrap-break-word\">\n              Manage your custom domains and SSL certificates\n            </CardDescription>\n          </div>\n          <Dialog onOpenChange={setCreateDialogOpen} open={createDialogOpen}>\n            <DialogTrigger asChild>\n              <Button className=\"w-full shrink-0 sm:w-auto\" type=\"button\">\n                <Plus className=\"size-4\" />\n                <span className=\"whitespace-nowrap\">Add Domain</span>\n              </Button>\n            </DialogTrigger>\n            <DialogContent className=\"sm:max-w-md\">\n              <DialogHeader>\n                <DialogTitle>Add Custom Domain</DialogTitle>\n                <DialogDescription>\n                  Add a custom domain to your account\n                </DialogDescription>\n              </DialogHeader>\n              <div className=\"flex flex-col gap-4\">\n                <Field>\n                  <FieldLabel htmlFor=\"domain\">\n                    Domain <span className=\"text-destructive\">*</span>\n                  </FieldLabel>\n                  <FieldContent>\n                    <InputGroup>\n                      <InputGroupInput\n                        id=\"domain\"\n                        onChange={(e) => setNewDomain(e.target.value)}\n                        placeholder=\"example.com\"\n                        type=\"text\"\n                        value={newDomain}\n                      />\n                    </InputGroup>\n                    {errors.domain && <FieldError>{errors.domain}</FieldError>}\n                    <FieldDescription>\n                      Enter your domain name without http:// or https://\n                    </FieldDescription>\n                  </FieldContent>\n                </Field>\n              </div>\n              <DialogFooter>\n                <Button\n                  onClick={() => setCreateDialogOpen(false)}\n                  type=\"button\"\n                  variant=\"outline\"\n                >\n                  Cancel\n                </Button>\n                <Button onClick={handleCreate} type=\"button\">\n                  Add Domain\n                </Button>\n              </DialogFooter>\n            </DialogContent>\n          </Dialog>\n        </div>\n      </CardHeader>\n      <CardContent>\n        {domains.length === 0 ? (\n          <div className=\"flex flex-col items-center justify-center gap-4 py-12 text-center\">\n            <div className=\"flex size-12 items-center justify-center rounded-full bg-muted\">\n              <Globe className=\"size-6 text-muted-foreground\" />\n            </div>\n            <div className=\"flex flex-col gap-2\">\n              <p className=\"font-medium text-sm\">No custom domains</p>\n              <p className=\"text-muted-foreground text-sm\">\n                Add a custom domain to get started\n              </p>\n            </div>\n          </div>\n        ) : (\n          <div className=\"flex flex-col gap-4\">\n            {domains.map((domain) => (\n              <div\n                className=\"flex flex-col gap-4 rounded-lg border p-4\"\n                key={domain.id}\n              >\n                <div className=\"flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between\">\n                  <div className=\"flex min-w-0 flex-1 flex-col gap-3\">\n                    <div className=\"flex flex-wrap items-center gap-2\">\n                      <div className=\"flex items-center gap-2\">\n                        <Globe className=\"size-5 text-muted-foreground\" />\n                        <span className=\"font-medium text-sm\">\n                          {domain.domain}\n                        </span>\n                      </div>\n                      {getStatusBadge(domain.status)}\n                      {domain.sslEnabled && (\n                        <Badge className=\"text-xs\" variant=\"default\">\n                          SSL Enabled\n                        </Badge>\n                      )}\n                    </div>\n                  </div>\n                  <div className=\"flex shrink-0 flex-wrap gap-2\">\n                    {domain.status === \"pending\" && (\n                      <Button\n                        className=\"w-full sm:w-auto\"\n                        onClick={() => onVerify?.(domain.id)}\n                        type=\"button\"\n                        variant=\"outline\"\n                      >\n                        <RefreshCw className=\"size-4\" />\n                        Verify\n                      </Button>\n                    )}\n                    <Button\n                      className=\"w-full sm:w-auto\"\n                      onClick={() => onToggleSSL?.(domain.id)}\n                      type=\"button\"\n                      variant=\"outline\"\n                    >\n                      {domain.sslEnabled ? (\n                        <>\n                          <X className=\"size-4\" />\n                          Disable SSL\n                        </>\n                      ) : (\n                        <>\n                          <Check className=\"size-4\" />\n                          Enable SSL\n                        </>\n                      )}\n                    </Button>\n                    <AlertDialog>\n                      <AlertDialogTrigger asChild>\n                        <Button\n                          className=\"w-full sm:w-auto\"\n                          type=\"button\"\n                          variant=\"destructive\"\n                        >\n                          <Trash2 className=\"size-4\" />\n                          Remove\n                        </Button>\n                      </AlertDialogTrigger>\n                      <AlertDialogContent>\n                        <AlertDialogHeader>\n                          <AlertDialogTitle>Remove Domain?</AlertDialogTitle>\n                          <AlertDialogDescription>\n                            This will remove the domain{\" \"}\n                            <strong>{domain.domain}</strong> from your account.\n                            This action cannot be undone.\n                          </AlertDialogDescription>\n                        </AlertDialogHeader>\n                        <AlertDialogFooter>\n                          <AlertDialogCancel>Cancel</AlertDialogCancel>\n                          <AlertDialogAction\n                            onClick={() => onDelete?.(domain.id)}\n                          >\n                            Remove Domain\n                          </AlertDialogAction>\n                        </AlertDialogFooter>\n                      </AlertDialogContent>\n                    </AlertDialog>\n                  </div>\n                </div>\n                {domain.status === \"pending\" && domain.dnsRecords && (\n                  <div className=\"flex w-full flex-col gap-3 rounded-lg border bg-muted/30 p-4\">\n                    <FieldLabel className=\"mb-0\">DNS Configuration</FieldLabel>\n                    <div className=\"flex flex-col gap-2\">\n                      {domain.dnsRecords.map((record, index) => (\n                        <div\n                          className=\"flex items-center justify-between rounded-lg border bg-background p-2\"\n                          key={index}\n                        >\n                          <div className=\"flex flex-col gap-1\">\n                            <span className=\"font-mono text-xs\">\n                              {record.type} {record.name}\n                            </span>\n                            <code className=\"font-mono text-muted-foreground text-xs\">\n                              {record.value}\n                            </code>\n                          </div>\n                          <Button\n                            aria-label=\"Copy DNS record\"\n                            onClick={() =>\n                              copyToClipboard(\n                                `${record.type} ${record.name} ${record.value}`\n                              )\n                            }\n                            size=\"icon-sm\"\n                            type=\"button\"\n                            variant=\"ghost\"\n                          >\n                            {copiedDomain ===\n                            `${record.type} ${record.name} ${record.value}` ? (\n                              <Check className=\"size-4 text-green-600\" />\n                            ) : (\n                              <Copy className=\"size-4\" />\n                            )}\n                          </Button>\n                        </div>\n                      ))}\n                    </div>\n                    <FieldDescription>\n                      Add these DNS records to your domain provider to verify\n                      ownership\n                    </FieldDescription>\n                  </div>\n                )}\n\n                {domain.verifiedAt && (\n                  <p className=\"text-muted-foreground text-xs\">\n                    Verified on {formatDate(domain.verifiedAt)}\n                  </p>\n                )}\n              </div>\n            ))}\n          </div>\n        )}\n      </CardContent>\n    </Card>\n  );\n}\n",
      "type": "registry:ui"
    }
  ],
  "categories": [
    "block",
    "settings"
  ],
  "type": "registry:ui"
}