Files
ipal-kit/dist/modules/consent/useConsent.js
T

80 lines
3.1 KiB
JavaScript

'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