@freshjuice/zest 0.1.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +46 -0
- package/dist/zest.de.js +104 -1
- package/dist/zest.de.js.map +1 -1
- package/dist/zest.de.min.js +1 -1
- package/dist/zest.en.js +104 -1
- package/dist/zest.en.js.map +1 -1
- package/dist/zest.en.min.js +1 -1
- package/dist/zest.es.js +104 -1
- package/dist/zest.es.js.map +1 -1
- package/dist/zest.es.min.js +1 -1
- package/dist/zest.esm.js +104 -1
- package/dist/zest.esm.js.map +1 -1
- package/dist/zest.esm.min.js +1 -1
- package/dist/zest.fr.js +104 -1
- package/dist/zest.fr.js.map +1 -1
- package/dist/zest.fr.min.js +1 -1
- package/dist/zest.it.js +104 -1
- package/dist/zest.it.js.map +1 -1
- package/dist/zest.it.min.js +1 -1
- package/dist/zest.ja.js +104 -1
- package/dist/zest.ja.js.map +1 -1
- package/dist/zest.ja.min.js +1 -1
- package/dist/zest.js +104 -1
- package/dist/zest.js.map +1 -1
- package/dist/zest.min.js +1 -1
- package/dist/zest.nl.js +104 -1
- package/dist/zest.nl.js.map +1 -1
- package/dist/zest.nl.min.js +1 -1
- package/dist/zest.pl.js +104 -1
- package/dist/zest.pl.js.map +1 -1
- package/dist/zest.pl.min.js +1 -1
- package/dist/zest.pt.js +104 -1
- package/dist/zest.pt.js.map +1 -1
- package/dist/zest.pt.min.js +1 -1
- package/dist/zest.ru.js +104 -1
- package/dist/zest.ru.js.map +1 -1
- package/dist/zest.ru.min.js +1 -1
- package/dist/zest.uk.js +104 -1
- package/dist/zest.uk.js.map +1 -1
- package/dist/zest.uk.min.js +1 -1
- package/dist/zest.zh.js +104 -1
- package/dist/zest.zh.js.map +1 -1
- package/dist/zest.zh.min.js +1 -1
- package/package.json +5 -4
- package/src/api/public-api.js +97 -0
- package/src/config/defaults.js +150 -0
- package/src/config/parser.js +104 -0
- package/src/core/categories.js +52 -0
- package/src/core/cookie-interceptor.js +116 -0
- package/src/core/dnt.js +56 -0
- package/src/core/known-trackers.js +168 -0
- package/src/core/pattern-matcher.js +96 -0
- package/src/core/script-blocker.js +308 -0
- package/src/core/storage-interceptor.js +169 -0
- package/src/i18n/lang-en.js +54 -0
- package/src/i18n/single/lang-de.js +55 -0
- package/src/i18n/single/lang-en.js +55 -0
- package/src/i18n/single/lang-es.js +55 -0
- package/src/i18n/single/lang-fr.js +55 -0
- package/src/i18n/single/lang-it.js +55 -0
- package/src/i18n/single/lang-ja.js +55 -0
- package/src/i18n/single/lang-nl.js +55 -0
- package/src/i18n/single/lang-pl.js +55 -0
- package/src/i18n/single/lang-pt.js +55 -0
- package/src/i18n/single/lang-ru.js +55 -0
- package/src/i18n/single/lang-uk.js +55 -0
- package/src/i18n/single/lang-zh.js +55 -0
- package/src/i18n/translations.js +546 -0
- package/src/index.js +377 -0
- package/src/integrations/consent-signals.js +71 -0
- package/src/storage/consent-store.js +177 -0
- package/src/storage/events.js +84 -0
- package/src/ui/banner.js +130 -0
- package/src/ui/modal.js +211 -0
- package/src/ui/styles.js +498 -0
- package/src/ui/widget.js +103 -0
package/dist/zest.nl.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var Zest=function(){"use strict";const e={essential:[/^zest_/,/^csrf/i,/^xsrf/i,/^session/i,/^__host-/i,/^__secure-/i],functional:[/^lang/i,/^locale/i,/^theme/i,/^preferences/i,/^ui_/i],analytics:[/^_ga/,/^_gid/,/^_gat/,/^_utm/,/^__utm/,/^plausible/i,/^_pk_/,/^matomo/i,/^_hj/,/^ajs_/],marketing:[/^_fbp/,/^_fbc/,/^_gcl/,/^_ttp/,/^ads/i,/^doubleclick/i,/^__gads/,/^__gpi/,/^_pin_/,/^li_/]};let t={...e};function n(e){for(const[n,o]of Object.entries(t))if(o.some(t=>t.test(e)))return n;return"marketing"}let o=null;const a=[];let s=()=>!1;function r(){return o}let i=null,c=null;const l=[],d=[];let u=()=>!1;function p(e,t,o){return new Proxy(e,{get(e,o){if("setItem"===o)return(o,a)=>{const s=n(o);u(s)?e.setItem(o,a):t.push({key:o,value:a,category:s,timestamp:Date.now()})};const a=e[o];return"function"==typeof a?a.bind(e):a}})}const g={analytics:["google-analytics.com","www.google-analytics.com","analytics.google.com","googletagmanager.com","www.googletagmanager.com","plausible.io","cloudflareinsights.com","static.cloudflareinsights.com"],marketing:["connect.facebook.net","www.facebook.com/tr","ads.google.com","www.googleadservices.com","googleads.g.doubleclick.net","pagead2.googlesyndication.com"]},m={analytics:[...g.analytics,"analytics.tiktok.com","matomo.","hotjar.com","static.hotjar.com","script.hotjar.com","clarity.ms","www.clarity.ms","heapanalytics.com","cdn.heapanalytics.com","mixpanel.com","cdn.mxpnl.com","segment.com","cdn.segment.com","api.segment.io","fullstory.com","rs.fullstory.com","amplitude.com","cdn.amplitude.com","mouseflow.com","cdn.mouseflow.com","luckyorange.com","cdn.luckyorange.net","crazyegg.com","script.crazyegg.com"],marketing:[...g.marketing,"snap.licdn.com","px.ads.linkedin.com","ads.linkedin.com","analytics.twitter.com","static.ads-twitter.com","t.co","analytics.tiktok.com","ads.tiktok.com","sc-static.net","tr.snapchat.com","ct.pinterest.com","pintrk.com","s.pinimg.com","widgets.pinterest.com","bat.bing.com","ads.yahoo.com","sp.analytics.yahoo.com","amazon-adsystem.com","z-na.amazon-adsystem.com","criteo.com","static.criteo.net","dis.criteo.com","taboola.com","cdn.taboola.com","trc.taboola.com","outbrain.com","widgets.outbrain.com","adroll.com","s.adroll.com"],functional:["cdn.onesignal.com","onesignal.com","pusher.com","js.pusher.com","intercom.io","widget.intercom.io","js.intercomcdn.com","crisp.chat","client.crisp.chat","cdn.livechatinc.com","livechatinc.com","tawk.to","embed.tawk.to","zendesk.com","static.zdassets.com"]};function f(e,t){try{const n=new URL(e).hostname.toLowerCase(),o=e.toLowerCase();for(const e of t)if(e.endsWith(".")){if(n.includes(e.slice(0,-1)))return!0}else{if(n===e||n.endsWith("."+e))return!0;if(o.includes(e))return!0}}catch(e){}return!1}function b(e,t="safe"){const n="strict"===t?m:g;for(const[t,o]of Object.entries(n))if(f(e,o))return t;return null}const h=[];let y=null,z="safe",x=[],w=()=>!1;function v(e){const t=e.getAttribute("data-consent-category");if(t)return t;if(e.hasAttribute("data-zest-allow"))return null;const n=e.src;if(!n)return null;const o=function(e){if(!e||0===x.length)return null;try{const t=new URL(e).hostname.toLowerCase();for(const e of x){const n="string"==typeof e?e:e.domain,o="string"==typeof e?"marketing":e.category||"marketing";if(t===n||t.endsWith("."+n))return o}}catch(e){}return null}(n);if(o)return o;switch(z){case"manual":default:return null;case"safe":case"strict":return b(n,z);case"doomsday":return function(e){try{const t=new URL(e).hostname,n=window.location.hostname,o=e=>e.replace(/^www\./,"");return o(t)!==o(n)}catch(e){return!1}}(n)?b(n,"strict")||"marketing":null}}function k(e){if(e.hasAttribute("data-zest-processed"))return!1;const t=v(e);if(!t)return e.setAttribute("data-zest-processed","allowed"),!1;if(w(t))return e.setAttribute("data-zest-processed","allowed"),!1;const n={category:t,src:e.src,inline:e.textContent,type:e.type,async:e.async,defer:e.defer,timestamp:Date.now()};return e.setAttribute("data-zest-processed","blocked"),e.setAttribute("data-consent-category",t),e.type="text/plain",e.src&&(e.setAttribute("data-blocked-src",e.src),e.removeAttribute("src")),h.push(n),!0}function _(e){const t=document.createElement("script");e.src?t.src=e.src:e.inline&&(t.textContent=e.inline),e.async&&(t.async=!0),e.defer&&(t.defer=!0),t.setAttribute("data-zest-processed","executed"),t.setAttribute("data-consent-executed","true"),document.head.appendChild(t)}function A(e){for(const t of e)for(const e of t.addedNodes)if("SCRIPT"!==e.nodeName||e.hasAttribute("data-zest-processed")||k(e),e.querySelectorAll){e.querySelectorAll("script:not([data-zest-processed])").forEach(k)}}function C(e="safe",t=[]){return z=e,x=t,document.querySelectorAll("script:not([data-zest-processed])").forEach(k),y=new MutationObserver(A),y.observe(document.documentElement,{childList:!0,subtree:!0}),!0}const j={essential:{id:"essential",label:"Essential",description:"Required for the website to function properly. Cannot be disabled.",required:!0,default:!0},functional:{id:"functional",label:"Functional",description:"Enable personalized features like language preferences and themes.",required:!1,default:!1},analytics:{id:"analytics",label:"Analytics",description:"Help us understand how visitors interact with our website.",required:!1,default:!1},marketing:{id:"marketing",label:"Marketing",description:"Used to deliver relevant advertisements and track campaign performance.",required:!1,default:!1}};function S(){if("undefined"==typeof navigator)return!1;const e=navigator.doNotTrack||window.doNotTrack||navigator.msDoNotTrack;return"1"===e||"yes"===e||!0===e||!0===navigator.globalPrivacyControl}const E={labels:{banner:{title:"Wij respecteren uw privacy",description:'Wij gebruiken cookies om uw browse-ervaring te verbeteren, gepersonaliseerde inhoud aan te bieden en ons verkeer te analyseren. Door op "Alles accepteren" te klikken, stemt u in met het gebruik van cookies.',acceptAll:"Alles accepteren",rejectAll:"Alles weigeren",settings:"Instellingen"},modal:{title:"Privacy-instellingen",description:"Beheer uw cookievoorkeuren. U kunt hieronder verschillende soorten cookies in- of uitschakelen.",save:"Voorkeuren opslaan",acceptAll:"Alles accepteren",rejectAll:"Alles weigeren"},widget:{label:"Cookie-instellingen"}},categories:{essential:{label:"Essentieel",description:"Noodzakelijk voor de goede werking van de website. Kunnen niet worden uitgeschakeld."},functional:{label:"Functioneel",description:"Maken gepersonaliseerde functies mogelijk zoals taal- en themavoorkeuren."},analytics:{label:"Analytisch",description:"Helpen ons te begrijpen hoe bezoekers onze website gebruiken."},marketing:{label:"Marketing",description:"Worden gebruikt om relevante advertenties te tonen en campagneprestaties te meten."}}};const R={lang:"auto",position:"bottom",theme:"auto",accentColor:"#0071e3",categories:j,labels:{banner:{title:"We value your privacy",description:'We use cookies to enhance your browsing experience, serve personalized content, and analyze our traffic. By clicking "Accept All", you consent to our use of cookies.',acceptAll:"Accept All",rejectAll:"Reject All",settings:"Settings"},modal:{title:"Privacy Settings",description:"Manage your cookie preferences. You can enable or disable different types of cookies below.",save:"Save Preferences",acceptAll:"Accept All",rejectAll:"Reject All"},widget:{label:"Cookie Settings"}},autoInit:!0,showWidget:!0,expiration:365,respectDNT:!0,dntBehavior:"reject",customStyles:"",mode:"safe",blockedDomains:[],policyUrl:null,imprintUrl:null,callbacks:{onAccept:null,onReject:null,onChange:null,onReady:null}};function N(e){const t={...R};e||(e={});const n=["lang","position","theme","accentColor","autoInit","showWidget","expiration","policyUrl","imprintUrl","customStyles","mode","blockedDomains","respectDNT","dntBehavior"];for(const o of n)void 0!==e[o]&&(t[o]=e[o]);t.lang="nl";const o=E,a=o.labels||{},s=e.labels||{};t.labels={banner:{...R.labels.banner,...a.banner,...s.banner},modal:{...R.labels.modal,...a.modal,...s.modal},widget:{...R.labels.widget,...a.widget,...s.widget}};const r=o.categories||{},i=e.categories||{};t.categories={...R.categories};for(const e of Object.keys(R.categories))t.categories[e]={...R.categories[e],...r[e],...i[e]};return e.callbacks&&(t.callbacks={...R.callbacks,...e.callbacks}),e.patterns&&(t.patterns=e.patterns),t}function $(){const e="undefined"!=typeof window&&window.ZestConfig?window.ZestConfig:{},t=function(){const e=document.currentScript||document.querySelector("script[data-zest]")||document.querySelector('script[src*="zest"]');if(!e)return{};const t={},n=e.getAttribute("data-position");n&&(t.position=n);const o=e.getAttribute("data-theme");o&&(t.theme=o);const a=e.getAttribute("data-accent")||e.getAttribute("data-accent-color");a&&(t.accentColor=a);const s=e.getAttribute("data-policy-url")||e.getAttribute("data-privacy-url");s&&(t.policyUrl=s);const r=e.getAttribute("data-imprint-url");r&&(t.imprintUrl=r);const i=e.getAttribute("data-show-widget");null!==i&&(t.showWidget="false"!==i);const c=e.getAttribute("data-auto-init");null!==c&&(t.autoInit="false"!==c);const l=e.getAttribute("data-expiration");return l&&(t.expiration=parseInt(l,10)),t}();return N({...e,...t})}let D=null;function T(){return D||(D=$()),D}const O="zest_consent";let q=null;function L(e){const t=r();t?.set?t.set.call(document,e):document.cookie=e}function M(){const e=r();return e?.get?e.get.call(document):document.cookie}function I(){try{const e=M().match(RegExp(O+"=([^;]+)"));if(e){const t=JSON.parse(decodeURIComponent(e[1]));return q=t.categories||{essential:!0,functional:!1,analytics:!1,marketing:!1},{...q}}}catch(e){}return q={essential:!0,functional:!1,analytics:!1,marketing:!1},{...q}}function W(){return q||(q=I()),{...q}}function U(e,t=365){const n=q?{...q}:{essential:!0,functional:!1,analytics:!1,marketing:!1};return q={essential:!0,functional:!!e.functional,analytics:!!e.analytics,marketing:!!e.marketing},function(e=365){q||(q={essential:!0,functional:!1,analytics:!1,marketing:!1});const t={version:"1.0",timestamp:Date.now(),categories:q},n=new Date(Date.now()+24*e*60*60*1e3).toUTCString();L(`${O}=${encodeURIComponent(JSON.stringify(t))}; expires=${n}; path=/; SameSite=Lax`)}(t),{current:{...q},previous:n}}function Z(e){return q||(q=I()),!0===q[e]}function P(e=365){return U({functional:!1,analytics:!1,marketing:!1},e)}function H(){try{return M().includes(O)}catch(e){return!1}}const Y={READY:"zest:ready",CONSENT:"zest:consent",REJECT:"zest:reject",CHANGE:"zest:change",SHOW:"zest:show",HIDE:"zest:hide"};function B(e,t={}){const n=new CustomEvent(e,{detail:t,bubbles:!0,cancelable:!0});return document.dispatchEvent(n),n}function F(e,t){return B(Y.CONSENT,{consent:e,previous:t})}function J(e){return B(Y.REJECT,{consent:e})}function X(e,t){return B(Y.CHANGE,{consent:e,previous:t})}function G(e="banner"){return B(Y.SHOW,{type:e})}function V(e="banner"){return B(Y.HIDE,{type:e})}function K(e){const t=e.accentColor||"#4F46E5";return`\n:host {\n --zest-accent: ${t};\n --zest-accent-hover: ${function(e,t){const n=parseInt(e.replace("#",""),16),o=Math.round(2.55*t);return"#"+(16777216+65536*Math.min(255,Math.max(0,(n>>16)+o))+256*Math.min(255,Math.max(0,(n>>8&255)+o))+Math.min(255,Math.max(0,(255&n)+o))).toString(16).slice(1)}(t,-15)};\n --zest-bg: #ffffff;\n --zest-bg-secondary: #f3f4f6;\n --zest-text: #1f2937;\n --zest-text-secondary: #6b7280;\n --zest-border: #e5e7eb;\n --zest-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1);\n --zest-radius: 12px;\n --zest-radius-sm: 8px;\n --zest-font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;\n\n font-family: var(--zest-font);\n font-size: 14px;\n line-height: 1.5;\n color: var(--zest-text);\n box-sizing: border-box;\n}\n\n:host([data-theme="dark"]) {\n --zest-bg: #1f2937;\n --zest-bg-secondary: #374151;\n --zest-text: #f9fafb;\n --zest-text-secondary: #9ca3af;\n --zest-border: #4b5563;\n --zest-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.4), 0 8px 10px -6px rgba(0, 0, 0, 0.3);\n}\n\n@media (prefers-color-scheme: dark) {\n :host([data-theme="auto"]) {\n --zest-bg: #1f2937;\n --zest-bg-secondary: #374151;\n --zest-text: #f9fafb;\n --zest-text-secondary: #9ca3af;\n --zest-border: #4b5563;\n --zest-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.4), 0 8px 10px -6px rgba(0, 0, 0, 0.3);\n }\n}\n\n*, *::before, *::after {\n box-sizing: border-box;\n}\n\n/* Banner */\n.zest-banner {\n position: fixed;\n z-index: 999999;\n max-width: 480px;\n padding: 20px;\n background: var(--zest-bg);\n border-radius: var(--zest-radius);\n box-shadow: var(--zest-shadow);\n animation: zest-slide-in 0.3s ease-out;\n}\n\n.zest-banner--bottom {\n bottom: 20px;\n left: 50%;\n transform: translateX(-50%);\n}\n\n.zest-banner--bottom-left {\n bottom: 20px;\n left: 20px;\n}\n\n.zest-banner--bottom-right {\n bottom: 20px;\n right: 20px;\n}\n\n.zest-banner--top {\n top: 20px;\n left: 50%;\n transform: translateX(-50%);\n}\n\n@keyframes zest-slide-in {\n from {\n opacity: 0;\n transform: translateX(-50%) translateY(20px);\n }\n to {\n opacity: 1;\n transform: translateX(-50%) translateY(0);\n }\n}\n\n.zest-banner--bottom-left {\n animation-name: zest-slide-in-left;\n}\n\n@keyframes zest-slide-in-left {\n from {\n opacity: 0;\n transform: translateY(20px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n.zest-banner--bottom-right {\n animation-name: zest-slide-in-right;\n}\n\n@keyframes zest-slide-in-right {\n from {\n opacity: 0;\n transform: translateY(20px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .zest-banner,\n .zest-modal {\n animation: none;\n }\n}\n\n.zest-banner__title {\n margin: 0 0 8px 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--zest-text);\n}\n\n.zest-banner__description {\n margin: 0 0 16px 0;\n font-size: 14px;\n color: var(--zest-text-secondary);\n}\n\n.zest-banner__buttons {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n/* Buttons */\n.zest-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 10px 16px;\n font-size: 14px;\n font-weight: 500;\n font-family: inherit;\n border: none;\n border-radius: var(--zest-radius-sm);\n cursor: pointer;\n transition: background-color 0.15s ease, transform 0.1s ease;\n}\n\n.zest-btn:hover {\n transform: translateY(-1px);\n}\n\n.zest-btn:active {\n transform: translateY(0);\n}\n\n.zest-btn:focus-visible {\n outline: 2px solid var(--zest-accent);\n outline-offset: 2px;\n}\n\n.zest-btn--primary {\n background: var(--zest-accent);\n color: #ffffff;\n}\n\n.zest-btn--primary:hover {\n background: var(--zest-accent-hover);\n}\n\n.zest-btn--secondary {\n background: var(--zest-bg-secondary);\n color: var(--zest-text);\n}\n\n.zest-btn--secondary:hover {\n background: var(--zest-border);\n}\n\n.zest-btn--ghost {\n background: transparent;\n color: var(--zest-text-secondary);\n}\n\n.zest-btn--ghost:hover {\n background: var(--zest-bg-secondary);\n color: var(--zest-text);\n}\n\n/* Modal */\n.zest-modal-overlay {\n position: fixed;\n inset: 0;\n z-index: 999998;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 20px;\n background: rgba(0, 0, 0, 0.5);\n animation: zest-fade-in 0.2s ease-out;\n}\n\n@keyframes zest-fade-in {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n.zest-modal {\n width: 100%;\n max-width: 500px;\n max-height: 90vh;\n overflow-y: auto;\n background: var(--zest-bg);\n border-radius: var(--zest-radius);\n box-shadow: var(--zest-shadow);\n animation: zest-modal-in 0.3s ease-out;\n}\n\n@keyframes zest-modal-in {\n from {\n opacity: 0;\n transform: scale(0.95);\n }\n to {\n opacity: 1;\n transform: scale(1);\n }\n}\n\n.zest-modal__header {\n padding: 20px 20px 0;\n}\n\n.zest-modal__title {\n margin: 0 0 8px 0;\n font-size: 18px;\n font-weight: 600;\n color: var(--zest-text);\n}\n\n.zest-modal__description {\n margin: 0;\n font-size: 14px;\n color: var(--zest-text-secondary);\n}\n\n.zest-modal__body {\n padding: 20px;\n}\n\n.zest-modal__footer {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n padding: 0 20px 20px;\n}\n\n/* Categories */\n.zest-category {\n padding: 16px;\n margin-bottom: 12px;\n background: var(--zest-bg-secondary);\n border-radius: var(--zest-radius-sm);\n}\n\n.zest-category:last-child {\n margin-bottom: 0;\n}\n\n.zest-category__header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n}\n\n.zest-category__info {\n flex: 1;\n}\n\n.zest-category__label {\n display: block;\n font-size: 14px;\n font-weight: 600;\n color: var(--zest-text);\n}\n\n.zest-category__description {\n margin: 4px 0 0;\n font-size: 13px;\n color: var(--zest-text-secondary);\n}\n\n/* Toggle Switch */\n.zest-toggle {\n position: relative;\n width: 44px;\n height: 24px;\n flex-shrink: 0;\n}\n\n.zest-toggle__input {\n position: absolute;\n opacity: 0;\n width: 100%;\n height: 100%;\n cursor: pointer;\n margin: 0;\n}\n\n.zest-toggle__input:disabled {\n cursor: not-allowed;\n}\n\n.zest-toggle__slider {\n position: absolute;\n inset: 0;\n background: var(--zest-border);\n border-radius: 12px;\n transition: background-color 0.2s ease;\n pointer-events: none;\n}\n\n.zest-toggle__slider::before {\n content: '';\n position: absolute;\n top: 2px;\n left: 2px;\n width: 20px;\n height: 20px;\n background: #ffffff;\n border-radius: 50%;\n transition: transform 0.2s ease;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\n}\n\n.zest-toggle__input:checked + .zest-toggle__slider {\n background: var(--zest-accent);\n}\n\n.zest-toggle__input:checked + .zest-toggle__slider::before {\n transform: translateX(20px);\n}\n\n.zest-toggle__input:focus-visible + .zest-toggle__slider {\n outline: 2px solid var(--zest-accent);\n outline-offset: 2px;\n}\n\n.zest-toggle__input:disabled + .zest-toggle__slider {\n opacity: 0.6;\n}\n\n/* Widget */\n.zest-widget {\n position: fixed;\n z-index: 999997;\n bottom: 20px;\n left: 20px;\n}\n\n.zest-widget__btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 48px;\n height: 48px;\n padding: 0;\n background: var(--zest-bg);\n border: 1px solid var(--zest-border);\n border-radius: 50%;\n box-shadow: var(--zest-shadow);\n cursor: pointer;\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n}\n\n.zest-widget__btn:hover {\n transform: scale(1.05);\n box-shadow: 0 12px 28px -5px rgba(0, 0, 0, 0.15);\n}\n\n.zest-widget__btn:focus-visible {\n outline: 2px solid var(--zest-accent);\n outline-offset: 2px;\n}\n\n.zest-widget__icon {\n width: 24px;\n height: 24px;\n fill: var(--zest-text);\n}\n\n/* Link */\n.zest-link {\n color: var(--zest-accent);\n text-decoration: none;\n}\n\n.zest-link:hover {\n text-decoration: underline;\n}\n\n/* Mobile */\n@media (max-width: 480px) {\n .zest-banner {\n left: 10px;\n right: 10px;\n max-width: none;\n transform: none;\n }\n\n .zest-banner--bottom,\n .zest-banner--bottom-left,\n .zest-banner--bottom-right {\n bottom: 10px;\n }\n\n .zest-banner--top {\n top: 10px;\n transform: none;\n }\n\n @keyframes zest-slide-in {\n from {\n opacity: 0;\n transform: translateY(20px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n\n .zest-banner__buttons {\n flex-direction: column;\n }\n\n .zest-btn {\n width: 100%;\n }\n\n .zest-modal-overlay {\n padding: 10px;\n }\n\n .zest-widget {\n bottom: 10px;\n left: 10px;\n }\n}\n\n/* Hidden utility */\n.zest-hidden {\n display: none !important;\n}\n${e.customStyles||""}\n`}let Q=null,ee=null;function te(e={}){Q?Q.classList.remove("zest-hidden"):function(e={}){if(Q)return Q;const t=T();Q=document.createElement("zest-banner"),Q.setAttribute("data-theme",t.theme||"light"),ee=Q.attachShadow({mode:"open"});const n=document.createElement("style");n.textContent=K(t),ee.appendChild(n);const o=document.createElement("div");o.innerHTML=function(e){const t=e.labels.banner;return`\n <div class="zest-banner zest-banner--${e.position||"bottom"}" role="dialog" aria-modal="false" aria-label="${t.title}">\n <h2 class="zest-banner__title">${t.title}</h2>\n <p class="zest-banner__description">${t.description}</p>\n <div class="zest-banner__buttons">\n <button type="button" class="zest-btn zest-btn--primary" data-action="accept-all">\n ${t.acceptAll}\n </button>\n <button type="button" class="zest-btn zest-btn--secondary" data-action="reject-all">\n ${t.rejectAll}\n </button>\n <button type="button" class="zest-btn zest-btn--ghost" data-action="settings">\n ${t.settings}\n </button>\n </div>\n </div>\n `}(t),ee.appendChild(o.firstElementChild);const a=ee.querySelector(".zest-banner");a.addEventListener("click",t=>{const n=t.target.dataset.action;if(n)switch(n){case"accept-all":e.onAcceptAll?.();break;case"reject-all":e.onRejectAll?.();break;case"settings":e.onSettings?.()}}),a.addEventListener("keydown",t=>{"Escape"===t.key&&e.onSettings?.()}),document.body.appendChild(Q),requestAnimationFrame(()=>{const e=ee.querySelector("button");e?.focus()})}(e)}function ne(){Q&&(Q.remove(),Q=null,ee=null)}let oe=null,ae=null,se={};function re(){if(!ae)return se;const e=ae.querySelectorAll(".zest-toggle__input"),t={essential:!0};return e.forEach(e=>{const n=e.dataset.category;n&&"essential"!==n&&(t[n]=e.checked)}),t}function ie(e={},t={}){if(oe)return oe;const n=T();se={...e},oe=document.createElement("zest-modal"),oe.setAttribute("data-theme",n.theme||"light"),ae=oe.attachShadow({mode:"open"});const o=document.createElement("style");o.textContent=K(n),ae.appendChild(o);const a=document.createElement("div");a.innerHTML=function(e,t){const n=e.labels.modal,o=Object.values(e.categories||j).map(e=>{return`\n <div class="zest-category">\n <div class="zest-category__header">\n <div class="zest-category__info">\n <span class="zest-category__label">${(n=e).label}</span>\n <p class="zest-category__description">${n.description}</p>\n </div>\n <label class="zest-toggle">\n <input\n type="checkbox"\n class="zest-toggle__input"\n data-category="${n.id}"\n ${t[e.id]??e.default?"checked":""}\n ${e.required?"disabled":""}\n aria-label="${n.label}"\n >\n <span class="zest-toggle__slider"></span>\n </label>\n </div>\n </div>\n `;var n}).join("");return`\n <div class="zest-modal-overlay" role="dialog" aria-modal="true" aria-label="${n.title}">\n <div class="zest-modal">\n <div class="zest-modal__header">\n <h2 class="zest-modal__title">${n.title}</h2>\n <p class="zest-modal__description">${n.description} ${e.policyUrl?`<a href="${e.policyUrl}" class="zest-link" target="_blank" rel="noopener">Privacy Policy</a>`:""}</p>\n </div>\n <div class="zest-modal__body">\n ${o}\n </div>\n <div class="zest-modal__footer">\n <button type="button" class="zest-btn zest-btn--primary" data-action="save">\n ${n.save}\n </button>\n <button type="button" class="zest-btn zest-btn--secondary" data-action="accept-all">\n ${n.acceptAll}\n </button>\n <button type="button" class="zest-btn zest-btn--ghost" data-action="reject-all">\n ${n.rejectAll}\n </button>\n </div>\n </div>\n </div>\n `}(n,e),ae.appendChild(a.firstElementChild);const s=ae.querySelector(".zest-modal-overlay");return s.addEventListener("click",e=>{const n=e.target.dataset.action;if(n)switch(n){case"save":t.onSave?.(re());break;case"accept-all":t.onAcceptAll?.();break;case"reject-all":t.onRejectAll?.()}else e.target===s&&t.onClose?.()}),s.addEventListener("keydown",e=>{"Escape"===e.key&&t.onClose?.()}),ae.querySelectorAll(".zest-toggle__input").forEach(e=>{e.addEventListener("change",()=>{se=re()})}),document.body.appendChild(oe),requestAnimationFrame(()=>{const e=ae.querySelector("button");e?.focus()}),oe}function ce(){oe&&(oe.remove(),oe=null,ae=null)}let le=null,de=null;function ue(e={}){le?le.style.display="":function(e={}){if(le)return le;const t=T();le=document.createElement("zest-widget"),le.setAttribute("data-theme",t.theme||"light"),de=le.attachShadow({mode:"open"});const n=document.createElement("style");n.textContent=K(t),de.appendChild(n);const o=document.createElement("div");o.innerHTML=function(e){const t=e.labels.widget;return`\n <div class="zest-widget">\n <button type="button" class="zest-widget__btn" aria-label="${t.label}" title="${t.label}">\n <span class="zest-widget__icon"><svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 2C6.477 2 2 6.477 2 12s4.477 10 10 10 10-4.477 10-10c0-.728-.078-1.437-.225-2.12a1 1 0 0 0-1.482-.63 3 3 0 0 1-4.086-3.72 1 1 0 0 0-.793-1.263A10.05 10.05 0 0 0 12 2zm0 2c.178 0 .354.006.528.017a5 5 0 0 0 5.955 5.955c.011.174.017.35.017.528 0 4.418-3.582 8-8 8s-8-3.582-8-8 3.582-8 8-8zm-4 6a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3zm5 0a1 1 0 1 0 0 2 1 1 0 0 0 0-2zm-2 4a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3z"/></svg></span>\n </button>\n </div>\n `}(t),de.appendChild(o.firstElementChild),de.querySelector(".zest-widget__btn").addEventListener("click",()=>{e.onClick?.()}),document.body.appendChild(le)}(e)}function pe(){le&&(le.style.display="none")}let ge=!1,me=null;function fe(e){return Z(e)}function be(e){!function(e){const t=[];for(const n of a)e.includes(n.category)?o?.set&&o.set.call(document,n.value):t.push(n);a.length=0,a.push(...t)}(e),function(e){const t=[];for(const n of l)e.includes(n.category)?i?.setItem(n.key,n.value):t.push(n);l.length=0,l.push(...t);const n=[];for(const t of d)e.includes(t.category)?c?.setItem(t.key,t.value):n.push(t);d.length=0,d.push(...n)}(e),function(e){const t=[];for(const n of h)e.includes(n.category)?_(n):t.push(n);h.length=0,h.push(...t),document.querySelectorAll('script[data-zest-processed="blocked"]').forEach(t=>{const n=t.getAttribute("data-consent-category");if(e.includes(n)){const e=document.createElement("script"),n=t.getAttribute("data-blocked-src");n?e.src=n:e.textContent=t.textContent,t.async&&(e.async=!0),t.defer&&(e.defer=!0),e.setAttribute("data-zest-processed","executed"),e.setAttribute("data-consent-executed","true"),t.parentNode?.replaceChild(e,t)}})}(e)}function he(){const e=function(e=365){return U({functional:!0,analytics:!0,marketing:!0},e)}(me.expiration),t=Object.keys(j);ne(),ce(),be(t),me.showWidget&&ue({onClick:xe}),F(e.current,e.previous),X(e.current,e.previous),me.callbacks?.onAccept?.(e.current),me.callbacks?.onChange?.(e.current)}function ye(){const e=P(me.expiration);ne(),ce(),me.showWidget&&ue({onClick:xe}),J(e.current),X(e.current,e.previous),me.callbacks?.onReject?.(),me.callbacks?.onChange?.(e.current)}function ze(e){const t=U(e,me.expiration),n=Object.keys(t.current).filter(e=>t.current[e]&&!t.previous[e]);n.length>0&&be(n),ce(),me.showWidget&&ue({onClick:xe});Object.entries(e).some(([e,t])=>"essential"!==e&&t)?F(t.current,t.previous):J(t.current),X(t.current,t.previous),me.callbacks?.onChange?.(t.current)}function xe(){ne(),pe(),ie(W(),{onSave:ze,onAcceptAll:he,onRejectAll:ye,onClose:we}),G("modal")}function we(){ce(),V("modal"),H()&&me.showWidget?ue({onClick:xe}):te({onAcceptAll:he,onRejectAll:ye,onSettings:xe})}function ve(r={}){if(ge)return console.warn("[Zest] Already initialized"),ke;me=function(e){return D=N(e),D}(r),me.patterns&&function(n){t={...e};for(const[e,o]of Object.entries(n))Array.isArray(o)&&(t[e]=o.map(e=>e instanceof RegExp?e:RegExp(e)))}(me.patterns),s=fe,function(e){u=e}(fe),function(e){w=e}(fe),o=Object.getOwnPropertyDescriptor(Document.prototype,"cookie"),o?Object.defineProperty(document,"cookie",{get:()=>o.get.call(document),set(e){const t=function(e){const t=e.match(/^([^=]+)/);return t?t[1].trim():null}(e);if(!t)return;const r=n(t);s(r)?o.set.call(document,e):a.push({value:e,name:t,category:r,timestamp:Date.now()})},configurable:!0}):console.warn("[Zest] Could not get cookie descriptor"),function(){try{return i=window.localStorage,c=window.sessionStorage,Object.defineProperty(window,"localStorage",{value:p(i,l),configurable:!0,writable:!1}),Object.defineProperty(window,"sessionStorage",{value:p(c,d),configurable:!0,writable:!1}),!0}catch(e){return console.warn("[Zest] Could not intercept storage APIs:",e),!1}}(),C(me.mode,me.blockedDomains);const g=I();ge=!0;let m=!1;if(S()&&me.respectDNT&&"ignore"!==me.dntBehavior&&"reject"===me.dntBehavior&&!H()){const e=P(me.expiration);m=!0,J(e.current),X(e.current,e.previous),me.callbacks?.onReject?.(),me.callbacks?.onChange?.(e.current)}return function(e){B(Y.READY,{consent:e})}(g),me.callbacks?.onReady?.(g),H()||m?me.showWidget&&ue({onClick:xe}):(te({onAcceptAll:he,onRejectAll:ye,onSettings:xe}),G("banner")),ke}const ke={init:ve,show(){ge?(ce(),pe(),te({onAcceptAll:he,onRejectAll:ye,onSettings:xe}),G("banner")):console.warn("[Zest] Not initialized. Call Zest.init() first.")},hide(){ne(),V("banner")},showSettings(){ge?xe():console.warn("[Zest] Not initialized. Call Zest.init() first.")},hideSettings(){ce(),V("modal")},getConsent:W,hasConsent:Z,hasConsentDecision:H,getConsentProof:function(){try{const e=M().match(RegExp(O+"=([^;]+)"));if(e)return JSON.parse(decodeURIComponent(e[1]))}catch(e){}return null},isDoNotTrackEnabled:S,getDNTDetails:function(){if("undefined"==typeof navigator)return{enabled:!1,source:null};const e=navigator.doNotTrack||window.doNotTrack||navigator.msDoNotTrack;return"1"===e||"yes"===e||!0===e?{enabled:!0,source:"dnt"}:!0===navigator.globalPrivacyControl?{enabled:!0,source:"gpc"}:{enabled:!1,source:null}},acceptAll(){ge?he():console.warn("[Zest] Not initialized. Call Zest.init() first.")},rejectAll(){ge?ye():console.warn("[Zest] Not initialized. Call Zest.init() first.")},reset(){L(O+"=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/"),q=null,ce(),le&&(le.remove(),le=null,de=null),ge&&(te({onAcceptAll:he,onRejectAll:ye,onSettings:xe}),G("banner"))},getConfig:T,EVENTS:Y};if("undefined"!=typeof window){window.Zest=ke;const e=()=>{!1!==$().autoInit&&ve(window.ZestConfig)};"loading"===document.readyState?document.addEventListener("DOMContentLoaded",e):e()}return ke}();
|
|
1
|
+
var Zest=function(){"use strict";const e={essential:[/^zest_/,/^csrf/i,/^xsrf/i,/^session/i,/^__host-/i,/^__secure-/i],functional:[/^lang/i,/^locale/i,/^theme/i,/^preferences/i,/^ui_/i],analytics:[/^_ga/,/^_gid/,/^_gat/,/^_utm/,/^__utm/,/^plausible/i,/^_pk_/,/^matomo/i,/^_hj/,/^ajs_/],marketing:[/^_fbp/,/^_fbc/,/^_gcl/,/^_ttp/,/^ads/i,/^doubleclick/i,/^__gads/,/^__gpi/,/^_pin_/,/^li_/]};let t={...e};function n(e){for(const[n,o]of Object.entries(t))if(o.some(t=>t.test(e)))return n;return"marketing"}let o=null;const a=[];let s=()=>!1;function r(){return o}let i=null,c=null;const l=[],d=[];let u=()=>!1;function p(e,t,o){return new Proxy(e,{get(e,o){if("setItem"===o)return(o,a)=>{const s=n(o);u(s)?e.setItem(o,a):t.push({key:o,value:a,category:s,timestamp:Date.now()})};const a=e[o];return"function"==typeof a?a.bind(e):a}})}const g={analytics:["google-analytics.com","www.google-analytics.com","analytics.google.com","googletagmanager.com","www.googletagmanager.com","plausible.io","cloudflareinsights.com","static.cloudflareinsights.com"],marketing:["connect.facebook.net","www.facebook.com/tr","ads.google.com","www.googleadservices.com","googleads.g.doubleclick.net","pagead2.googlesyndication.com"]},m={analytics:[...g.analytics,"analytics.tiktok.com","matomo.","hotjar.com","static.hotjar.com","script.hotjar.com","clarity.ms","www.clarity.ms","heapanalytics.com","cdn.heapanalytics.com","mixpanel.com","cdn.mxpnl.com","segment.com","cdn.segment.com","api.segment.io","fullstory.com","rs.fullstory.com","amplitude.com","cdn.amplitude.com","mouseflow.com","cdn.mouseflow.com","luckyorange.com","cdn.luckyorange.net","crazyegg.com","script.crazyegg.com"],marketing:[...g.marketing,"snap.licdn.com","px.ads.linkedin.com","ads.linkedin.com","analytics.twitter.com","static.ads-twitter.com","t.co","analytics.tiktok.com","ads.tiktok.com","sc-static.net","tr.snapchat.com","ct.pinterest.com","pintrk.com","s.pinimg.com","widgets.pinterest.com","bat.bing.com","ads.yahoo.com","sp.analytics.yahoo.com","amazon-adsystem.com","z-na.amazon-adsystem.com","criteo.com","static.criteo.net","dis.criteo.com","taboola.com","cdn.taboola.com","trc.taboola.com","outbrain.com","widgets.outbrain.com","adroll.com","s.adroll.com"],functional:["cdn.onesignal.com","onesignal.com","pusher.com","js.pusher.com","intercom.io","widget.intercom.io","js.intercomcdn.com","crisp.chat","client.crisp.chat","cdn.livechatinc.com","livechatinc.com","tawk.to","embed.tawk.to","zendesk.com","static.zdassets.com"]};function f(e,t){try{const n=new URL(e).hostname.toLowerCase(),o=e.toLowerCase();for(const e of t)if(e.endsWith(".")){if(n.includes(e.slice(0,-1)))return!0}else{if(n===e||n.endsWith("."+e))return!0;if(o.includes(e))return!0}}catch(e){}return!1}function b(e,t="safe"){const n="strict"===t?m:g;for(const[t,o]of Object.entries(n))if(f(e,o))return t;return null}const y=[];let h=null,z="safe",w=[],x=()=>!1;function v(e){const t=e.getAttribute("data-consent-category");if(t)return t;if(e.hasAttribute("data-zest-allow"))return null;const n=e.src;if(!n)return null;const o=function(e){if(!e||0===w.length)return null;try{const t=new URL(e).hostname.toLowerCase();for(const e of w){const n="string"==typeof e?e:e.domain,o="string"==typeof e?"marketing":e.category||"marketing";if(t===n||t.endsWith("."+n))return o}}catch(e){}return null}(n);if(o)return o;switch(z){case"manual":default:return null;case"safe":case"strict":return b(n,z);case"doomsday":return function(e){try{const t=new URL(e).hostname,n=window.location.hostname,o=e=>e.replace(/^www\./,"");return o(t)!==o(n)}catch(e){return!1}}(n)?b(n,"strict")||"marketing":null}}function k(e){if(e.hasAttribute("data-zest-processed"))return!1;const t=v(e);if(!t)return e.setAttribute("data-zest-processed","allowed"),!1;if(x(t))return e.setAttribute("data-zest-processed","allowed"),!1;const n={category:t,src:e.src,inline:e.textContent,type:e.type,async:e.async,defer:e.defer,timestamp:Date.now()};return e.setAttribute("data-zest-processed","blocked"),e.setAttribute("data-consent-category",t),e.type="text/plain",e.src&&(e.setAttribute("data-blocked-src",e.src),e.removeAttribute("src")),y.push(n),!0}function _(e){const t=document.createElement("script");e.src?t.src=e.src:e.inline&&(t.textContent=e.inline),e.async&&(t.async=!0),e.defer&&(t.defer=!0),t.setAttribute("data-zest-processed","executed"),t.setAttribute("data-consent-executed","true"),document.head.appendChild(t)}function A(e){for(const t of e)for(const e of t.addedNodes)if("SCRIPT"!==e.nodeName||e.hasAttribute("data-zest-processed")||k(e),e.querySelectorAll){e.querySelectorAll("script:not([data-zest-processed])").forEach(k)}}function C(e="safe",t=[]){return z=e,w=t,document.querySelectorAll("script:not([data-zest-processed])").forEach(k),h=new MutationObserver(A),h.observe(document.documentElement,{childList:!0,subtree:!0}),!0}const j={essential:{id:"essential",label:"Essential",description:"Required for the website to function properly. Cannot be disabled.",required:!0,default:!0},functional:{id:"functional",label:"Functional",description:"Enable personalized features like language preferences and themes.",required:!1,default:!1},analytics:{id:"analytics",label:"Analytics",description:"Help us understand how visitors interact with our website.",required:!1,default:!1},marketing:{id:"marketing",label:"Marketing",description:"Used to deliver relevant advertisements and track campaign performance.",required:!1,default:!1}};function S(){if("undefined"==typeof navigator)return!1;const e=navigator.doNotTrack||window.doNotTrack||navigator.msDoNotTrack;return"1"===e||"yes"===e||!0===e||!0===navigator.globalPrivacyControl}function E(e,t,n){const o=n?"default":"update";t.consentModeGoogle&&function(e,t){if(window.dataLayer=window.dataLayer||[],"function"==typeof window.gtag)window.gtag("consent",e,t);else{function n(){window.dataLayer.push(arguments)}n("consent",e,t)}}(o,function(e){const t=e=>e?"granted":"denied";return{ad_storage:t(e.marketing),ad_user_data:t(e.marketing),ad_personalization:t(e.marketing),analytics_storage:t(e.analytics),functionality_storage:"granted",personalization_storage:t(e.functional)}}(e)),t.consentModeMicrosoft&&function(e,t){window.uetq=window.uetq||[],window.uetq.push("consent",e,t)}(o,function(e){return{ad_storage:e.marketing?"granted":"denied"}}(e))}const M={labels:{banner:{title:"Wij respecteren uw privacy",description:'Wij gebruiken cookies om uw browse-ervaring te verbeteren, gepersonaliseerde inhoud aan te bieden en ons verkeer te analyseren. Door op "Alles accepteren" te klikken, stemt u in met het gebruik van cookies.',acceptAll:"Alles accepteren",rejectAll:"Alles weigeren",settings:"Instellingen"},modal:{title:"Privacy-instellingen",description:"Beheer uw cookievoorkeuren. U kunt hieronder verschillende soorten cookies in- of uitschakelen.",save:"Voorkeuren opslaan",acceptAll:"Alles accepteren",rejectAll:"Alles weigeren"},widget:{label:"Cookie-instellingen"}},categories:{essential:{label:"Essentieel",description:"Noodzakelijk voor de goede werking van de website. Kunnen niet worden uitgeschakeld."},functional:{label:"Functioneel",description:"Maken gepersonaliseerde functies mogelijk zoals taal- en themavoorkeuren."},analytics:{label:"Analytisch",description:"Helpen ons te begrijpen hoe bezoekers onze website gebruiken."},marketing:{label:"Marketing",description:"Worden gebruikt om relevante advertenties te tonen en campagneprestaties te meten."}}};const R={lang:"auto",position:"bottom",theme:"auto",accentColor:"#0071e3",categories:j,labels:{banner:{title:"We value your privacy",description:'We use cookies to enhance your browsing experience, serve personalized content, and analyze our traffic. By clicking "Accept All", you consent to our use of cookies.',acceptAll:"Accept All",rejectAll:"Reject All",settings:"Settings"},modal:{title:"Privacy Settings",description:"Manage your cookie preferences. You can enable or disable different types of cookies below.",save:"Save Preferences",acceptAll:"Accept All",rejectAll:"Reject All"},widget:{label:"Cookie Settings"}},autoInit:!0,showWidget:!0,expiration:365,respectDNT:!0,dntBehavior:"reject",customStyles:"",consentModeGoogle:!1,consentModeMicrosoft:!1,mode:"safe",blockedDomains:[],policyUrl:null,imprintUrl:null,callbacks:{onAccept:null,onReject:null,onChange:null,onReady:null}};function N(e){const t={...R};e||(e={});const n=["lang","position","theme","accentColor","autoInit","showWidget","expiration","policyUrl","imprintUrl","customStyles","mode","blockedDomains","respectDNT","dntBehavior","consentModeGoogle","consentModeMicrosoft"];for(const o of n)void 0!==e[o]&&(t[o]=e[o]);t.lang="nl";const o=M,a=o.labels||{},s=e.labels||{};t.labels={banner:{...R.labels.banner,...a.banner,...s.banner},modal:{...R.labels.modal,...a.modal,...s.modal},widget:{...R.labels.widget,...a.widget,...s.widget}};const r=o.categories||{},i=e.categories||{};t.categories={...R.categories};for(const e of Object.keys(R.categories))t.categories[e]={...R.categories[e],...r[e],...i[e]};return e.callbacks&&(t.callbacks={...R.callbacks,...e.callbacks}),e.patterns&&(t.patterns=e.patterns),t}function $(){const e="undefined"!=typeof window&&window.ZestConfig?window.ZestConfig:{},t=function(){const e=document.currentScript||document.querySelector("script[data-zest]")||document.querySelector('script[src*="zest"]');if(!e)return{};const t={},n=e.getAttribute("data-position");n&&(t.position=n);const o=e.getAttribute("data-theme");o&&(t.theme=o);const a=e.getAttribute("data-accent")||e.getAttribute("data-accent-color");a&&(t.accentColor=a);const s=e.getAttribute("data-policy-url")||e.getAttribute("data-privacy-url");s&&(t.policyUrl=s);const r=e.getAttribute("data-imprint-url");r&&(t.imprintUrl=r);const i=e.getAttribute("data-show-widget");null!==i&&(t.showWidget="false"!==i);const c=e.getAttribute("data-auto-init");null!==c&&(t.autoInit="false"!==c);const l=e.getAttribute("data-expiration");l&&(t.expiration=parseInt(l,10));const d=e.getAttribute("data-consent-mode-google");null!==d&&(t.consentModeGoogle="false"!==d);const u=e.getAttribute("data-consent-mode-microsoft");return null!==u&&(t.consentModeMicrosoft="false"!==u),t}();return N({...e,...t})}let D=null;function q(){return D||(D=$()),D}const L="zest_consent";let T=null;function O(e){const t=r();t?.set?t.set.call(document,e):document.cookie=e}function I(){const e=r();return e?.get?e.get.call(document):document.cookie}function W(){try{const e=I().match(RegExp(L+"=([^;]+)"));if(e){const t=JSON.parse(decodeURIComponent(e[1]));return T=t.categories||{essential:!0,functional:!1,analytics:!1,marketing:!1},{...T}}}catch(e){}return T={essential:!0,functional:!1,analytics:!1,marketing:!1},{...T}}function U(){return T||(T=W()),{...T}}function Z(e,t=365){const n=T?{...T}:{essential:!0,functional:!1,analytics:!1,marketing:!1};return T={essential:!0,functional:!!e.functional,analytics:!!e.analytics,marketing:!!e.marketing},function(e=365){T||(T={essential:!0,functional:!1,analytics:!1,marketing:!1});const t={version:"1.0",timestamp:Date.now(),categories:T},n=new Date(Date.now()+24*e*60*60*1e3).toUTCString();O(`${L}=${encodeURIComponent(JSON.stringify(t))}; expires=${n}; path=/; SameSite=Lax`)}(t),{current:{...T},previous:n}}function P(e){return T||(T=W()),!0===T[e]}function H(e=365){return Z({functional:!1,analytics:!1,marketing:!1},e)}function Y(){try{return I().includes(L)}catch(e){return!1}}const B={READY:"zest:ready",CONSENT:"zest:consent",REJECT:"zest:reject",CHANGE:"zest:change",SHOW:"zest:show",HIDE:"zest:hide"};function G(e,t={}){const n=new CustomEvent(e,{detail:t,bubbles:!0,cancelable:!0});return document.dispatchEvent(n),n}function F(e,t){return G(B.CONSENT,{consent:e,previous:t})}function J(e){return G(B.REJECT,{consent:e})}function X(e,t){return G(B.CHANGE,{consent:e,previous:t})}function V(e="banner"){return G(B.SHOW,{type:e})}function K(e="banner"){return G(B.HIDE,{type:e})}function Q(e){const t=e.accentColor||"#4F46E5";return`\n:host {\n --zest-accent: ${t};\n --zest-accent-hover: ${function(e,t){const n=parseInt(e.replace("#",""),16),o=Math.round(2.55*t);return"#"+(16777216+65536*Math.min(255,Math.max(0,(n>>16)+o))+256*Math.min(255,Math.max(0,(n>>8&255)+o))+Math.min(255,Math.max(0,(255&n)+o))).toString(16).slice(1)}(t,-15)};\n --zest-bg: #ffffff;\n --zest-bg-secondary: #f3f4f6;\n --zest-text: #1f2937;\n --zest-text-secondary: #6b7280;\n --zest-border: #e5e7eb;\n --zest-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1);\n --zest-radius: 12px;\n --zest-radius-sm: 8px;\n --zest-font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;\n\n font-family: var(--zest-font);\n font-size: 14px;\n line-height: 1.5;\n color: var(--zest-text);\n box-sizing: border-box;\n}\n\n:host([data-theme="dark"]) {\n --zest-bg: #1f2937;\n --zest-bg-secondary: #374151;\n --zest-text: #f9fafb;\n --zest-text-secondary: #9ca3af;\n --zest-border: #4b5563;\n --zest-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.4), 0 8px 10px -6px rgba(0, 0, 0, 0.3);\n}\n\n@media (prefers-color-scheme: dark) {\n :host([data-theme="auto"]) {\n --zest-bg: #1f2937;\n --zest-bg-secondary: #374151;\n --zest-text: #f9fafb;\n --zest-text-secondary: #9ca3af;\n --zest-border: #4b5563;\n --zest-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.4), 0 8px 10px -6px rgba(0, 0, 0, 0.3);\n }\n}\n\n*, *::before, *::after {\n box-sizing: border-box;\n}\n\n/* Banner */\n.zest-banner {\n position: fixed;\n z-index: 999999;\n max-width: 480px;\n padding: 20px;\n background: var(--zest-bg);\n border-radius: var(--zest-radius);\n box-shadow: var(--zest-shadow);\n animation: zest-slide-in 0.3s ease-out;\n}\n\n.zest-banner--bottom {\n bottom: 20px;\n left: 50%;\n transform: translateX(-50%);\n}\n\n.zest-banner--bottom-left {\n bottom: 20px;\n left: 20px;\n}\n\n.zest-banner--bottom-right {\n bottom: 20px;\n right: 20px;\n}\n\n.zest-banner--top {\n top: 20px;\n left: 50%;\n transform: translateX(-50%);\n}\n\n@keyframes zest-slide-in {\n from {\n opacity: 0;\n transform: translateX(-50%) translateY(20px);\n }\n to {\n opacity: 1;\n transform: translateX(-50%) translateY(0);\n }\n}\n\n.zest-banner--bottom-left {\n animation-name: zest-slide-in-left;\n}\n\n@keyframes zest-slide-in-left {\n from {\n opacity: 0;\n transform: translateY(20px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n.zest-banner--bottom-right {\n animation-name: zest-slide-in-right;\n}\n\n@keyframes zest-slide-in-right {\n from {\n opacity: 0;\n transform: translateY(20px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .zest-banner,\n .zest-modal {\n animation: none;\n }\n}\n\n.zest-banner__title {\n margin: 0 0 8px 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--zest-text);\n}\n\n.zest-banner__description {\n margin: 0 0 16px 0;\n font-size: 14px;\n color: var(--zest-text-secondary);\n}\n\n.zest-banner__buttons {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n/* Buttons */\n.zest-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 10px 16px;\n font-size: 14px;\n font-weight: 500;\n font-family: inherit;\n border: none;\n border-radius: var(--zest-radius-sm);\n cursor: pointer;\n transition: background-color 0.15s ease, transform 0.1s ease;\n}\n\n.zest-btn:hover {\n transform: translateY(-1px);\n}\n\n.zest-btn:active {\n transform: translateY(0);\n}\n\n.zest-btn:focus-visible {\n outline: 2px solid var(--zest-accent);\n outline-offset: 2px;\n}\n\n.zest-btn--primary {\n background: var(--zest-accent);\n color: #ffffff;\n}\n\n.zest-btn--primary:hover {\n background: var(--zest-accent-hover);\n}\n\n.zest-btn--secondary {\n background: var(--zest-bg-secondary);\n color: var(--zest-text);\n}\n\n.zest-btn--secondary:hover {\n background: var(--zest-border);\n}\n\n.zest-btn--ghost {\n background: transparent;\n color: var(--zest-text-secondary);\n}\n\n.zest-btn--ghost:hover {\n background: var(--zest-bg-secondary);\n color: var(--zest-text);\n}\n\n/* Modal */\n.zest-modal-overlay {\n position: fixed;\n inset: 0;\n z-index: 999998;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 20px;\n background: rgba(0, 0, 0, 0.5);\n animation: zest-fade-in 0.2s ease-out;\n}\n\n@keyframes zest-fade-in {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n.zest-modal {\n width: 100%;\n max-width: 500px;\n max-height: 90vh;\n overflow-y: auto;\n background: var(--zest-bg);\n border-radius: var(--zest-radius);\n box-shadow: var(--zest-shadow);\n animation: zest-modal-in 0.3s ease-out;\n}\n\n@keyframes zest-modal-in {\n from {\n opacity: 0;\n transform: scale(0.95);\n }\n to {\n opacity: 1;\n transform: scale(1);\n }\n}\n\n.zest-modal__header {\n padding: 20px 20px 0;\n}\n\n.zest-modal__title {\n margin: 0 0 8px 0;\n font-size: 18px;\n font-weight: 600;\n color: var(--zest-text);\n}\n\n.zest-modal__description {\n margin: 0;\n font-size: 14px;\n color: var(--zest-text-secondary);\n}\n\n.zest-modal__body {\n padding: 20px;\n}\n\n.zest-modal__footer {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n padding: 0 20px 20px;\n}\n\n/* Categories */\n.zest-category {\n padding: 16px;\n margin-bottom: 12px;\n background: var(--zest-bg-secondary);\n border-radius: var(--zest-radius-sm);\n}\n\n.zest-category:last-child {\n margin-bottom: 0;\n}\n\n.zest-category__header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n}\n\n.zest-category__info {\n flex: 1;\n}\n\n.zest-category__label {\n display: block;\n font-size: 14px;\n font-weight: 600;\n color: var(--zest-text);\n}\n\n.zest-category__description {\n margin: 4px 0 0;\n font-size: 13px;\n color: var(--zest-text-secondary);\n}\n\n/* Toggle Switch */\n.zest-toggle {\n position: relative;\n width: 44px;\n height: 24px;\n flex-shrink: 0;\n}\n\n.zest-toggle__input {\n position: absolute;\n opacity: 0;\n width: 100%;\n height: 100%;\n cursor: pointer;\n margin: 0;\n}\n\n.zest-toggle__input:disabled {\n cursor: not-allowed;\n}\n\n.zest-toggle__slider {\n position: absolute;\n inset: 0;\n background: var(--zest-border);\n border-radius: 12px;\n transition: background-color 0.2s ease;\n pointer-events: none;\n}\n\n.zest-toggle__slider::before {\n content: '';\n position: absolute;\n top: 2px;\n left: 2px;\n width: 20px;\n height: 20px;\n background: #ffffff;\n border-radius: 50%;\n transition: transform 0.2s ease;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\n}\n\n.zest-toggle__input:checked + .zest-toggle__slider {\n background: var(--zest-accent);\n}\n\n.zest-toggle__input:checked + .zest-toggle__slider::before {\n transform: translateX(20px);\n}\n\n.zest-toggle__input:focus-visible + .zest-toggle__slider {\n outline: 2px solid var(--zest-accent);\n outline-offset: 2px;\n}\n\n.zest-toggle__input:disabled + .zest-toggle__slider {\n opacity: 0.6;\n}\n\n/* Widget */\n.zest-widget {\n position: fixed;\n z-index: 999997;\n bottom: 20px;\n left: 20px;\n}\n\n.zest-widget__btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 48px;\n height: 48px;\n padding: 0;\n background: var(--zest-bg);\n border: 1px solid var(--zest-border);\n border-radius: 50%;\n box-shadow: var(--zest-shadow);\n cursor: pointer;\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n}\n\n.zest-widget__btn:hover {\n transform: scale(1.05);\n box-shadow: 0 12px 28px -5px rgba(0, 0, 0, 0.15);\n}\n\n.zest-widget__btn:focus-visible {\n outline: 2px solid var(--zest-accent);\n outline-offset: 2px;\n}\n\n.zest-widget__icon {\n width: 24px;\n height: 24px;\n fill: var(--zest-text);\n}\n\n/* Link */\n.zest-link {\n color: var(--zest-accent);\n text-decoration: none;\n}\n\n.zest-link:hover {\n text-decoration: underline;\n}\n\n/* Mobile */\n@media (max-width: 480px) {\n .zest-banner {\n left: 10px;\n right: 10px;\n max-width: none;\n transform: none;\n }\n\n .zest-banner--bottom,\n .zest-banner--bottom-left,\n .zest-banner--bottom-right {\n bottom: 10px;\n }\n\n .zest-banner--top {\n top: 10px;\n transform: none;\n }\n\n @keyframes zest-slide-in {\n from {\n opacity: 0;\n transform: translateY(20px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n\n .zest-banner__buttons {\n flex-direction: column;\n }\n\n .zest-btn {\n width: 100%;\n }\n\n .zest-modal-overlay {\n padding: 10px;\n }\n\n .zest-widget {\n bottom: 10px;\n left: 10px;\n }\n}\n\n/* Hidden utility */\n.zest-hidden {\n display: none !important;\n}\n${e.customStyles||""}\n`}let ee=null,te=null;function ne(e={}){ee?ee.classList.remove("zest-hidden"):function(e={}){if(ee)return ee;const t=q();ee=document.createElement("zest-banner"),ee.setAttribute("data-theme",t.theme||"light"),te=ee.attachShadow({mode:"open"});const n=document.createElement("style");n.textContent=Q(t),te.appendChild(n);const o=document.createElement("div");o.innerHTML=function(e){const t=e.labels.banner;return`\n <div class="zest-banner zest-banner--${e.position||"bottom"}" role="dialog" aria-modal="false" aria-label="${t.title}">\n <h2 class="zest-banner__title">${t.title}</h2>\n <p class="zest-banner__description">${t.description}</p>\n <div class="zest-banner__buttons">\n <button type="button" class="zest-btn zest-btn--primary" data-action="accept-all">\n ${t.acceptAll}\n </button>\n <button type="button" class="zest-btn zest-btn--secondary" data-action="reject-all">\n ${t.rejectAll}\n </button>\n <button type="button" class="zest-btn zest-btn--ghost" data-action="settings">\n ${t.settings}\n </button>\n </div>\n </div>\n `}(t),te.appendChild(o.firstElementChild);const a=te.querySelector(".zest-banner");a.addEventListener("click",t=>{const n=t.target.dataset.action;if(n)switch(n){case"accept-all":e.onAcceptAll?.();break;case"reject-all":e.onRejectAll?.();break;case"settings":e.onSettings?.()}}),a.addEventListener("keydown",t=>{"Escape"===t.key&&e.onSettings?.()}),document.body.appendChild(ee),requestAnimationFrame(()=>{const e=te.querySelector("button");e?.focus()})}(e)}function oe(){ee&&(ee.remove(),ee=null,te=null)}let ae=null,se=null,re={};function ie(){if(!se)return re;const e=se.querySelectorAll(".zest-toggle__input"),t={essential:!0};return e.forEach(e=>{const n=e.dataset.category;n&&"essential"!==n&&(t[n]=e.checked)}),t}function ce(e={},t={}){if(ae)return ae;const n=q();re={...e},ae=document.createElement("zest-modal"),ae.setAttribute("data-theme",n.theme||"light"),se=ae.attachShadow({mode:"open"});const o=document.createElement("style");o.textContent=Q(n),se.appendChild(o);const a=document.createElement("div");a.innerHTML=function(e,t){const n=e.labels.modal,o=Object.values(e.categories||j).map(e=>{return`\n <div class="zest-category">\n <div class="zest-category__header">\n <div class="zest-category__info">\n <span class="zest-category__label">${(n=e).label}</span>\n <p class="zest-category__description">${n.description}</p>\n </div>\n <label class="zest-toggle">\n <input\n type="checkbox"\n class="zest-toggle__input"\n data-category="${n.id}"\n ${t[e.id]??e.default?"checked":""}\n ${e.required?"disabled":""}\n aria-label="${n.label}"\n >\n <span class="zest-toggle__slider"></span>\n </label>\n </div>\n </div>\n `;var n}).join("");return`\n <div class="zest-modal-overlay" role="dialog" aria-modal="true" aria-label="${n.title}">\n <div class="zest-modal">\n <div class="zest-modal__header">\n <h2 class="zest-modal__title">${n.title}</h2>\n <p class="zest-modal__description">${n.description} ${e.policyUrl?`<a href="${e.policyUrl}" class="zest-link" target="_blank" rel="noopener">Privacy Policy</a>`:""}</p>\n </div>\n <div class="zest-modal__body">\n ${o}\n </div>\n <div class="zest-modal__footer">\n <button type="button" class="zest-btn zest-btn--primary" data-action="save">\n ${n.save}\n </button>\n <button type="button" class="zest-btn zest-btn--secondary" data-action="accept-all">\n ${n.acceptAll}\n </button>\n <button type="button" class="zest-btn zest-btn--ghost" data-action="reject-all">\n ${n.rejectAll}\n </button>\n </div>\n </div>\n </div>\n `}(n,e),se.appendChild(a.firstElementChild);const s=se.querySelector(".zest-modal-overlay");return s.addEventListener("click",e=>{const n=e.target.dataset.action;if(n)switch(n){case"save":t.onSave?.(ie());break;case"accept-all":t.onAcceptAll?.();break;case"reject-all":t.onRejectAll?.()}else e.target===s&&t.onClose?.()}),s.addEventListener("keydown",e=>{"Escape"===e.key&&t.onClose?.()}),se.querySelectorAll(".zest-toggle__input").forEach(e=>{e.addEventListener("change",()=>{re=ie()})}),document.body.appendChild(ae),requestAnimationFrame(()=>{const e=se.querySelector("button");e?.focus()}),ae}function le(){ae&&(ae.remove(),ae=null,se=null)}let de=null,ue=null;function pe(e={}){de?de.style.display="":function(e={}){if(de)return de;const t=q();de=document.createElement("zest-widget"),de.setAttribute("data-theme",t.theme||"light"),ue=de.attachShadow({mode:"open"});const n=document.createElement("style");n.textContent=Q(t),ue.appendChild(n);const o=document.createElement("div");o.innerHTML=function(e){const t=e.labels.widget;return`\n <div class="zest-widget">\n <button type="button" class="zest-widget__btn" aria-label="${t.label}" title="${t.label}">\n <span class="zest-widget__icon"><svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 2C6.477 2 2 6.477 2 12s4.477 10 10 10 10-4.477 10-10c0-.728-.078-1.437-.225-2.12a1 1 0 0 0-1.482-.63 3 3 0 0 1-4.086-3.72 1 1 0 0 0-.793-1.263A10.05 10.05 0 0 0 12 2zm0 2c.178 0 .354.006.528.017a5 5 0 0 0 5.955 5.955c.011.174.017.35.017.528 0 4.418-3.582 8-8 8s-8-3.582-8-8 3.582-8 8-8zm-4 6a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3zm5 0a1 1 0 1 0 0 2 1 1 0 0 0 0-2zm-2 4a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3z"/></svg></span>\n </button>\n </div>\n `}(t),ue.appendChild(o.firstElementChild),ue.querySelector(".zest-widget__btn").addEventListener("click",()=>{e.onClick?.()}),document.body.appendChild(de)}(e)}function ge(){de&&(de.style.display="none")}let me=!1,fe=null;function be(e){return P(e)}function ye(e){!function(e){const t=[];for(const n of a)e.includes(n.category)?o?.set&&o.set.call(document,n.value):t.push(n);a.length=0,a.push(...t)}(e),function(e){const t=[];for(const n of l)e.includes(n.category)?i?.setItem(n.key,n.value):t.push(n);l.length=0,l.push(...t);const n=[];for(const t of d)e.includes(t.category)?c?.setItem(t.key,t.value):n.push(t);d.length=0,d.push(...n)}(e),function(e){const t=[];for(const n of y)e.includes(n.category)?_(n):t.push(n);y.length=0,y.push(...t),document.querySelectorAll('script[data-zest-processed="blocked"]').forEach(t=>{const n=t.getAttribute("data-consent-category");if(e.includes(n)){const e=document.createElement("script"),n=t.getAttribute("data-blocked-src");n?e.src=n:e.textContent=t.textContent,t.async&&(e.async=!0),t.defer&&(e.defer=!0),e.setAttribute("data-zest-processed","executed"),e.setAttribute("data-consent-executed","true"),t.parentNode?.replaceChild(e,t)}})}(e)}function he(){const e=function(e=365){return Z({functional:!0,analytics:!0,marketing:!0},e)}(fe.expiration),t=Object.keys(j);E(e.current,fe,!1),oe(),le(),ye(t),fe.showWidget&&pe({onClick:xe}),F(e.current,e.previous),X(e.current,e.previous),fe.callbacks?.onAccept?.(e.current),fe.callbacks?.onChange?.(e.current)}function ze(){const e=H(fe.expiration);E(e.current,fe,!1),oe(),le(),fe.showWidget&&pe({onClick:xe}),J(e.current),X(e.current,e.previous),fe.callbacks?.onReject?.(),fe.callbacks?.onChange?.(e.current)}function we(e){const t=Z(e,fe.expiration);E(t.current,fe,!1);const n=Object.keys(t.current).filter(e=>t.current[e]&&!t.previous[e]);n.length>0&&ye(n),le(),fe.showWidget&&pe({onClick:xe});Object.entries(e).some(([e,t])=>"essential"!==e&&t)?F(t.current,t.previous):J(t.current),X(t.current,t.previous),fe.callbacks?.onChange?.(t.current)}function xe(){oe(),ge(),ce(U(),{onSave:we,onAcceptAll:he,onRejectAll:ze,onClose:ve}),V("modal")}function ve(){le(),K("modal"),Y()&&fe.showWidget?pe({onClick:xe}):ne({onAcceptAll:he,onRejectAll:ze,onSettings:xe})}function ke(r={}){if(me)return console.warn("[Zest] Already initialized"),_e;fe=function(e){return D=N(e),D}(r),E({functional:!1,analytics:!1,marketing:!1},fe,!0),fe.patterns&&function(n){t={...e};for(const[e,o]of Object.entries(n))Array.isArray(o)&&(t[e]=o.map(e=>e instanceof RegExp?e:RegExp(e)))}(fe.patterns),s=be,function(e){u=e}(be),function(e){x=e}(be),o=Object.getOwnPropertyDescriptor(Document.prototype,"cookie"),o?Object.defineProperty(document,"cookie",{get:()=>o.get.call(document),set(e){const t=function(e){const t=e.match(/^([^=]+)/);return t?t[1].trim():null}(e);if(!t)return;const r=n(t);s(r)?o.set.call(document,e):a.push({value:e,name:t,category:r,timestamp:Date.now()})},configurable:!0}):console.warn("[Zest] Could not get cookie descriptor"),function(){try{return i=window.localStorage,c=window.sessionStorage,Object.defineProperty(window,"localStorage",{value:p(i,l),configurable:!0,writable:!1}),Object.defineProperty(window,"sessionStorage",{value:p(c,d),configurable:!0,writable:!1}),!0}catch(e){return console.warn("[Zest] Could not intercept storage APIs:",e),!1}}(),C(fe.mode,fe.blockedDomains);const g=W();me=!0,Y()&&E(g,fe,!1);let m=!1;if(S()&&fe.respectDNT&&"ignore"!==fe.dntBehavior&&"reject"===fe.dntBehavior&&!Y()){const e=H(fe.expiration);m=!0,E(e.current,fe,!1),J(e.current),X(e.current,e.previous),fe.callbacks?.onReject?.(),fe.callbacks?.onChange?.(e.current)}return function(e){G(B.READY,{consent:e})}(g),fe.callbacks?.onReady?.(g),Y()||m?fe.showWidget&&pe({onClick:xe}):(ne({onAcceptAll:he,onRejectAll:ze,onSettings:xe}),V("banner")),_e}const _e={init:ke,show(){me?(le(),ge(),ne({onAcceptAll:he,onRejectAll:ze,onSettings:xe}),V("banner")):console.warn("[Zest] Not initialized. Call Zest.init() first.")},hide(){oe(),K("banner")},showSettings(){me?xe():console.warn("[Zest] Not initialized. Call Zest.init() first.")},hideSettings(){le(),K("modal")},getConsent:U,hasConsent:P,hasConsentDecision:Y,getConsentProof:function(){try{const e=I().match(RegExp(L+"=([^;]+)"));if(e)return JSON.parse(decodeURIComponent(e[1]))}catch(e){}return null},isDoNotTrackEnabled:S,getDNTDetails:function(){if("undefined"==typeof navigator)return{enabled:!1,source:null};const e=navigator.doNotTrack||window.doNotTrack||navigator.msDoNotTrack;return"1"===e||"yes"===e||!0===e?{enabled:!0,source:"dnt"}:!0===navigator.globalPrivacyControl?{enabled:!0,source:"gpc"}:{enabled:!1,source:null}},acceptAll(){me?he():console.warn("[Zest] Not initialized. Call Zest.init() first.")},rejectAll(){me?ze():console.warn("[Zest] Not initialized. Call Zest.init() first.")},reset(){O(L+"=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/"),T=null,le(),de&&(de.remove(),de=null,ue=null),me&&(ne({onAcceptAll:he,onRejectAll:ze,onSettings:xe}),V("banner"))},getConfig:q,EVENTS:B};if("undefined"!=typeof window){window.Zest=_e;const e=()=>{!1!==$().autoInit&&ke(window.ZestConfig)};"loading"===document.readyState?document.addEventListener("DOMContentLoaded",e):e()}return _e}();
|
package/dist/zest.pl.js
CHANGED
|
@@ -842,6 +842,78 @@ var Zest = (function () {
|
|
|
842
842
|
return { enabled: false, source: null };
|
|
843
843
|
}
|
|
844
844
|
|
|
845
|
+
/**
|
|
846
|
+
* Consent Signals - Optional vendor consent mode integrations
|
|
847
|
+
*
|
|
848
|
+
* Pushes consent state to Google Consent Mode v2 and/or Microsoft UET
|
|
849
|
+
* Consent Mode when enabled via config.
|
|
850
|
+
*/
|
|
851
|
+
|
|
852
|
+
/**
|
|
853
|
+
* Map Zest consent state to Google Consent Mode v2 signals
|
|
854
|
+
*/
|
|
855
|
+
function toGoogleSignals(consent) {
|
|
856
|
+
const g = (val) => val ? 'granted' : 'denied';
|
|
857
|
+
return {
|
|
858
|
+
ad_storage: g(consent.marketing),
|
|
859
|
+
ad_user_data: g(consent.marketing),
|
|
860
|
+
ad_personalization: g(consent.marketing),
|
|
861
|
+
analytics_storage: g(consent.analytics),
|
|
862
|
+
functionality_storage: 'granted', // essential is always true
|
|
863
|
+
personalization_storage: g(consent.functional)
|
|
864
|
+
};
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
/**
|
|
868
|
+
* Push consent signal to Google via gtag or dataLayer fallback.
|
|
869
|
+
* Uses a local function to preserve the `arguments` object shape
|
|
870
|
+
* that gtag/dataLayer expects (not an array).
|
|
871
|
+
*/
|
|
872
|
+
function pushGoogle(type, signals) {
|
|
873
|
+
window.dataLayer = window.dataLayer || [];
|
|
874
|
+
if (typeof window.gtag === 'function') {
|
|
875
|
+
window.gtag('consent', type, signals);
|
|
876
|
+
} else {
|
|
877
|
+
function gtagFallback() { window.dataLayer.push(arguments); }
|
|
878
|
+
gtagFallback('consent', type, signals);
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
/**
|
|
883
|
+
* Map Zest consent state to Microsoft UET signal.
|
|
884
|
+
* Microsoft UET only exposes ad_storage.
|
|
885
|
+
*/
|
|
886
|
+
function toMicrosoftSignals(consent) {
|
|
887
|
+
return { ad_storage: consent.marketing ? 'granted' : 'denied' };
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
/**
|
|
891
|
+
* Push consent signal to Microsoft UET
|
|
892
|
+
*/
|
|
893
|
+
function pushMicrosoft(type, signals) {
|
|
894
|
+
window.uetq = window.uetq || [];
|
|
895
|
+
window.uetq.push('consent', type, signals);
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
/**
|
|
899
|
+
* Apply consent signals to enabled vendor integrations.
|
|
900
|
+
*
|
|
901
|
+
* @param {Object} consent Current Zest consent state
|
|
902
|
+
* @param {Object} config Merged Zest config
|
|
903
|
+
* @param {boolean} isDefault true on first call (pushes 'default'), false for updates
|
|
904
|
+
*/
|
|
905
|
+
function applyConsentSignals(consent, config, isDefault) {
|
|
906
|
+
const type = isDefault ? 'default' : 'update';
|
|
907
|
+
|
|
908
|
+
if (config.consentModeGoogle) {
|
|
909
|
+
pushGoogle(type, toGoogleSignals(consent));
|
|
910
|
+
}
|
|
911
|
+
|
|
912
|
+
if (config.consentModeMicrosoft) {
|
|
913
|
+
pushMicrosoft(type, toMicrosoftSignals(consent));
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
|
|
845
917
|
/**
|
|
846
918
|
* PL only translation - auto-generated
|
|
847
919
|
* Do not edit manually, run: npm run build
|
|
@@ -953,6 +1025,10 @@ var Zest = (function () {
|
|
|
953
1025
|
// Custom styles to inject into Shadow DOM
|
|
954
1026
|
customStyles: '',
|
|
955
1027
|
|
|
1028
|
+
// Vendor consent mode integrations (optional)
|
|
1029
|
+
consentModeGoogle: false,
|
|
1030
|
+
consentModeMicrosoft: false,
|
|
1031
|
+
|
|
956
1032
|
// Blocking mode: 'manual' | 'safe' | 'strict' | 'doomsday'
|
|
957
1033
|
mode: 'safe',
|
|
958
1034
|
|
|
@@ -983,7 +1059,7 @@ var Zest = (function () {
|
|
|
983
1059
|
}
|
|
984
1060
|
|
|
985
1061
|
// Simple properties
|
|
986
|
-
const simpleKeys = ['lang', 'position', 'theme', 'accentColor', 'autoInit', 'showWidget', 'expiration', 'policyUrl', 'imprintUrl', 'customStyles', 'mode', 'blockedDomains', 'respectDNT', 'dntBehavior'];
|
|
1062
|
+
const simpleKeys = ['lang', 'position', 'theme', 'accentColor', 'autoInit', 'showWidget', 'expiration', 'policyUrl', 'imprintUrl', 'customStyles', 'mode', 'blockedDomains', 'respectDNT', 'dntBehavior', 'consentModeGoogle', 'consentModeMicrosoft'];
|
|
987
1063
|
for (const key of simpleKeys) {
|
|
988
1064
|
if (userConfig[key] !== undefined) {
|
|
989
1065
|
config[key] = userConfig[key];
|
|
@@ -1093,6 +1169,13 @@ var Zest = (function () {
|
|
|
1093
1169
|
const expiration = script.getAttribute('data-expiration');
|
|
1094
1170
|
if (expiration) config.expiration = parseInt(expiration, 10);
|
|
1095
1171
|
|
|
1172
|
+
// Consent mode integrations
|
|
1173
|
+
const consentModeGoogle = script.getAttribute('data-consent-mode-google');
|
|
1174
|
+
if (consentModeGoogle !== null) config.consentModeGoogle = consentModeGoogle !== 'false';
|
|
1175
|
+
|
|
1176
|
+
const consentModeMicrosoft = script.getAttribute('data-consent-mode-microsoft');
|
|
1177
|
+
if (consentModeMicrosoft !== null) config.consentModeMicrosoft = consentModeMicrosoft !== 'false';
|
|
1178
|
+
|
|
1096
1179
|
return config;
|
|
1097
1180
|
}
|
|
1098
1181
|
|
|
@@ -2324,6 +2407,8 @@ ${config.customStyles || ''}
|
|
|
2324
2407
|
const result = acceptAll(config.expiration);
|
|
2325
2408
|
const categories = getCategoryIds();
|
|
2326
2409
|
|
|
2410
|
+
applyConsentSignals(result.current, config, false);
|
|
2411
|
+
|
|
2327
2412
|
hideBanner();
|
|
2328
2413
|
hideModal();
|
|
2329
2414
|
|
|
@@ -2345,6 +2430,8 @@ ${config.customStyles || ''}
|
|
|
2345
2430
|
function handleRejectAll() {
|
|
2346
2431
|
const result = rejectAll(config.expiration);
|
|
2347
2432
|
|
|
2433
|
+
applyConsentSignals(result.current, config, false);
|
|
2434
|
+
|
|
2348
2435
|
hideBanner();
|
|
2349
2436
|
hideModal();
|
|
2350
2437
|
|
|
@@ -2364,6 +2451,8 @@ ${config.customStyles || ''}
|
|
|
2364
2451
|
function handleSavePreferences(selections) {
|
|
2365
2452
|
const result = updateConsent(selections, config.expiration);
|
|
2366
2453
|
|
|
2454
|
+
applyConsentSignals(result.current, config, false);
|
|
2455
|
+
|
|
2367
2456
|
// Find newly allowed categories
|
|
2368
2457
|
const newlyAllowed = Object.keys(result.current).filter(
|
|
2369
2458
|
cat => result.current[cat] && !result.previous[cat]
|
|
@@ -2442,6 +2531,13 @@ ${config.customStyles || ''}
|
|
|
2442
2531
|
// Merge config
|
|
2443
2532
|
config = setConfig(userConfig);
|
|
2444
2533
|
|
|
2534
|
+
// Push default denied state to vendor consent mode APIs (must happen before scripts load)
|
|
2535
|
+
applyConsentSignals(
|
|
2536
|
+
{ functional: false, analytics: false, marketing: false },
|
|
2537
|
+
config,
|
|
2538
|
+
true
|
|
2539
|
+
);
|
|
2540
|
+
|
|
2445
2541
|
// Set patterns if provided
|
|
2446
2542
|
if (config.patterns) {
|
|
2447
2543
|
setPatterns(config.patterns);
|
|
@@ -2462,6 +2558,11 @@ ${config.customStyles || ''}
|
|
|
2462
2558
|
|
|
2463
2559
|
initialized = true;
|
|
2464
2560
|
|
|
2561
|
+
// Push update for returning visitors with saved consent
|
|
2562
|
+
if (hasConsentDecision()) {
|
|
2563
|
+
applyConsentSignals(consent, config, false);
|
|
2564
|
+
}
|
|
2565
|
+
|
|
2465
2566
|
// Check Do Not Track / Global Privacy Control
|
|
2466
2567
|
const dntEnabled = isDoNotTrackEnabled();
|
|
2467
2568
|
let dntApplied = false;
|
|
@@ -2472,6 +2573,8 @@ ${config.customStyles || ''}
|
|
|
2472
2573
|
const result = rejectAll(config.expiration);
|
|
2473
2574
|
dntApplied = true;
|
|
2474
2575
|
|
|
2576
|
+
applyConsentSignals(result.current, config, false);
|
|
2577
|
+
|
|
2475
2578
|
// Emit events
|
|
2476
2579
|
emitReject(result.current);
|
|
2477
2580
|
emitChange(result.current, result.previous);
|