@scaleway/use-analytics
Version:
A small hook to handle events analytics
157 lines (156 loc) • 5.17 kB
JavaScript
;
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const jsxRuntime = require("react/jsx-runtime");
const cookie = require("cookie");
const react = require("react");
const useDestinations = require("../analytics/useDestinations.cjs");
const constants = require("../constants.cjs");
const array = require("../helpers/array.cjs");
const isClient = require("../helpers/isClient.cjs");
const misc = require("../helpers/misc.cjs");
const types = require("../types.cjs");
const CookieConsentContext = react.createContext(void 0);
const useCookieConsent = () => {
const context = react.useContext(CookieConsentContext);
if (context === void 0) {
throw new Error(
"useCookieConsent must be used within a CookieConsentProvider"
);
}
return context;
};
const CookieConsentProvider = ({
children,
isConsentRequired,
manualDestinations,
config,
cookiePrefix = constants.COOKIE_PREFIX,
consentMaxAge = constants.CONSENT_MAX_AGE,
consentAdvertisingMaxAge = constants.CONSENT_ADVERTISING_MAX_AGE,
cookiesOptions = constants.COOKIES_OPTIONS
}) => {
const [needConsent, setNeedsConsent] = react.useState(false);
const [cookies, setCookies] = react.useState(
isClient.IS_CLIENT ? cookie.parse(document.cookie) : {}
);
const {
destinations: analyticsDestinations,
isLoaded: isDestinationsLoaded
} = useDestinations.useDestinations(config);
const destinations = react.useMemo(
() => array.uniq([
...(analyticsDestinations ?? []).map(
(dest) => ({
category: dest.consents[0] ?? "essential",
displayName: dest.displayName,
name: dest.name
})
),
...manualDestinations ?? []
]),
[analyticsDestinations, manualDestinations]
);
const destinationsHash = react.useMemo(
() => misc.stringToHash(
array.uniq(destinations.map(({ name }) => name)).sort().join(void 0)
),
[destinations]
);
react.useEffect(() => {
setNeedsConsent(
isConsentRequired && cookies[constants.HASH_COOKIE] !== destinationsHash.toString() && analyticsDestinations !== void 0
);
}, [isConsentRequired, destinationsHash, analyticsDestinations, cookies]);
const cookieConsent = react.useMemo(
() => constants.CATEGORIES.reduce(
(acc, category) => ({
...acc,
[category]: isConsentRequired || needConsent ? cookies[`${cookiePrefix}_${category}`] === "true" : true
}),
{}
),
[isConsentRequired, cookiePrefix, needConsent, cookies]
);
const saveConsent = react.useCallback(
(categoriesConsent) => {
for (const [consentName, consentValue] of Object.entries(
categoriesConsent
)) {
const consentCategoryName = types.isCategoryKind(consentName) ? consentName : "unknown";
const cookieName = `${cookiePrefix}_${consentCategoryName}`;
if (!consentValue) {
document.cookie = cookie.serialize(cookieName, "", {
...cookiesOptions,
expires: /* @__PURE__ */ new Date(0)
});
} else {
document.cookie = cookie.serialize(cookieName, consentValue.toString(), {
...cookiesOptions,
maxAge: consentCategoryName === "advertising" ? consentAdvertisingMaxAge : consentMaxAge
});
}
setCookies((prevCookies) => ({
...prevCookies,
[cookieName]: consentValue ? "true" : "false"
}));
}
document.cookie = cookie.serialize(constants.HASH_COOKIE, destinationsHash.toString(), {
...cookiesOptions,
// Here we use the shortest max age to force to ask again for expired consent
maxAge: consentAdvertisingMaxAge
});
setCookies((prevCookies) => ({
...prevCookies,
[constants.HASH_COOKIE]: destinationsHash.toString()
}));
setNeedsConsent(false);
},
[
destinationsHash,
consentAdvertisingMaxAge,
consentMaxAge,
cookiePrefix,
cookiesOptions
]
);
const allowedConsents = react.useMemo(
() => Object.keys(cookieConsent).filter(
// oxlint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
(key) => !cookieConsent[key]
),
[cookieConsent]
);
const deniedConsents = react.useMemo(
() => Object.keys(cookieConsent).filter(
// oxlint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
(key) => !allowedConsents.includes(key)
),
[cookieConsent, allowedConsents]
);
const value = react.useMemo(
() => ({
allowedConsents,
categories: constants.CATEGORIES,
categoriesConsent: cookieConsent,
cookies,
deniedConsents,
destinations,
isDestinationsLoaded,
needConsent,
saveConsent
}),
[
destinations,
isDestinationsLoaded,
needConsent,
allowedConsents,
deniedConsents,
cookieConsent,
saveConsent,
cookies
]
);
return /* @__PURE__ */ jsxRuntime.jsx(CookieConsentContext.Provider, { value, children });
};
exports.CookieConsentProvider = CookieConsentProvider;
exports.useCookieConsent = useCookieConsent;