{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "dns-record-manager",
  "title": "Dns Record Manager",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-react/blocks/dns-record-manager/DnsRecordManager.tsx",
      "content": "'use client'\n\nimport * as React from 'react'\nimport {\n  Check,\n  Cloud,\n  CloudOff,\n  Copy,\n  Download,\n  Edit2,\n  FileCode,\n  Globe,\n  MoreHorizontal,\n  Plus,\n  Search,\n  ShieldAlert,\n  ShieldCheck,\n  Trash2,\n  X,\n} from 'lucide-react'\nimport { cn } from '@/lib/utils'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'\nimport {\n  DropdownMenu,\n  DropdownMenuContent,\n  DropdownMenuItem,\n  DropdownMenuSeparator,\n  DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu'\nimport { Input } from '@/components/ui/input'\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'\nimport { Separator } from '@/components/ui/separator'\nimport { Switch } from '@/components/ui/switch'\nimport { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'\n\nexport type DnsRecordType = 'A' | 'AAAA' | 'CNAME' | 'MX' | 'TXT' | 'CAA'\n\nexport interface DnsRecord {\n  id: string\n  type: DnsRecordType\n  name: string\n  content: string\n  ttl: string\n  proxied: boolean\n  priority?: number\n  comment?: string\n}\n\nexport interface DnsRecordManagerProps {\n  domain?: string\n  nameservers?: string[]\n  dnssecEnabled?: boolean\n  initialRecords?: DnsRecord[]\n  initialAddOpen?: boolean\n  className?: string\n}\n\nconst defaultRecords: DnsRecord[] = [\n  {\n    id: 'rec-1',\n    type: 'A',\n    name: '@',\n    content: '76.76.21.21',\n    ttl: 'Auto',\n    proxied: true,\n    comment: 'Apex production load balancer',\n  },\n  {\n    id: 'rec-2',\n    type: 'CNAME',\n    name: 'www',\n    content: 'cname.vercel-dns.com',\n    ttl: 'Auto',\n    proxied: true,\n    comment: 'Primary web redirect',\n  },\n  {\n    id: 'rec-3',\n    type: 'CNAME',\n    name: 'api',\n    content: 'api-gateway.uipkge.net',\n    ttl: '300s',\n    proxied: false,\n    comment: 'Direct REST gateway route',\n  },\n  {\n    id: 'rec-4',\n    type: 'AAAA',\n    name: '@',\n    content: '2606:4700:3038::6815:1515',\n    ttl: 'Auto',\n    proxied: true,\n    comment: 'IPv6 edge ingress',\n  },\n  {\n    id: 'rec-5',\n    type: 'MX',\n    name: 'mail',\n    content: 'aspmx.l.google.com',\n    ttl: '3600s',\n    proxied: false,\n    priority: 10,\n    comment: 'Google Workspace MX',\n  },\n  {\n    id: 'rec-6',\n    type: 'TXT',\n    name: '_dmarc',\n    content: 'v=spf1 include:_spf.google.com ~all',\n    ttl: '3600s',\n    proxied: false,\n    comment: 'Sender Policy Framework verification',\n  },\n  {\n    id: 'rec-7',\n    type: 'CAA',\n    name: '@',\n    content: '0 issue \"letsencrypt.org\"',\n    ttl: 'Auto',\n    proxied: false,\n    comment: 'Certificate authority restriction',\n  },\n]\n\nconst typeBadgeStyles: Record<DnsRecordType, { bg: string; text: string; border: string }> = {\n  A: {\n    bg: 'bg-info/10',\n    text: 'text-info',\n    border: 'border-info/30',\n  },\n  AAAA: {\n    bg: 'bg-chart-1/10',\n    text: 'text-chart-1',\n    border: 'border-chart-1/30',\n  },\n  CNAME: {\n    bg: 'bg-chart-2/10',\n    text: 'text-chart-2',\n    border: 'border-chart-2/30',\n  },\n  MX: {\n    bg: 'bg-warning/10',\n    text: 'text-warning',\n    border: 'border-warning/30',\n  },\n  TXT: {\n    bg: 'bg-success/10',\n    text: 'text-success',\n    border: 'border-success/30',\n  },\n  CAA: {\n    bg: 'bg-info/10',\n    text: 'text-info',\n    border: 'border-info/30',\n  },\n}\n\nconst placeholderMap: Record<DnsRecordType, string> = {\n  A: 'e.g. 76.76.21.21',\n  AAAA: 'e.g. 2606:4700:3038::6815:1515',\n  CNAME: 'e.g. cname.vercel-dns.com',\n  MX: 'e.g. mail.google.com',\n  TXT: 'e.g. v=spf1 include:_spf.google.com ~all',\n  CAA: 'e.g. 0 issue \"letsencrypt.org\"',\n}\n\nexport function DnsRecordManager({\n  domain = 'uipkge.dev',\n  nameservers = ['ns1.uipkge.net', 'ns2.uipkge.net'],\n  dnssecEnabled = true,\n  initialRecords,\n  initialAddOpen = false,\n  className,\n}: DnsRecordManagerProps) {\n  const [records, setRecords] = React.useState<DnsRecord[]>(() =>\n    initialRecords ? initialRecords.map((r) => ({ ...r })) : defaultRecords.map((r) => ({ ...r })),\n  )\n\n  const [searchQuery, setSearchQuery] = React.useState('')\n  const [selectedTypeFilter, setSelectedTypeFilter] = React.useState<string>('ALL')\n  const [isAddOpen, setIsAddOpen] = React.useState(initialAddOpen)\n  const [isZoneFileOpen, setIsZoneFileOpen] = React.useState(false)\n  const [editingId, setEditingId] = React.useState<string | null>(null)\n\n  // Form states\n  const [formType, setFormType] = React.useState<DnsRecordType>('A')\n  const [formName, setFormName] = React.useState('')\n  const [formContent, setFormContent] = React.useState('')\n  const [formTtl, setFormTtl] = React.useState('Auto')\n  const [formProxied, setFormProxied] = React.useState(true)\n  const [formPriority, setFormPriority] = React.useState(10)\n  const [formComment, setFormComment] = React.useState('')\n\n  const [copiedKey, setCopiedKey] = React.useState<string | null>(null)\n  const copyTimeoutRef = React.useRef<number | undefined>(undefined)\n\n  const copyText = React.useCallback(async (key: string, text: string) => {\n    try {\n      await navigator.clipboard.writeText(text)\n      setCopiedKey(key)\n      window.clearTimeout(copyTimeoutRef.current)\n      copyTimeoutRef.current = window.setTimeout(() => {\n        setCopiedKey(null)\n      }, 1600)\n    } catch {\n      // Clipboard unavailable\n    }\n  }, [])\n\n  const handleTypeChange = (newType: DnsRecordType) => {\n    setFormType(newType)\n    if (['MX', 'TXT', 'CAA'].includes(newType)) {\n      setFormProxied(false)\n    } else if (!editingId) {\n      setFormProxied(true)\n    }\n  }\n\n  const toggleProxy = (id: string) => {\n    setRecords((prev) =>\n      prev.map((r) => {\n        if (r.id === id && ['A', 'AAAA', 'CNAME'].includes(r.type)) {\n          return { ...r, proxied: !r.proxied }\n        }\n        return r\n      }),\n    )\n  }\n\n  const deleteRecord = (id: string) => {\n    setRecords((prev) => prev.filter((r) => r.id !== id))\n    if (editingId === id) {\n      cancelForm()\n    }\n  }\n\n  const startAdd = () => {\n    setEditingId(null)\n    setFormType('A')\n    setFormName('')\n    setFormContent('')\n    setFormTtl('Auto')\n    setFormProxied(true)\n    setFormPriority(10)\n    setFormComment('')\n    setIsAddOpen(true)\n  }\n\n  const startEdit = (record: DnsRecord) => {\n    setEditingId(record.id)\n    setFormType(record.type)\n    setFormName(record.name)\n    setFormContent(record.content)\n    setFormTtl(record.ttl)\n    setFormProxied(record.proxied)\n    setFormPriority(record.priority ?? 10)\n    setFormComment(record.comment ?? '')\n    setIsAddOpen(true)\n  }\n\n  const cancelForm = () => {\n    setIsAddOpen(false)\n    setEditingId(null)\n  }\n\n  const saveRecord = () => {\n    const name = formName.trim() || '@'\n    const content = formContent.trim()\n    if (!content) return\n\n    if (editingId) {\n      setRecords((prev) =>\n        prev.map((r) => {\n          if (r.id === editingId) {\n            return {\n              ...r,\n              type: formType,\n              name,\n              content,\n              ttl: formTtl,\n              proxied: ['A', 'AAAA', 'CNAME'].includes(formType) ? formProxied : false,\n              priority: formType === 'MX' ? Number(formPriority) : undefined,\n              comment: formComment.trim() || undefined,\n            }\n          }\n          return r\n        }),\n      )\n    } else {\n      const newRecord: DnsRecord = {\n        id: `rec-${Date.now()}`,\n        type: formType,\n        name,\n        content,\n        ttl: formTtl,\n        proxied: ['A', 'AAAA', 'CNAME'].includes(formType) ? formProxied : false,\n        priority: formType === 'MX' ? Number(formPriority) : undefined,\n        comment: formComment.trim() || undefined,\n      }\n      setRecords((prev) => [newRecord, ...prev])\n    }\n\n    cancelForm()\n  }\n\n  const filteredRecords = React.useMemo(() => {\n    const query = searchQuery.trim().toLowerCase()\n    return records.filter((record) => {\n      const matchesType = selectedTypeFilter === 'ALL' || record.type === selectedTypeFilter\n      const matchesQuery =\n        !query ||\n        record.name.toLowerCase().includes(query) ||\n        record.content.toLowerCase().includes(query) ||\n        record.type.toLowerCase().includes(query) ||\n        (record.comment && record.comment.toLowerCase().includes(query))\n      return matchesType && matchesQuery\n    })\n  }, [records, searchQuery, selectedTypeFilter])\n\n  const zoneFileContent = React.useMemo(() => {\n    const date = new Date().toISOString().split('T')[0].replace(/-/g, '')\n    const lines: string[] = [\n      `; BIND zone file for ${domain}`,\n      `; Generated on ${new Date().toUTCString()}`,\n      `$ORIGIN ${domain}.`,\n      `$TTL 3600`,\n      ``,\n      `; SOA Record`,\n      `@       IN  SOA  ${nameservers[0]}. hostmaster.${domain}. (`,\n      `                 ${date}01 ; Serial`,\n      `                 7200       ; Refresh (2 hours)`,\n      `                 3600       ; Retry (1 hour)`,\n      `                 1209600    ; Expire (2 weeks)`,\n      `                 3600       ; Minimum TTL (1 hour)`,\n      `)`,\n      ``,\n      `; Nameservers`,\n    ]\n\n    nameservers.forEach((ns) => {\n      lines.push(`@       IN  NS   ${ns}.`)\n    })\n\n    lines.push('', '; Resource Records')\n\n    for (const r of records) {\n      const recName = (r.name === '@' ? '@' : r.name).padEnd(12, ' ')\n      const ttlValue = r.ttl === 'Auto' ? '3600' : r.ttl.replace('s', '')\n      const ttlStr = ttlValue.padEnd(6, ' ')\n      const typeStr = r.type.padEnd(7, ' ')\n\n      if (r.type === 'MX') {\n        const prio = String(r.priority ?? 10).padEnd(4, ' ')\n        lines.push(`${recName} ${ttlStr} IN  ${typeStr} ${prio} ${r.content}.`)\n      } else if (r.type === 'TXT') {\n        lines.push(`${recName} ${ttlStr} IN  ${typeStr} \"${r.content}\"`)\n      } else if (r.type === 'CNAME') {\n        lines.push(`${recName} ${ttlStr} IN  ${typeStr} ${r.content}.`)\n      } else {\n        lines.push(`${recName} ${ttlStr} IN  ${typeStr} ${r.content}`)\n      }\n    }\n\n    return lines.join('\\n')\n  }, [domain, nameservers, records])\n\n  const downloadZoneFile = () => {\n    const blob = new Blob([zoneFileContent], { type: 'text/plain;charset=utf-8' })\n    const url = URL.createObjectURL(blob)\n    const a = document.createElement('a')\n    a.href = url\n    a.download = `${domain}.zone`\n    document.body.appendChild(a)\n    a.click()\n    document.body.removeChild(a)\n    URL.revokeObjectURL(url)\n  }\n\n  const resolveHostname = (recordName: string): string => {\n    if (recordName === '@') return domain\n    return `${recordName}.${domain}`\n  }\n\n  return (\n    <div data-slot=\"dns-record-manager\" className={cn('w-full space-y-6', className)}>\n      {/* Domain Header & Status Card */}\n      <Card className=\"border-border bg-card shadow-xs\">\n        <CardHeader className=\"pb-4\">\n          <div className=\"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n            <div className=\"space-y-1.5\">\n              <div className=\"flex flex-wrap items-center gap-2.5\">\n                <div className=\"bg-primary/10 text-primary flex size-8 items-center justify-center rounded-lg\">\n                  <Globe className=\"size-4.5\" />\n                </div>\n                <h2 className=\"text-foreground text-xl font-bold tracking-tight sm:text-2xl\">{domain}</h2>\n                {dnssecEnabled ? (\n                  <Badge variant=\"outline\" className=\"border-success/30 bg-success/10 text-success gap-1.5 py-0.5\">\n                    <span className=\"bg-success size-1.5 rounded-full\" />\n                    <ShieldCheck className=\"size-3.5\" />\n                    Active · DNSSEC Enabled\n                  </Badge>\n                ) : (\n                  <Badge variant=\"outline\" className=\"border-warning/30 bg-warning/10 text-warning gap-1.5 py-0.5\">\n                    <span className=\"bg-warning size-1.5 rounded-full\" />\n                    <ShieldAlert className=\"size-3.5\" />\n                    Active · DNSSEC Inactive\n                  </Badge>\n                )}\n              </div>\n              <p className=\"text-muted-foreground text-xs sm:text-sm\">\n                Authoritative DNS routing and global edge proxy management for {domain}.\n              </p>\n            </div>\n\n            {/* Header CTA Buttons */}\n            <div className=\"flex items-center gap-2\">\n              <Button\n                variant=\"outline\"\n                size=\"sm\"\n                className=\"h-8 gap-1.5 text-xs font-medium\"\n                onClick={() => setIsZoneFileOpen((prev) => !prev)}\n              >\n                <FileCode className=\"size-3.5\" />\n                {isZoneFileOpen ? 'Hide Zone File' : 'Export Zone File'}\n              </Button>\n              <Button size=\"sm\" className=\"h-8 gap-1.5 text-xs font-medium\" onClick={startAdd}>\n                <Plus className=\"size-3.5\" />\n                Add Record\n              </Button>\n            </div>\n          </div>\n\n          <Separator className=\"my-4\" />\n\n          {/* Nameserver Inspector Bar */}\n          <div className=\"flex flex-wrap items-center justify-between gap-3 text-xs\">\n            <div className=\"flex flex-wrap items-center gap-2\">\n              <span className=\"text-muted-foreground font-medium\">Nameservers:</span>\n              <div className=\"flex flex-wrap items-center gap-1.5\">\n                {nameservers.map((ns) => (\n                  <button\n                    key={ns}\n                    type=\"button\"\n                    aria-label={`Copy nameserver ${ns}`}\n                    className=\"border-border bg-muted/60 hover:bg-muted focus-visible:ring-ring/50 group text-foreground flex min-h-6 items-center gap-1.5 rounded-md border px-2.5 py-1 font-mono text-xs transition-colors focus-visible:ring-[2px] focus-visible:outline-none\"\n                    onClick={() => copyText(ns, ns)}\n                  >\n                    <span>{ns}</span>\n                    {copiedKey === ns ? (\n                      <Check className=\"text-success size-3\" />\n                    ) : (\n                      <Copy className=\"text-muted-foreground group-hover:text-foreground size-3\" />\n                    )}\n                  </button>\n                ))}\n              </div>\n            </div>\n            <div className=\"text-muted-foreground flex items-center gap-2\">\n              <span className=\"bg-success size-2 animate-pulse rounded-full\" />\n              <span>Propagation: 100% Synced</span>\n            </div>\n          </div>\n        </CardHeader>\n      </Card>\n\n      {/* Zone File Export Card (Collapsible) */}\n      {isZoneFileOpen && (\n        <Card className=\"border-border bg-card shadow-xs\">\n          <CardHeader className=\"pb-3\">\n            <div className=\"flex items-center justify-between\">\n              <div>\n                <CardTitle className=\"text-sm font-semibold sm:text-base\">BIND RFC 1035 Zone File</CardTitle>\n                <CardDescription className=\"text-xs\">\n                  Complete DNS zone mapping for {domain} ready for import into Route53, Bind9, or Cloudflare.\n                </CardDescription>\n              </div>\n              <Button\n                variant=\"ghost\"\n                size=\"icon-sm\"\n                className=\"size-7\"\n                aria-label=\"Close zone file viewer\"\n                onClick={() => setIsZoneFileOpen(false)}\n              >\n                <X className=\"size-4\" />\n              </Button>\n            </div>\n          </CardHeader>\n          <CardContent className=\"space-y-3 pt-0\">\n            <div className=\"relative\">\n              <pre className=\"border-border bg-muted/70 text-foreground max-h-56 overflow-x-auto rounded-lg border p-3 font-mono text-xs leading-relaxed select-all\">\n                {zoneFileContent}\n              </pre>\n            </div>\n            <div className=\"flex items-center justify-end gap-2\">\n              <Button\n                variant=\"outline\"\n                size=\"sm\"\n                className=\"h-8 gap-1.5 text-xs\"\n                onClick={() => copyText('zone-file', zoneFileContent)}\n              >\n                {copiedKey === 'zone-file' ? (\n                  <Check className=\"text-success size-3.5\" />\n                ) : (\n                  <Copy className=\"size-3.5\" />\n                )}\n                {copiedKey === 'zone-file' ? 'Copied Zone File' : 'Copy Zone Content'}\n              </Button>\n              <Button\n                aria-label=\"Download attachment\"\n                size=\"sm\"\n                className=\"h-8 gap-1.5 text-xs\"\n                onClick={downloadZoneFile}\n              >\n                <Download className=\"size-3.5\" />\n                Download .zone File\n              </Button>\n            </div>\n          </CardContent>\n        </Card>\n      )}\n\n      {/* Add / Edit DNS Record Card */}\n      {isAddOpen && (\n        <Card className=\"border-primary/30 bg-muted/20 shadow-xs\">\n          <CardHeader className=\"pb-4\">\n            <div className=\"flex items-center justify-between\">\n              <div>\n                <CardTitle className=\"text-base font-semibold\">\n                  {editingId ? 'Edit DNS Record' : 'Add New DNS Record'}\n                </CardTitle>\n                <CardDescription className=\"text-xs\">\n                  {editingId\n                    ? 'Update configuration, target destination, or edge proxy status.'\n                    : `Configure host routing, MX exchangers, or verification TXT tags for ${domain}.`}\n                </CardDescription>\n              </div>\n              <Button\n                variant=\"ghost\"\n                size=\"icon-sm\"\n                className=\"size-7\"\n                aria-label=\"Cancel record form\"\n                onClick={cancelForm}\n              >\n                <X className=\"size-4\" />\n              </Button>\n            </div>\n          </CardHeader>\n          <CardContent className=\"space-y-4 pt-0\">\n            <div className=\"grid grid-cols-1 gap-3 sm:grid-cols-12\">\n              {/* Type Select */}\n              <div className=\"sm:col-span-3\">\n                <label htmlFor=\"dns-type\" className=\"text-foreground mb-1.5 block text-xs font-medium\">\n                  Type\n                </label>\n                <Select value={formType} onValueChange={(val) => handleTypeChange(val as DnsRecordType)}>\n                  <SelectTrigger id=\"dns-type\" className=\"w-full [&_svg]:shrink-0 [&>span]:truncate\">\n                    <SelectValue placeholder=\"Record type\" />\n                  </SelectTrigger>\n                  <SelectContent>\n                    <SelectItem value=\"A\">A (IPv4 Address)</SelectItem>\n                    <SelectItem value=\"AAAA\">AAAA (IPv6 Address)</SelectItem>\n                    <SelectItem value=\"CNAME\">CNAME (Canonical Alias)</SelectItem>\n                    <SelectItem value=\"MX\">MX (Mail Exchanger)</SelectItem>\n                    <SelectItem value=\"TXT\">TXT (Text Record)</SelectItem>\n                    <SelectItem value=\"CAA\">CAA (Cert Authority)</SelectItem>\n                  </SelectContent>\n                </Select>\n              </div>\n\n              {/* Name Input */}\n              <div className=\"sm:col-span-5\">\n                <label htmlFor=\"dns-name\" className=\"text-foreground mb-1.5 block text-xs font-medium\">\n                  Name / Subdomain <span className=\"text-muted-foreground font-normal\">(@ for root)</span>\n                </label>\n                <Input\n                  id=\"dns-name\"\n                  value={formName}\n                  onChange={(e) => setFormName(e.target.value)}\n                  placeholder=\"@ or subdomain\"\n                  className=\"font-mono text-xs\"\n                />\n              </div>\n\n              {/* TTL Select */}\n              <div className=\"sm:col-span-4\">\n                <label htmlFor=\"dns-ttl\" className=\"text-foreground mb-1.5 block text-xs font-medium\">\n                  TTL\n                </label>\n                <Select value={formTtl} onValueChange={setFormTtl}>\n                  <SelectTrigger id=\"dns-ttl\" className=\"w-full [&_svg]:shrink-0 [&>span]:truncate\">\n                    <SelectValue placeholder=\"TTL\" />\n                  </SelectTrigger>\n                  <SelectContent>\n                    <SelectItem value=\"Auto\">Auto (Automatic)</SelectItem>\n                    <SelectItem value=\"60s\">1 min (60s)</SelectItem>\n                    <SelectItem value=\"300s\">5 mins (300s)</SelectItem>\n                    <SelectItem value=\"1800s\">30 mins (1800s)</SelectItem>\n                    <SelectItem value=\"3600s\">1 hour (3600s)</SelectItem>\n                    <SelectItem value=\"86400s\">1 day (86400s)</SelectItem>\n                  </SelectContent>\n                </Select>\n              </div>\n            </div>\n\n            <div className={cn('grid grid-cols-1 gap-3', formType === 'MX' ? 'sm:grid-cols-12' : '')}>\n              {/* Content / Target Input */}\n              <div className={formType === 'MX' ? 'sm:col-span-9' : 'w-full'}>\n                <label htmlFor=\"dns-content\" className=\"text-foreground mb-1.5 block text-xs font-medium\">\n                  {formType === 'A'\n                    ? 'IPv4 Address'\n                    : formType === 'AAAA'\n                      ? 'IPv6 Address'\n                      : formType === 'CNAME'\n                        ? 'Target Domain'\n                        : formType === 'MX'\n                          ? 'Mail Server Hostname'\n                          : formType === 'TXT'\n                            ? 'TXT Content / Value'\n                            : 'Target / Tag Value'}\n                </label>\n                <Input\n                  id=\"dns-content\"\n                  value={formContent}\n                  onChange={(e) => setFormContent(e.target.value)}\n                  placeholder={placeholderMap[formType]}\n                  className=\"font-mono text-xs\"\n                />\n              </div>\n\n              {/* Priority Input for MX */}\n              {formType === 'MX' && (\n                <div className=\"sm:col-span-3\">\n                  <label htmlFor=\"dns-priority\" className=\"text-foreground mb-1.5 block text-xs font-medium\">\n                    Priority\n                  </label>\n                  <Input\n                    id=\"dns-priority\"\n                    type=\"number\"\n                    min={0}\n                    max={65535}\n                    value={formPriority}\n                    onChange={(e) => setFormPriority(Number(e.target.value))}\n                    placeholder=\"10\"\n                    className=\"font-mono text-xs\"\n                  />\n                </div>\n              )}\n            </div>\n\n            {/* Optional Comment */}\n            <div>\n              <label htmlFor=\"dns-comment\" className=\"text-foreground mb-1.5 block text-xs font-medium\">\n                Comment <span className=\"text-muted-foreground font-normal\">(optional note)</span>\n              </label>\n              <Input\n                id=\"dns-comment\"\n                value={formComment}\n                onChange={(e) => setFormComment(e.target.value)}\n                placeholder=\"e.g. Production ingress or verification tag\"\n                className=\"text-xs\"\n              />\n            </div>\n\n            {/* Proxy Switch (for A, AAAA, CNAME) */}\n            {['A', 'AAAA', 'CNAME'].includes(formType) && (\n              <div className=\"border-border bg-background/80 flex items-center justify-between rounded-lg border p-3\">\n                <div className=\"space-y-0.5\">\n                  <div className=\"flex items-center gap-2\">\n                    <Cloud className=\"text-warning size-4\" />\n                    <span className=\"text-foreground text-xs font-medium\">Proxy Status</span>\n                  </div>\n                  <p className=\"text-muted-foreground text-xs\">\n                    {formProxied\n                      ? 'Proxied: Accelerate traffic and protect origin IP behind Cloudflare edge.'\n                      : 'DNS only: Direct traffic route without edge proxy caching.'}\n                  </p>\n                </div>\n                <Switch id=\"proxy-toggle\" checked={formProxied} onCheckedChange={setFormProxied} />\n              </div>\n            )}\n\n            {/* Form Actions */}\n            <div className=\"flex items-center justify-end gap-2 pt-2\">\n              <Button variant=\"outline\" size=\"sm\" className=\"h-8 text-xs\" onClick={cancelForm}>\n                Cancel\n              </Button>\n              <Button size=\"sm\" className=\"h-8 text-xs\" disabled={!formContent.trim()} onClick={saveRecord}>\n                {editingId ? 'Update Record' : 'Save Record'}\n              </Button>\n            </div>\n          </CardContent>\n        </Card>\n      )}\n\n      {/* DNS Records Management Section */}\n      <div className=\"space-y-3\">\n        {/* Toolbar Filter & Search */}\n        <div className=\"flex flex-col gap-2.5 sm:flex-row sm:items-center sm:justify-between\">\n          <div className=\"relative w-full max-w-sm\">\n            <Search className=\"text-muted-foreground pointer-events-none absolute top-1/2 left-2.5 size-3.5 -translate-y-1/2\" />\n            <Input\n              value={searchQuery}\n              onChange={(e) => setSearchQuery(e.target.value)}\n              placeholder=\"Search records by name, target, or content...\"\n              className=\"h-8.5 pl-8 text-xs\"\n            />\n          </div>\n\n          {/* Type Filter Buttons */}\n          <div className=\"flex items-center gap-1.5 overflow-x-auto pb-1 sm:pb-0\">\n            <button\n              type=\"button\"\n              className={cn(\n                'min-h-6 rounded-md px-2.5 py-1 text-xs font-medium transition-colors',\n                selectedTypeFilter === 'ALL'\n                  ? 'bg-primary text-primary-foreground shadow-xs'\n                  : 'bg-muted/70 text-muted-foreground hover:bg-muted hover:text-foreground',\n              )}\n              onClick={() => setSelectedTypeFilter('ALL')}\n            >\n              All ({records.length})\n            </button>\n            {(['A', 'CNAME', 'MX', 'TXT', 'AAAA', 'CAA'] as DnsRecordType[]).map((t) => (\n              <button\n                key={t}\n                type=\"button\"\n                className={cn(\n                  'min-h-6 min-w-6 rounded-md px-2 py-1 font-mono text-xs font-medium transition-colors',\n                  selectedTypeFilter === t\n                    ? 'bg-primary text-primary-foreground shadow-xs'\n                    : 'bg-muted/70 text-muted-foreground hover:bg-muted hover:text-foreground',\n                )}\n                onClick={() => setSelectedTypeFilter(t)}\n              >\n                {t}\n              </button>\n            ))}\n          </div>\n        </div>\n\n        {/* DNS Records Table */}\n        <div className=\"border-border bg-card overflow-hidden rounded-lg border shadow-xs\">\n          <div className=\"overflow-x-auto\">\n            <Table>\n              <TableHeader>\n                <TableRow className=\"bg-muted/40\">\n                  <TableHead className=\"w-24\">Type</TableHead>\n                  <TableHead className=\"min-w-[140px]\">Name</TableHead>\n                  <TableHead className=\"min-w-[240px]\">Target Content</TableHead>\n                  <TableHead className=\"w-28 text-center\">Proxy Status</TableHead>\n                  <TableHead className=\"w-20\">TTL</TableHead>\n                  <TableHead className=\"w-12 text-right\">\n                    <span className=\"sr-only\">Actions</span>\n                  </TableHead>\n                </TableRow>\n              </TableHeader>\n              <TableBody>\n                {filteredRecords.map((record) => (\n                  <TableRow\n                    key={record.id}\n                    className={cn(\n                      'hover:bg-muted/30 transition-colors',\n                      editingId === record.id ? 'bg-primary/5' : undefined,\n                    )}\n                  >\n                    {/* Record Type Badge */}\n                    <TableCell>\n                      <span\n                        className={cn(\n                          'inline-flex items-center justify-center rounded-md border px-2 py-0.5 font-mono text-xs font-bold',\n                          typeBadgeStyles[record.type].bg,\n                          typeBadgeStyles[record.type].text,\n                          typeBadgeStyles[record.type].border,\n                        )}\n                      >\n                        {record.type}\n                      </span>\n                    </TableCell>\n\n                    {/* Name & Hostname helper */}\n                    <TableCell>\n                      <div className=\"flex flex-col\">\n                        <span className=\"text-foreground font-mono text-xs font-semibold\">{record.name}</span>\n                        <span className=\"text-muted-foreground truncate font-mono text-xs\">\n                          {resolveHostname(record.name)}\n                        </span>\n                      </div>\n                    </TableCell>\n\n                    {/* Target Content with Copy button */}\n                    <TableCell>\n                      <div className=\"flex items-center gap-2\">\n                        <div className=\"min-w-0 flex-1\">\n                          <div className=\"flex items-center gap-1.5\">\n                            {record.type === 'MX' && (\n                              <span className=\"border-border bg-muted text-muted-foreground rounded px-1 font-mono text-xs\">\n                                Pri {record.priority}\n                              </span>\n                            )}\n                            <code className=\"text-foreground/90 font-mono text-xs break-all select-all\">\n                              {record.content}\n                            </code>\n                          </div>\n                          {record.comment && (\n                            <p className=\"text-muted-foreground mt-0.5 truncate text-xs\">{record.comment}</p>\n                          )}\n                        </div>\n\n                        <Button\n                          variant=\"ghost\"\n                          size=\"icon-sm\"\n                          className=\"text-muted-foreground hover:text-foreground size-7 shrink-0\"\n                          aria-label={`Copy content for ${record.name}`}\n                          onClick={() => copyText(record.id, record.content)}\n                        >\n                          {copiedKey === record.id ? (\n                            <Check className=\"text-success size-3.5\" />\n                          ) : (\n                            <Copy className=\"size-3.5\" />\n                          )}\n                        </Button>\n                      </div>\n                    </TableCell>\n\n                    {/* Proxy Status Switch / Cloud badge */}\n                    <TableCell className=\"text-center\">\n                      {['A', 'AAAA', 'CNAME'].includes(record.type) ? (\n                        <div className=\"flex justify-center\">\n                          <button\n                            type=\"button\"\n                            aria-label={`Toggle proxy status for ${record.name}, currently ${record.proxied ? 'proxied' : 'dns only'}`}\n                            className={cn(\n                              'group inline-flex min-h-6 items-center gap-1.5 rounded-full border px-2.5 py-0.5 text-xs font-medium transition-colors focus-visible:ring-[2px] focus-visible:outline-none',\n                              record.proxied\n                                ? 'border-warning/30 bg-warning/10 text-warning hover:bg-warning/20 text-warning'\n                                : 'border-border bg-muted/60 text-muted-foreground hover:bg-muted hover:text-foreground',\n                            )}\n                            onClick={() => toggleProxy(record.id)}\n                          >\n                            {record.proxied ? (\n                              <Cloud className=\"fill-warning text-warning size-3.5\" />\n                            ) : (\n                              <CloudOff className=\"text-muted-foreground group-hover:text-foreground size-3.5\" />\n                            )}\n                            <span>{record.proxied ? 'Proxied' : 'DNS only'}</span>\n                          </button>\n                        </div>\n                      ) : (\n                        <div className=\"flex justify-center\">\n                          <span className=\"text-muted-foreground/60 inline-flex items-center gap-1 font-mono text-xs\">\n                            <CloudOff className=\"size-3\" />\n                            DNS only\n                          </span>\n                        </div>\n                      )}\n                    </TableCell>\n\n                    {/* TTL Badge */}\n                    <TableCell>\n                      <Badge variant=\"outline\" className=\"border-border bg-muted/40 font-mono text-xs font-normal\">\n                        {record.ttl}\n                      </Badge>\n                    </TableCell>\n\n                    {/* Row Actions Dropdown */}\n                    <TableCell className=\"text-right\">\n                      <DropdownMenu>\n                        <DropdownMenuTrigger asChild>\n                          <Button variant=\"ghost\" size=\"icon-sm\" className=\"text-muted-foreground size-7 p-0\">\n                            <MoreHorizontal className=\"size-4\" />\n                            <span className=\"sr-only\">Open record actions</span>\n                          </Button>\n                        </DropdownMenuTrigger>\n                        <DropdownMenuContent align=\"end\" className=\"w-44\">\n                          <DropdownMenuItem onClick={() => startEdit(record)}>\n                            <Edit2 className=\"mr-2 size-3.5\" />\n                            Edit Record\n                          </DropdownMenuItem>\n                          <DropdownMenuItem onClick={() => copyText(record.id, record.content)}>\n                            <Copy className=\"mr-2 size-3.5\" />\n                            Copy Target\n                          </DropdownMenuItem>\n                          <DropdownMenuItem\n                            onClick={() =>\n                              copyText(`${record.id}-bind`, `${record.name} IN ${record.type} ${record.content}`)\n                            }\n                          >\n                            <FileCode className=\"mr-2 size-3.5\" />\n                            Copy BIND Row\n                          </DropdownMenuItem>\n                          <DropdownMenuSeparator />\n                          <DropdownMenuItem\n                            className=\"text-destructive focus:text-destructive\"\n                            onClick={() => deleteRecord(record.id)}\n                          >\n                            <Trash2 className=\"mr-2 size-3.5\" />\n                            Delete Record\n                          </DropdownMenuItem>\n                        </DropdownMenuContent>\n                      </DropdownMenu>\n                    </TableCell>\n                  </TableRow>\n                ))}\n\n                {/* Empty State */}\n                {filteredRecords.length === 0 && (\n                  <TableRow>\n                    <TableCell colSpan={6} className=\"h-32 text-center\">\n                      <div className=\"flex flex-col items-center justify-center gap-1.5 text-center\">\n                        <Globe className=\"text-muted-foreground/50 size-8\" />\n                        <p className=\"text-foreground text-sm font-medium\">No DNS records found</p>\n                        <p className=\"text-muted-foreground max-w-sm text-xs\">\n                          {searchQuery\n                            ? 'No records match your search filter query.'\n                            : 'No records configured for this domain yet. Add your first record to begin routing.'}\n                        </p>\n                        <Button size=\"sm\" className=\"mt-2 h-7 gap-1 text-xs\" onClick={startAdd}>\n                          <Plus className=\"size-3\" />\n                          Add DNS Record\n                        </Button>\n                      </div>\n                    </TableCell>\n                  </TableRow>\n                )}\n              </TableBody>\n            </Table>\n          </div>\n        </div>\n\n        {/* Table Footer info */}\n        <div className=\"text-muted-foreground flex flex-wrap items-center justify-between gap-2 px-1 text-xs\">\n          <p>\n            Showing <span className=\"text-foreground font-medium\">{filteredRecords.length}</span> of{' '}\n            <span className=\"text-foreground font-medium\">{records.length}</span> configured records\n          </p>\n          <div className=\"flex items-center gap-4\">\n            <span className=\"flex items-center gap-1.5\">\n              <span className=\"bg-warning size-2 rounded-full\" />\n              {records.filter((r) => r.proxied).length} Proxied\n            </span>\n            <span className=\"flex items-center gap-1.5\">\n              <span className=\"bg-muted-foreground size-2 rounded-full\" />\n              {records.filter((r) => !r.proxied).length} DNS Only\n            </span>\n          </div>\n        </div>\n      </div>\n    </div>\n  )\n}\n",
      "type": "registry:block",
      "target": "~/components/blocks/DnsRecordManager.tsx"
    }
  ],
  "dependencies": [
    "lucide-react"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/react/badge.json",
    "https://uipkge.dev/r/react/button.json",
    "https://uipkge.dev/r/react/card.json",
    "https://uipkge.dev/r/react/dropdown-menu.json",
    "https://uipkge.dev/r/react/input.json",
    "https://uipkge.dev/r/react/select.json",
    "https://uipkge.dev/r/react/separator.json",
    "https://uipkge.dev/r/react/switch.json",
    "https://uipkge.dev/r/react/table.json"
  ],
  "description": "Cloudflare/Vercel style DNS records management table and nameserver inspector with type badges, proxy toggle, copyable values, zone file exporter, and add/edit record panel.",
  "categories": [
    "devops",
    "dashboard",
    "data"
  ]
}