cloudflare-next-intl 0.6.17 → 0.6.18

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.
@@ -18,23 +18,24 @@ const ClarityScript = dynamic(() => import('./clarity_script'));
18
18
  * `false` — render manually instead if you set `autoWireAnalytics: false`.
19
19
  */
20
20
  export default function CookieConsentAnalytics({ config }) {
21
- const { consent } = useCookieConsent();
21
+ const { consent, requiresConsent } = useCookieConsent();
22
+ const granted = consent === true || !requiresConsent;
22
23
  useEffect(() => {
23
- if (consent === null)
24
+ if (consent === null && requiresConsent)
24
25
  return;
25
26
  const w = window;
26
27
  if (typeof w.gtag !== 'function')
27
28
  return;
28
- const state = consent ? 'granted' : 'denied';
29
+ const state = granted ? 'granted' : 'denied';
29
30
  w.gtag('consent', 'update', {
30
31
  ad_storage: state,
31
32
  ad_user_data: state,
32
33
  ad_personalization: state,
33
34
  analytics_storage: state,
34
35
  });
35
- }, [consent]);
36
+ }, [consent, requiresConsent, granted]);
36
37
  const hasGoogle = Boolean(config.googleAnalyticsId || config.googleAdsId || config.googleAdSenseId);
37
- return (_jsxs(_Fragment, { children: [hasGoogle && (_jsx("script", { id: "cookie-consent-google-consent-mode", dangerouslySetInnerHTML: { __html: googleConsentModeBootstrapScript(config) } })), consent === true && config.cloudflareBeaconToken && (_jsx("script", { defer: true, src: "https://static.cloudflareinsights.com/beacon.min.js", "data-cf-beacon": config.cloudflareBeaconToken })), consent === true && config.clarityProjectId && _jsx(ClarityScript, { projectId: config.clarityProjectId })] }));
38
+ return (_jsxs(_Fragment, { children: [hasGoogle && (_jsx("script", { id: "cookie-consent-google-consent-mode", dangerouslySetInnerHTML: { __html: googleConsentModeBootstrapScript(config) } })), granted && config.cloudflareBeaconToken && (_jsx("script", { defer: true, src: "https://static.cloudflareinsights.com/beacon.min.js", "data-cf-beacon": config.cloudflareBeaconToken })), granted && config.clarityProjectId && _jsx(ClarityScript, { projectId: config.clarityProjectId })] }));
38
39
  }
39
40
  /**
40
41
  * Denies storage by default and loads the configured Google tags; the
@@ -13,8 +13,8 @@ import { defaultCookieDialogClassNames } from './default_dialog_styles';
13
13
  * particular design system.
14
14
  */
15
15
  export default function CookieConsentDialog({ message, link, privacyPolicyLinkText, acceptText, declineText, hideDecline = false, id = 'cookie-consent-dialog', classNames, styles, render, }) {
16
- const { consent, isMounted, setConsent, privacyPolicyPath } = useCookieConsent();
17
- if (!isMounted || consent !== null)
16
+ const { consent, requiresConsent, isMounted, setConsent, privacyPolicyPath } = useCookieConsent();
17
+ if (!isMounted || !requiresConsent || consent !== null)
18
18
  return null;
19
19
  if (render)
20
20
  return _jsx(_Fragment, { children: render({ setConsent }) });
@@ -65,19 +65,18 @@ export default function CookieConsentProvider({ requiresConsent = true, children
65
65
  const [isMounted, setIsMounted] = useState(false);
66
66
  const pathname = usePathname();
67
67
  useEffect(() => {
68
- // `undefined` (no cookie at all) means a genuine first visit auto-
69
- // accept applies. `'null'` (explicitly stored by `setConsent(null)`,
70
- // e.g. a "cookie settings" button) means the visitor already decided
71
- // once and is being asked to re-decide, so it must NOT auto-accept
72
- // again otherwise it'd immediately flip back to `true` whenever
73
- // `requiresConsent` is `false` (e.g. always in dev, see
74
- // `resolveRequiresConsent`), reopening then instantly re-closing the
75
- // dialog on the next navigation/refresh.
68
+ // `consent` reflects only what the visitor actually decidednever
69
+ // auto-set to `true` just because `requiresConsent` is `false`.
70
+ // Whether the banner shows / analytics unlock for a not-required
71
+ // visitor is `requiresConsent`'s job (see `CookieConsentDialog`/
72
+ // `CookieConsentAnalytics`), not something baked into `consent`
73
+ // itself; otherwise there's no way to tell "not required" apart
74
+ // from "explicitly accepted" (e.g. the settings button in the nav
75
+ // bar, which only renders once consent has been decided).
76
76
  const rawConsent = getCookie(consentCookieName);
77
77
  const storedConsent = parseConsent(rawConsent);
78
78
  const isFirstVisit = rawConsent === null;
79
- const autoAccepted = isFirstVisit && !requiresConsent;
80
- setConsentState(autoAccepted ? true : storedConsent);
79
+ setConsentState(storedConsent);
81
80
  setIsMounted(true);
82
81
  if (isFirstVisit || !policyDate)
83
82
  return;
@@ -121,6 +120,6 @@ export default function CookieConsentProvider({ requiresConsent = true, children
121
120
  acknowledgePrivacyPolicyUpdate();
122
121
  }
123
122
  }, [pathname, privacyPolicyUpdated, privacyPolicyPath, acknowledgePrivacyPolicyUpdate]);
124
- const contextValue = useMemo(() => ({ consent, privacyPolicyUpdated, isMounted, setConsent, acknowledgePrivacyPolicyUpdate, privacyPolicyPath }), [consent, privacyPolicyUpdated, isMounted, setConsent, acknowledgePrivacyPolicyUpdate, privacyPolicyPath]);
123
+ const contextValue = useMemo(() => ({ consent, requiresConsent, privacyPolicyUpdated, isMounted, setConsent, acknowledgePrivacyPolicyUpdate, privacyPolicyPath }), [consent, requiresConsent, privacyPolicyUpdated, isMounted, setConsent, acknowledgePrivacyPolicyUpdate, privacyPolicyPath]);
125
124
  return (_jsx(CookieConsentContext.Provider, { value: contextValue, children: children }));
126
125
  }
@@ -4,6 +4,15 @@ export type ConsentValue = boolean | null;
4
4
  export interface CookieConsentContextType {
5
5
  /** Current consent value; `null` until the visitor decides. */
6
6
  consent: ConsentValue;
7
+ /**
8
+ * Resolved server-side from `cookieConsent.getCountryCode`/
9
+ * `gdprCountries` (see `resolveRequiresConsent`). `false` means the
10
+ * visitor's country doesn't require consent at all — the default
11
+ * `CookieConsentDialog` stays hidden and `CookieConsentAnalytics`
12
+ * unlocks immediately, even while `consent` itself is still `null`
13
+ * (never decided, since there was nothing to decide).
14
+ */
15
+ requiresConsent: boolean;
7
16
  /**
8
17
  * `false` until the client has read the stored consent/date cookies once
9
18
  * (always `false` during SSR and the first client render, to avoid a
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cloudflare-next-intl",
3
- "version": "0.6.17",
3
+ "version": "0.6.18",
4
4
  "description": "Optimized Next Intl Package Special for App Router and Cloudflare",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",