{"_id":"@bulut5/ck","_rev":"10-623b9e19b98c2fbf0295e458ab9d75c5","name":"@bulut5/ck","dist-tags":{"latest":"0.6.0"},"versions":{"0.1.0":{"name":"@bulut5/ck","version":"0.1.0","license":"MIT","_id":"@bulut5/ck@0.1.0","maintainers":[{"name":"bulut5","email":"konton@omtago.se"}],"dist":{"shasum":"4d43b9f5c5683b34e6a8cd3af0813f924373ff45","tarball":"https://registry.npmjs.org/@bulut5/ck/-/ck-0.1.0.tgz","fileCount":4,"integrity":"sha512-2pT6u2BxQR7Xu62cfiQyoRnoEKYUvq/1n7isvW+AMLiUmtI3JnE412aueu2lk7h4W2YHLZdROaZOoKKFd6RIDg==","signatures":[{"sig":"MEQCIBMMjUhZhhA+gurubENv7ZuO5R4ySce7M3A4c8lSMYbVAiB+UhqrBjAis3D3egeuvtZpwM4zt2e7r9FX0R3S2wdDuA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":9970},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"bd4da91d1a79b65cb85bd2b2ea1bc84888a35060","scripts":{"dev":"tsup --watch","build":"tsup","typecheck":"tsc --noEmit","prepublishOnly":"tsup"},"_npmUser":{"name":"bulut5","email":"konton@omtago.se"},"_npmVersion":"10.9.0","description":"Lightweight cookie-consent banner with Google Consent Mode v2 + Microsoft UET signaling for React.","directories":{},"sideEffects":false,"_nodeVersion":"22.12.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.0","react":"^18.3.1","react-dom":"^18.3.1","typescript":"^5.5.0","@types/react":"^18.3.3"},"peerDependencies":{"react":">=18","react-dom":">=18"},"_npmOperationalInternal":{"tmp":"tmp/ck_0.1.0_1782247168471_0.17119954361957368","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@bulut5/ck","version":"0.2.0","license":"MIT","_id":"@bulut5/ck@0.2.0","maintainers":[{"name":"omtago","email":"konton@omtago.se"}],"dist":{"shasum":"c762ea845fdd3be121f697774f82acf9428007d7","tarball":"https://registry.npmjs.org/@bulut5/ck/-/ck-0.2.0.tgz","fileCount":4,"integrity":"sha512-fo5RksE/QqU1g3wTcmo1Nr/FT8NoVFuYIA/WSXvgA5QwO+SDXnxWapD52bxBq5vxDxFEOJdwdbqn0v3WOnRwDA==","signatures":[{"sig":"MEQCIErKCWtB0l8eH5pKuMDu+PbnHliUyBBjj3JNvlim6SXhAiB7xvw4uId3tDFUepmySZ32yk0V73fcO+GjIOdU5bMpqQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":10601},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"b0dcb3a98207c0a9ea8def42e6801509a8c49a2f","scripts":{"dev":"tsup --watch","build":"tsup","typecheck":"tsc --noEmit","prepublishOnly":"tsup"},"_npmUser":{"name":"omtago","email":"konton@omtago.se"},"_npmVersion":"10.9.0","description":"Lightweight cookie-consent banner with Google Consent Mode v2 + Microsoft UET signaling for React.","directories":{},"sideEffects":false,"_nodeVersion":"22.12.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.0","react":"^18.3.1","react-dom":"^18.3.1","typescript":"^5.5.0","@types/react":"^18.3.3"},"peerDependencies":{"react":">=18","react-dom":">=18"},"_npmOperationalInternal":{"tmp":"tmp/ck_0.2.0_1782294415163_0.9477547966592337","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"@bulut5/ck","version":"0.3.0","license":"MIT","_id":"@bulut5/ck@0.3.0","maintainers":[{"name":"omtago","email":"konton@omtago.se"}],"dist":{"shasum":"e2520e7b854b95f72718e8f91bbb5aa8ddb2a624","tarball":"https://registry.npmjs.org/@bulut5/ck/-/ck-0.3.0.tgz","fileCount":4,"integrity":"sha512-LxDfkD0XYW3HfYireucYraJJGgNt+CilPMcouy2EkUYhlm7S+6jIzOnDnP0EWyyS0rXjHRsZizxcdSATG7nJvw==","signatures":[{"sig":"MEUCIHAfVO0wKp6gmIU/230RkERReOzbu7puzRj4NxI1IjrcAiEAstaW1Ls3VnfiyiM99poTy1MGZoKf+YGFtV14gNZsA4I=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":13970},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"08d483ca7e91020f84fd0a75879eba4b49a9c2ce","scripts":{"dev":"tsup --watch","build":"tsup","typecheck":"tsc --noEmit","prepublishOnly":"tsup"},"_npmUser":{"name":"omtago","email":"konton@omtago.se"},"_npmVersion":"10.9.0","description":"Lightweight cookie-consent banner with Google Consent Mode v2 + Microsoft UET signaling for React.","directories":{},"sideEffects":false,"_nodeVersion":"22.12.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.0","react":"^18.3.1","react-dom":"^18.3.1","typescript":"^5.5.0","@types/react":"^18.3.3"},"peerDependencies":{"react":">=18","react-dom":">=18"},"_npmOperationalInternal":{"tmp":"tmp/ck_0.3.0_1785501189956_0.8163369126140807","host":"s3://npm-registry-packages-npm-production"}},"0.4.1":{"name":"@bulut5/ck","version":"0.4.1","license":"MIT","_id":"@bulut5/ck@0.4.1","maintainers":[{"name":"omtago","email":"konton@omtago.se"}],"dist":{"shasum":"dfba0ff3abbc3c9976ff14f00ac2a00101ce0046","tarball":"https://registry.npmjs.org/@bulut5/ck/-/ck-0.4.1.tgz","fileCount":4,"integrity":"sha512-/OEipIU7JyojlRABr75/yXxkBwuTuCO5C41mUiRlxh3N/RRjgSvjF5hPTAopAb8ZufY0+UTrwP3paU5HsJP+xQ==","signatures":[{"sig":"MEUCIQCYViWOkTKebbmoEZrsZDwc8KWdH3sodzASvmoa48yv8AIgS9WjufnWxsTSoBizBYH3C+iWy/X05OQNjA0e10IqJz8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":17437},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"08d483ca7e91020f84fd0a75879eba4b49a9c2ce","scripts":{"dev":"tsup --watch","build":"tsup","typecheck":"tsc --noEmit","prepublishOnly":"tsup"},"_npmUser":{"name":"omtago","email":"konton@omtago.se"},"_npmVersion":"10.9.0","description":"Lightweight cookie-consent banner with Google Consent Mode v2 + Microsoft UET signaling for React.","directories":{},"sideEffects":false,"_nodeVersion":"22.12.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.0","react":"^18.3.1","react-dom":"^18.3.1","typescript":"^5.5.0","@types/react":"^18.3.3"},"peerDependencies":{"react":">=18","react-dom":">=18"},"_npmOperationalInternal":{"tmp":"tmp/ck_0.4.1_1785786283650_0.11089490856337725","host":"s3://npm-registry-packages-npm-production"}},"0.4.2":{"name":"@bulut5/ck","version":"0.4.2","license":"MIT","_id":"@bulut5/ck@0.4.2","maintainers":[{"name":"omtago","email":"konton@omtago.se"}],"dist":{"shasum":"c6e93e8219a1d497b5573323396f696bfb32e7bb","tarball":"https://registry.npmjs.org/@bulut5/ck/-/ck-0.4.2.tgz","fileCount":4,"integrity":"sha512-xBsNyOxhMzleVGr6gA+D7GKfgQuG85aoBnpBMVdA7mW+JCOwtrz2gIFluUKH7DvP55S0pOi9sOQTDcYBXoUmmQ==","signatures":[{"sig":"MEYCIQDKHlim5MREF7wsDntUL0yWzB21NAVffCYj8w/rvH7dvQIhAIxL9AOJw/Xzv9WtSXfddaJSrpi0aK/tQct81GVd+0vP","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":17509},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"75e32277a6fdba795847044faae1877b73b1232c","scripts":{"dev":"tsup --watch","build":"tsup","typecheck":"tsc --noEmit","check-leaks":"node scripts/check-leaks.mjs","prepublishOnly":"tsup && node scripts/check-leaks.mjs"},"_npmUser":{"name":"omtago","email":"konton@omtago.se"},"_npmVersion":"10.9.0","description":"Lightweight cookie-consent banner with Google Consent Mode v2 + Microsoft UET signaling for React.","directories":{},"sideEffects":false,"_nodeVersion":"22.12.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.0","react":"^18.3.1","react-dom":"^18.3.1","typescript":"^5.5.0","@types/react":"^18.3.3"},"peerDependencies":{"react":">=18","react-dom":">=18"},"_npmOperationalInternal":{"tmp":"tmp/ck_0.4.2_1787133184876_0.08054540653698372","host":"s3://npm-registry-packages-npm-production"}},"0.5.0":{"name":"@bulut5/ck","version":"0.5.0","license":"MIT","_id":"@bulut5/ck@0.5.0","maintainers":[{"name":"omtago","email":"konton@omtago.se"}],"dist":{"shasum":"9ff8972f237b61cfd984b742b4d63657fc3b4a2d","tarball":"https://registry.npmjs.org/@bulut5/ck/-/ck-0.5.0.tgz","fileCount":5,"integrity":"sha512-zNmNSCGRE+MeLfEHwuFKD9Mp3dNphmymsH3qr+LAhM5rs/Jc11rbQiZ1Es8wp1CLIvBI1w534r/9MG80lkTbsQ==","signatures":[{"sig":"MEUCIFGXMEU+RNSKK81PgfggH1DyjK3X1rQuH0QAwO5IhdtGAiEAoGmAXKxSOWw+ZfuWG4UU4iZb45kuSDma5XTvGY5OCH4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":26453},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./vanilla":"./dist/vanilla.js"},"gitHead":"5629f50ec2b65c015c1a1d96cd667c2951897b5d","scripts":{"dev":"tsup --watch","build":"tsup","typecheck":"tsc --noEmit","check-leaks":"node scripts/check-leaks.mjs","prepublishOnly":"tsup && node scripts/check-leaks.mjs"},"_npmUser":{"name":"omtago","email":"konton@omtago.se"},"_npmVersion":"10.9.0","description":"Lightweight cookie-consent banner with Google Consent Mode v2 + Microsoft UET signaling.","directories":{},"sideEffects":false,"_nodeVersion":"22.12.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.0","react":"^18.3.1","react-dom":"^18.3.1","typescript":"^5.5.0","@types/react":"^18.3.3"},"peerDependencies":{"react":">=18","react-dom":">=18"},"_npmOperationalInternal":{"tmp":"tmp/ck_0.5.0_1787135756785_0.3836266270041664","host":"s3://npm-registry-packages-npm-production"}},"0.6.0":{"name":"@bulut5/ck","version":"0.6.0","description":"Lightweight cookie-consent banner with Google Consent Mode v2 + Microsoft UET signaling.","license":"MIT","type":"module","main":"./dist/index.js","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./vanilla":"./dist/vanilla.js"},"sideEffects":false,"publishConfig":{"access":"public"},"scripts":{"build":"tsup","dev":"tsup --watch","typecheck":"tsc --noEmit","check-leaks":"node scripts/check-leaks.mjs","prepublishOnly":"tsup && node scripts/check-leaks.mjs"},"peerDependencies":{"react":">=18","react-dom":">=18"},"devDependencies":{"@types/react":"^18.3.3","react":"^18.3.1","react-dom":"^18.3.1","tsup":"^8.3.0","typescript":"^5.5.0"},"_id":"@bulut5/ck@0.6.0","gitHead":"dd9aeb7ba5b8704d249aff3204b9f85e53021335","_nodeVersion":"22.12.0","_npmVersion":"10.9.0","dist":{"integrity":"sha512-/q8OfDFt59gWncE6evLcPftyL5jM2jNM10ZCDKYCULyzrl/u/KbnQenICXuho7Qd5RC+FXrLJr9k5rrbt1PVrQ==","shasum":"b0ceb9144b86e33204cda7e7a0eb15cf2762e6c2","tarball":"https://registry.npmjs.org/@bulut5/ck/-/ck-0.6.0.tgz","fileCount":5,"unpackedSize":30781,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIH8l/6UAgNcvK0vZVuAeDxqtRF7rxTjNnQtg7eE/0zXkAiButAMCNRuyy71MEOl5E1XsNfkvtGj5bNUojmsZMrao3w=="}]},"_npmUser":{"name":"omtago","email":"konton@omtago.se"},"directories":{},"maintainers":[{"name":"omtago","email":"konton@omtago.se"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/ck_0.6.0_1788348355668_0.14415702576273026"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-23T20:39:28.268Z","modified":"2026-09-02T11:25:56.050Z","0.1.0":"2026-06-23T20:39:28.607Z","0.2.0":"2026-06-24T09:46:55.293Z","0.3.0":"2026-07-31T12:33:10.089Z","0.4.0":"2026-08-03T19:38:50.802Z","0.4.1":"2026-08-03T19:44:43.813Z","0.4.2":"2026-08-19T09:53:05.020Z","0.5.0":"2026-08-19T10:35:56.924Z","0.6.0":"2026-09-02T11:25:55.831Z"},"license":"MIT","description":"Lightweight cookie-consent banner with Google Consent Mode v2 + Microsoft UET signaling.","maintainers":[{"name":"omtago","email":"konton@omtago.se"}],"readme":"# ck\r\n\r\nA lightweight, dependency-free cookie-consent banner for React that signals\r\n[Google Consent Mode v2](https://developers.google.com/tag-platform/security/guides/consent)\r\nand Microsoft UET. Default-deny, granular categories, SSR-safe, themeable with Tailwind.\r\n\r\n## Install\r\n\r\n```sh\r\nnpm i @bulut5/ck\r\n```\r\n\r\n## Usage\r\n\r\n```tsx\r\nimport { ConsentProvider, CookieConsent } from \"@bulut5/ck\";\r\n\r\nconst config = {\r\n  brand: \"example\",\r\n  locale: \"en-GB\",\r\n  privacyPolicyUrl: \"/privacy\",\r\n  copy: { /* … see BrandConfig */ },\r\n};\r\n\r\nexport default function App() {\r\n  return (\r\n    <ConsentProvider config={config}>\r\n      {/* your app */}\r\n      <CookieConsent />\r\n    </ConsentProvider>\r\n  );\r\n}\r\n```\r\n\r\n## Prompt timing and appearance\r\n\r\nBy default the card opens on mount for an undecided visitor. Two options change when and how\r\nit appears, without changing what it asks or how the decision is stored.\r\n\r\n```tsx\r\nexport const consentConfig: BrandConfig = {\r\n  // ...\r\n  prompt: \"onInteraction\",   // \"immediate\" (default) | \"onInteraction\" | \"manual\"\r\n};\r\n\r\n<CookieConsent appearance=\"strip\" />   // \"card\" (default) | \"strip\"\r\n```\r\n\r\n`prompt`\r\n\r\n- `immediate` — on mount, as before.\r\n- `onInteraction` — 400 ms after the visitor's first pointer, key or scroll input, so it never\r\n  lands under the finger that just tapped. Consent Mode stays at its default until the decision.\r\n- `manual` — never opens by itself. The page calls `reopen()` from `useConsent()` when it wants\r\n  the prompt.\r\n\r\nIn every mode the floating badge is rendered whenever the prompt is not showing, so settings\r\nare always one tap away.\r\n\r\n`appearance`\r\n\r\n- `card` — the bottom-right card.\r\n- `strip` — one full-width bar along the bottom: body, policy link, Accept, Reject and Select.\r\n  Reject keeps the same size and weight as Accept. Select opens the card for the category view.\r\n\r\n## Sharing one decision across subdomains\r\n\r\nBy default the decision is stored in `localStorage`, which is scoped to the **origin** — so\r\n`www.example.com` and `lp.example.com` never share it, and a visitor moving between them is\r\nasked twice. When one brand spans several hosts, set `storage.cookieDomain` and the record\r\nmoves to a cookie scoped to that domain:\r\n\r\n```tsx\r\nexport const consentConfig: BrandConfig = {\r\n  brand: \"example\",\r\n  locale: \"en-GB\",\r\n  privacyPolicyUrl: \"https://www.example.com/privacy-policy\",\r\n  storage: { cookieDomain: \".example.com\" },   // leading dot optional\r\n  copy: copyForLocale(\"en-GB\"),\r\n};\r\n```\r\n\r\nCookie attributes: `Path=/`, `SameSite=Lax`, `Max-Age` from `storage.cookieMaxAgeDays`\r\n(default 180), and `Secure` on https (omitted on http so localhost still works). A cookie is\r\nthe only mechanism browsers offer here — the old iframe + `postMessage` trick is broken by\r\nSafari ITP and Chrome's storage partitioning.\r\n\r\nTwo things to know:\r\n\r\n- **`cookieDomain` must be a domain the page can set a cookie for** — a parent of the current\r\n  host, and not a public suffix. Browsers silently drop cookies that violate this, so a wrong\r\n  value degrades to \"no consent is ever remembered\" rather than to an error. Verify in\r\n  DevTools → Application → Cookies after the first deploy.\r\n- **Switching an existing site to a cookie re-prompts its current visitors once.** There is\r\n  deliberately no localStorage→cookie migration: a stale per-origin record would defeat the\r\n  point of sharing. Every property on the shared domain should be switched together.\r\n\r\nThe consent record is itself strictly necessary, so storing it needs no consent.\r\n\r\n## Locale presets\r\n\r\n`copy` can come from a bundled preset instead of being written out per site. Presets ship for\r\n`en-GB` and `sv-SE`. They are **deliberately generic** — plain, voiceless boilerplate meant as a\r\nlawful starting point, not finished copy. Expect to override them for your own voice:\r\n\r\n```tsx\r\nimport { copyForLocale, SV_SE_COPY, type BrandConfig } from \"@bulut5/ck\";\r\n\r\nexport const consentConfig: BrandConfig = {\r\n  brand: \"example\",\r\n  locale: \"sv-SE\",\r\n  privacyPolicyUrl: \"https://example.com/integritetspolicy/\",\r\n  copy: SV_SE_COPY,               // or: copyForLocale(\"sv-SE\")\r\n};\r\n```\r\n\r\n`copyForLocale` falls back to the bare language (`sv-FI` → `sv-SE`) and then to `en-GB`, so an\r\nunknown tag still renders a banner. Override wholesale, or spread over a preset to change only\r\nsome strings: `copy: { ...SV_SE_COPY, body: \"…your wording…\" }`.\r\n\r\nWhatever you override, keep reject worded exactly as plainly as accept — ICO/PECR and IMY both\r\nrequire equal prominence.\r\n\r\nThe host page should set the Google Consent Mode default to `denied` inline in `<head>` before\r\nthe bundle loads; the banner flips signals to `granted` on consent. Tailwind consumers should add\r\n`./node_modules/@bulut5/ck/dist/**/*.{js,mjs}` to their `content` so the banner classes compile.\r\n\r\nMIT licensed.\r\n","readmeFilename":"README.md"}