cookiebanner-finally
Version:
Headless cookie banner library for Next.js with shadcn philosophy
2 lines • 6.9 kB
JavaScript
import {createContext,useState,useEffect,useContext}from'react';import w from'js-cookie';import {jsx,Fragment,jsxs}from'react/jsx-runtime';var A=(n=>(n.Necessary="necessary",n.Preferences="preferences",n.Analytics="analytics",n.Marketing="marketing",n))(A||{}),u={necessary:true,preferences:false,analytics:false,marketing:false},N={consentRequired:"This content requires consent for {category} cookies.",managePreferences:"Manage Cookie Preferences",loading:"Loading..."};var D="cookie-consent",V={expires:365,path:"/",sameSite:"strict"},g=class{cookieName;cookieOptions;constructor(e=D,t=V){this.cookieName=e,this.cookieOptions=t;}getConsentPreferences(){try{let e=this.getCookieValue();if(!e)return {...u};let t=JSON.parse(e);return {...u,...t,necessary:!0}}catch(e){return console.error("Error parsing consent preferences",e),{...u}}}saveConsentPreferences(e){let r={...this.getConsentPreferences(),...e,necessary:true,lastUpdated:new Date().toISOString()};try{this.setCookieValue(JSON.stringify(r));}catch(n){console.error("Error saving consent preferences",n);}return r}hasConsent(e){return this.getConsentPreferences()[e]===true}acceptAll(){return this.saveConsentPreferences({necessary:true,preferences:true,analytics:true,marketing:true})}denyAll(){return this.saveConsentPreferences({necessary:true,preferences:false,analytics:false,marketing:false})}hasConsentBeenGiven(){try{return this.getCookieValue()!==null}catch{return false}}getCookieValue(){return typeof window<"u"&&typeof document<"u"&&w.get(this.cookieName)||null}setCookieValue(e){typeof window<"u"&&typeof document<"u"&&w.set(this.cookieName,e,this.cookieOptions);}},E=new g;var R=createContext({preferences:u,isConsentGiven:false,showBanner:false,acceptAll:()=>{},denyAll:()=>{},updatePreferences:()=>{},closeBanner:()=>{},resetBanner:()=>{},hasConsentFor:()=>false}),K=({children:o,cookieName:e,cookieExpires:t,initialPreferences:r,autoShowBanner:n=true})=>{let[s]=useState(()=>e||t?new g(e,t?{expires:t,path:"/",sameSite:"strict"}:void 0):E),[c,f]=useState(u),[a,i]=useState(false),[v,C]=useState(false),[L,M]=useState(false);useEffect(()=>{let l=s.hasConsentBeenGiven();r&&!l&&s.saveConsentPreferences(r);let b=s.getConsentPreferences();f(b),i(l),C(n&&!l),M(true);},[s,r,n]);let G=()=>{let l=s.acceptAll();f(l),i(true),C(false);},O=()=>{let l=s.denyAll();f(l),i(true),C(false);},F=(l,b=false)=>{let I=s.saveConsentPreferences(l);f(I),i(true),b&&C(false);},T=()=>{C(false);},U=()=>{C(true);},_=l=>s.hasConsent(l);return L?jsx(R.Provider,{value:{preferences:c,isConsentGiven:a,showBanner:v,acceptAll:G,denyAll:O,updatePreferences:F,closeBanner:T,resetBanner:U,hasConsentFor:_},children:o}):jsx(Fragment,{children:o})},p=()=>{let o=useContext(R);if(o===void 0)throw new Error("useConsentContext must be used within a ConsentProvider");return o};function z(){let{showBanner:o,isConsentGiven:e,acceptAll:t,denyAll:r,closeBanner:n,resetBanner:s}=p();return {isVisible:o,isConsentGiven:e,acceptAll:t,denyAll:r,close:n,show:s}}function H(){let{preferences:o,updatePreferences:e,hasConsentFor:t}=p(),r=!o||Object.keys(o).length===0;return {preferences:o,isLoading:r,isEnabled:c=>t(c),updatePreferences:e,updateCategory:(c,f)=>{e({[c]:f},false);}}}function x(o){let{hasConsentFor:e,resetBanner:t}=p(),[r,n]=useState(false);return useEffect(()=>{n(true);},[]),{hasConsent:r?e(o):false,isLoading:!r,showConsentPrompt:()=>{t();}}}var P=class{scripts=new Map;loadedScripts=new Set;register(e){if(!e.id)throw new Error("Script ID is required");if(!e.category)throw new Error("Script category is required");if(!e.src&&!e.content)throw new Error("Either src or content is required");this.scripts.set(e.id,e);}registerBatch(e){e.forEach(t=>this.register(t));}loadScript(e,t){let r=this.scripts.get(e);return r?this.loadedScripts.has(e)?Promise.resolve(true):t?new Promise(n=>{r.src?this.loadExternalScript(r,()=>{this.loadedScripts.add(e),n(true);}):r.content&&(this.loadInlineScript(r),this.loadedScripts.add(e),n(true));}):Promise.resolve(false):(console.error(`Script with ID ${e} not found`),Promise.resolve(false))}loadScriptsByCategory(e,t){let r=Array.from(this.scripts.values()).filter(n=>n.category===e);return Promise.all(r.map(n=>this.loadScript(n.id,t)))}isLoaded(e){return this.loadedScripts.has(e)}getAllScripts(){return Array.from(this.scripts.values())}getScriptsByCategory(e){return Array.from(this.scripts.values()).filter(t=>t.category===e)}loadExternalScript(e,t){if(typeof document>"u")return;let r=document.createElement("script");e.src&&(r.src=e.src),e.attributes&&Object.entries(e.attributes).forEach(([n,s])=>{r.setAttribute(n,s);}),r.onload=t,r.onerror=n=>{console.error(`Failed to load script: ${e.id}`,n),t();},document.head.appendChild(r);}loadInlineScript(e){if(typeof document>"u"||!e.content)return;let t=document.createElement("script");t.text=e.content,e.attributes&&Object.entries(e.attributes).forEach(([r,n])=>{t.setAttribute(r,n);});try{document.head.appendChild(t);}catch(r){console.error(`Error executing inline script: ${e.id}`,r);}}},d=new P;function h(){let{hasConsentFor:o}=p(),[e,t]=useState(false);return useEffect(()=>{t(true);},[]),{register:a=>{e&&d.register(a);},registerBatch:a=>{e&&d.registerBatch(a);},load:async a=>{if(!e)return false;let i=d.getAllScripts().find(C=>C.id===a);if(!i)return console.error(`Script with ID ${a} not found`),false;let v=o(i.category);return d.loadScript(a,v)},loadCategory:a=>{if(!e)return Promise.resolve([]);let i=o(a);return d.loadScriptsByCategory(a,i)},isLoaded:a=>e?d.isLoaded(a):false}}var Z=({children:o,category:e,fallback:t,loading:r,showPromptOnClick:n=true,messages:s={}})=>{let{hasConsent:c,isLoading:f,showConsentPrompt:a}=x(e),i={...N,...s};return f?r?jsx(Fragment,{children:r}):jsx("div",{children:i.loading}):c?jsx(Fragment,{children:o}):t?jsx(Fragment,{children:t}):jsxs("div",{className:"cookie-consent-gate-fallback",children:[jsx("p",{children:i.consentRequired?.replace("{category}",e)}),n&&jsx("button",{onClick:a,className:"cookie-consent-gate-button",children:i.managePreferences})]})};var te=({script:o,onLoad:e,autoLoad:t=true})=>{let{register:r,load:n,isLoaded:s}=h();return useEffect(()=>{r(o);},[r,o]),useEffect(()=>{t&&n(o.id).then(c=>{c&&e&&e();});},[n,o.id,t,e]),null},re=({scripts:o,onLoad:e,autoLoad:t=true})=>{let{registerBatch:r,load:n}=h();return useEffect(()=>{r(o);},[r,o]),useEffect(()=>{t&&Promise.all(o.map(s=>n(s.id))).then(s=>{s.every(Boolean)&&e&&e();});},[n,o,t,e]),null};export{A as ConsentCategory,Z as ConsentGate,K as ConsentProvider,g as CookieManager,N as DEFAULT_CONSENT_GATE_MESSAGES,u as DEFAULT_CONSENT_PREFERENCES,re as ScriptBatchLoader,te as ScriptLoader,P as ScriptManager,E as cookieManager,d as scriptManager,p as useConsentContext,x as useConsentGate,z as useCookieBanner,H as useCookiePreferences,h as useScriptLoader};//# sourceMappingURL=index.js.map
//# sourceMappingURL=index.js.map