{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "cookie-consent-preferences",
  "title": "Cookie Consent — Preferences",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-angular/blocks/cookie-consent-preferences/cookie-consent-preferences.component.ts",
      "content": "// Granular cookie-consent dialog: each category lists its purpose and retention\n// with a switch, and strictly-necessary stays visible as a locked row rather than\n// hidden. Port of the React block 1:1.\nimport { ChangeDetectionStrategy, Component, Input, signal } from '@angular/core'\nimport { Lock, LucideAngularModule } from 'lucide-angular'\nimport { UiBadgeComponent } from '@/ui/badge/badge.component'\nimport { UiButtonComponent } from '@/ui/button/button.component'\nimport {\n  UiDialogComponent,\n  UiDialogContentComponent,\n  UiDialogDescriptionComponent,\n  UiDialogFooterComponent,\n  UiDialogHeaderComponent,\n  UiDialogTitleComponent,\n} from '@/ui/dialog/dialog.component'\nimport { UiSeparatorComponent } from '@/ui/separator/separator.component'\nimport { UiSwitchComponent } from '@/ui/switch/switch.component'\n\nexport interface CookieConsentCategory {\n  id: string\n  label: string\n  purpose: string\n  retention: string\n  locked: boolean\n}\n\nexport const cookieConsentCategories: CookieConsentCategory[] = [\n  {\n    id: 'necessary',\n    label: 'Strictly necessary',\n    purpose: 'Session and sign-in state. Without these the app cannot keep you logged in.',\n    retention: 'Session',\n    locked: true,\n  },\n  {\n    id: 'analytics',\n    label: 'Product analytics',\n    purpose: 'Which pages are read and where people give up. Aggregated, never sold.',\n    retention: '13 months',\n    locked: false,\n  },\n  {\n    id: 'support',\n    label: 'Support chat',\n    purpose: 'Keeps a conversation open across page loads so you do not repeat yourself.',\n    retention: '30 days',\n    locked: false,\n  },\n]\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.Eager,\n  selector: 'ui-cookie-consent-preferences, [ui-cookie-consent-preferences]',\n  standalone: true,\n  // React renders the root <div> itself: the host stays out of layout.\n  host: { '[attr.class]': '\"contents\"' },\n  imports: [\n    LucideAngularModule,\n    UiBadgeComponent,\n    UiButtonComponent,\n    UiDialogComponent,\n    UiDialogContentComponent,\n    UiDialogDescriptionComponent,\n    UiDialogFooterComponent,\n    UiDialogHeaderComponent,\n    UiDialogTitleComponent,\n    UiSeparatorComponent,\n    UiSwitchComponent,\n  ],\n  template: `\n    <div data-slot=\"cookie-consent-preferences\">\n      <ui-dialog [open]=\"open()\" (openChange)=\"open.set($event)\">\n        <ui-dialog-content class=\"sm:max-w-lg\">\n          <div ui-dialog-header>\n            <span ui-badge variant=\"secondary\" class=\"w-fit\">Privacy</span>\n            <h2 ui-dialog-title class=\"mt-3 text-xl\">Choose what we store</h2>\n            <p ui-dialog-description>\n              Each category says what it is for and how long it is kept. Nothing here is advertising.\n            </p>\n          </div>\n\n          <div ui-separator></div>\n\n          <ul class=\"space-y-4\">\n            @for (category of categories; track category.id) {\n              <li class=\"flex items-start gap-4\">\n                <div class=\"min-w-0 flex-1\">\n                  <div class=\"flex flex-wrap items-center gap-2\">\n                    <p class=\"text-sm font-medium\">{{ category.label }}</p>\n                    @if (category.locked) {\n                      <span ui-badge variant=\"outline\" class=\"gap-1\">\n                        <lucide-icon [img]=\"Lock\" class=\"size-2.5\" aria-hidden=\"true\" />\n                        Required\n                      </span>\n                    }\n                  </div>\n                  <p class=\"text-muted-foreground mt-1 text-xs leading-relaxed\">{{ category.purpose }}</p>\n                  <p class=\"text-muted-foreground/80 mt-1 font-mono text-xs\">Kept {{ category.retention }}</p>\n                </div>\n                <button\n                  ui-switch\n                  [checked]=\"choices()[category.id] ?? false\"\n                  [disabled]=\"category.locked\"\n                  [attr.aria-label]=\"'Allow ' + category.label\"\n                  class=\"mt-1 shrink-0\"\n                  (checkedChange)=\"setChoice(category.id, $event)\"\n                ></button>\n              </li>\n            }\n          </ul>\n\n          <div ui-dialog-footer class=\"sm:justify-start\">\n            <button ui-button (click)=\"saveChoices()\">Save choices</button>\n            <button ui-button variant=\"outline\" (click)=\"rejectOptional()\">Reject optional</button>\n          </div>\n        </ui-dialog-content>\n      </ui-dialog>\n    </div>\n  `,\n})\nexport class UiCookieConsentPreferencesComponent {\n  protected readonly Lock = Lock\n  protected readonly categories = cookieConsentCategories\n\n  @Input() set initialOpen(v: boolean) {\n    this.open.set(v ?? true)\n  }\n  @Input('class') className?: string\n\n  readonly open = signal(true)\n  readonly choices = signal<Record<string, boolean>>({ necessary: true, analytics: false, support: false })\n\n  setChoice(id: string, value: boolean): void {\n    this.choices.update((prev) => ({ ...prev, [id]: value }))\n  }\n\n  saveChoices(): void {\n    this.open.set(false)\n  }\n\n  rejectOptional(): void {\n    this.choices.update((prev) => {\n      const next: Record<string, boolean> = {}\n      for (const category of cookieConsentCategories) next[category.id] = category.locked ? prev[category.id]! : false\n      return next\n    })\n    this.open.set(false)\n  }\n}\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/cookie-consent-preferences/cookie-consent-preferences.component.ts"
    },
    {
      "path": "packages/registry-angular/blocks/cookie-consent-preferences/index.ts",
      "content": "export {\n  UiCookieConsentPreferencesComponent,\n  cookieConsentCategories,\n  type CookieConsentCategory,\n} from './cookie-consent-preferences.component'\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/cookie-consent-preferences/index.ts"
    }
  ],
  "dependencies": [
    "lucide-angular"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/angular/badge.json",
    "https://uipkge.dev/r/angular/button.json",
    "https://uipkge.dev/r/angular/dialog.json",
    "https://uipkge.dev/r/angular/separator.json",
    "https://uipkge.dev/r/angular/switch.json"
  ],
  "description": "Granular consent dialog listing each cookie category with its purpose, retention, and a switch, with strictly-necessary shown as locked rather than hidden.",
  "categories": [
    "marketing"
  ],
  "deprecated": true,
  "replacedBy": "cookie-consent"
}