cookie-app 2.0.0

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.
@@ -0,0 +1,357 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+
3
+ /** The level of consent granted by the user. */
4
+ type ConsentLevel = 'all' | 'necessary';
5
+ /** Banner language. `'auto'` detects from `navigator.language`. */
6
+ type Language = 'fr' | 'en' | 'auto';
7
+ /** Banner display style. */
8
+ type BannerStyle = 'bar' | 'popup' | 'corner';
9
+ /** Banner position (applies to bar and corner styles). */
10
+ type BannerPosition = 'top' | 'bottom';
11
+ /** Color theme for the banner. */
12
+ type BannerTheme = 'light' | 'dark';
13
+ /** Animation type for the banner entrance/exit. */
14
+ type Animation = 'slide' | 'fade';
15
+ /** Custom text overrides for one language. */
16
+ interface ConsentTexts {
17
+ /** Banner title. */
18
+ title?: string;
19
+ /** Banner message/description. */
20
+ message?: string;
21
+ /** Accept button label. */
22
+ accept?: string;
23
+ /** Reject button label. */
24
+ reject?: string;
25
+ /** Privacy policy link text. */
26
+ privacy?: string;
27
+ /** "Powered by" text (only shown when `poweredBy` is true). */
28
+ powered?: string;
29
+ }
30
+ /** Props for the `<CookieConsent>` component. */
31
+ interface CookieConsentProps {
32
+ /**
33
+ * Banner language. `'auto'` detects from `navigator.language`.
34
+ * @default 'fr'
35
+ */
36
+ lang?: Language;
37
+ /**
38
+ * Banner position — applies to `bar` and `corner` styles.
39
+ * @default 'bottom'
40
+ */
41
+ position?: BannerPosition;
42
+ /**
43
+ * Color theme.
44
+ * @default 'light'
45
+ */
46
+ theme?: BannerTheme;
47
+ /**
48
+ * Banner display style.
49
+ * - `'bar'` — full-width bar fixed to top or bottom.
50
+ * - `'popup'` — centered modal with overlay.
51
+ * - `'corner'` — small widget in the corner.
52
+ * @default 'bar'
53
+ */
54
+ style?: BannerStyle;
55
+ /**
56
+ * Enable glassmorphism (frosted glass) effect.
57
+ * @default false
58
+ */
59
+ glassmorphism?: boolean;
60
+ /**
61
+ * URL to your privacy policy page.
62
+ * @default '/politique-de-confidentialite'
63
+ */
64
+ privacyUrl?: string;
65
+ /**
66
+ * Show a "Powered by Rayels" attribution link.
67
+ * @default false
68
+ */
69
+ poweredBy?: boolean;
70
+ /**
71
+ * Brand color for the Accept button and reconsent button.
72
+ * Any valid CSS color string.
73
+ * @default '#1d4ed8'
74
+ */
75
+ brandColor?: string;
76
+ /**
77
+ * Number of days before consent expires and the banner reappears.
78
+ * @default 365
79
+ */
80
+ expiryDays?: number;
81
+ /**
82
+ * Show a floating reconsent button after the user makes a choice.
83
+ * @default true
84
+ */
85
+ showReconsent?: boolean;
86
+ /**
87
+ * Animation type for banner entrance and exit.
88
+ * @default 'slide'
89
+ */
90
+ animation?: Animation;
91
+ /**
92
+ * Show cookie emoji icon in the banner title and reconsent button.
93
+ * @default true
94
+ */
95
+ showIcon?: boolean;
96
+ /**
97
+ * Custom CSS injected as a `<style>` tag. Target `#loi25-banner`
98
+ * and `#loi25-reconsent`.
99
+ * @default ''
100
+ */
101
+ customCss?: string;
102
+ /**
103
+ * Custom texts for the French banner. Unset fields use built-in defaults.
104
+ */
105
+ textsFr?: ConsentTexts;
106
+ /**
107
+ * Custom texts for the English banner. Unset fields use built-in defaults.
108
+ */
109
+ textsEn?: ConsentTexts;
110
+ /**
111
+ * Callback fired when the user makes a consent choice.
112
+ * Use this to log consent to your backend, analytics, etc.
113
+ */
114
+ onConsent?: (level: ConsentLevel) => void;
115
+ /**
116
+ * Enable Google Consent Mode v2. Automatically manages `ad_storage`,
117
+ * `analytics_storage`, `ad_user_data`, and `ad_personalization` signals.
118
+ *
119
+ * For full compliance, also place a synchronous `<script>` in `<head>`
120
+ * using `getConsentModeScript()` **before** the Google tag loads.
121
+ * @default false
122
+ */
123
+ consentMode?: boolean;
124
+ /**
125
+ * When `true` and `ad_storage` is denied, ad click identifiers in pings
126
+ * are redacted and requests go through a cookieless domain.
127
+ * Maps to `gtag('set', 'ads_data_redaction', true)`.
128
+ * @default false
129
+ */
130
+ adsDataRedaction?: boolean;
131
+ /**
132
+ * When `true`, passes ad click information (GCLID / DCLID) through URL
133
+ * parameters across pages when `ad_storage` is denied.
134
+ * Maps to `gtag('set', 'url_passthrough', true)`.
135
+ * @default false
136
+ */
137
+ urlPassthrough?: boolean;
138
+ /**
139
+ * ISO 3166-2 region codes to scope the consent default.
140
+ * Example: `['CA-QC']` for Quebec only.
141
+ * When set, the consent defaults only apply to visitors from those regions,
142
+ * preserving full measurement for visitors elsewhere.
143
+ */
144
+ consentModeRegion?: string[];
145
+ /**
146
+ * Milliseconds Google tags wait for a consent update before firing.
147
+ * Required because React banners always load asynchronously.
148
+ * @default 500
149
+ */
150
+ waitForUpdate?: number;
151
+ /**
152
+ * Raw HTML string of analytics/tracking scripts to block until consent.
153
+ * Scripts are only injected into `<head>` after the user clicks "Accept All".
154
+ *
155
+ * Supports Google Analytics, Google Tag Manager, Meta Pixel, Hotjar, etc.
156
+ * @default ''
157
+ */
158
+ scripts?: string;
159
+ /**
160
+ * Force a page reload after "Accept All" when `scripts` are provided.
161
+ * Useful for scripts that must run at page load time (e.g., GTM).
162
+ * @default false
163
+ */
164
+ reloadOnConsent?: boolean;
165
+ }
166
+ /** Return type for the `useConsent` hook. */
167
+ interface ConsentState {
168
+ /** Current consent level, or `null` if no valid consent exists. */
169
+ consent: ConsentLevel | null;
170
+ /** Whether the user has given any consent that hasn't expired. */
171
+ hasConsent: boolean;
172
+ /** Reset consent — clears stored consent and triggers the banner to reappear. */
173
+ resetConsent: () => void;
174
+ /** Programmatically set the consent level. */
175
+ setConsent: (level: ConsentLevel) => void;
176
+ }
177
+
178
+ /**
179
+ * Quebec Law 25 cookie consent banner.
180
+ *
181
+ * Drop-in React component with script blocking, Google Consent Mode v2,
182
+ * 3 banner styles (bar / popup / corner), bilingual support, and smooth
183
+ * animations. Zero external dependencies.
184
+ *
185
+ * **Google Consent Mode v2 compliance** requires a synchronous inline
186
+ * `<script>` in `<head>` that sets consent defaults **before** Google tags
187
+ * load. Use `getConsentModeScript()` for this. The `<CookieConsent>`
188
+ * component then handles the `consent('update', ...)` calls when the user
189
+ * interacts with the banner.
190
+ *
191
+ * @example
192
+ * ```tsx
193
+ * // app/layout.tsx (Next.js 15 App Router)
194
+ * import { CookieConsent, getConsentModeScript } from 'cookie-app';
195
+ *
196
+ * export default function RootLayout({ children }) {
197
+ * return (
198
+ * <html lang="fr">
199
+ * <head>
200
+ * // 1. Consent defaults — MUST come before the Google tag
201
+ * <script dangerouslySetInnerHTML=&#123;&#123; __html: getConsentModeScript() &#125;&#125; />
202
+ * // 2. Google tag (gtag.js)
203
+ * <script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXX" />
204
+ * </head>
205
+ * <body>
206
+ * {children}
207
+ * // 3. Consent banner — handles consent('update') on user choice
208
+ * <CookieConsent
209
+ * lang="auto"
210
+ * style="popup"
211
+ * theme="dark"
212
+ * glassmorphism
213
+ * consentMode
214
+ * adsDataRedaction
215
+ * urlPassthrough
216
+ * privacyUrl="/privacy"
217
+ * onConsent={(level) => console.log('Consent:', level)}
218
+ * />
219
+ * </body>
220
+ * </html>
221
+ * );
222
+ * }
223
+ * ```
224
+ */
225
+ declare function CookieConsent({ lang, position, theme, style, glassmorphism, privacyUrl, poweredBy, brandColor, expiryDays, showReconsent, animation, showIcon, customCss, textsFr, textsEn, onConsent, consentMode, adsDataRedaction, urlPassthrough, consentModeRegion, waitForUpdate, scripts, reloadOnConsent, }: CookieConsentProps): react_jsx_runtime.JSX.Element | null;
226
+
227
+ /**
228
+ * React hook to read and manage cookie consent state.
229
+ *
230
+ * SSR-safe — returns `null` consent on the server.
231
+ * Automatically syncs across tabs and with the `<CookieConsent>` component.
232
+ *
233
+ * @param expiryDays - Number of days before consent expires. Default: 365.
234
+ *
235
+ * @example
236
+ * ```tsx
237
+ * const { consent, hasConsent, resetConsent } = useConsent();
238
+ *
239
+ * if (hasConsent && consent === 'all') {
240
+ * // User accepted all cookies
241
+ * }
242
+ * ```
243
+ */
244
+ declare function useConsent(expiryDays?: number): ConsentState;
245
+
246
+ /** Options for the synchronous consent mode default script. */
247
+ interface ConsentModeDefaults {
248
+ /** Default state for advertising cookie storage. @default 'denied' */
249
+ analytics_storage?: 'granted' | 'denied';
250
+ /** Default state for analytics cookie storage. @default 'denied' */
251
+ ad_storage?: 'granted' | 'denied';
252
+ /** Default state for sending user data to Google for advertising. @default 'denied' */
253
+ ad_user_data?: 'granted' | 'denied';
254
+ /** Default state for personalized advertising. @default 'denied' */
255
+ ad_personalization?: 'granted' | 'denied';
256
+ /** Default state for functionality storage (e.g. language settings). @default 'granted' */
257
+ functionality_storage?: 'granted' | 'denied';
258
+ /** Default state for personalization storage (e.g. video recommendations). @default 'granted' */
259
+ personalization_storage?: 'granted' | 'denied';
260
+ /** Default state for security storage (e.g. authentication, fraud prevention). @default 'granted' */
261
+ security_storage?: 'granted' | 'denied';
262
+ /**
263
+ * Milliseconds Google tags wait for a consent update before firing.
264
+ * Required for async consent banners (React components always load async).
265
+ * @default 500
266
+ */
267
+ wait_for_update?: number;
268
+ /**
269
+ * ISO 3166-2 region codes to scope the consent defaults.
270
+ * Example: `['CA-QC']` for Quebec only.
271
+ */
272
+ region?: string[];
273
+ /**
274
+ * When `true` and `ad_storage` is denied, ad click identifiers in pings
275
+ * are redacted and requests go through a cookieless domain.
276
+ * @default false
277
+ */
278
+ ads_data_redaction?: boolean;
279
+ /**
280
+ * When `true`, passes ad click information (GCLID/DCLID) through URL
281
+ * parameters across pages when `ad_storage` is denied.
282
+ * @default false
283
+ */
284
+ url_passthrough?: boolean;
285
+ /**
286
+ * Number of days before stored consent expires.
287
+ * Must match the `expiryDays` prop on `<CookieConsent>`.
288
+ * @default 365
289
+ */
290
+ expiry_days?: number;
291
+ }
292
+ /**
293
+ * Returns a self-contained JavaScript string that sets Google Consent Mode v2
294
+ * defaults **synchronously**. Place this in `<head>` **before** the Google tag
295
+ * (gtag.js or GTM) so that consent defaults are visible when tags initialize.
296
+ *
297
+ * On returning visits where the user previously accepted all cookies, the
298
+ * script also calls `consent('update', ...)` immediately so tags fire with
299
+ * full measurement data without waiting for the React banner to hydrate.
300
+ *
301
+ * @example
302
+ * ```tsx
303
+ * // app/layout.tsx (Next.js App Router)
304
+ * import { getConsentModeScript } from 'cookie-app';
305
+ *
306
+ * export default function RootLayout({ children }) {
307
+ * return (
308
+ * <html lang="fr">
309
+ * <head>
310
+ * // Consent defaults — MUST come before the Google tag
311
+ * <script dangerouslySetInnerHTML=&#123;&#123; __html: getConsentModeScript() &#125;&#125; />
312
+ * // Google tag (gtag.js) goes AFTER the consent default
313
+ * </head>
314
+ * <body>
315
+ * {children}
316
+ * <CookieConsent consentMode />
317
+ * </body>
318
+ * </html>
319
+ * );
320
+ * }
321
+ * ```
322
+ */
323
+ declare function getConsentModeScript(options?: ConsentModeDefaults): string;
324
+
325
+ /** localStorage key for consent level ('all' | 'necessary'). */
326
+ declare const STORAGE_KEY = "loi25-consent";
327
+ /** localStorage key for consent timestamp. */
328
+ declare const STORAGE_DATE_KEY = "loi25-consent-date";
329
+ /** Custom event name dispatched when consent changes programmatically. */
330
+ declare const CONSENT_CHANGE_EVENT = "loi25-consent-change";
331
+ /** Default brand color (blue). */
332
+ declare const DEFAULT_BRAND_COLOR = "#1d4ed8";
333
+ /** Default consent expiry in days. */
334
+ declare const DEFAULT_EXPIRY_DAYS = 365;
335
+ /** Default wait_for_update value in milliseconds for Google Consent Mode v2. */
336
+ declare const DEFAULT_WAIT_FOR_UPDATE = 500;
337
+ /** Default banner texts for both languages. */
338
+ declare const DEFAULT_TEXTS: {
339
+ readonly fr: {
340
+ readonly title: "Respect de votre vie privée";
341
+ readonly message: "Ce site utilise des témoins (cookies) pour améliorer votre expérience. Conformément à la Loi 25 du Québec, nous demandons votre consentement.";
342
+ readonly accept: "Tout accepter";
343
+ readonly reject: "Nécessaires seulement";
344
+ readonly privacy: "Politique de confidentialité";
345
+ readonly powered: "Propulsé par";
346
+ };
347
+ readonly en: {
348
+ readonly title: "Your Privacy Matters";
349
+ readonly message: "This website uses cookies to improve your experience. In compliance with Quebec's Law 25, we ask for your consent.";
350
+ readonly accept: "Accept All";
351
+ readonly reject: "Necessary Only";
352
+ readonly privacy: "Privacy Policy";
353
+ readonly powered: "Powered by";
354
+ };
355
+ };
356
+
357
+ export { type Animation, type BannerPosition, type BannerStyle, type BannerTheme, CONSENT_CHANGE_EVENT, type ConsentLevel, type ConsentModeDefaults, type ConsentState, type ConsentTexts, CookieConsent, type CookieConsentProps, DEFAULT_BRAND_COLOR, DEFAULT_EXPIRY_DAYS, DEFAULT_TEXTS, DEFAULT_WAIT_FOR_UPDATE, type Language, STORAGE_DATE_KEY, STORAGE_KEY, getConsentModeScript, useConsent };