cloudflare-next-intl 0.5.6 → 0.5.7

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.
@@ -1,4 +1,4 @@
1
- import type { CookieDialogClassNames, CookieDialogStyles } from '../../types';
1
+ import type { ConsentValue, CookieDialogClassNames, CookieDialogStyles } from '../../types';
2
2
  export interface CookieConsentDialogProps {
3
3
  /** Banner message text. */
4
4
  message?: React.ReactNode;
@@ -23,7 +23,7 @@ export interface CookieConsentDialogProps {
23
23
  * bypasses the default markup entirely. Use for a fully bespoke dialog.
24
24
  */
25
25
  render?: (props: {
26
- setConsent: (value: boolean) => void;
26
+ setConsent: (value: ConsentValue) => void;
27
27
  }) => React.ReactNode;
28
28
  }
29
29
  /**
@@ -65,11 +65,20 @@ export default function CookieConsentProvider({ requiresConsent = true, children
65
65
  const [isMounted, setIsMounted] = useState(false);
66
66
  const pathname = usePathname();
67
67
  useEffect(() => {
68
- const storedConsent = parseConsent(getCookie(consentCookieName));
69
- const autoAccepted = storedConsent === null && !requiresConsent;
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.
76
+ const rawConsent = getCookie(consentCookieName);
77
+ const storedConsent = parseConsent(rawConsent);
78
+ const isFirstVisit = rawConsent === null;
79
+ const autoAccepted = isFirstVisit && !requiresConsent;
70
80
  setConsentState(autoAccepted ? true : storedConsent);
71
81
  setIsMounted(true);
72
- const isFirstVisit = storedConsent === null && !autoAccepted;
73
82
  if (isFirstVisit || !policyDate)
74
83
  return;
75
84
  const storedDateRaw = getCookie(dateCookieName);
@@ -81,10 +90,18 @@ export default function CookieConsentProvider({ requiresConsent = true, children
81
90
  setPrivacyPolicyUpdated(!Number.isNaN(storedDate.getTime()) && storedDate < policyDate);
82
91
  // eslint-disable-next-line react-hooks/exhaustive-deps
83
92
  }, []);
93
+ // `value: null` stores the literal string `'null'` (rather than clearing
94
+ // the cookie) so the mount effect above can tell "explicitly reset" apart
95
+ // from "no cookie yet" and skip auto-accept accordingly.
84
96
  const setConsent = useCallback((value) => {
85
- setCookie({ name: consentCookieName, value, maxAge });
86
- if (policyDate)
87
- setCookie({ name: dateCookieName, value: policyDate.toISOString(), maxAge });
97
+ if (value === null) {
98
+ setCookie({ name: consentCookieName, value: 'null', maxAge });
99
+ }
100
+ else {
101
+ setCookie({ name: consentCookieName, value, maxAge });
102
+ if (policyDate)
103
+ setCookie({ name: dateCookieName, value: policyDate.toISOString(), maxAge });
104
+ }
88
105
  setConsentState(value);
89
106
  setPrivacyPolicyUpdated(false);
90
107
  // eslint-disable-next-line react-hooks/exhaustive-deps
@@ -18,8 +18,13 @@ export interface CookieConsentContextType {
18
18
  * acknowledged yet. Always `false` when `privacyPolicyDate` is unset.
19
19
  */
20
20
  privacyPolicyUpdated: boolean;
21
- /** Accepts (or rejects, with `false`) cookie consent and persists it. */
22
- setConsent: (value: boolean) => void;
21
+ /**
22
+ * Accepts (or rejects, with `false`) cookie consent and persists it.
23
+ * Pass `null` to clear the stored decision and reset `consent` back to
24
+ * `null`, so the default `CookieConsentDialog` banner reappears (e.g.
25
+ * for a "cookie settings" button).
26
+ */
27
+ setConsent: (value: ConsentValue) => void;
23
28
  /** Acknowledges the privacy-policy update banner and persists the new date. */
24
29
  acknowledgePrivacyPolicyUpdate: () => void;
25
30
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cloudflare-next-intl",
3
- "version": "0.5.6",
3
+ "version": "0.5.7",
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",