diff --git a/CHANGELOG.md b/CHANGELOG.md index d6d6fc5..144b8ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +2.8.0 +===== + +* (feature) Add `ConsentManagerIntegration`. +* (improvement) Add `hasAnyConsnet` to `useCookiebot`. + + 2.7.7 ===== diff --git a/package.json b/package.json index 53f555f..d37ba7f 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "zod": "^4.3.6" }, "optionalDependencies": { - "next": "^15.5.12", + "next": "^15.5.12 || ^16.1.6", "react": "^19.2.4", "react-dom": "^19.2.4" }, diff --git a/src/next/components/Snippet/ConsentManagerIntegration.tsx b/src/next/components/Snippet/ConsentManagerIntegration.tsx new file mode 100644 index 0000000..0ea4f6c --- /dev/null +++ b/src/next/components/Snippet/ConsentManagerIntegration.tsx @@ -0,0 +1,88 @@ +"use client"; + +import React, {Fragment, type ReactElement, type ReactNode} from "react"; +import {Cookiebot, type ConsentManagerProps} from "./Cookiebot"; +import {Usercentrics, type UsercentricsProps} from "./Usercentrics"; +import {UsercentricsV3, type UsercentricsV3Props} from "./UsercentricsV3"; +import {useCookiebot} from "../../../react/hooks/cookiebot"; +import {useUsercentrics} from "../../../react/hooks/usercentrics"; + +type CookiebotIntegration = Readonly & { + cookiebot: ConsentManagerProps["id"]; +}>; + +type UsercentricsV2Integration = Readonly & { + usercentricsV2: UsercentricsProps["id"]; +}>; + +type UsercentricsV3Integration = Readonly & { + usercentricsV3: UsercentricsV3Props["id"]; +}>; + +type ConsentIntegration = CookiebotIntegration | UsercentricsV2Integration | UsercentricsV3Integration; + +function isCookiebot (consent: ConsentIntegration): consent is CookiebotIntegration +{ + return "cookiebot" in consent; +} + +function isUsercentricsV2 (consent: ConsentIntegration): consent is UsercentricsV2Integration +{ + return "usercentricsV2" in consent; +} + +function isUsercentricsV3 (consent: ConsentIntegration): consent is UsercentricsV3Integration +{ + return "usercentricsV3" in consent; +} + +type ConsentManagerIntegrationProps = Readonly<{ + embedOnAnyConsent?: ReactNode; + consent: ConsentIntegration; +}>; + +export function ConsentManagerIntegration (props: ConsentManagerIntegrationProps): ReactElement | null +{ + const {consent, embedOnAnyConsent} = props; + + const cookiebot = useCookiebot(); + const usercentrics = useUsercentrics(); + + if (isCookiebot(consent)) + { + const {cookiebot: cookieBotId, ...rest} = consent; + + return ( + + + {cookiebot.hasAnyConsent && embedOnAnyConsent} + + ); + } + + if (isUsercentricsV2(consent)) + { + const {usercentricsV2: usercentricsId, ...rest} = consent; + + return ( + + + {usercentrics.hasAnyConsent && embedOnAnyConsent} + + ); + } + + if (isUsercentricsV3(consent)) + { + const {usercentricsV3: usercentricsId, ...rest} = consent; + + return ( + + + {usercentrics.hasAnyConsent && embedOnAnyConsent} + + ); + } + + throw new Error("No supported consent option given."); +} diff --git a/src/react/hooks/cookiebot.ts b/src/react/hooks/cookiebot.ts index fdd89dc..2f6c723 100644 --- a/src/react/hooks/cookiebot.ts +++ b/src/react/hooks/cookiebot.ts @@ -12,7 +12,8 @@ type WindowWithCookiebot = Window & Readonly<{ statistics: boolean; method: "explicit"; stamp: string; - } + }; + consented: boolean; }; }>; @@ -26,6 +27,7 @@ type ConsentSettings = { type CookiebotSettings = Readonly<{ openConsentManager(): void; consent: Omit; + hasAnyConsent: boolean; }>; /** @@ -33,6 +35,7 @@ type CookiebotSettings = Readonly<{ */ export function useCookiebot () : CookiebotSettings { + const [hasAnyConsent, setHasAnyConsent] = useState(false); const [consent, setConsent] = useState({ stamp: "unset", marketing: false, @@ -51,6 +54,7 @@ export function useCookiebot () : CookiebotSettings return; } + setHasAnyConsent(global.Cookiebot.consented); setConsent({ ...global.Cookiebot.consent, }); @@ -71,5 +75,6 @@ export function useCookiebot () : CookiebotSettings { (window as WindowWithCookiebot).Cookiebot?.renew(); }, + hasAnyConsent, }; }