react-lgpd-consent 0.2.0 → 0.2.2
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/COMPLIANCE.md +231 -87
- package/README.md +181 -19
- package/dist/{PreferencesModal-QQOOLRDY.js → PreferencesModal-UL552BFP.js} +1 -1
- package/dist/{chunk-JTPCDTOQ.js → chunk-JAX63PBG.js} +366 -161
- package/dist/index.cjs +374 -157
- package/dist/index.d.cts +110 -19
- package/dist/index.d.ts +110 -19
- package/dist/index.js +9 -3
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -36,15 +36,55 @@ function readConsentCookie(name = DEFAULT_COOKIE_OPTS.name) {
|
|
|
36
36
|
const raw = import_js_cookie.default.get(name);
|
|
37
37
|
if (!raw) return null;
|
|
38
38
|
try {
|
|
39
|
-
|
|
39
|
+
const data = JSON.parse(raw);
|
|
40
|
+
if (!data.version) {
|
|
41
|
+
return migrateLegacyCookie(data);
|
|
42
|
+
}
|
|
43
|
+
if (data.version !== COOKIE_SCHEMA_VERSION) {
|
|
44
|
+
console.warn(
|
|
45
|
+
`[react-lgpd-consent] Cookie version mismatch: ${data.version} != ${COOKIE_SCHEMA_VERSION}`
|
|
46
|
+
);
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
return data;
|
|
40
50
|
} catch {
|
|
41
51
|
return null;
|
|
42
52
|
}
|
|
43
53
|
}
|
|
44
|
-
function
|
|
54
|
+
function migrateLegacyCookie(legacyData) {
|
|
55
|
+
try {
|
|
56
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
57
|
+
return {
|
|
58
|
+
version: COOKIE_SCHEMA_VERSION,
|
|
59
|
+
consented: legacyData.consented || false,
|
|
60
|
+
preferences: legacyData.preferences || { necessary: true },
|
|
61
|
+
consentDate: now,
|
|
62
|
+
// Não temos o original, usar data atual
|
|
63
|
+
lastUpdate: now,
|
|
64
|
+
source: "banner",
|
|
65
|
+
// Assumir origem banner
|
|
66
|
+
isModalOpen: false
|
|
67
|
+
// Nunca persistir estado de UI
|
|
68
|
+
};
|
|
69
|
+
} catch {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
function writeConsentCookie(state, source = "banner", opts) {
|
|
45
74
|
if (typeof document === "undefined") return;
|
|
75
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
46
76
|
const o = { ...DEFAULT_COOKIE_OPTS, ...opts };
|
|
47
|
-
|
|
77
|
+
const cookieData = {
|
|
78
|
+
version: COOKIE_SCHEMA_VERSION,
|
|
79
|
+
consented: state.consented,
|
|
80
|
+
preferences: state.preferences,
|
|
81
|
+
consentDate: state.consentDate || now,
|
|
82
|
+
// Preservar data original ou usar atual
|
|
83
|
+
lastUpdate: now,
|
|
84
|
+
source
|
|
85
|
+
// isModalOpen NÃO é persistido (campo de UI apenas)
|
|
86
|
+
};
|
|
87
|
+
import_js_cookie.default.set(o.name, JSON.stringify(cookieData), {
|
|
48
88
|
expires: o.maxAgeDays,
|
|
49
89
|
sameSite: o.sameSite,
|
|
50
90
|
secure: o.secure,
|
|
@@ -56,7 +96,7 @@ function removeConsentCookie(opts) {
|
|
|
56
96
|
const o = { ...DEFAULT_COOKIE_OPTS, ...opts };
|
|
57
97
|
import_js_cookie.default.remove(o.name, { path: o.path });
|
|
58
98
|
}
|
|
59
|
-
var import_js_cookie, DEFAULT_COOKIE_OPTS;
|
|
99
|
+
var import_js_cookie, DEFAULT_COOKIE_OPTS, COOKIE_SCHEMA_VERSION;
|
|
60
100
|
var init_cookieUtils = __esm({
|
|
61
101
|
"src/utils/cookieUtils.ts"() {
|
|
62
102
|
"use strict";
|
|
@@ -68,6 +108,7 @@ var init_cookieUtils = __esm({
|
|
|
68
108
|
secure: typeof window !== "undefined" ? window.location.protocol === "https:" : false,
|
|
69
109
|
path: "/"
|
|
70
110
|
};
|
|
111
|
+
COOKIE_SCHEMA_VERSION = "1.0";
|
|
71
112
|
}
|
|
72
113
|
});
|
|
73
114
|
|
|
@@ -145,74 +186,212 @@ var init_theme = __esm({
|
|
|
145
186
|
}
|
|
146
187
|
});
|
|
147
188
|
|
|
189
|
+
// src/utils/developerGuidance.ts
|
|
190
|
+
function analyzeDeveloperConfiguration(config) {
|
|
191
|
+
const guidance = {
|
|
192
|
+
warnings: [],
|
|
193
|
+
suggestions: [],
|
|
194
|
+
activeCategoriesInfo: [],
|
|
195
|
+
usingDefaults: !config
|
|
196
|
+
};
|
|
197
|
+
const finalConfig = config || DEFAULT_PROJECT_CATEGORIES;
|
|
198
|
+
if (!config) {
|
|
199
|
+
guidance.warnings.push(
|
|
200
|
+
'LGPD-CONSENT: Nenhuma configura\xE7\xE3o de categorias especificada. Usando padr\xE3o: necessary + analytics. Para produ\xE7\xE3o, recomenda-se especificar explicitamente as categorias via prop "categories".'
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
guidance.activeCategoriesInfo.push({
|
|
204
|
+
id: "necessary",
|
|
205
|
+
name: "Cookies Necess\xE1rios",
|
|
206
|
+
description: "Essenciais para funcionamento b\xE1sico do site",
|
|
207
|
+
essential: true,
|
|
208
|
+
uiRequired: false
|
|
209
|
+
// Não precisa de toggle (sempre ativo)
|
|
210
|
+
});
|
|
211
|
+
const enabledCategories = finalConfig.enabledCategories || [];
|
|
212
|
+
const categoryNames = {
|
|
213
|
+
analytics: {
|
|
214
|
+
name: "Cookies Anal\xEDticos",
|
|
215
|
+
description: "Medem uso e performance do site"
|
|
216
|
+
},
|
|
217
|
+
functional: {
|
|
218
|
+
name: "Cookies Funcionais",
|
|
219
|
+
description: "Melhoram experi\xEAncia e funcionalidades"
|
|
220
|
+
},
|
|
221
|
+
marketing: {
|
|
222
|
+
name: "Cookies de Marketing",
|
|
223
|
+
description: "Publicidade direcionada e campanhas"
|
|
224
|
+
},
|
|
225
|
+
social: {
|
|
226
|
+
name: "Cookies de Redes Sociais",
|
|
227
|
+
description: "Integra\xE7\xE3o com plataformas sociais"
|
|
228
|
+
},
|
|
229
|
+
personalization: {
|
|
230
|
+
name: "Cookies de Personaliza\xE7\xE3o",
|
|
231
|
+
description: "Adaptam conte\xFAdo \xE0s prefer\xEAncias do usu\xE1rio"
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
enabledCategories.forEach((categoryId) => {
|
|
235
|
+
const categoryInfo = categoryNames[categoryId];
|
|
236
|
+
if (categoryInfo) {
|
|
237
|
+
guidance.activeCategoriesInfo.push({
|
|
238
|
+
id: categoryId,
|
|
239
|
+
name: categoryInfo.name,
|
|
240
|
+
description: categoryInfo.description,
|
|
241
|
+
essential: false,
|
|
242
|
+
uiRequired: true
|
|
243
|
+
// Precisa de toggle na UI
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
});
|
|
247
|
+
const customCategories = finalConfig.customCategories || [];
|
|
248
|
+
customCategories.forEach((category) => {
|
|
249
|
+
guidance.activeCategoriesInfo.push({
|
|
250
|
+
id: category.id,
|
|
251
|
+
name: category.name,
|
|
252
|
+
description: category.description,
|
|
253
|
+
essential: category.essential === true,
|
|
254
|
+
uiRequired: category.essential !== true
|
|
255
|
+
// Apenas não-essenciais precisam toggle
|
|
256
|
+
});
|
|
257
|
+
});
|
|
258
|
+
const totalToggleable = guidance.activeCategoriesInfo.filter(
|
|
259
|
+
(c) => c.uiRequired
|
|
260
|
+
).length;
|
|
261
|
+
if (totalToggleable === 0) {
|
|
262
|
+
guidance.suggestions.push(
|
|
263
|
+
'Apenas cookies necess\xE1rios est\xE3o configurados. Para compliance completo LGPD, considere adicionar categorias como "analytics" ou "functional" conforme uso real.'
|
|
264
|
+
);
|
|
265
|
+
}
|
|
266
|
+
if (totalToggleable > 5) {
|
|
267
|
+
guidance.warnings.push(
|
|
268
|
+
`${totalToggleable} categorias opcionais detectadas. UI com muitas op\xE7\xF5es pode ' +
|
|
269
|
+
'prejudicar experi\xEAncia do usu\xE1rio. Considere agrupar categorias similares.`
|
|
270
|
+
);
|
|
271
|
+
}
|
|
272
|
+
const poorDescriptions = customCategories.filter(
|
|
273
|
+
(c) => !c.description || c.description.length < 10
|
|
274
|
+
);
|
|
275
|
+
if (poorDescriptions.length > 0) {
|
|
276
|
+
guidance.warnings.push(
|
|
277
|
+
`Categorias customizadas com descri\xE7\xF5es inadequadas: ${poorDescriptions.map((c) => c.id).join(", ")}. Descri\xE7\xF5es claras s\xE3o obrigat\xF3rias para compliance LGPD.`
|
|
278
|
+
);
|
|
279
|
+
}
|
|
280
|
+
return guidance;
|
|
281
|
+
}
|
|
282
|
+
function logDeveloperGuidance(guidance) {
|
|
283
|
+
const isProduction = typeof globalThis !== "undefined" && globalThis.__LGPD_PRODUCTION__ || typeof window !== "undefined" && !window.__LGPD_DEV__;
|
|
284
|
+
if (isProduction) return;
|
|
285
|
+
if (guidance.warnings.length > 0) {
|
|
286
|
+
console.group("\u{1F7E8} LGPD-CONSENT: Avisos de Configura\xE7\xE3o");
|
|
287
|
+
guidance.warnings.forEach((warning) => console.warn(warning));
|
|
288
|
+
console.groupEnd();
|
|
289
|
+
}
|
|
290
|
+
if (guidance.suggestions.length > 0) {
|
|
291
|
+
console.group("\u{1F4A1} LGPD-CONSENT: Sugest\xF5es");
|
|
292
|
+
guidance.suggestions.forEach((suggestion) => console.info(suggestion));
|
|
293
|
+
console.groupEnd();
|
|
294
|
+
}
|
|
295
|
+
if (guidance.usingDefaults) {
|
|
296
|
+
console.info(
|
|
297
|
+
'\u{1F4CB} LGPD-CONSENT: Usando configura\xE7\xE3o padr\xE3o. Para personalizar, use a prop "categories" no ConsentProvider.'
|
|
298
|
+
);
|
|
299
|
+
}
|
|
300
|
+
console.group("\u{1F527} LGPD-CONSENT: Categorias Ativas (para UI customizada)");
|
|
301
|
+
console.table(
|
|
302
|
+
guidance.activeCategoriesInfo.map((cat) => ({
|
|
303
|
+
ID: cat.id,
|
|
304
|
+
Nome: cat.name,
|
|
305
|
+
"Toggle UI?": cat.uiRequired ? "\u2705 SIM" : "\u274C N\xC3O (sempre ativo)",
|
|
306
|
+
"Essencial?": cat.essential ? "\u{1F512} SIM" : "\u2699\uFE0F N\xC3O"
|
|
307
|
+
}))
|
|
308
|
+
);
|
|
309
|
+
console.groupEnd();
|
|
310
|
+
}
|
|
311
|
+
var React, DEFAULT_PROJECT_CATEGORIES;
|
|
312
|
+
var init_developerGuidance = __esm({
|
|
313
|
+
"src/utils/developerGuidance.ts"() {
|
|
314
|
+
"use strict";
|
|
315
|
+
React = __toESM(require("react"), 1);
|
|
316
|
+
DEFAULT_PROJECT_CATEGORIES = {
|
|
317
|
+
enabledCategories: ["analytics"],
|
|
318
|
+
// Só analytics além de necessary
|
|
319
|
+
customCategories: []
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
});
|
|
323
|
+
|
|
148
324
|
// src/context/CategoriesContext.tsx
|
|
149
325
|
function CategoriesProvider({
|
|
326
|
+
children,
|
|
150
327
|
categories,
|
|
151
|
-
|
|
328
|
+
// LEGACY: prop antiga (apenas customCategories)
|
|
329
|
+
config
|
|
330
|
+
// NOVO: configuração completa
|
|
152
331
|
}) {
|
|
153
|
-
const
|
|
154
|
-
|
|
332
|
+
const contextValue = React2.useMemo(() => {
|
|
333
|
+
let finalConfig;
|
|
334
|
+
if (categories && !config) {
|
|
335
|
+
finalConfig = {
|
|
336
|
+
enabledCategories: DEFAULT_PROJECT_CATEGORIES.enabledCategories,
|
|
337
|
+
customCategories: categories
|
|
338
|
+
};
|
|
339
|
+
} else {
|
|
340
|
+
finalConfig = config || DEFAULT_PROJECT_CATEGORIES;
|
|
341
|
+
}
|
|
342
|
+
const guidance = analyzeDeveloperConfiguration(
|
|
343
|
+
config || (categories ? { customCategories: categories } : void 0)
|
|
344
|
+
);
|
|
345
|
+
const toggleableCategories = guidance.activeCategoriesInfo.filter(
|
|
346
|
+
(cat) => cat.uiRequired
|
|
347
|
+
);
|
|
348
|
+
return {
|
|
349
|
+
config: finalConfig,
|
|
350
|
+
guidance,
|
|
351
|
+
toggleableCategories,
|
|
352
|
+
allCategories: guidance.activeCategoriesInfo,
|
|
353
|
+
legacyCategories: categories || []
|
|
354
|
+
};
|
|
355
|
+
}, [config, categories]);
|
|
356
|
+
React2.useEffect(() => {
|
|
357
|
+
logDeveloperGuidance(contextValue.guidance);
|
|
358
|
+
}, [contextValue.guidance]);
|
|
359
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CategoriesContext.Provider, { value: contextValue, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CategoriesCtx.Provider, { value: contextValue.legacyCategories, children }) });
|
|
155
360
|
}
|
|
156
|
-
function
|
|
157
|
-
|
|
361
|
+
function useCategories() {
|
|
362
|
+
const context = React2.useContext(CategoriesContext);
|
|
363
|
+
if (!context) {
|
|
364
|
+
throw new Error(
|
|
365
|
+
"useCategories deve ser usado dentro de CategoriesProvider. Certifique-se de que o ConsentProvider est\xE1 envolvendo seu componente."
|
|
366
|
+
);
|
|
367
|
+
}
|
|
368
|
+
return context;
|
|
158
369
|
}
|
|
159
|
-
function
|
|
160
|
-
const
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
},
|
|
170
|
-
{
|
|
171
|
-
id: "analytics",
|
|
172
|
-
name: "Analytics e Estat\xEDsticas",
|
|
173
|
-
description: "Permitem medir audi\xEAncia e desempenho, gerando estat\xEDsticas an\xF4nimas de uso.",
|
|
174
|
-
essential: false,
|
|
175
|
-
cookies: ["_ga", "_ga_*", "_gid", "_gat", "gtag"]
|
|
176
|
-
},
|
|
177
|
-
{
|
|
178
|
-
id: "functional",
|
|
179
|
-
name: "Cookies Funcionais",
|
|
180
|
-
description: "Melhoram a experi\xEAncia do usu\xE1rio, lembrando prefer\xEAncias e configura\xE7\xF5es.",
|
|
181
|
-
essential: false,
|
|
182
|
-
cookies: ["language", "theme", "timezone", "preferences"]
|
|
183
|
-
},
|
|
184
|
-
{
|
|
185
|
-
id: "marketing",
|
|
186
|
-
name: "Marketing e Publicidade",
|
|
187
|
-
description: "Utilizados para publicidade direcionada e medi\xE7\xE3o de campanhas publicit\xE1rias.",
|
|
188
|
-
essential: false,
|
|
189
|
-
cookies: ["_fbp", "fr", "tr", "ads_*", "doubleclick"]
|
|
190
|
-
},
|
|
191
|
-
{
|
|
192
|
-
id: "social",
|
|
193
|
-
name: "Redes Sociais",
|
|
194
|
-
description: "Permitem compartilhamento e integra\xE7\xE3o com redes sociais como Facebook, YouTube, etc.",
|
|
195
|
-
essential: false,
|
|
196
|
-
cookies: ["__Secure-*", "sb", "datr", "c_user", "social_*"]
|
|
197
|
-
},
|
|
198
|
-
{
|
|
199
|
-
id: "personalization",
|
|
200
|
-
name: "Personaliza\xE7\xE3o",
|
|
201
|
-
description: "Adaptam o conte\xFAdo e interface \xE0s prefer\xEAncias individuais do usu\xE1rio.",
|
|
202
|
-
essential: false,
|
|
203
|
-
cookies: ["personalization_*", "content_*", "layout_*"]
|
|
204
|
-
}
|
|
205
|
-
];
|
|
206
|
-
return [...defaultCategories, ...customCategories];
|
|
207
|
-
}, [customCategories]);
|
|
370
|
+
function useCategoryStatus(categoryId) {
|
|
371
|
+
const { allCategories } = useCategories();
|
|
372
|
+
const category = allCategories.find((cat) => cat.id === categoryId);
|
|
373
|
+
return {
|
|
374
|
+
isActive: !!category,
|
|
375
|
+
isEssential: category?.essential || false,
|
|
376
|
+
needsToggle: category?.uiRequired || false,
|
|
377
|
+
name: category?.name,
|
|
378
|
+
description: category?.description
|
|
379
|
+
};
|
|
208
380
|
}
|
|
209
|
-
|
|
381
|
+
function useCustomCategories() {
|
|
382
|
+
return React2.useContext(CategoriesCtx);
|
|
383
|
+
}
|
|
384
|
+
var React2, import_jsx_runtime, CategoriesContext, CategoriesCtx;
|
|
210
385
|
var init_CategoriesContext = __esm({
|
|
211
386
|
"src/context/CategoriesContext.tsx"() {
|
|
212
387
|
"use strict";
|
|
213
|
-
|
|
388
|
+
React2 = __toESM(require("react"), 1);
|
|
389
|
+
init_developerGuidance();
|
|
214
390
|
import_jsx_runtime = require("react/jsx-runtime");
|
|
215
|
-
|
|
391
|
+
CategoriesContext = React2.createContext(
|
|
392
|
+
null
|
|
393
|
+
);
|
|
394
|
+
CategoriesCtx = React2.createContext([]);
|
|
216
395
|
}
|
|
217
396
|
});
|
|
218
397
|
|
|
@@ -292,12 +471,25 @@ function PreferencesModal({
|
|
|
292
471
|
}) {
|
|
293
472
|
const { preferences, setPreferences, closePreferences, isModalOpen } = useConsent();
|
|
294
473
|
const texts = useConsentTexts();
|
|
295
|
-
const
|
|
474
|
+
const { toggleableCategories } = useCategories();
|
|
475
|
+
const [tempPreferences, setTempPreferences] = (0, import_react.useState)(
|
|
476
|
+
() => {
|
|
477
|
+
const initialPrefs = { necessary: true };
|
|
478
|
+
toggleableCategories.forEach((category) => {
|
|
479
|
+
initialPrefs[category.id] = preferences[category.id] ?? false;
|
|
480
|
+
});
|
|
481
|
+
return initialPrefs;
|
|
482
|
+
}
|
|
483
|
+
);
|
|
296
484
|
(0, import_react.useEffect)(() => {
|
|
297
485
|
if (isModalOpen) {
|
|
298
|
-
|
|
486
|
+
const syncedPrefs = { necessary: true };
|
|
487
|
+
toggleableCategories.forEach((category) => {
|
|
488
|
+
syncedPrefs[category.id] = preferences[category.id] ?? false;
|
|
489
|
+
});
|
|
490
|
+
setTempPreferences(syncedPrefs);
|
|
299
491
|
}
|
|
300
|
-
}, [isModalOpen, preferences]);
|
|
492
|
+
}, [isModalOpen, preferences, toggleableCategories]);
|
|
301
493
|
const open = DialogProps2?.open ?? isModalOpen ?? false;
|
|
302
494
|
const handleSave = () => {
|
|
303
495
|
setPreferences(tempPreferences);
|
|
@@ -318,38 +510,23 @@ function PreferencesModal({
|
|
|
318
510
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_DialogContent.default, { dividers: true, children: [
|
|
319
511
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_Typography2.default, { variant: "body2", sx: { mb: 2 }, children: texts.modalIntro }),
|
|
320
512
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_FormGroup.default, { children: [
|
|
321
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
322
|
-
import_FormControlLabel.default,
|
|
323
|
-
{
|
|
324
|
-
control: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
325
|
-
import_Switch.default,
|
|
326
|
-
{
|
|
327
|
-
checked: tempPreferences.analytics,
|
|
328
|
-
onChange: (e) => setTempPreferences((prev) => ({
|
|
329
|
-
...prev,
|
|
330
|
-
analytics: e.target.checked
|
|
331
|
-
}))
|
|
332
|
-
}
|
|
333
|
-
),
|
|
334
|
-
label: "Cookies Anal\xEDticos (medem uso do site)"
|
|
335
|
-
}
|
|
336
|
-
),
|
|
337
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
513
|
+
toggleableCategories.map((category) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
338
514
|
import_FormControlLabel.default,
|
|
339
515
|
{
|
|
340
516
|
control: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
341
517
|
import_Switch.default,
|
|
342
518
|
{
|
|
343
|
-
checked: tempPreferences.
|
|
519
|
+
checked: tempPreferences[category.id] ?? false,
|
|
344
520
|
onChange: (e) => setTempPreferences((prev) => ({
|
|
345
521
|
...prev,
|
|
346
|
-
|
|
522
|
+
[category.id]: e.target.checked
|
|
347
523
|
}))
|
|
348
524
|
}
|
|
349
525
|
),
|
|
350
|
-
label:
|
|
351
|
-
}
|
|
352
|
-
|
|
526
|
+
label: `${category.name} - ${category.description}`
|
|
527
|
+
},
|
|
528
|
+
category.id
|
|
529
|
+
)),
|
|
353
530
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
354
531
|
import_FormControlLabel.default,
|
|
355
532
|
{
|
|
@@ -382,6 +559,7 @@ var init_PreferencesModal = __esm({
|
|
|
382
559
|
import_Switch = __toESM(require("@mui/material/Switch"), 1);
|
|
383
560
|
import_Typography2 = __toESM(require("@mui/material/Typography"), 1);
|
|
384
561
|
import_react = require("react");
|
|
562
|
+
init_CategoriesContext();
|
|
385
563
|
init_useConsent();
|
|
386
564
|
init_Branding();
|
|
387
565
|
import_jsx_runtime3 = require("react/jsx-runtime");
|
|
@@ -398,6 +576,18 @@ function createInitialPreferences(customCategories) {
|
|
|
398
576
|
}
|
|
399
577
|
return prefs;
|
|
400
578
|
}
|
|
579
|
+
function createFullConsentState(consented, preferences, source, isModalOpen = false, existingState) {
|
|
580
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
581
|
+
return {
|
|
582
|
+
version: "1.0",
|
|
583
|
+
consented,
|
|
584
|
+
preferences,
|
|
585
|
+
consentDate: existingState?.consentDate || now,
|
|
586
|
+
lastUpdate: now,
|
|
587
|
+
source,
|
|
588
|
+
isModalOpen
|
|
589
|
+
};
|
|
590
|
+
}
|
|
401
591
|
function reducer(state, action) {
|
|
402
592
|
switch (action.type) {
|
|
403
593
|
case "ACCEPT_ALL": {
|
|
@@ -405,11 +595,7 @@ function reducer(state, action) {
|
|
|
405
595
|
Object.keys(prefs).forEach((key) => {
|
|
406
596
|
prefs[key] = true;
|
|
407
597
|
});
|
|
408
|
-
return
|
|
409
|
-
consented: true,
|
|
410
|
-
preferences: prefs,
|
|
411
|
-
isModalOpen: false
|
|
412
|
-
};
|
|
598
|
+
return createFullConsentState(true, prefs, "banner", false, state);
|
|
413
599
|
}
|
|
414
600
|
case "REJECT_ALL": {
|
|
415
601
|
const prefs = createInitialPreferences(action.customCategories);
|
|
@@ -420,11 +606,7 @@ function reducer(state, action) {
|
|
|
420
606
|
}
|
|
421
607
|
});
|
|
422
608
|
}
|
|
423
|
-
return
|
|
424
|
-
consented: true,
|
|
425
|
-
preferences: prefs,
|
|
426
|
-
isModalOpen: false
|
|
427
|
-
};
|
|
609
|
+
return createFullConsentState(true, prefs, "banner", false, state);
|
|
428
610
|
}
|
|
429
611
|
case "SET_CATEGORY":
|
|
430
612
|
return {
|
|
@@ -432,38 +614,50 @@ function reducer(state, action) {
|
|
|
432
614
|
preferences: {
|
|
433
615
|
...state.preferences,
|
|
434
616
|
[action.category]: action.value
|
|
435
|
-
}
|
|
617
|
+
},
|
|
618
|
+
lastUpdate: (/* @__PURE__ */ new Date()).toISOString()
|
|
436
619
|
};
|
|
437
620
|
case "SET_PREFERENCES":
|
|
438
|
-
return
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
621
|
+
return createFullConsentState(
|
|
622
|
+
true,
|
|
623
|
+
action.preferences,
|
|
624
|
+
"modal",
|
|
625
|
+
false,
|
|
626
|
+
state
|
|
627
|
+
);
|
|
444
628
|
case "OPEN_MODAL":
|
|
445
629
|
return { ...state, isModalOpen: true };
|
|
446
630
|
case "CLOSE_MODAL":
|
|
447
|
-
return
|
|
448
|
-
|
|
631
|
+
return createFullConsentState(
|
|
632
|
+
true,
|
|
633
|
+
state.preferences,
|
|
634
|
+
"modal",
|
|
635
|
+
false,
|
|
636
|
+
state
|
|
637
|
+
);
|
|
449
638
|
case "RESET": {
|
|
450
|
-
return
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
639
|
+
return createFullConsentState(
|
|
640
|
+
false,
|
|
641
|
+
createInitialPreferences(action.customCategories),
|
|
642
|
+
"programmatic",
|
|
643
|
+
false
|
|
644
|
+
);
|
|
455
645
|
}
|
|
456
646
|
case "HYDRATE":
|
|
457
|
-
return { ...action.state };
|
|
647
|
+
return { ...action.state, isModalOpen: false };
|
|
648
|
+
// Nunca hidratar com modal aberto
|
|
458
649
|
default:
|
|
459
650
|
return state;
|
|
460
651
|
}
|
|
461
652
|
}
|
|
462
653
|
function ConsentProvider({
|
|
463
654
|
initialState,
|
|
655
|
+
categories,
|
|
656
|
+
// NOVO: configuração completa de categorias
|
|
464
657
|
texts: textsProp,
|
|
465
658
|
theme,
|
|
466
659
|
customCategories,
|
|
660
|
+
// LEGACY: compatibilidade
|
|
467
661
|
scriptIntegrations,
|
|
468
662
|
PreferencesModalComponent,
|
|
469
663
|
preferencesModalProps = {},
|
|
@@ -474,29 +668,41 @@ function ConsentProvider({
|
|
|
474
668
|
cookie: cookieOpts,
|
|
475
669
|
children
|
|
476
670
|
}) {
|
|
477
|
-
const texts =
|
|
671
|
+
const texts = React3.useMemo(
|
|
478
672
|
() => ({ ...DEFAULT_TEXTS, ...textsProp ?? {} }),
|
|
479
673
|
[textsProp]
|
|
480
674
|
);
|
|
481
|
-
const cookie =
|
|
675
|
+
const cookie = React3.useMemo(
|
|
482
676
|
() => ({ ...DEFAULT_COOKIE_OPTS, ...cookieOpts ?? {} }),
|
|
483
677
|
[cookieOpts]
|
|
484
678
|
);
|
|
485
|
-
const appliedTheme =
|
|
679
|
+
const appliedTheme = React3.useMemo(
|
|
486
680
|
() => theme || defaultConsentTheme,
|
|
487
681
|
[theme]
|
|
488
682
|
);
|
|
489
|
-
const
|
|
683
|
+
const finalCategoriesConfig = React3.useMemo(() => {
|
|
684
|
+
if (categories) return categories;
|
|
685
|
+
if (customCategories) {
|
|
686
|
+
return {
|
|
687
|
+
enabledCategories: ["analytics"],
|
|
688
|
+
// padrão quando usando API antiga
|
|
689
|
+
customCategories
|
|
690
|
+
};
|
|
691
|
+
}
|
|
692
|
+
return void 0;
|
|
693
|
+
}, [categories, customCategories]);
|
|
694
|
+
const boot = React3.useMemo(() => {
|
|
490
695
|
if (initialState) return { ...initialState, isModalOpen: false };
|
|
491
|
-
return
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
696
|
+
return createFullConsentState(
|
|
697
|
+
false,
|
|
698
|
+
createInitialPreferences(customCategories),
|
|
699
|
+
"banner",
|
|
700
|
+
false
|
|
701
|
+
);
|
|
496
702
|
}, [initialState, customCategories]);
|
|
497
|
-
const [state, dispatch] =
|
|
498
|
-
const [isHydrated, setIsHydrated] =
|
|
499
|
-
|
|
703
|
+
const [state, dispatch] = React3.useReducer(reducer, boot);
|
|
704
|
+
const [isHydrated, setIsHydrated] = React3.useState(false);
|
|
705
|
+
React3.useEffect(() => {
|
|
500
706
|
if (!initialState) {
|
|
501
707
|
const saved = readConsentCookie(cookie.name);
|
|
502
708
|
if (saved?.consented) {
|
|
@@ -506,24 +712,24 @@ function ConsentProvider({
|
|
|
506
712
|
}
|
|
507
713
|
setIsHydrated(true);
|
|
508
714
|
}, [cookie.name, initialState]);
|
|
509
|
-
|
|
510
|
-
if (state.consented) writeConsentCookie(state, cookie);
|
|
715
|
+
React3.useEffect(() => {
|
|
716
|
+
if (state.consented) writeConsentCookie(state, state.source, cookie);
|
|
511
717
|
}, [state, cookie]);
|
|
512
|
-
const prevConsented =
|
|
513
|
-
|
|
718
|
+
const prevConsented = React3.useRef(state.consented);
|
|
719
|
+
React3.useEffect(() => {
|
|
514
720
|
if (!prevConsented.current && state.consented && onConsentGiven) {
|
|
515
721
|
setTimeout(() => onConsentGiven(state), 150);
|
|
516
722
|
}
|
|
517
723
|
prevConsented.current = state.consented;
|
|
518
724
|
}, [state, onConsentGiven]);
|
|
519
|
-
const prevPrefs =
|
|
520
|
-
|
|
725
|
+
const prevPrefs = React3.useRef(state.preferences);
|
|
726
|
+
React3.useEffect(() => {
|
|
521
727
|
if (state.consented && onPreferencesSaved && prevPrefs.current !== state.preferences) {
|
|
522
728
|
setTimeout(() => onPreferencesSaved(state.preferences), 150);
|
|
523
729
|
prevPrefs.current = state.preferences;
|
|
524
730
|
}
|
|
525
731
|
}, [state, onPreferencesSaved]);
|
|
526
|
-
const api =
|
|
732
|
+
const api = React3.useMemo(() => {
|
|
527
733
|
const acceptAll = () => dispatch({ type: "ACCEPT_ALL", customCategories });
|
|
528
734
|
const rejectAll = () => dispatch({ type: "REJECT_ALL", customCategories });
|
|
529
735
|
const setPreference = (category, value) => dispatch({ type: "SET_CATEGORY", category, value });
|
|
@@ -547,53 +753,55 @@ function ConsentProvider({
|
|
|
547
753
|
resetConsent
|
|
548
754
|
};
|
|
549
755
|
}, [state, cookie, customCategories]);
|
|
550
|
-
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_styles2.ThemeProvider, { theme: appliedTheme, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(StateCtx.Provider, { value: state, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ActionsCtx.Provider, { value: api, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(TextsCtx.Provider, { value: texts, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(HydrationCtx.Provider, { value: isHydrated, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
756
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_styles2.ThemeProvider, { theme: appliedTheme, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(StateCtx.Provider, { value: state, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ActionsCtx.Provider, { value: api, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(TextsCtx.Provider, { value: texts, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(HydrationCtx.Provider, { value: isHydrated, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
757
|
+
CategoriesProvider,
|
|
758
|
+
{
|
|
759
|
+
config: finalCategoriesConfig,
|
|
760
|
+
categories: customCategories,
|
|
761
|
+
children: [
|
|
762
|
+
children,
|
|
763
|
+
!disableAutomaticModal && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(React3.Suspense, { fallback: null, children: PreferencesModalComponent ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PreferencesModalComponent, { ...preferencesModalProps }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PreferencesModal2, { hideBranding }) })
|
|
764
|
+
]
|
|
765
|
+
}
|
|
766
|
+
) }) }) }) }) });
|
|
554
767
|
}
|
|
555
768
|
function useConsentStateInternal() {
|
|
556
|
-
const ctx =
|
|
769
|
+
const ctx = React3.useContext(StateCtx);
|
|
557
770
|
if (!ctx)
|
|
558
771
|
throw new Error("useConsentState must be used within ConsentProvider");
|
|
559
772
|
return ctx;
|
|
560
773
|
}
|
|
561
774
|
function useConsentActionsInternal() {
|
|
562
|
-
const ctx =
|
|
775
|
+
const ctx = React3.useContext(ActionsCtx);
|
|
563
776
|
if (!ctx)
|
|
564
777
|
throw new Error("useConsentActions must be used within ConsentProvider");
|
|
565
778
|
return ctx;
|
|
566
779
|
}
|
|
567
780
|
function useConsentTextsInternal() {
|
|
568
|
-
const ctx =
|
|
781
|
+
const ctx = React3.useContext(TextsCtx);
|
|
569
782
|
return ctx;
|
|
570
783
|
}
|
|
571
784
|
function useConsentHydrationInternal() {
|
|
572
|
-
return
|
|
785
|
+
return React3.useContext(HydrationCtx);
|
|
573
786
|
}
|
|
574
|
-
var
|
|
787
|
+
var React3, import_styles2, import_jsx_runtime4, PreferencesModal2, DEFAULT_PREFERENCES, DEFAULT_TEXTS, StateCtx, ActionsCtx, TextsCtx, HydrationCtx;
|
|
575
788
|
var init_ConsentContext = __esm({
|
|
576
789
|
"src/context/ConsentContext.tsx"() {
|
|
577
790
|
"use strict";
|
|
578
|
-
|
|
791
|
+
React3 = __toESM(require("react"), 1);
|
|
579
792
|
import_styles2 = require("@mui/material/styles");
|
|
580
793
|
init_cookieUtils();
|
|
581
794
|
init_theme();
|
|
582
795
|
init_CategoriesContext();
|
|
583
796
|
import_jsx_runtime4 = require("react/jsx-runtime");
|
|
584
|
-
PreferencesModal2 =
|
|
797
|
+
PreferencesModal2 = React3.lazy(
|
|
585
798
|
() => Promise.resolve().then(() => (init_PreferencesModal(), PreferencesModal_exports)).then((m) => ({
|
|
586
799
|
default: m.PreferencesModal
|
|
587
800
|
}))
|
|
588
801
|
);
|
|
589
802
|
DEFAULT_PREFERENCES = {
|
|
590
|
-
necessary: true
|
|
803
|
+
necessary: true
|
|
591
804
|
// Sempre ativo (essencial)
|
|
592
|
-
analytics: false,
|
|
593
|
-
functional: false,
|
|
594
|
-
marketing: false,
|
|
595
|
-
social: false,
|
|
596
|
-
personalization: false
|
|
597
805
|
};
|
|
598
806
|
DEFAULT_TEXTS = {
|
|
599
807
|
// Textos básicos
|
|
@@ -624,10 +832,10 @@ var init_ConsentContext = __esm({
|
|
|
624
832
|
transferCountries: void 0
|
|
625
833
|
// Exibido se definido
|
|
626
834
|
};
|
|
627
|
-
StateCtx =
|
|
628
|
-
ActionsCtx =
|
|
629
|
-
TextsCtx =
|
|
630
|
-
HydrationCtx =
|
|
835
|
+
StateCtx = React3.createContext(null);
|
|
836
|
+
ActionsCtx = React3.createContext(null);
|
|
837
|
+
TextsCtx = React3.createContext(DEFAULT_TEXTS);
|
|
838
|
+
HydrationCtx = React3.createContext(false);
|
|
631
839
|
}
|
|
632
840
|
});
|
|
633
841
|
|
|
@@ -669,14 +877,17 @@ __export(index_exports, {
|
|
|
669
877
|
ConsentProvider: () => ConsentProvider,
|
|
670
878
|
ConsentScriptLoader: () => ConsentScriptLoader,
|
|
671
879
|
CookieBanner: () => CookieBanner,
|
|
880
|
+
DEFAULT_PROJECT_CATEGORIES: () => DEFAULT_PROJECT_CATEGORIES,
|
|
672
881
|
FloatingPreferencesButton: () => FloatingPreferencesButton,
|
|
673
882
|
PreferencesModal: () => PreferencesModal,
|
|
883
|
+
analyzeDeveloperConfiguration: () => analyzeDeveloperConfiguration,
|
|
674
884
|
createGoogleAnalyticsIntegration: () => createGoogleAnalyticsIntegration,
|
|
675
885
|
createGoogleTagManagerIntegration: () => createGoogleTagManagerIntegration,
|
|
676
886
|
createUserWayIntegration: () => createUserWayIntegration,
|
|
677
887
|
defaultConsentTheme: () => defaultConsentTheme,
|
|
678
888
|
loadScript: () => loadScript,
|
|
679
|
-
|
|
889
|
+
useCategories: () => useCategories,
|
|
890
|
+
useCategoryStatus: () => useCategoryStatus,
|
|
680
891
|
useConsent: () => useConsent,
|
|
681
892
|
useConsentHydration: () => useConsentHydration,
|
|
682
893
|
useConsentScriptLoader: () => useConsentScriptLoader,
|
|
@@ -910,15 +1121,15 @@ function loadScript(id, src, category = null, attrs = {}) {
|
|
|
910
1121
|
init_theme();
|
|
911
1122
|
|
|
912
1123
|
// src/utils/ConsentScriptLoader.tsx
|
|
913
|
-
var
|
|
1124
|
+
var React4 = __toESM(require("react"), 1);
|
|
914
1125
|
init_useConsent();
|
|
915
1126
|
function ConsentScriptLoader({
|
|
916
1127
|
integrations,
|
|
917
1128
|
reloadOnChange = false
|
|
918
1129
|
}) {
|
|
919
1130
|
const { preferences, consented } = useConsent();
|
|
920
|
-
const loadedScripts =
|
|
921
|
-
|
|
1131
|
+
const loadedScripts = React4.useRef(/* @__PURE__ */ new Set());
|
|
1132
|
+
React4.useEffect(() => {
|
|
922
1133
|
if (!consented) return;
|
|
923
1134
|
integrations.forEach(async (integration) => {
|
|
924
1135
|
const shouldLoad = preferences[integration.category];
|
|
@@ -949,7 +1160,7 @@ function ConsentScriptLoader({
|
|
|
949
1160
|
}
|
|
950
1161
|
function useConsentScriptLoader() {
|
|
951
1162
|
const { preferences, consented } = useConsent();
|
|
952
|
-
return
|
|
1163
|
+
return React4.useCallback(
|
|
953
1164
|
async (integration) => {
|
|
954
1165
|
if (!consented) {
|
|
955
1166
|
console.warn(
|
|
@@ -1046,6 +1257,9 @@ var COMMON_INTEGRATIONS = {
|
|
|
1046
1257
|
googleTagManager: createGoogleTagManagerIntegration,
|
|
1047
1258
|
userway: createUserWayIntegration
|
|
1048
1259
|
};
|
|
1260
|
+
|
|
1261
|
+
// src/index.ts
|
|
1262
|
+
init_developerGuidance();
|
|
1049
1263
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1050
1264
|
0 && (module.exports = {
|
|
1051
1265
|
COMMON_INTEGRATIONS,
|
|
@@ -1053,14 +1267,17 @@ var COMMON_INTEGRATIONS = {
|
|
|
1053
1267
|
ConsentProvider,
|
|
1054
1268
|
ConsentScriptLoader,
|
|
1055
1269
|
CookieBanner,
|
|
1270
|
+
DEFAULT_PROJECT_CATEGORIES,
|
|
1056
1271
|
FloatingPreferencesButton,
|
|
1057
1272
|
PreferencesModal,
|
|
1273
|
+
analyzeDeveloperConfiguration,
|
|
1058
1274
|
createGoogleAnalyticsIntegration,
|
|
1059
1275
|
createGoogleTagManagerIntegration,
|
|
1060
1276
|
createUserWayIntegration,
|
|
1061
1277
|
defaultConsentTheme,
|
|
1062
1278
|
loadScript,
|
|
1063
|
-
|
|
1279
|
+
useCategories,
|
|
1280
|
+
useCategoryStatus,
|
|
1064
1281
|
useConsent,
|
|
1065
1282
|
useConsentHydration,
|
|
1066
1283
|
useConsentScriptLoader,
|