cloudflare-next-intl 0.5.3 → 0.5.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/cookie_consent/client/components/cookie_consent_dialog.js +2 -1
- package/dist/src/cookie_consent/client/components/default_dialog_styles.js +1 -1
- package/dist/src/cookie_consent/client/components/dialog_portal.d.ts +11 -0
- package/dist/src/cookie_consent/client/components/dialog_portal.js +13 -0
- package/dist/src/cookie_consent/client/components/privacy_policy_update_dialog.js +2 -1
- package/dist/src/cookie_consent/client/cookie_consent_provider.d.ts +4 -1
- package/dist/src/cookie_consent/client/cookie_consent_provider.js +15 -1
- package/package.json +1 -1
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import useCookieConsent from '../use_cookie_consent';
|
|
4
4
|
import DefaultPrivacyPolicyLink from './default_privacy_policy_link';
|
|
5
|
+
import DialogPortal from './dialog_portal';
|
|
5
6
|
import { getLocaleCache } from '../../../general/cache_variables';
|
|
6
7
|
import { defaultCookieConsentText } from './default_dialog_text';
|
|
7
8
|
import { defaultCookieDialogClassNames } from './default_dialog_styles';
|
|
@@ -26,5 +27,5 @@ export default function CookieConsentDialog({ message, link, privacyPolicyLinkTe
|
|
|
26
27
|
const resolvedLink = link !== undefined
|
|
27
28
|
? link
|
|
28
29
|
: _jsx(DefaultPrivacyPolicyLink, { privacyPolicyPath: privacyPolicyPath, text: resolvedPrivacyPolicyLinkText, className: resolvedClassNames.link });
|
|
29
|
-
return (_jsxs("div", { id: id, role: "dialog", "aria-modal": "false", "aria-labelledby": `${id}-title`, className: resolvedClassNames.root, style: styles?.root, children: [_jsxs("p", { id: `${id}-title`, className: resolvedClassNames.message, style: styles?.message, children: [resolvedMessage, resolvedLink ? _jsxs("span", { children: [" ", resolvedLink] }) : null] }), _jsxs("div", { className: resolvedClassNames.actions, style: styles?.actions, children: [!hideDecline && (_jsx("button", { type: "button", onClick: () => setConsent(false), className: resolvedClassNames.declineButton, style: styles?.declineButton, children: resolvedDeclineText })), _jsx("button", { type: "button", onClick: () => setConsent(true), className: resolvedClassNames.acceptButton, style: styles?.acceptButton, children: resolvedAcceptText })] })] }));
|
|
30
|
+
return (_jsx(DialogPortal, { children: _jsxs("div", { id: id, role: "dialog", "aria-modal": "false", "aria-labelledby": `${id}-title`, className: resolvedClassNames.root, style: styles?.root, children: [_jsxs("p", { id: `${id}-title`, className: resolvedClassNames.message, style: styles?.message, children: [resolvedMessage, resolvedLink ? _jsxs("span", { children: [" ", resolvedLink] }) : null] }), _jsxs("div", { className: resolvedClassNames.actions, style: styles?.actions, children: [!hideDecline && (_jsx("button", { type: "button", onClick: () => setConsent(false), className: resolvedClassNames.declineButton, style: styles?.declineButton, children: resolvedDeclineText })), _jsx("button", { type: "button", onClick: () => setConsent(true), className: resolvedClassNames.acceptButton, style: styles?.acceptButton, children: resolvedAcceptText })] })] }) }));
|
|
30
31
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export const defaultCookieDialogClassNames = {
|
|
2
|
-
root: 'fixed bottom-0 w-full bg-cyan-50 dark:bg-cyan-950 text-gray-800 dark:text-gray-200 z-
|
|
2
|
+
root: 'fixed bottom-0 w-full bg-cyan-50 dark:bg-cyan-950 text-gray-800 dark:text-gray-200 z-[2147483647] flex flex-col sm:flex-row sm:justify-between items-center gap-3 sticky border-t border-t-gray-600 dark:border-t-gray-400 rounded-t-2xl px-4 py-3',
|
|
3
3
|
message: 'text-sm sm:text-base text-gray-600 dark:text-gray-300',
|
|
4
4
|
link: 'underline font-bold duration-200 text-gray-600 hover:text-cyan-800 dark:text-gray-200 dark:hover:text-gray-100 active:text-cyan-700',
|
|
5
5
|
actions: 'flex flex-row gap-2',
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Renders `children` into `document.body` via a portal, so the default
|
|
3
|
+
* dialogs always stack on top of the host app regardless of its own
|
|
4
|
+
* stacking contexts (a `z-index` alone can't escape an ancestor with
|
|
5
|
+
* `transform`/`filter`/`opacity`/`isolation`, all common in app shells).
|
|
6
|
+
* Only called client-side (both dialogs already gate on `isMounted`), so
|
|
7
|
+
* `document` is always defined here.
|
|
8
|
+
*/
|
|
9
|
+
export default function DialogPortal({ children }: {
|
|
10
|
+
children: React.ReactNode;
|
|
11
|
+
}): React.ReactPortal;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { createPortal } from 'react-dom';
|
|
3
|
+
/**
|
|
4
|
+
* Renders `children` into `document.body` via a portal, so the default
|
|
5
|
+
* dialogs always stack on top of the host app regardless of its own
|
|
6
|
+
* stacking contexts (a `z-index` alone can't escape an ancestor with
|
|
7
|
+
* `transform`/`filter`/`opacity`/`isolation`, all common in app shells).
|
|
8
|
+
* Only called client-side (both dialogs already gate on `isMounted`), so
|
|
9
|
+
* `document` is always defined here.
|
|
10
|
+
*/
|
|
11
|
+
export default function DialogPortal({ children }) {
|
|
12
|
+
return createPortal(children, document.body);
|
|
13
|
+
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import useCookieConsent from '../use_cookie_consent';
|
|
4
4
|
import DefaultPrivacyPolicyLink from './default_privacy_policy_link';
|
|
5
|
+
import DialogPortal from './dialog_portal';
|
|
5
6
|
import { getLocaleCache } from '../../../general/cache_variables';
|
|
6
7
|
import { defaultPrivacyPolicyUpdateText } from './default_dialog_text';
|
|
7
8
|
import { defaultCookieDialogClassNames } from './default_dialog_styles';
|
|
@@ -25,5 +26,5 @@ export default function PrivacyPolicyUpdateDialog({ message, link, privacyPolicy
|
|
|
25
26
|
const resolvedLink = link !== undefined
|
|
26
27
|
? link
|
|
27
28
|
: _jsx(DefaultPrivacyPolicyLink, { privacyPolicyPath: privacyPolicyPath, text: resolvedPrivacyPolicyLinkText, className: resolvedClassNames.link });
|
|
28
|
-
return (_jsxs("div", { id: id, role: "dialog", "aria-modal": "false", "aria-labelledby": `${id}-title`, className: resolvedClassNames.root, style: styles?.root, children: [_jsxs("p", { id: `${id}-title`, className: resolvedClassNames.message, style: styles?.message, children: [resolvedMessage, resolvedLink ? _jsxs("span", { children: [" ", resolvedLink] }) : null] }), _jsx("button", { type: "button", onClick: acknowledgePrivacyPolicyUpdate, "aria-label": resolvedCloseText, className: resolvedClassNames.closeButton, style: styles?.closeButton, children: resolvedCloseText })] }));
|
|
29
|
+
return (_jsx(DialogPortal, { children: _jsxs("div", { id: id, role: "dialog", "aria-modal": "false", "aria-labelledby": `${id}-title`, className: resolvedClassNames.root, style: styles?.root, children: [_jsxs("p", { id: `${id}-title`, className: resolvedClassNames.message, style: styles?.message, children: [resolvedMessage, resolvedLink ? _jsxs("span", { children: [" ", resolvedLink] }) : null] }), _jsx("button", { type: "button", onClick: acknowledgePrivacyPolicyUpdate, "aria-label": resolvedCloseText, className: resolvedClassNames.closeButton, style: styles?.closeButton, children: resolvedCloseText })] }) }));
|
|
29
30
|
}
|
|
@@ -11,7 +11,10 @@ export declare const CookieConsentContext: import("react").Context<CookieConsent
|
|
|
11
11
|
* `cookieConsent.privacyPolicyDate` is configured: once a visitor has
|
|
12
12
|
* consented, if their stored consent date predates `privacyPolicyDate`,
|
|
13
13
|
* `privacyPolicyUpdated` becomes `true` until they call
|
|
14
|
-
* `acknowledgePrivacyPolicyUpdate()
|
|
14
|
+
* `acknowledgePrivacyPolicyUpdate()` — or until they navigate to
|
|
15
|
+
* `cookieConsent.privacyPolicyPath`, which auto-acknowledges it (visiting
|
|
16
|
+
* the page counts as having seen the update; skipped entirely when
|
|
17
|
+
* `privacyPolicyPath` is `false`).
|
|
15
18
|
*
|
|
16
19
|
* @param requiresConsent Resolved server-side from
|
|
17
20
|
* `cookieConsent.getCountryCode`/`gdprCountries` — `false` means the
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
3
|
import { createContext, useCallback, useEffect, useMemo, useState } from 'react';
|
|
4
|
+
import { usePathname } from 'next/navigation';
|
|
4
5
|
import config from '../../config/intl_config';
|
|
5
6
|
import requireCookieConsentConfig from '../require_config';
|
|
6
7
|
import getCookie from '../../client/functions/get_cookie';
|
|
@@ -25,7 +26,10 @@ function parseConsent(raw) {
|
|
|
25
26
|
* `cookieConsent.privacyPolicyDate` is configured: once a visitor has
|
|
26
27
|
* consented, if their stored consent date predates `privacyPolicyDate`,
|
|
27
28
|
* `privacyPolicyUpdated` becomes `true` until they call
|
|
28
|
-
* `acknowledgePrivacyPolicyUpdate()
|
|
29
|
+
* `acknowledgePrivacyPolicyUpdate()` — or until they navigate to
|
|
30
|
+
* `cookieConsent.privacyPolicyPath`, which auto-acknowledges it (visiting
|
|
31
|
+
* the page counts as having seen the update; skipped entirely when
|
|
32
|
+
* `privacyPolicyPath` is `false`).
|
|
29
33
|
*
|
|
30
34
|
* @param requiresConsent Resolved server-side from
|
|
31
35
|
* `cookieConsent.getCountryCode`/`gdprCountries` — `false` means the
|
|
@@ -59,6 +63,7 @@ export default function CookieConsentProvider({ requiresConsent = true, children
|
|
|
59
63
|
const [consent, setConsentState] = useState(null);
|
|
60
64
|
const [privacyPolicyUpdated, setPrivacyPolicyUpdated] = useState(false);
|
|
61
65
|
const [isMounted, setIsMounted] = useState(false);
|
|
66
|
+
const pathname = usePathname();
|
|
62
67
|
useEffect(() => {
|
|
63
68
|
const storedConsent = parseConsent(getCookie(consentCookieName));
|
|
64
69
|
const autoAccepted = storedConsent === null && !requiresConsent;
|
|
@@ -90,6 +95,15 @@ export default function CookieConsentProvider({ requiresConsent = true, children
|
|
|
90
95
|
setPrivacyPolicyUpdated(false);
|
|
91
96
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
92
97
|
}, []);
|
|
98
|
+
// Visiting the privacy-policy page itself counts as having seen the
|
|
99
|
+
// update — auto-acknowledge instead of also showing the banner there.
|
|
100
|
+
// `pathname` still carries the locale prefix (e.g. `/de/privacy-policy`),
|
|
101
|
+
// so match on a trailing segment rather than strict equality.
|
|
102
|
+
useEffect(() => {
|
|
103
|
+
if (privacyPolicyUpdated && privacyPolicyPath !== false && pathname.endsWith(privacyPolicyPath)) {
|
|
104
|
+
acknowledgePrivacyPolicyUpdate();
|
|
105
|
+
}
|
|
106
|
+
}, [pathname, privacyPolicyUpdated, privacyPolicyPath, acknowledgePrivacyPolicyUpdate]);
|
|
93
107
|
const contextValue = useMemo(() => ({ consent, privacyPolicyUpdated, isMounted, setConsent, acknowledgePrivacyPolicyUpdate, privacyPolicyPath }), [consent, privacyPolicyUpdated, isMounted, setConsent, acknowledgePrivacyPolicyUpdate, privacyPolicyPath]);
|
|
94
108
|
return (_jsx(CookieConsentContext.Provider, { value: contextValue, children: children }));
|
|
95
109
|
}
|