'use client'; import { useCallback, useEffect, useState } from 'react'; import { LOCALE_COOKIE_NAME } from '../i18n/index.js'; import { ACCEPT_ALL_CONSENT, DEFAULT_CONSENT, REJECT_ALL_CONSENT } from './categories.js'; import { updateConsent } from './googleConsent.js'; import { CONSENT_COOKIE, CONSENT_MAX_AGE, parseConsent, serializeConsent } from './storage.js'; /** * Cookies to delete when consent for a category is withdrawn. Keyed by * category. The plugin knows about its own functional cookie (locale); clients * can extend this via the `cookieMap` arg to useConsent if they set their own. */ const DEFAULT_COOKIE_MAP = { functional: [ LOCALE_COOKIE_NAME ] }; /** Expire a cookie now, across the whole site. */ function deleteCookie(name) { document.cookie = `${name}=;path=/;max-age=0;samesite=lax`; } export function useConsent(cookieMap = DEFAULT_COOKIE_MAP) { const [state, setState] = useState(DEFAULT_CONSENT); const [decided, setDecided] = useState(false); useEffect(()=>{ const raw = document.cookie.split('; ').find((c)=>c.startsWith(`${CONSENT_COOKIE}=`))?.split('=')[1]; const parsed = parseConsent(raw); if (parsed) { setState(parsed); setDecided(true); } }, []); const persist = useCallback((next)=>{ // Withdrawal cleanup: for any category flipping true → false, delete the // cookies tied to it. GDPR: withdrawing consent must stop the processing, // so a functional cookie (e.g. locale) written under consent has to go when // that consent is revoked. Uses the current `state` as the previous value. for (const cat of Object.keys(cookieMap)){ const wasGranted = state[cat] === true; const nowDenied = next[cat] !== true; if (wasGranted && nowDenied) { for (const name of cookieMap[cat] ?? []){ deleteCookie(name); } } } document.cookie = `${CONSENT_COOKIE}=${serializeConsent(next)};path=/;max-age=${CONSENT_MAX_AGE};samesite=lax`; setState(next); setDecided(true); // Tell Google right away. Tags are already on the page holding whatever // defaults Analytics set at load; without this update they keep them for // the rest of the session and never write their cookies — the banner would // look like it worked while nothing changed. updateConsent(next); }, [ state, cookieMap ]); const acceptAll = useCallback(()=>persist(ACCEPT_ALL_CONSENT), [ persist ]); const rejectAll = useCallback(()=>persist(REJECT_ALL_CONSENT), [ persist ]); const savePreferences = useCallback((choices)=>persist({ ...DEFAULT_CONSENT, ...choices, necessary: true }), [ persist ]); const reopen = useCallback(()=>setDecided(false), []); return { acceptAll, decided, rejectAll, reopen, savePreferences, state }; } //# sourceMappingURL=useConsent.js.map