@afex-dapps/cookie
Version:
Cookie Consent library for React
551 lines (533 loc) • 16.9 kB
JavaScript
var __defProp = Object.defineProperty;
var __defProps = Object.defineProperties;
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __propIsEnum = Object.prototype.propertyIsEnumerable;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __spreadValues = (a, b) => {
for (var prop in b || (b = {}))
if (__hasOwnProp.call(b, prop))
__defNormalProp(a, prop, b[prop]);
if (__getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(b)) {
if (__propIsEnum.call(b, prop))
__defNormalProp(a, prop, b[prop]);
}
return a;
};
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
var __objRest = (source, exclude) => {
var target = {};
for (var prop in source)
if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
target[prop] = source[prop];
if (source != null && __getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(source)) {
if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
target[prop] = source[prop];
}
return target;
};
var __async = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
// src/constants/attributes.ts
var cookieConsentAttributes = {
/**
* @description
* Use this value to accept all cookie categories.
*
* @example
*
* ```html
* <button type="button" data-cc="accept-all">Accept all categories</button>
* <a href="#" data-cc={cookieConsentAttributes.acceptAll}>Accept all categories</a>
* ```
*/
acceptAll: "accept-all",
/**
* @description
* Use this value to accept the current selection inside the preferences modal.
*
* @example
*
* ```html
* <button type="button" data-cc="accept-custom">Accept selection</button>
* <a href="#" data-cc={cookieConsentAttributes.acceptCustom}>Accept selection</a>
* ```
*/
acceptCustom: "accept-custom",
/**
* @description
* Use this value to accept only the necessary cookie categories.
*
* @example
*
* ```html
* <button type="button" data-cc="accept-necessary">Reject all categories</button>
* <a href="#" data-cc={cookieConsentAttributes.acceptNecessary}>Reject all categories</a>
* ```
*/
acceptNecessary: "accept-necessary",
/**
* @description
* Use this value to show the consentModal. If the consent modal does not exist, it will be generated on the fly.
*
* @example
*
* ```html
* <button type="button" data-cc="show-consentModal">View Consent Modal</button>
* <a href="#" data-cc={cookieConsentAttributes.showConsentModal}>View Consent Modal</a>
* ```
*/
showConsentModal: "show-consentModal",
/**
* @description
* Use this value to show the preferencesModal.
*
* @example
*
* ```html
* <button type="button" data-cc="show-preferencesModal">View Preferences Modal</button>
* <a href="#" data-cc={cookieConsentAttributes.showPreferencesModal}>View Preferences Modal</a>
* ```
*/
showPreferencesModal: "show-preferencesModal"
};
// src/constants/events.ts
var cookieConsentEvents = {
/**
* @description
* This event is triggered when the user modifies their preferences and only if consent has already been provided.
*
* @example
*
* ```js
* cookieConsentEvents.onChange // "cc:onChange"
* window.addEventListener('cc:onChange', ({ detail }) => {
* // detail.cookie
* // detail.changedCategories
* // detail.changedServices
* });
* ```
*/
onChange: "cc:onChange",
/**
* @description
* This event is triggered the very first time the user expresses their choice of consent — just like onFirstConsent — but also on every subsequent page load.
*
* @example
*
* ```js
* cookieConsentEvents.onConsent // "cc:onConsent"
* window.addEventListener('cc:onConsent', ({ detail }) => {
* // detail.cookie
* });
* ```
*/
onConsent: "cc:onConsent",
/**
* @description
* This event is triggered only the very first time that the user expresses their choice of consent (accept/reject).
*
* @example
*
* ```js
* cookieConsentEvents.onFirstConsent // "cc:onFirstConsent"
* window.addEventListener('cc:onFirstConsent', ({ detail }) => {
* // detail.cookie
* });
* ```
*/
onFirstConsent: "cc:onFirstConsent",
/**
* @description
* This event is triggered when one of the modals is hidden.
*
* @example
*
* ```js
* cookieConsentEvents.onModalHide // "cc:onModalHide"
* window.addEventListener('cc:onModalHide', ({ detail }) => {
* // detail.modalName
* });
* ```
*/
onModalHide: "cc:onModalHide",
/**
* @description
* This event is triggered when a modal is created and appended to the DOM.
*
* @example
*
* ```js
* cookieConsentEvents.onModalReady // "cc:onModalReady"
* window.addEventListener('cc:onModalReady', ({ detail }) => {
* // detail.modalName
* // detail.modal
* });
* ```
*/
onModalReady: "cc:onModalReady",
/**
* @description
* This event is triggered when one of the modals is visible.
*
* @example
*
* ```js
* cookieConsentEvents.onModalShow // "cc:onModalShow"
* window.addEventListener('cc:onModalShow', ({ detail }) => {
* // detail.modalName
* });
* ```
*/
onModalShow: "cc:onModalShow"
};
// src/helpers/is-dictionary/index.ts
function isDictionary(value) {
return Object.prototype.toString.call(value) === "[object Object]";
}
// src/helpers/is-valid-key/index.ts
function isValidKey(key) {
return key !== "__proto__" && key !== "constructor" && key !== "prototype";
}
// src/helpers/is-object/index.ts
function isObject(value) {
return value !== null && typeof value === "object";
}
// src/functions/clone-deep/index.ts
function cloneDeep(value, visited = /* @__PURE__ */ new WeakMap()) {
if (!isObject(value)) return value;
if (visited.has(value)) return visited.get(value);
if (value instanceof Date) {
return new Date(value.getTime());
}
if (value instanceof RegExp) {
return new RegExp(value.source, value.flags);
}
if (Array.isArray(value)) {
const clone = [];
visited.set(value, clone);
value.forEach((item, index) => {
clone[index] = cloneDeep(item, visited);
});
return clone;
}
if (isDictionary(value)) {
const result = Object.create(
Object.getPrototypeOf(value),
Object.getOwnPropertyDescriptors(value)
);
visited.set(value, result);
Reflect.ownKeys(result).forEach((key) => {
if (isValidKey(key) && Reflect.has(result, key)) {
const clone = cloneDeep(Reflect.get(result, key), visited);
Reflect.set(result, key, clone);
}
});
return result;
}
return value;
}
// src/functions/deep-merge/index.ts
function deepMerge(target, ...sources) {
return deepMergeInternal(target, sources, /* @__PURE__ */ new WeakMap());
}
function deepMergeInternal(target, sources, visited) {
if (!sources.length || sources.every((source) => !source)) {
return cloneDeep(target, visited);
}
if (isObject(target) && visited.has(target)) {
return visited.get(target);
}
const result = cloneDeep(target, visited);
if (isObject(target)) visited.set(target, result);
for (const source of sources) {
if (!source) continue;
for (const key of Reflect.ownKeys(source)) {
if (!isValidKey(key)) continue;
const targetValue = result[key];
const sourceValue = Reflect.get(source, key);
if (sourceValue === void 0) continue;
if (isObject(sourceValue) && visited.has(sourceValue)) {
Reflect.set(result, key, visited.get(sourceValue));
continue;
}
if (isDictionary(targetValue) && isDictionary(sourceValue)) {
Reflect.set(
result,
key,
deepMergeInternal(targetValue, [sourceValue], visited)
);
continue;
}
Reflect.set(result, key, cloneDeep(sourceValue, visited));
}
}
return result;
}
// src/constants/configuration.ts
var defaultConfiguration = {
autoClearCookies: true,
autoShow: false,
categories: {
analytics: {
enabled: true,
readOnly: false
},
necessary: {
enabled: true,
readOnly: true
}
},
cookie: {
expiresAfterDays: 180,
name: "_cc-cookie",
path: "/",
sameSite: "Strict",
secure: true,
useLocalStorage: false
},
disablePageInteraction: false,
hideFromBots: true,
language: {
autoDetect: "browser",
default: "en",
rtl: "ar",
translations: {
en: {
consentModal: {
acceptAllBtn: "Accept all",
acceptNecessaryBtn: "Reject all",
description: "Our site uses scripts (e.g. cookies) to collect and store data such as personal identifiers (IP address, session details) and browsing activity. This helps us deliver content, ensure security, enhance user experience, and support marketing. You can reject non-essential cookies or adjust your preferences by clicking here.",
showPreferencesBtn: "Manage Individual preferences",
title: "Cookie preferences"
},
preferencesModal: {
acceptAllBtn: "Accept all",
acceptNecessaryBtn: "Reject all",
closeIconLabel: "Close modal",
savePreferencesBtn: "Accept current selection",
sections: [],
title: "Manage cookie preferences"
}
}
}
},
manageScriptTags: true
};
// src/functions/create-cookie-configuration/index.ts
function createCookieConfiguration(options) {
return deepMerge(defaultConfiguration, options);
}
// src/functions/create-cookie-styles/index.ts
function createCookieStyles(styles) {
return styles;
}
// src/functions/css/index.ts
function css(variable) {
return `var(${variable})`;
}
// src/hooks/use-cookie-banner.ts
import * as CookieConsent2 from "vanilla-cookieconsent";
import { useCallback as useCallback2, useEffect as useEffect3, useMemo as useMemo2 } from "react";
// src/hooks/use-cookie-styles.ts
import { useEffect, useInsertionEffect, useLayoutEffect } from "react";
// src/functions/serialize-cookie-styles/index.ts
import { serializeStyles } from "@emotion/serialize";
function serializeCookieStyles(styles) {
return serializeStyles([styles]).styles;
}
// src/hooks/use-cookie-styles.ts
var useIsomorphicLayoutEffect = typeof window !== "undefined" ? useLayoutEffect : useEffect;
function useCookieStyles(activeTheme = "light", styles) {
useInsertionEffect(() => {
if (!styles) return;
const style = document.createElement("style");
style.innerHTML = serializeCookieStyles(styles);
document.head.insertAdjacentHTML("beforeend", style.outerHTML);
}, [styles]);
useIsomorphicLayoutEffect(() => {
if (!activeTheme) return;
const variants = { dark: "cc--darkmode", light: "default-light" };
const classes = document.documentElement.classList;
const theme = variants[activeTheme];
classes.toggle(theme, true);
}, [activeTheme]);
}
// src/functions/firebase/index.ts
import * as CookieConsent from "vanilla-cookieconsent";
import { initializeApp } from "firebase/app";
import { collection, doc, getDoc, getFirestore, setDoc } from "firebase/firestore/lite";
import { useCallback, useMemo } from "react";
function useSetupFirebase(firebaseConfig = { collectionName: "AFEX" }) {
const { collectionName, projectId } = firebaseConfig;
const app = useMemo(() => {
if (!projectId) return null;
try {
return initializeApp(firebaseConfig);
} catch (error) {
console.error("Failed to initialize Firebase:", error);
return null;
}
}, [firebaseConfig]);
const db = useMemo(() => {
if (!app) return null;
return getFirestore(app);
}, [app]);
const updateUserCookieData = useCallback(
(_0, ..._1) => __async(null, [_0, ..._1], function* (data, documentId = data.userId, onError) {
if (!collectionName || !documentId || !db) return null;
if (data.userId !== documentId) {
CookieConsent.setCookieData({
mode: "update",
value: { userId: data.userId }
});
}
try {
const cookieSettingsRef = collection(db, collectionName);
const newDocRef = doc(cookieSettingsRef, documentId);
yield setDoc(newDocRef, data);
return newDocRef.id;
} catch (error) {
onError == null ? void 0 : onError(error);
return null;
}
}),
[collectionName, db]
);
const retrieveUserCookieData = useCallback(
(documentId, onError) => __async(null, null, function* () {
if (!collectionName || !documentId || !db) return null;
try {
const cookieSettingsRef = collection(db, collectionName);
const docRef = doc(cookieSettingsRef, documentId);
const docSnapshot = yield getDoc(docRef);
if (!docSnapshot.exists()) return null;
return __spreadValues({ id: docSnapshot.id }, docSnapshot.data());
} catch (error) {
onError == null ? void 0 : onError(error);
return null;
}
}),
[collectionName, db]
);
return { retrieveUserCookieData, updateUserCookieData };
}
// src/hooks/use-unique-user-id/index.ts
import { useEffect as useEffect2, useState } from "react";
import { v4, v5 } from "uuid";
function useUniqueUserId() {
const [userId, setUserId] = useState(() => v4());
useEffect2(() => {
try {
const userInfo = {
browser: navigator.userAgent,
location: document.location.origin,
referrer: document.referrer,
screen_height: screen.height,
screen_width: screen.width
};
const userInfoString = Object.values(userInfo).join("|");
const clientSpecificId = v5(userInfoString, v5.URL);
setUserId(clientSpecificId);
} catch (error) {
console.error("Error generating client-specific unique user ID; will use initial random UUID:", error);
}
}, []);
return userId;
}
// src/hooks/use-cookie-banner.ts
function useCookieBanner({
activeTheme = "light",
configuration,
delay = 1e3,
firebase,
styles
} = {}) {
const userId = useUniqueUserId();
const _a = useMemo2(() => {
return deepMerge(
defaultConfiguration,
configuration
);
}, [configuration]), { onChange, onFirstConsent } = _a, options = __objRest(_a, ["onChange", "onFirstConsent"]);
const { retrieveUserCookieData, updateUserCookieData } = useSetupFirebase(firebase);
const logConsent = useCallback2(() => {
const cookie = CookieConsent2.getCookie();
const preferences = CookieConsent2.getUserPreferences();
if (firebase == null ? void 0 : firebase.apiKey) {
updateUserCookieData({
cookie,
language: options.language.default,
preferences,
userId
});
}
}, [
firebase == null ? void 0 : firebase.apiKey,
options.language.default,
updateUserCookieData,
userId
]);
const updateUserId = useCallback2(
(newUserId, onError) => __async(null, null, function* () {
if (firebase == null ? void 0 : firebase.apiKey) {
yield updateUserCookieData({ userId: newUserId }, userId, onError);
}
}),
[firebase == null ? void 0 : firebase.apiKey, userId, updateUserCookieData]
);
useEffect3(() => {
CookieConsent2.run(__spreadProps(__spreadValues({}, options), {
onChange: (param) => {
logConsent();
onChange == null ? void 0 : onChange(param);
},
onFirstConsent: (param) => {
logConsent();
onFirstConsent == null ? void 0 : onFirstConsent(param);
}
}));
const timeoutId = setTimeout(CookieConsent2.show, delay);
return () => {
clearTimeout(timeoutId);
};
}, [options, delay, logConsent, onFirstConsent, onChange]);
useEffect3(() => {
CookieConsent2.setCookieData({
mode: "update",
value: { userId }
});
}, [userId]);
useCookieStyles(activeTheme, styles);
return { retrieveUserCookieData, updateUserCookieData, updateUserId, userId };
}
export {
cookieConsentAttributes,
cookieConsentEvents,
createCookieConfiguration,
createCookieStyles,
css,
useCookieBanner
};
//# sourceMappingURL=index.js.map