{
  "$schema": "https://shadcn-vue.com/schema/registry-item.json",
  "name": "privacy-data-export-portal",
  "title": "Privacy Data Export Portal",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-vue/blocks/privacy-data-export-portal/PrivacyDataExportPortal.vue",
      "content": "<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\nimport type { HTMLAttributes } from 'vue'\nimport {\n  Activity,\n  Archive,\n  Calendar,\n  Check,\n  CheckCircle2,\n  Clock,\n  CreditCard,\n  Download,\n  FileSpreadsheet,\n  FileText,\n  FolderArchive,\n  HardDrive,\n  Info,\n  Loader2,\n  Lock,\n  RefreshCw,\n  ShieldCheck,\n  User,\n} from 'lucide-vue-next'\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 { Checkbox } from '@/components/ui/checkbox'\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'\nimport { Separator } from '@/components/ui/separator'\nimport { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'\n\nexport type ExportFormat = 'zip' | 'json' | 'csv'\nexport type ArchiveStatus = 'ready' | 'processing' | 'expired'\n\nexport interface DataCategory {\n  id: string\n  name: string\n  description: string\n  sizeMb: number\n  recordCount: string\n  icon: any\n}\n\nexport interface ArchiveRecord {\n  id: string\n  name: string\n  format: ExportFormat\n  requestedAt: string\n  expiresAt: string\n  expiresInDays: number\n  sizeMb: number\n  categories: string[]\n  status: ArchiveStatus\n}\n\ninterface Props {\n  initialCategories?: string[]\n  initialFormat?: ExportFormat\n  class?: HTMLAttributes['class']\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n  initialCategories: () => ['profile', 'activity', 'financial', 'workspace'],\n  initialFormat: 'zip',\n})\n\nconst categories: DataCategory[] = [\n  {\n    id: 'profile',\n    name: 'Profile & Identity',\n    description: 'Account details, email history, avatar, and authentication security credentials.',\n    sizeMb: 1.4,\n    recordCount: '12 records',\n    icon: User,\n  },\n  {\n    id: 'activity',\n    name: 'Activity & Audit Logs',\n    description: 'Login history, device sessions, security events, and API access traces.',\n    sizeMb: 8.6,\n    recordCount: '1,420 events',\n    icon: Activity,\n  },\n  {\n    id: 'financial',\n    name: 'Financial & Transactions',\n    description: 'Invoices, payment receipts, subscription history, and billing ledger entries.',\n    sizeMb: 3.2,\n    recordCount: '48 entries',\n    icon: CreditCard,\n  },\n  {\n    id: 'workspace',\n    name: 'Workspace Content & Projects',\n    description: 'Created blocks, saved templates, comments, custom presets, and file uploads.',\n    sizeMb: 35.0,\n    recordCount: '312 objects',\n    icon: FolderArchive,\n  },\n]\n\nconst initialArchives: ArchiveRecord[] = [\n  {\n    id: 'DPA-2026-0814',\n    name: 'DPA-2026-0814.zip',\n    format: 'zip',\n    requestedAt: 'Aug 14, 2026 · 09:24 UTC',\n    expiresAt: 'Aug 25, 2026',\n    expiresInDays: 4,\n    sizeMb: 42.1,\n    categories: ['Profile', 'Logs', 'Workspace', 'Billing'],\n    status: 'ready',\n  },\n  {\n    id: 'DPA-2026-0820',\n    name: 'DPA-2026-0820.json',\n    format: 'json',\n    requestedAt: 'Aug 20, 2026 · 14:15 UTC',\n    expiresAt: 'Aug 27, 2026',\n    expiresInDays: 7,\n    sizeMb: 8.6,\n    categories: ['Activity & Audit Logs'],\n    status: 'processing',\n  },\n  {\n    id: 'DPA-2026-0201',\n    name: 'DPA-2026-0201.zip',\n    format: 'zip',\n    requestedAt: 'Feb 01, 2026 · 11:02 UTC',\n    expiresAt: 'Feb 08, 2026',\n    expiresInDays: 0,\n    sizeMb: 38.4,\n    categories: ['Full Account Archive'],\n    status: 'expired',\n  },\n]\n\nconst selectedCategories = ref<string[]>([...props.initialCategories])\nconst selectedFormat = ref<ExportFormat>(props.initialFormat)\nconst archives = ref<ArchiveRecord[]>([...initialArchives])\nconst isGenerating = ref(false)\nconst notification = ref<{ title: string; message: string; type: 'success' | 'info' } | null>(null)\n\nconst totalSelectedSize = computed(() => {\n  const sum = categories.filter((c) => selectedCategories.value.includes(c.id)).reduce((acc, c) => acc + c.sizeMb, 0)\n  return sum.toFixed(1)\n})\n\nconst isAllSelected = computed(() => selectedCategories.value.length === categories.length)\n\nfunction toggleCategory(categoryId: string) {\n  if (selectedCategories.value.includes(categoryId)) {\n    selectedCategories.value = selectedCategories.value.filter((id) => id !== categoryId)\n  } else {\n    selectedCategories.value = [...selectedCategories.value, categoryId]\n  }\n}\n\nfunction toggleAll() {\n  if (isAllSelected.value) {\n    selectedCategories.value = []\n  } else {\n    selectedCategories.value = categories.map((c) => c.id)\n  }\n}\n\nfunction requestFullExport() {\n  selectedCategories.value = categories.map((c) => c.id)\n  selectedFormat.value = 'zip'\n  triggerExport('Full Data Export')\n}\n\nfunction triggerExport(label = 'Custom Data Export') {\n  if (selectedCategories.value.length === 0) return\n\n  isGenerating.value = true\n  notification.value = {\n    title: 'Archive Request Queued',\n    message: `${label} requested. Compiling ${selectedCategories.value.length} categories (${totalSelectedSize.value} MB) with AES-256 encryption.`,\n    type: 'info',\n  }\n\n  setTimeout(() => {\n    const newId = `DPA-${new Date().toISOString().slice(0, 10).replace(/-/g, '')}-${Math.floor(100 + Math.random() * 900)}`\n    const ext = selectedFormat.value\n    const catNames = categories.filter((c) => selectedCategories.value.includes(c.id)).map((c) => c.name.split(' ')[0])\n\n    const newRecord: ArchiveRecord = {\n      id: newId,\n      name: `${newId}.${ext}`,\n      format: selectedFormat.value,\n      requestedAt: 'Just now',\n      expiresAt: '7 days from now',\n      expiresInDays: 7,\n      sizeMb: parseFloat(totalSelectedSize.value),\n      categories: catNames,\n      status: 'ready',\n    }\n\n    archives.value = [newRecord, ...archives.value]\n    isGenerating.value = false\n    notification.value = {\n      title: 'Archive Ready',\n      message: `Export package ${newRecord.name} (${newRecord.sizeMb} MB) has been generated and is ready for download.`,\n      type: 'success',\n    }\n  }, 1200)\n}\n\nfunction handleDownload(archive: ArchiveRecord) {\n  notification.value = {\n    title: 'Download Initiated',\n    message: `Securely downloading ${archive.name} (${archive.sizeMb} MB). SHA-256 checksum verified.`,\n    type: 'success',\n  }\n}\n\nfunction handleReRequest(archive: ArchiveRecord) {\n  notification.value = {\n    title: 'Archive Re-generation Requested',\n    message: `Re-generating expired archive for ${archive.categories.join(', ')}.`,\n    type: 'info',\n  }\n}\n</script>\n\n<template>\n  <div data-slot=\"privacy-data-export-portal\" :class=\"cn('w-full space-y-6', props.class)\">\n    <!-- Header Bar -->\n    <div class=\"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n      <div class=\"space-y-1\">\n        <div class=\"flex items-center gap-2\">\n          <h1 class=\"text-foreground text-2xl font-bold tracking-tight sm:text-3xl\">\n            Data Privacy & Personal Data Export\n          </h1>\n          <Badge\n            variant=\"outline\"\n            class=\"border-primary/20 bg-primary/5 text-primary hidden items-center gap-1 text-xs font-medium sm:inline-flex\"\n          >\n            <Lock class=\"size-3\" />\n            GDPR Art. 15\n          </Badge>\n        </div>\n        <p class=\"text-muted-foreground text-sm\">\n          Request, generate, and download your complete personal data archives under GDPR Article 15.\n        </p>\n      </div>\n      <div class=\"flex items-center gap-2.5\">\n        <Button\n          type=\"button\"\n          size=\"default\"\n          class=\"gap-2 shadow-xs\"\n          :disabled=\"isGenerating\"\n          @click=\"requestFullExport\"\n        >\n          <Download class=\"size-4\" />\n          Request Full Data Export\n        </Button>\n      </div>\n    </div>\n\n    <!-- Notification Banner -->\n    <div\n      v-if=\"notification\"\n      :class=\"\n        cn(\n          'flex items-start gap-3 rounded-lg border p-4 text-sm transition-colors',\n          notification.type === 'success'\n            ? 'border-success/30 bg-success/10 text-success'\n            : 'border-info/30 bg-info/10 text-info',\n        )\n      \"\n    >\n      <CheckCircle2 v-if=\"notification.type === 'success'\" class=\"text-success mt-0.5 size-5 shrink-0\" />\n      <Info v-else class=\"text-info mt-0.5 size-5 shrink-0\" />\n      <div class=\"flex-1 space-y-0.5\">\n        <p class=\"font-medium\">{{ notification.title }}</p>\n        <p class=\"text-xs opacity-90\">{{ notification.message }}</p>\n      </div>\n      <Button variant=\"ghost\" size=\"sm\" class=\"h-7 px-2 text-xs hover:bg-transparent\" @click=\"notification = null\">\n        Dismiss\n      </Button>\n    </div>\n\n    <!-- 4 Privacy & Governance Stat Cards -->\n    <div class=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4\">\n      <!-- Stat 1: Account Creation Date -->\n      <Card class=\"border-border shadow-xs\">\n        <CardHeader class=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n          <CardTitle class=\"text-muted-foreground text-sm font-medium\">Account Creation Date</CardTitle>\n          <div\n            class=\"border-border bg-muted/50 text-foreground flex size-8 items-center justify-center rounded-md border\"\n          >\n            <Calendar class=\"text-muted-foreground size-4\" />\n          </div>\n        </CardHeader>\n        <CardContent class=\"space-y-1\">\n          <div class=\"text-foreground text-xl font-bold tracking-tight tabular-nums\">Nov 12, 2024</div>\n          <p class=\"text-muted-foreground text-xs\">\n            <span class=\"text-foreground font-medium tabular-nums\">1.8 years</span> active account age\n          </p>\n        </CardContent>\n      </Card>\n\n      <!-- Stat 2: Total Data Footprint -->\n      <Card class=\"border-border shadow-xs\">\n        <CardHeader class=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n          <CardTitle class=\"text-muted-foreground text-sm font-medium\">Total Data Footprint</CardTitle>\n          <div\n            class=\"border-border bg-muted/50 text-foreground flex size-8 items-center justify-center rounded-md border\"\n          >\n            <HardDrive class=\"text-muted-foreground size-4\" />\n          </div>\n        </CardHeader>\n        <CardContent class=\"space-y-1\">\n          <div class=\"text-foreground text-xl font-bold tracking-tight tabular-nums\">48.2 MB</div>\n          <p class=\"text-muted-foreground text-xs\">Across 6 storage domains</p>\n        </CardContent>\n      </Card>\n\n      <!-- Stat 3: Active Data Retention Policy -->\n      <Card class=\"border-border shadow-xs\">\n        <CardHeader class=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n          <CardTitle class=\"text-muted-foreground text-sm font-medium\">Data Retention Policy</CardTitle>\n          <div\n            class=\"border-border bg-muted/50 text-foreground flex size-8 items-center justify-center rounded-md border\"\n          >\n            <Clock class=\"text-muted-foreground size-4\" />\n          </div>\n        </CardHeader>\n        <CardContent class=\"space-y-1\">\n          <div class=\"text-foreground text-xl font-bold tracking-tight tabular-nums\">30-Day Policy</div>\n          <p class=\"text-muted-foreground text-xs\">Automated purge of activity logs</p>\n        </CardContent>\n      </Card>\n\n      <!-- Stat 4: Consent Status -->\n      <Card class=\"border-border shadow-xs\">\n        <CardHeader class=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n          <CardTitle class=\"text-muted-foreground text-sm font-medium\">Consent Status</CardTitle>\n          <div\n            class=\"border-success/20 bg-success/10 text-success flex size-8 items-center justify-center rounded-md border\"\n          >\n            <ShieldCheck class=\"size-4\" />\n          </div>\n        </CardHeader>\n        <CardContent class=\"space-y-1\">\n          <div class=\"text-foreground text-xl font-bold tracking-tight tabular-nums\">3 / 3 Active</div>\n          <p class=\"text-success text-xs font-medium\">Required Consents Active</p>\n        </CardContent>\n      </Card>\n    </div>\n\n    <!-- Select Data Categories for Export -->\n    <Card class=\"border-border shadow-xs\">\n      <CardHeader class=\"flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between\">\n        <div class=\"space-y-1\">\n          <CardTitle class=\"text-foreground text-lg font-semibold\"> Select Data Categories for Export </CardTitle>\n          <CardDescription>\n            Choose specific data domains to compile into your encrypted archive package.\n          </CardDescription>\n        </div>\n        <Button variant=\"outline\" size=\"sm\" class=\"h-8 self-start text-xs sm:self-auto\" @click=\"toggleAll\">\n          {{ isAllSelected ? 'Deselect All' : 'Select All Categories' }}\n        </Button>\n      </CardHeader>\n      <CardContent class=\"space-y-6\">\n        <!-- Checkbox Grid of 4 Categories -->\n        <div class=\"grid grid-cols-1 gap-3.5 md:grid-cols-2\">\n          <div\n            v-for=\"cat in categories\"\n            :key=\"cat.id\"\n            :class=\"\n              cn(\n                'group flex cursor-pointer items-start gap-3.5 rounded-lg border p-4 transition-colors',\n                selectedCategories.includes(cat.id)\n                  ? 'border-primary/50 bg-primary/5 dark:bg-primary/10 shadow-xs'\n                  : 'border-border bg-card hover:bg-muted/40',\n              )\n            \"\n            @click=\"toggleCategory(cat.id)\"\n          >\n            <Checkbox\n              :id=\"`category-${cat.id}`\"\n              :checked=\"selectedCategories.includes(cat.id)\"\n              class=\"mt-1\"\n              @update:checked=\"toggleCategory(cat.id)\"\n              @click.stop\n            />\n            <div class=\"min-w-0 flex-1 space-y-1.5\">\n              <div class=\"flex items-center justify-between gap-2\">\n                <div class=\"flex items-center gap-2\">\n                  <component :is=\"cat.icon\" class=\"text-muted-foreground size-4\" />\n                  <label\n                    :for=\"`category-${cat.id}`\"\n                    class=\"text-foreground cursor-pointer text-sm leading-none font-medium\"\n                    @click.stop=\"toggleCategory(cat.id)\"\n                  >\n                    {{ cat.name }}\n                  </label>\n                </div>\n                <Badge variant=\"secondary\" class=\"shrink-0 font-mono text-xs tabular-nums\"> {{ cat.sizeMb }} MB </Badge>\n              </div>\n              <p class=\"text-muted-foreground text-xs leading-relaxed\">\n                {{ cat.description }}\n              </p>\n              <div class=\"text-muted-foreground/80 text-xs tabular-nums\">\n                Estimated footprint: <span class=\"text-foreground font-medium\">{{ cat.recordCount }}</span>\n              </div>\n            </div>\n          </div>\n        </div>\n\n        <Separator />\n\n        <!-- Format selector and generation action bar -->\n        <div class=\"flex flex-col gap-4 sm:flex-row sm:flex-wrap sm:items-center sm:justify-between\">\n          <div class=\"flex flex-col gap-1.5 sm:flex-row sm:items-center sm:gap-3\">\n            <label class=\"text-foreground text-sm font-medium whitespace-nowrap\"> Export Format: </label>\n            <Select v-model=\"selectedFormat\">\n              <SelectTrigger class=\"bg-background w-full sm:w-[260px]\">\n                <SelectValue placeholder=\"Select export format\" />\n              </SelectTrigger>\n              <SelectContent>\n                <SelectItem value=\"zip\">\n                  <div class=\"flex items-center gap-2\">\n                    <Archive class=\"text-muted-foreground size-3.5\" />\n                    <span>Complete ZIP Bundle (.zip)</span>\n                  </div>\n                </SelectItem>\n                <SelectItem value=\"json\">\n                  <div class=\"flex items-center gap-2\">\n                    <FileText class=\"text-muted-foreground size-3.5\" />\n                    <span>JSON Archive (.json)</span>\n                  </div>\n                </SelectItem>\n                <SelectItem value=\"csv\">\n                  <div class=\"flex items-center gap-2\">\n                    <FileSpreadsheet class=\"text-muted-foreground size-3.5\" />\n                    <span>CSV Spreadsheet (.csv)</span>\n                  </div>\n                </SelectItem>\n              </SelectContent>\n            </Select>\n          </div>\n\n          <div class=\"flex flex-col items-stretch gap-3 sm:flex-row sm:items-center\">\n            <div class=\"text-muted-foreground text-xs sm:text-right\">\n              Selected:\n              <span class=\"text-foreground font-semibold tabular-nums\"\n                >{{ selectedCategories.length }} of {{ categories.length }} categories</span\n              >\n              <span class=\"text-foreground font-semibold tabular-nums\">~{{ totalSelectedSize }} MB</span>\n            </div>\n            <Button\n              type=\"button\"\n              class=\"gap-2 shadow-xs\"\n              :disabled=\"selectedCategories.length === 0 || isGenerating\"\n              @click=\"() => triggerExport('Custom Data Export')\"\n            >\n              <Loader2 v-if=\"isGenerating\" class=\"size-4 animate-spin\" />\n              <Archive v-else class=\"size-4\" />\n              {{ isGenerating ? 'Compiling Archive...' : 'Generate Data Archive' }}\n            </Button>\n          </div>\n        </div>\n      </CardContent>\n    </Card>\n\n    <!-- Legal Compliance Notice Box -->\n    <div\n      class=\"border-border bg-muted/40 text-muted-foreground flex items-start gap-3 rounded-lg border p-4 text-xs shadow-xs\"\n    >\n      <Lock class=\"text-muted-foreground mt-0.5 size-4 shrink-0\" />\n      <p class=\"leading-relaxed\">\n        Under <span class=\"text-foreground font-medium\">GDPR Article 15</span> (Right of Access) and\n        <span class=\"text-foreground font-medium\">CCPA §1798.100</span>, you are entitled to request and receive all\n        personal data processed by this service. Export packages are generated on-demand, encrypted with AES-256, and\n        available for download for 7 days before automated deletion.\n      </p>\n    </div>\n\n    <!-- Export Archive History Table -->\n    <Card class=\"border-border shadow-xs\">\n      <CardHeader>\n        <div class=\"flex items-center justify-between\">\n          <div class=\"space-y-1\">\n            <CardTitle class=\"text-foreground text-lg font-semibold\">Export Archive History</CardTitle>\n            <CardDescription>\n              Previous data archive requests and generation status. Downloads remain available for 7 days.\n            </CardDescription>\n          </div>\n          <Badge variant=\"outline\" class=\"font-mono text-xs tabular-nums\"> {{ archives.length }} archives </Badge>\n        </div>\n      </CardHeader>\n      <CardContent class=\"p-0\">\n        <div class=\"overflow-x-auto\">\n          <Table>\n            <TableHeader>\n              <TableRow>\n                <TableHead class=\"min-w-[220px]\">Archive ID & Format</TableHead>\n                <TableHead class=\"min-w-[170px]\">Request Date</TableHead>\n                <TableHead class=\"min-w-[140px]\">Expiration</TableHead>\n                <TableHead class=\"min-w-[100px] text-right\">File Size</TableHead>\n                <TableHead class=\"min-w-[150px]\">Status</TableHead>\n                <TableHead class=\"min-w-[140px] text-right\">Action</TableHead>\n              </TableRow>\n            </TableHeader>\n            <TableBody>\n              <TableRow v-for=\"arc in archives\" :key=\"arc.id\" class=\"hover:bg-muted/40\">\n                <TableCell>\n                  <div class=\"space-y-1\">\n                    <div class=\"flex items-center gap-2\">\n                      <span class=\"text-foreground font-mono text-xs font-semibold\">{{ arc.name }}</span>\n                      <Badge variant=\"outline\" class=\"px-1.5 py-0 font-mono text-xs uppercase\">\n                        {{ arc.format }}\n                      </Badge>\n                    </div>\n                    <p class=\"text-muted-foreground text-xs\">\n                      {{ arc.categories.join(', ') }}\n                    </p>\n                  </div>\n                </TableCell>\n                <TableCell class=\"text-muted-foreground text-xs tabular-nums\">\n                  {{ arc.requestedAt }}\n                </TableCell>\n                <TableCell>\n                  <div class=\"space-y-0.5\">\n                    <span\n                      :class=\"\n                        cn(\n                          'text-xs font-medium tabular-nums',\n                          arc.status === 'expired'\n                            ? 'text-muted-foreground line-through'\n                            : arc.expiresInDays <= 4\n                              ? 'text-warning'\n                              : 'text-muted-foreground',\n                        )\n                      \"\n                    >\n                      {{ arc.status === 'expired' ? 'Expired' : `Expires in ${arc.expiresInDays} days` }}\n                    </span>\n                    <p class=\"text-muted-foreground/70 text-xs tabular-nums\">\n                      {{ arc.expiresAt }}\n                    </p>\n                  </div>\n                </TableCell>\n                <TableCell class=\"text-foreground text-right font-mono text-xs font-medium tabular-nums\">\n                  {{ arc.sizeMb.toFixed(1) }} MB\n                </TableCell>\n                <TableCell>\n                  <Badge\n                    v-if=\"arc.status === 'ready'\"\n                    variant=\"outline\"\n                    class=\"border-success/30 bg-success/10 text-success items-center gap-1.5 text-xs font-medium\"\n                  >\n                    <Check class=\"size-3\" />\n                    Ready for Download\n                  </Badge>\n                  <Badge\n                    v-else-if=\"arc.status === 'processing'\"\n                    variant=\"outline\"\n                    class=\"border-warning/30 bg-warning/10 text-warning items-center gap-1.5 text-xs font-medium\"\n                  >\n                    <Loader2 class=\"size-3 animate-spin\" />\n                    Processing Archive\n                  </Badge>\n                  <Badge v-else variant=\"secondary\" class=\"text-muted-foreground text-xs\"> Expired </Badge>\n                </TableCell>\n                <TableCell class=\"text-right\">\n                  <Button\n                    aria-label=\"Download attachment\"\n                    v-if=\"arc.status === 'ready'\"\n                    size=\"sm\"\n                    class=\"h-8 gap-1.5 text-xs shadow-xs\"\n                    @click=\"handleDownload(arc)\"\n                  >\n                    <Download class=\"size-3.5\" />\n                    Download ZIP\n                  </Button>\n                  <Button\n                    v-else-if=\"arc.status === 'processing'\"\n                    size=\"sm\"\n                    variant=\"secondary\"\n                    disabled\n                    class=\"h-8 gap-1.5 text-xs opacity-75\"\n                  >\n                    <Loader2 class=\"size-3.5 animate-spin\" />\n                    Processing...\n                  </Button>\n                  <Button v-else size=\"sm\" variant=\"outline\" class=\"h-8 gap-1.5 text-xs\" @click=\"handleReRequest(arc)\">\n                    <RefreshCw class=\"size-3.5\" />\n                    Re-request\n                  </Button>\n                </TableCell>\n              </TableRow>\n            </TableBody>\n          </Table>\n        </div>\n      </CardContent>\n    </Card>\n  </div>\n</template>\n",
      "type": "registry:block",
      "target": "~/app/components/blocks/PrivacyDataExportPortal.vue"
    }
  ],
  "dependencies": [
    "lucide-vue-next"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/vue/badge.json",
    "https://uipkge.dev/r/vue/button.json",
    "https://uipkge.dev/r/vue/card.json",
    "https://uipkge.dev/r/vue/checkbox.json",
    "https://uipkge.dev/r/vue/select.json",
    "https://uipkge.dev/r/vue/separator.json",
    "https://uipkge.dev/r/vue/table.json"
  ],
  "description": "GDPR Article 15 and CCPA personal data export portal with privacy governance stat cards, granular category export selector, format chooser, and export archive history table.",
  "categories": [
    "legal",
    "security",
    "app"
  ]
}