{"_id":"@analytics-debugger/consent-modal","_rev":"2-5cfdda8e3175476e6efd79fb617257a2","name":"@analytics-debugger/consent-modal","dist-tags":{"latest":"1.0.1"},"versions":{"1.0.0":{"name":"@analytics-debugger/consent-modal","version":"1.0.0","keywords":["consent","cookie","cookie-consent","gdpr","ccpa","privacy","google-consent-mode","gcm-v2","analytics","shadow-dom","i18n","dark-mode","web-component"],"author":{"name":"Analytics Debugger","email":"contact@analytics-debugger.com"},"license":"MIT","_id":"@analytics-debugger/consent-modal@1.0.0","maintainers":[{"name":"thyngster","email":"thyngster@gmail.com"}],"homepage":"https://www.analytics-debugger.com/tools/consent-modal","bugs":{"url":"https://github.com/analytics-debugger/consent-modal/issues"},"dist":{"shasum":"f263e102426367e004aefd043304daef5bb3dffe","tarball":"https://registry.npmjs.org/@analytics-debugger/consent-modal/-/consent-modal-1.0.0.tgz","fileCount":28,"integrity":"sha512-vAA/9+4cW5fVPHxG21PG44xjzFuLaDgcpWQFIMX+UtSov+yPW9eclBE1CEYcTjCQrv5VI0W3v/Vc5XWI/96QhQ==","signatures":[{"sig":"MEYCIQDErIat8ElHxJcXS6g5yIwT0leTyvEAUtMAGBy28ufUmAIhAINxwxKH+GrW55qD8kti3nbQpHFQhlNj9bCAnPXo9MeP","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":71914},"main":"dist/dta-cm.umd.js","type":"module","types":"dist/index.d.ts","unpkg":"dist/dta-cm.umd.js","module":"dist/dta-cm.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/dta-cm.js","require":"./dist/dta-cm.umd.js"},"./i18n/*":"./i18n/*"},"scripts":{"dev":"vite","test":"vitest run","build":"vite build","preview":"vite preview","typecheck":"tsc --noEmit","test:watch":"vitest","release:major":"npm version major && git push && git push --tags","release:minor":"npm version minor && git push && git push --tags","release:patch":"npm version patch && git push && git push --tags","test:coverage":"vitest run --coverage","prepublishOnly":"npm run build"},"_npmUser":{"name":"thyngster","email":"thyngster@gmail.com"},"jsdelivr":"dist/dta-cm.umd.js","repository":{"url":"git+https://github.com/analytics-debugger/consent-modal.git","type":"git"},"_npmVersion":"11.9.0","description":"Lightweight cookie consent modal with Shadow DOM encapsulation, Google Consent Mode v2, i18n, and dark mode. Zero dependencies, ~6KB gzipped.","directories":{},"sideEffects":false,"_nodeVersion":"24.14.0","_hasShrinkwrap":false,"devDependencies":{"vite":"^8.0.0","vitest":"^4.1.0","happy-dom":"^20.8.4","typescript":"^5.9.3","@vitest/coverage-v8":"^4.1.0"},"_npmOperationalInternal":{"tmp":"tmp/consent-modal_1.0.0_1773786585327_0.03564812518662053","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@analytics-debugger/consent-modal","version":"1.0.1","description":"Lightweight cookie consent modal with Shadow DOM encapsulation, Google Consent Mode v2, i18n, and dark mode. Zero dependencies, ~6KB gzipped.","type":"module","main":"dist/dta-cm.umd.js","module":"dist/dta-cm.js","unpkg":"dist/dta-cm.umd.js","jsdelivr":"dist/dta-cm.umd.js","types":"dist/index.d.ts","exports":{".":{"import":"./dist/dta-cm.js","require":"./dist/dta-cm.umd.js","types":"./dist/index.d.ts"},"./i18n/*":"./i18n/*"},"sideEffects":false,"scripts":{"dev":"vite","build":"vite build","preview":"vite preview","typecheck":"tsc --noEmit","test":"vitest run","test:watch":"vitest","test:coverage":"vitest run --coverage","prepublishOnly":"npm run build","release:patch":"npm version patch && git push && git push --tags","release:minor":"npm version minor && git push && git push --tags","release:major":"npm version major && git push && git push --tags"},"keywords":["consent","cookie","cookie-consent","gdpr","ccpa","privacy","google-consent-mode","gcm-v2","analytics","shadow-dom","i18n","dark-mode","web-component"],"author":{"name":"Analytics Debugger","email":"contact@analytics-debugger.com"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/analytics-debugger/consent-modal.git"},"homepage":"https://www.analytics-debugger.com/tools/consent-modal","bugs":{"url":"https://github.com/analytics-debugger/consent-modal/issues"},"devDependencies":{"@vitest/coverage-v8":"^4.1.0","happy-dom":"^20.8.4","typescript":"^5.9.3","vite":"^8.0.0","vitest":"^4.1.0"},"gitHead":"b9bfcb86f1dfbb7790b3e9e3375c78e994e2bd3c","_id":"@analytics-debugger/consent-modal@1.0.1","_nodeVersion":"24.14.0","_npmVersion":"11.9.0","dist":{"integrity":"sha512-AeZw+3sLaE8VcsCPx4eY62T6YeTCF6dh2+26B0irOJj6brRmWs+hrAfnnck2ufAS2zpXcnXTba7laidVsRodJw==","shasum":"35a9d3d3f9d5c7d34b1b4a4ac8fcb477411f91a9","tarball":"https://registry.npmjs.org/@analytics-debugger/consent-modal/-/consent-modal-1.0.1.tgz","fileCount":28,"unpackedSize":74762,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIAHyO1bok7If0wHpSb8mgeJ8y0O7BLzgR9C3JsqeX38iAiBRdULR/cyWIM/4rTnnWpwtwHyrkVAo+esoiSUh3D9f4w=="}]},"_npmUser":{"name":"thyngster","email":"thyngster@gmail.com"},"directories":{},"maintainers":[{"name":"thyngster","email":"thyngster@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/consent-modal_1.0.1_1773833643097_0.14404969724550343"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-17T22:29:45.252Z","modified":"2026-03-18T11:34:03.387Z","1.0.0":"2026-03-17T22:29:45.466Z","1.0.1":"2026-03-18T11:34:03.237Z"},"bugs":{"url":"https://github.com/analytics-debugger/consent-modal/issues"},"author":{"name":"Analytics Debugger","email":"contact@analytics-debugger.com"},"license":"MIT","homepage":"https://www.analytics-debugger.com/tools/consent-modal","keywords":["consent","cookie","cookie-consent","gdpr","ccpa","privacy","google-consent-mode","gcm-v2","analytics","shadow-dom","i18n","dark-mode","web-component"],"repository":{"type":"git","url":"git+https://github.com/analytics-debugger/consent-modal.git"},"description":"Lightweight cookie consent modal with Shadow DOM encapsulation, Google Consent Mode v2, i18n, and dark mode. Zero dependencies, ~6KB gzipped.","maintainers":[{"name":"thyngster","email":"thyngster@gmail.com"}],"readme":"# @analytics-debugger/consent-modal\r\n\r\n[![npm version](https://img.shields.io/npm/v/@analytics-debugger/consent-modal?color=c6ff00&label=npm)](https://www.npmjs.com/package/@analytics-debugger/consent-modal)\r\n[![npm bundle size](https://img.shields.io/bundlephobia/minzip/@analytics-debugger/consent-modal?color=c6ff00&label=gzip)](https://bundlephobia.com/package/@analytics-debugger/consent-modal)\r\n[![CI](https://img.shields.io/github/actions/workflow/status/analytics-debugger/consent-modal/ci.yml?branch=main&label=CI)](https://github.com/analytics-debugger/consent-modal/actions/workflows/ci.yml)\r\n[![License](https://img.shields.io/npm/l/@analytics-debugger/consent-modal?color=c6ff00)](LICENSE)\r\n[![Zero Dependencies](https://img.shields.io/badge/dependencies-0-c6ff00)](package.json)\r\n\r\nLightweight, framework-agnostic cookie consent modal with Shadow DOM encapsulation, Google Consent Mode v2 support, i18n, and dark mode. Zero dependencies.\r\n\r\n| | Size |\r\n|---|---|\r\n| Raw (ESM) | 16.4 KB |\r\n| Raw (UMD) | 14.9 KB |\r\n| Gzipped | **~5.1 KB** |\r\n\r\n\r\n<img width=\"738\" height=\"557\" alt=\"image\" src=\"https://github.com/user-attachments/assets/da654758-a508-4c67-aecd-44f78c48c88b\" />\r\n<img width=\"712\" height=\"658\" alt=\"image\" src=\"https://github.com/user-attachments/assets/220c3b4a-41b6-48a1-8bfd-19ea767a50e1\" />\r\n\r\n## Features\r\n\r\n- **Shadow DOM encapsulation** -- styles are fully isolated; no CSS leaks in or out\r\n- **Google Consent Mode v2** -- fires `consent default` and `consent update` commands automatically\r\n- **i18n** -- built-in locale files (en, es, de, fr) with auto-detection of browser language\r\n- **Dark mode** -- `true`, `false`, or `'auto'` (follows `prefers-color-scheme`)\r\n- **Block navigation** -- prevent users from navigating away before giving consent\r\n- **Configurable categories** -- any number of categories with optional `locked`, `default`, and `emoji` properties\r\n- **Custom accent color** -- single property to theme the modal\r\n- **Cookie persistence** -- stores consent with `created_timestamp` and `updated_timestamp`\r\n- **HTML template partials** -- override individual parts of the modal markup\r\n- **Custom events** -- open the modal or settings panel from anywhere via `window.dispatchEvent`\r\n- **Callbacks** -- `onAcceptAll`, `onRejectAll`, `onSave`, `onChange`\r\n- **ESM + UMD builds** -- works with bundlers, `<script>` tags, jsdelivr, and unpkg\r\n- **Zero dependencies**\r\n- **MIT licensed**\r\n\r\n## Installation\r\n\r\n```bash\r\nnpm install @analytics-debugger/consent-modal\r\n```\r\n\r\nOr with other package managers:\r\n\r\n```bash\r\nyarn add @analytics-debugger/consent-modal\r\npnpm add @analytics-debugger/consent-modal\r\nbun add @analytics-debugger/consent-modal\r\n```\r\n\r\n## Quick Start\r\n\r\n```ts\r\nimport { createConsentModal } from '@analytics-debugger/consent-modal'\r\n\r\nconst modal = createConsentModal({\r\n  categories: [\r\n    { key: 'necessary', label: 'Essential', emoji: '🛡️', description: 'Required for the site to function.', locked: true, default: true },\r\n    { key: 'analytics', label: 'Analytics', emoji: '📊', sublabel: 'Performance', description: 'Helps us understand how the site is used.' },\r\n    { key: 'marketing', label: 'Marketing', emoji: '🎯', sublabel: 'Targeting', description: 'Used for personalized advertising.' },\r\n  ],\r\n  privacyPolicyUrl: '/privacy',\r\n  accentColor: '#c6ff00',\r\n  darkMode: 'auto',\r\n  onAcceptAll: (state) => console.log('Accepted all:', state),\r\n  onChange: (state) => console.log('Consent changed:', state),\r\n})\r\n```\r\n\r\nThe modal will appear automatically on first visit. Once the user makes a choice, the consent state is persisted in a cookie and the modal will not appear again until the cookie expires.\r\n\r\n## Configuration\r\n\r\nAll options are passed to `createConsentModal(options)`.\r\n\r\n### Required\r\n\r\n| Option | Type | Description |\r\n|---|---|---|\r\n| `categories` | `ConsentCategory[]` | Array of consent categories to display. |\r\n\r\n### Optional\r\n\r\n| Option | Type | Default | Description |\r\n|---|---|---|---|\r\n| `cookieName` | `string` | `'cm_consent'` | Name of the cookie used to persist consent. |\r\n| `cookieDays` | `number` | `365` | Cookie expiration in days. |\r\n| `privacyPolicyUrl` | `string` | -- | URL to link in the footer. |\r\n| `logoUrl` | `string` | -- | Path to a logo image displayed in the modal header. |\r\n| `accentColor` | `string` | -- | CSS color applied to buttons and toggles. |\r\n| `darkMode` | `boolean \\| 'auto'` | -- | Enable dark mode. `'auto'` follows the user's OS preference. |\r\n| `blockNavigation` | `boolean` | `false` | Prevent navigation (beforeunload + popstate) while the modal is open. |\r\n| `autoShow` | `boolean` | `true` | Automatically show the modal if no consent cookie is found. |\r\n| `locale` | `string` | `'en'` | Active locale key. |\r\n| `locales` | `Record<string, ConsentLocale>` | -- | Locale data keyed by language code. |\r\n| `detectLocale` | `boolean` | `false` | Auto-detect the browser's language and select a matching locale. |\r\n| `texts` | `ConsentTexts` | -- | Override default UI strings (heading, buttons, etc.). |\r\n| `gcmMappings` | `GCMMapping` | See below | Map GCM storage types to your category keys. |\r\n| `onAcceptAll` | `(state) => void` | -- | Called when the user accepts all categories. |\r\n| `onRejectAll` | `(state) => void` | -- | Called when the user rejects non-essential categories. |\r\n| `onSave` | `(state) => void` | -- | Called when the user saves custom choices. |\r\n| `onChange` | `(state) => void` | -- | Called on any consent change (accept, reject, or save). |\r\n\r\n### ConsentCategory\r\n\r\n```ts\r\ninterface ConsentCategory {\r\n  key: string          // Unique identifier (e.g. 'analytics')\r\n  label: string        // Display name\r\n  description: string  // Longer explanation shown in the settings panel\r\n  sublabel?: string    // Secondary label (e.g. 'Performance Cookies')\r\n  emoji?: string       // Emoji displayed next to the label\r\n  locked?: boolean     // If true, the toggle is always on and cannot be disabled\r\n  default?: boolean    // Initial state when no consent cookie exists\r\n}\r\n```\r\n\r\n### ConsentTexts\r\n\r\nAll text strings are optional. Provide only the ones you want to override.\r\n\r\n```ts\r\ninterface ConsentTexts {\r\n  heading?: string            // Main heading\r\n  subheading?: string         // Subheading below the main heading\r\n  descriptionP1?: string      // First paragraph\r\n  descriptionP2?: string      // Second paragraph\r\n  acceptAll?: string          // Accept all button label\r\n  rejectAll?: string          // Reject all button label\r\n  customize?: string          // \"Let me choose\" button label\r\n  customizeHeading?: string   // Settings panel heading\r\n  customizeSubheading?: string // Settings panel subheading\r\n  saveChoices?: string        // Save button label\r\n  back?: string               // Back button label\r\n  footerText?: string         // Footer text before privacy link\r\n  privacyPolicyLink?: string  // Privacy policy link text\r\n}\r\n```\r\n\r\n## i18n\r\n\r\nBuilt-in locale files are included for `en`, `es`, `de`, and `fr` under the `i18n/` directory. You can also supply your own translations.\r\n\r\n```ts\r\nconst modal = createConsentModal({\r\n  categories: [/* ... */],\r\n  locale: 'es',\r\n  locales: {\r\n    es: {\r\n      texts: {\r\n        heading: 'Tu privacidad importa',\r\n        acceptAll: 'Aceptar todo',\r\n        rejectAll: 'Rechazar todo',\r\n        customize: 'Personalizar',\r\n        saveChoices: 'Guardar preferencias',\r\n      },\r\n      categories: {\r\n        necessary: { label: 'Esenciales', description: 'Necesarias para el funcionamiento del sitio.' },\r\n        analytics: { label: 'Analítica', sublabel: 'Rendimiento', description: 'Nos ayudan a mejorar el sitio.' },\r\n        marketing: { label: 'Marketing', sublabel: 'Segmentación', description: 'Para publicidad personalizada.' },\r\n      },\r\n    },\r\n  },\r\n})\r\n```\r\n\r\n### Auto-detection\r\n\r\nSet `detectLocale: true` to automatically select a locale based on the browser's `navigator.language`. The library checks for an exact match first (`pt-BR`), then falls back to the base language (`pt`), and finally defaults to `'en'`.\r\n\r\n```ts\r\ncreateConsentModal({\r\n  categories: [/* ... */],\r\n  detectLocale: true,\r\n  locales: { es: { /* ... */ }, fr: { /* ... */ } },\r\n})\r\n```\r\n\r\n### Changing locale at runtime\r\n\r\n```ts\r\nmodal.setLocale('fr')\r\nmodal.show() // Will render in French\r\n```\r\n\r\n## Dark Mode\r\n\r\n```ts\r\n// Always dark\r\ncreateConsentModal({ categories: [/* ... */], darkMode: true })\r\n\r\n// Always light\r\ncreateConsentModal({ categories: [/* ... */], darkMode: false })\r\n\r\n// Follow OS preference (prefers-color-scheme)\r\ncreateConsentModal({ categories: [/* ... */], darkMode: 'auto' })\r\n```\r\n\r\n## Block Navigation\r\n\r\nWhen `blockNavigation: true`, the modal prevents the user from navigating away (via `beforeunload` and `popstate`) until consent is given. Navigation is restored as soon as the user accepts, rejects, or saves their choices.\r\n\r\n```ts\r\ncreateConsentModal({\r\n  categories: [/* ... */],\r\n  blockNavigation: true,\r\n})\r\n```\r\n\r\n## Google Consent Mode v2\r\n\r\nThe library automatically pushes `consent default` and `consent update` commands to `dataLayer` based on the user's choices. Map each GCM storage type to one of your category keys:\r\n\r\n```ts\r\ncreateConsentModal({\r\n  categories: [\r\n    { key: 'necessary', label: 'Essential', description: '...', locked: true, default: true },\r\n    { key: 'analytics', label: 'Analytics', description: '...' },\r\n    { key: 'marketing', label: 'Marketing', description: '...' },\r\n  ],\r\n  gcmMappings: {\r\n    ad_storage: 'marketing',\r\n    analytics_storage: 'analytics',\r\n    ad_user_data: 'marketing',\r\n    ad_personalization: 'marketing',\r\n    functionality_storage: 'necessary',\r\n    personalization_storage: 'necessary',\r\n    security_storage: 'necessary',\r\n  },\r\n})\r\n```\r\n\r\n### Default mappings\r\n\r\nIf you omit `gcmMappings`, the following defaults are used:\r\n\r\n```ts\r\n{\r\n  ad_storage: 'marketing',\r\n  analytics_storage: 'analytics',\r\n  ad_user_data: 'marketing',\r\n  ad_personalization: 'marketing',\r\n}\r\n```\r\n\r\n## Custom Templates\r\n\r\nThe modal UI is built from HTML partials located in `templates/parts/`. The available partials are:\r\n\r\n- `header.html` -- logo and close button area\r\n- `description.html` -- heading, subheading, and body text\r\n- `actions-main.html` -- accept all, reject all, and customize buttons\r\n- `category.html` -- individual category toggle row\r\n- `actions-details.html` -- save choices and back buttons\r\n- `footer.html` -- privacy policy link\r\n- `close.html` -- close button icon\r\n- `decoration.html` -- decorative elements\r\n\r\n## CDN Usage\r\n\r\nLoad the UMD build directly from a CDN. No bundler required.\r\n\r\n### jsdelivr\r\n\r\n```html\r\n<script src=\"https://cdn.jsdelivr.net/npm/@analytics-debugger/consent-modal/dist/dta-cm.umd.js\"></script>\r\n<script>\r\n  var modal = ConsentModal.createConsentModal({\r\n    categories: [\r\n      { key: 'necessary', label: 'Essential', description: 'Required.', locked: true, default: true },\r\n      { key: 'analytics', label: 'Analytics', description: 'Usage data.' },\r\n    ],\r\n    privacyPolicyUrl: '/privacy',\r\n  })\r\n</script>\r\n```\r\n\r\n### unpkg\r\n\r\n```html\r\n<script src=\"https://unpkg.com/@analytics-debugger/consent-modal/dist/dta-cm.umd.js\"></script>\r\n```\r\n\r\n## Google Tag Manager Integration\r\n\r\nWhen using the consent modal with GTM, consent defaults must fire **before** GTM loads. The recommended approach is a two-part setup:\r\n\r\n### Step 1: Inline consent defaults (before GTM snippet)\r\n\r\nAdd this script in the `<head>` **before** your GTM container snippet. This ensures all tags start in a denied state, and any previously saved consent is applied immediately.\r\n\r\n```html\r\n<script>\r\nwindow.dataLayer=window.dataLayer||[];\r\nfunction gtag(){dataLayer.push(arguments)}\r\ngtag('consent','default',{\r\n  ad_storage:'denied',\r\n  analytics_storage:'denied',\r\n  ad_user_data:'denied',\r\n  ad_personalization:'denied',\r\n  wait_for_update:500\r\n});\r\nvar m=document.cookie.match(/(?:^|; )my_consent=([^;]*)/);\r\nif(m){try{var c=JSON.parse(decodeURIComponent(m[1]));\r\ngtag('consent','update',{\r\n  ad_storage:c.marketing?'granted':'denied',\r\n  analytics_storage:c.analytics?'granted':'denied',\r\n  ad_user_data:c.marketing?'granted':'denied',\r\n  ad_personalization:c.marketing?'granted':'denied'\r\n})}catch(e){}}\r\n</script>\r\n<!-- GTM snippet goes here -->\r\n```\r\n\r\nReplace `my_consent` with your `cookieName` value, and adjust the category key mappings (`c.marketing`, `c.analytics`) to match your configuration.\r\n\r\n### Step 2: Load the modal via GTM Custom HTML tag\r\n\r\nCreate a Custom HTML tag in GTM that fires on All Pages with high priority:\r\n\r\n```html\r\n<script>\r\n(function(){\r\n  var s = document.createElement('script');\r\n  s.src = 'https://cdn.jsdelivr.net/npm/@analytics-debugger/consent-modal/dist/dta-cm.umd.js';\r\n  s.onload = function(){\r\n    ConsentModal.createConsentModal({\r\n      categories: [\r\n        { key: 'necessary', label: 'Essential', emoji: '\\ud83d\\udee1\\ufe0f', description: 'Required for the site to work.', locked: true, default: true },\r\n        { key: 'analytics', label: 'Analytics', emoji: '\\ud83d\\udcca', description: 'Helps us improve the site.', sublabel: 'Performance' },\r\n        { key: 'marketing', label: 'Marketing', emoji: '\\ud83c\\udfaf', description: 'Personalized advertising.', sublabel: 'Targeting' }\r\n      ],\r\n      cookieName: 'my_consent',\r\n      privacyPolicyUrl: '/privacy',\r\n      accentColor: '#c6ff00',\r\n      autoShow: true\r\n    });\r\n  };\r\n  document.head.appendChild(s);\r\n})();\r\n</script>\r\n```\r\n\r\nThe library handles `consent update` calls automatically when the user interacts with the modal. GTM tags configured with consent checks will fire or hold based on the current state.\r\n\r\n### How it works\r\n\r\n1. Page loads, inline script sets `consent default` to `denied` for all storage types\r\n2. If a saved cookie exists, the inline script immediately fires `consent update` with the saved preferences\r\n3. GTM loads and checks consent state -- tags that require consent will wait\r\n4. The consent modal library loads and shows the modal to first-time visitors\r\n5. When the user makes a choice, the library fires `consent update` and GTM tags respond accordingly\r\n\r\n## API Reference\r\n\r\n`createConsentModal(options)` returns an instance with the following methods:\r\n\r\n### `modal.show()`\r\n\r\nOpens the consent modal (main view).\r\n\r\n### `modal.showSettings()`\r\n\r\nOpens the consent modal directly to the settings/customization panel.\r\n\r\n### `modal.hide()`\r\n\r\nCloses the modal with a transition animation.\r\n\r\n### `modal.getState()`\r\n\r\nReturns the current consent state as a plain object.\r\n\r\n```ts\r\nmodal.getState()\r\n// { necessary: true, analytics: false, marketing: false }\r\n```\r\n\r\n### `modal.isGranted(key)`\r\n\r\nReturns `true` if the given category is currently granted.\r\n\r\n```ts\r\nmodal.isGranted('analytics') // false\r\n```\r\n\r\n### `modal.setLocale(locale)`\r\n\r\nChanges the active locale. If the modal is currently rendered, it will be destroyed and rebuilt on the next `show()` call.\r\n\r\n### `modal.getLocale()`\r\n\r\nReturns the current locale string.\r\n\r\n### `modal.destroy()`\r\n\r\nRemoves the modal from the DOM and cleans up event listeners.\r\n\r\n## Events\r\n\r\nYou can open the modal from anywhere in your application by dispatching custom events on `window`:\r\n\r\n```js\r\n// Open the main consent view\r\nwindow.dispatchEvent(new Event('consent-modal:open'))\r\n\r\n// Open the settings/customization view directly\r\nwindow.dispatchEvent(new Event('consent-modal:settings'))\r\n```\r\n\r\nThis is useful for \"Manage cookies\" links in footers or settings pages:\r\n\r\n```html\r\n<a href=\"#\" onclick=\"window.dispatchEvent(new Event('consent-modal:settings')); return false;\">\r\n  Manage cookie preferences\r\n</a>\r\n```\r\n\r\n## Cookie Format\r\n\r\nThe consent cookie is stored as JSON with the following shape:\r\n\r\n```json\r\n{\r\n  \"necessary\": true,\r\n  \"analytics\": false,\r\n  \"marketing\": false,\r\n  \"created_timestamp\": 1710000000000,\r\n  \"updated_timestamp\": 1710000000000\r\n}\r\n```\r\n\r\nThe `created_timestamp` is set once on first consent. The `updated_timestamp` is refreshed every time the user changes their preferences.\r\n\r\n## Browser Support\r\n\r\nWorks in all modern browsers (Chrome, Firefox, Safari, Edge). Shadow DOM is required -- IE11 is not supported.\r\n\r\n## License\r\n\r\nMIT -- Copyright (c) 2026 Analytics Debugger S.L.U.\r\n","readmeFilename":"README.md"}