react-lgpd-consent 0.3.7 → 0.4.1

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,5 @@
1
1
  // src/components/PreferencesModal.tsx
2
+ import Box2 from "@mui/material/Box";
2
3
  import Button2 from "@mui/material/Button";
3
4
  import Dialog from "@mui/material/Dialog";
4
5
  import DialogActions from "@mui/material/DialogActions";
@@ -8,183 +9,262 @@ import FormControlLabel from "@mui/material/FormControlLabel";
8
9
  import FormGroup from "@mui/material/FormGroup";
9
10
  import Switch from "@mui/material/Switch";
10
11
  import Typography3 from "@mui/material/Typography";
11
- import { useEffect as useEffect3, useState as useState2 } from "react";
12
+ import { useEffect as useEffect3, useState as useState3 } from "react";
12
13
 
13
14
  // src/context/CategoriesContext.tsx
14
15
  import * as React2 from "react";
15
16
 
16
- // src/utils/developerGuidance.ts
17
- import React from "react";
18
- var DEFAULT_PROJECT_CATEGORIES = {
19
- enabledCategories: ["analytics"]
17
+ // src/utils/cookieRegistry.ts
18
+ var COOKIE_PATTERNS_BY_CATEGORY = {
19
+ necessary: ["cookieConsent"],
20
+ analytics: ["_ga", "_ga_*", "_gid", "_gcl_au", "_hj*", "mp_*", "_clck", "_clsk"],
21
+ functional: ["intercom-*", "__zlcmid", "_zendesk_shared_session", "_userway_*"],
22
+ marketing: ["_fbp", "fr"],
23
+ social: [],
24
+ personalization: []
20
25
  };
21
- function analyzeDeveloperConfiguration(config) {
22
- const guidance = {
23
- warnings: [],
24
- suggestions: [],
25
- activeCategoriesInfo: [],
26
- usingDefaults: !config
27
- };
28
- const finalConfig = config || DEFAULT_PROJECT_CATEGORIES;
29
- if (!config) {
30
- guidance.warnings.push(
31
- '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".'
32
- );
33
- }
34
- guidance.activeCategoriesInfo.push({
35
- id: "necessary",
36
- name: "Cookies Necess\xE1rios",
37
- description: "Essenciais para funcionamento b\xE1sico do site",
38
- essential: true,
39
- uiRequired: false
40
- });
41
- const enabledCategories = finalConfig.enabledCategories || [];
42
- const categoryNames = {
43
- analytics: {
44
- name: "Cookies Anal\xEDticos",
45
- description: "Medem uso e performance do site"
26
+ var COOKIE_INFO_BY_INTEGRATION = {
27
+ "google-analytics": [
28
+ {
29
+ name: "_ga",
30
+ purpose: "Identifica\xE7\xE3o \xFAnica de visitantes para an\xE1lise de tr\xE1fego",
31
+ duration: "2 anos",
32
+ provider: "Google Analytics"
46
33
  },
47
- functional: {
48
- name: "Cookies Funcionais",
49
- description: "Melhoram experi\xEAncia e funcionalidades"
34
+ {
35
+ name: "_ga_*",
36
+ purpose: "Rastreamento de sess\xF5es e eventos espec\xEDficos do stream GA4",
37
+ duration: "2 anos",
38
+ provider: "Google Analytics"
50
39
  },
51
- marketing: {
52
- name: "Cookies de Marketing",
53
- description: "Publicidade direcionada e campanhas"
40
+ {
41
+ name: "_gid",
42
+ purpose: "Distin\xE7\xE3o de visitantes \xFAnicos em per\xEDodo de 24h",
43
+ duration: "24 horas",
44
+ provider: "Google Analytics"
45
+ }
46
+ ],
47
+ "google-tag-manager": [
48
+ {
49
+ name: "_gcl_au",
50
+ purpose: "Rastreamento de convers\xF5es de an\xFAncios",
51
+ duration: "90 dias",
52
+ provider: "Google"
53
+ }
54
+ ],
55
+ hotjar: [
56
+ {
57
+ name: "_hjSession_*",
58
+ purpose: "Rastreamento de sess\xE3o",
59
+ duration: "30 minutos",
60
+ provider: "Hotjar"
54
61
  },
55
- social: {
56
- name: "Cookies de Redes Sociais",
57
- description: "Integra\xE7\xE3o com plataformas sociais"
62
+ {
63
+ name: "_hjSessionUser_*",
64
+ purpose: "Persist\xEAncia de usu\xE1rio entre sess\xF5es",
65
+ duration: "365 dias",
66
+ provider: "Hotjar"
58
67
  },
59
- personalization: {
60
- name: "Cookies de Personaliza\xE7\xE3o",
61
- description: "Adaptam conte\xFAdo \xE0s prefer\xEAncias do usu\xE1rio"
68
+ {
69
+ name: "_hjFirstSeen",
70
+ purpose: "Detec\xE7\xE3o da primeira visita do usu\xE1rio",
71
+ duration: "Sess\xE3o",
72
+ provider: "Hotjar"
62
73
  }
63
- };
64
- enabledCategories.forEach((categoryId) => {
65
- const categoryInfo = categoryNames[categoryId];
66
- if (categoryInfo) {
67
- guidance.activeCategoriesInfo.push({
68
- id: categoryId,
69
- name: categoryInfo.name,
70
- description: categoryInfo.description,
71
- essential: false,
72
- uiRequired: true
73
- });
74
+ ],
75
+ mixpanel: [
76
+ {
77
+ name: "mp_*",
78
+ purpose: "Rastreamento de eventos e propriedades do usu\xE1rio para analytics",
79
+ duration: "1 ano",
80
+ provider: "Mixpanel"
81
+ }
82
+ ],
83
+ clarity: [
84
+ {
85
+ name: "_clck",
86
+ purpose: "Identificador de usu\xE1rio",
87
+ duration: "365 dias",
88
+ provider: "Microsoft"
89
+ },
90
+ { name: "_clsk", purpose: "Rastreamento de sess\xE3o", duration: "1 dia", provider: "Microsoft" }
91
+ ],
92
+ intercom: [
93
+ {
94
+ name: "intercom-id-*",
95
+ purpose: "Identificador do usu\xE1rio",
96
+ duration: "9 meses",
97
+ provider: "Intercom"
98
+ },
99
+ {
100
+ name: "intercom-session-*",
101
+ purpose: "Gerenciamento de sess\xE3o",
102
+ duration: "1 semana",
103
+ provider: "Intercom"
74
104
  }
105
+ ],
106
+ "zendesk-chat": [
107
+ {
108
+ name: "__zlcmid",
109
+ purpose: "Identificador de sess\xE3o de chat",
110
+ duration: "1 ano",
111
+ provider: "Zendesk"
112
+ },
113
+ {
114
+ name: "_zendesk_shared_session",
115
+ purpose: "Gerenciamento de sess\xE3o",
116
+ duration: "Sess\xE3o",
117
+ provider: "Zendesk"
118
+ }
119
+ ],
120
+ userway: [
121
+ {
122
+ name: "_userway_*",
123
+ purpose: "Prefer\xEAncias de acessibilidade",
124
+ duration: "1 ano",
125
+ provider: "UserWay"
126
+ }
127
+ ],
128
+ "facebook-pixel": [
129
+ { name: "_fbp", purpose: "Rastreamento de an\xFAncios", duration: "90 dias", provider: "Meta" },
130
+ { name: "fr", purpose: "Direcionamento de an\xFAncios", duration: "90 dias", provider: "Meta" }
131
+ ]
132
+ };
133
+ var INTEGRATION_DEFAULT_CATEGORY = {
134
+ "google-analytics": "analytics",
135
+ "google-tag-manager": "analytics",
136
+ hotjar: "analytics",
137
+ mixpanel: "analytics",
138
+ clarity: "analytics",
139
+ intercom: "functional",
140
+ "zendesk-chat": "functional",
141
+ userway: "functional",
142
+ "facebook-pixel": "marketing"
143
+ };
144
+ var COOKIE_CATALOG_OVERRIDES = {};
145
+ var COOKIE_CATEGORY_OVERRIDES = {};
146
+ function setCookieCatalogOverrides(overrides) {
147
+ COOKIE_CATALOG_OVERRIDES = {
148
+ byCategory: { ...COOKIE_CATALOG_OVERRIDES.byCategory || {}, ...overrides.byCategory || {} },
149
+ byIntegration: {
150
+ ...COOKIE_CATALOG_OVERRIDES.byIntegration || {},
151
+ ...overrides.byIntegration || {}
152
+ }
153
+ };
154
+ }
155
+ function setCookieCategoryOverrides(map) {
156
+ COOKIE_CATEGORY_OVERRIDES = { ...COOKIE_CATEGORY_OVERRIDES, ...map };
157
+ }
158
+ function matchPattern(name, pattern) {
159
+ if (pattern.endsWith("*")) return name.startsWith(pattern.slice(0, -1));
160
+ return name === pattern;
161
+ }
162
+ function getCookiesInfoForCategory(categoryId, usedIntegrations) {
163
+ const result = [];
164
+ usedIntegrations.forEach((id) => {
165
+ const defaultCat = INTEGRATION_DEFAULT_CATEGORY[id];
166
+ const defaults = COOKIE_INFO_BY_INTEGRATION[id] || [];
167
+ const list = COOKIE_CATALOG_OVERRIDES.byIntegration?.[id] || defaults;
168
+ list.forEach((desc) => {
169
+ const overrideCat = Object.entries(COOKIE_CATEGORY_OVERRIDES).find(
170
+ ([pattern]) => matchPattern(desc.name, pattern)
171
+ )?.[1];
172
+ const finalCat = overrideCat ?? defaultCat;
173
+ if (finalCat === categoryId && !result.find((d) => d.name === desc.name)) result.push(desc);
174
+ });
75
175
  });
76
- const totalToggleable = guidance.activeCategoriesInfo.filter((c) => c.uiRequired).length;
77
- if (totalToggleable === 0) {
78
- guidance.suggestions.push(
79
- 'Apenas cookies necess\xE1rios est\xE3o configurados. Para compliance completo LGPD, considere adicionar categorias como "analytics" ou "functional" conforme uso real.'
80
- );
176
+ const catOverride = COOKIE_CATALOG_OVERRIDES.byCategory?.[categoryId];
177
+ if (catOverride) {
178
+ catOverride.forEach((d) => {
179
+ const idx = result.findIndex((x) => x.name === d.name);
180
+ if (idx >= 0) result[idx] = d;
181
+ else result.push(d);
182
+ });
81
183
  }
82
- if (totalToggleable > 5) {
83
- guidance.warnings.push(
84
- `${totalToggleable} categorias opcionais detectadas. UI com muitas op\xE7\xF5es pode prejudicar experi\xEAncia do usu\xE1rio. Considere agrupar categorias similares.`
85
- );
184
+ if (categoryId === "necessary") {
185
+ if (!result.find((d) => d.name === "cookieConsent")) {
186
+ result.push({
187
+ name: "cookieConsent",
188
+ purpose: "Armazena suas prefer\xEAncias de consentimento",
189
+ duration: "365 dias",
190
+ provider: "Este site"
191
+ });
192
+ }
86
193
  }
87
- return guidance;
194
+ return result;
88
195
  }
89
- function logDeveloperGuidance(guidance, disableGuidanceProp) {
90
- const gt = globalThis;
91
- const nodeEnv = typeof gt.process !== "undefined" ? gt.process?.env?.NODE_ENV : void 0;
92
- const isProd = nodeEnv === "production" || gt.__LGPD_PRODUCTION__ === true;
93
- const isDisabled = !!disableGuidanceProp || gt.__LGPD_DISABLE_GUIDANCE__ === true;
94
- if (isProd || isDisabled) return;
95
- const PREFIX = "[\u{1F36A} LGPD-CONSENT]";
96
- if (guidance.warnings.length > 0) {
97
- console.group(`${PREFIX} \u26A0\uFE0F Avisos de Configura\xE7\xE3o`);
98
- guidance.warnings.forEach((msg) => console.warn(`${PREFIX} ${msg}`));
99
- console.groupEnd();
100
- }
101
- if (guidance.suggestions.length > 0) {
102
- console.group(`${PREFIX} \u{1F4A1} Sugest\xF5es`);
103
- guidance.suggestions.forEach((msg) => console.info(`${PREFIX} ${msg}`));
104
- console.groupEnd();
105
- }
106
- if (guidance.usingDefaults) {
107
- console.warn(
108
- `${PREFIX} \u{1F4CB} Usando configura\xE7\xE3o padr\xE3o. Para personalizar, use a prop "categories" no ConsentProvider.`
109
- );
110
- }
111
- const rows = guidance.activeCategoriesInfo.map((cat) => ({
112
- ID: cat.id,
113
- Nome: cat.name,
114
- "Toggle UI?": cat.uiRequired ? "\u2705 SIM" : "\u274C N\xC3O (sempre ativo)",
115
- "Essencial?": cat.essential ? "\u{1F512} SIM" : "\u2699\uFE0F N\xC3O"
116
- }));
117
- if (typeof console.table === "function") {
118
- console.group(`${PREFIX} \u{1F527} Categorias Ativas (para UI customizada)`);
119
- console.table(rows);
120
- console.info(`${PREFIX} \u2139\uFE0F Use estes dados para criar componentes customizados adequados.`);
121
- console.groupEnd();
122
- } else {
123
- console.log(`${PREFIX} \u{1F527} Categorias Ativas (para UI customizada)`, rows);
124
- console.info(`${PREFIX} \u2139\uFE0F Use estes dados para criar componentes customizados adequados.`);
196
+
197
+ // src/utils/cookieDiscovery.ts
198
+ function discoverRuntimeCookies() {
199
+ if (typeof document === "undefined" || !document.cookie) return [];
200
+ const names = Array.from(
201
+ new Set(
202
+ document.cookie.split(";").map((s) => s.trim()).filter(Boolean).map((s) => s.split("=")[0])
203
+ )
204
+ );
205
+ const list = names.map((name) => ({ name }));
206
+ try {
207
+ ;
208
+ globalThis.__LGPD_DISCOVERED_COOKIES__ = list;
209
+ } catch {
125
210
  }
211
+ return list;
126
212
  }
127
- function useDeveloperGuidance(config, disableGuidanceProp) {
128
- const guidance = React.useMemo(() => {
129
- return analyzeDeveloperConfiguration(config);
130
- }, [config]);
131
- React.useEffect(() => {
132
- if (!disableGuidanceProp) {
133
- logDeveloperGuidance(guidance, disableGuidanceProp);
213
+ function detectConsentCookieName() {
214
+ if (typeof document === "undefined" || !document.cookie) return null;
215
+ try {
216
+ const pairs = document.cookie.split(";").map((s) => s.trim()).filter(Boolean);
217
+ for (const p of pairs) {
218
+ const [name, ...rest] = p.split("=");
219
+ const raw = rest.join("=");
220
+ if (!raw) continue;
221
+ let val = raw;
222
+ try {
223
+ val = decodeURIComponent(raw);
224
+ } catch {
225
+ }
226
+ if (val.startsWith("{")) {
227
+ try {
228
+ const obj = JSON.parse(val);
229
+ if (obj && typeof obj === "object" && "preferences" in obj && "version" in obj) {
230
+ return name;
231
+ }
232
+ } catch {
233
+ }
234
+ }
134
235
  }
135
- }, [guidance, disableGuidanceProp]);
136
- return guidance;
137
- }
138
-
139
- // src/context/CategoriesContext.tsx
140
- import { jsx } from "react/jsx-runtime";
141
- var CategoriesContext = React2.createContext(null);
142
- function CategoriesProvider({
143
- children,
144
- config,
145
- disableDeveloperGuidance
146
- }) {
147
- const contextValue = React2.useMemo(() => {
148
- const finalConfig = config || DEFAULT_PROJECT_CATEGORIES;
149
- const guidance = analyzeDeveloperConfiguration(config);
150
- const toggleableCategories = guidance.activeCategoriesInfo.filter((cat) => cat.uiRequired);
151
- return {
152
- config: finalConfig,
153
- guidance,
154
- toggleableCategories,
155
- allCategories: guidance.activeCategoriesInfo
156
- };
157
- }, [config]);
158
- React2.useEffect(() => {
159
- logDeveloperGuidance(contextValue.guidance, disableDeveloperGuidance);
160
- }, [contextValue.guidance, disableDeveloperGuidance]);
161
- return /* @__PURE__ */ jsx(CategoriesContext.Provider, { value: contextValue, children });
162
- }
163
- function useCategories() {
164
- const context = React2.useContext(CategoriesContext);
165
- if (!context) {
166
- throw new Error(
167
- "useCategories deve ser usado dentro de CategoriesProvider. Certifique-se de que o ConsentProvider est\xE1 envolvendo seu componente."
168
- );
236
+ } catch {
169
237
  }
170
- return context;
238
+ return null;
171
239
  }
172
- function useCategoryStatus(categoryId) {
173
- const { allCategories } = useCategories();
174
- const category = allCategories.find((cat) => cat.id === categoryId);
175
- return {
176
- isActive: !!category,
177
- isEssential: category?.essential || false,
178
- needsToggle: category?.uiRequired || false,
179
- name: category?.name,
180
- description: category?.description
181
- };
240
+ function categorizeDiscoveredCookies(discovered, registerOverrides = false) {
241
+ const list = discovered || globalThis.__LGPD_DISCOVERED_COOKIES__ || [];
242
+ const out = {};
243
+ function matchPattern2(name, pattern) {
244
+ if (pattern.endsWith("*")) return name.startsWith(pattern.slice(0, -1));
245
+ return name === pattern;
246
+ }
247
+ list.filter((d) => d.name && d.name !== "cookieConsent").forEach((d) => {
248
+ let assigned = null;
249
+ Object.keys(COOKIE_PATTERNS_BY_CATEGORY).forEach((cat2) => {
250
+ if (assigned) return;
251
+ const patterns = COOKIE_PATTERNS_BY_CATEGORY[cat2] || [];
252
+ if (patterns.some((p) => matchPattern2(d.name, p))) assigned = cat2;
253
+ });
254
+ const cat = assigned || "analytics";
255
+ out[cat] = out[cat] || [];
256
+ if (!out[cat].find((x) => x.name === d.name)) out[cat].push(d);
257
+ });
258
+ if (registerOverrides) {
259
+ const byCategory = {};
260
+ Object.entries(out).forEach(([cat, cookies]) => {
261
+ byCategory[cat] = cookies;
262
+ });
263
+ setCookieCatalogOverrides({ byCategory });
264
+ }
265
+ return out;
182
266
  }
183
267
 
184
- // src/context/ConsentContext.tsx
185
- import * as React4 from "react";
186
- import { ThemeProvider } from "@mui/material/styles";
187
-
188
268
  // src/utils/cookieUtils.ts
189
269
  import Cookies from "js-cookie";
190
270
 
@@ -455,6 +535,478 @@ function removeConsentCookie(opts) {
455
535
  logger.info("Consent cookie removed");
456
536
  }
457
537
 
538
+ // src/utils/developerGuidance.ts
539
+ import React from "react";
540
+ var DEFAULT_PROJECT_CATEGORIES = {
541
+ enabledCategories: ["analytics"]
542
+ };
543
+ function calculateComplianceScore(guidance) {
544
+ let score = 0;
545
+ const maxScore = 100;
546
+ if (!guidance.usingDefaults) score += 30;
547
+ const totalCategories = guidance.activeCategoriesInfo.length;
548
+ const toggleableCategories = guidance.activeCategoriesInfo.filter((c) => c.uiRequired).length;
549
+ if (totalCategories > 1) score += 20;
550
+ if (toggleableCategories >= 2 && toggleableCategories <= 4) score += 25;
551
+ const criticalWarnings = guidance.messages.filter((m) => m.severity === "error").length;
552
+ const warnings = guidance.messages.filter((m) => m.severity === "warning").length;
553
+ if (criticalWarnings === 0) score += 15;
554
+ if (warnings === 0) score += 10;
555
+ return Math.min(score, maxScore);
556
+ }
557
+ function analyzeDeveloperConfiguration(config) {
558
+ const guidance = {
559
+ warnings: [],
560
+ suggestions: [],
561
+ messages: [],
562
+ activeCategoriesInfo: [],
563
+ usingDefaults: !config,
564
+ complianceScore: 0
565
+ };
566
+ const addMessage = (severity, message, category, actionable = true) => {
567
+ const guidanceMessage = { severity, message, category, actionable };
568
+ guidance.messages.push(guidanceMessage);
569
+ if (severity === "warning" || severity === "error") {
570
+ guidance.warnings.push(message);
571
+ } else {
572
+ guidance.suggestions.push(message);
573
+ }
574
+ };
575
+ const finalConfig = config || DEFAULT_PROJECT_CATEGORIES;
576
+ if (!config) {
577
+ addMessage(
578
+ "warning",
579
+ 'LGPD-CONSENT: Nenhuma configura\xE7\xE3o de categorias especificada. Usando padr\xE3o: necessary + analytics. Para produ\xE7\xE3o, especifique explicitamente as categorias via prop "categories".',
580
+ "configuration"
581
+ );
582
+ }
583
+ guidance.activeCategoriesInfo.push({
584
+ id: "necessary",
585
+ name: "Cookies Necess\xE1rios",
586
+ description: "Essenciais para funcionamento b\xE1sico do site",
587
+ essential: true,
588
+ uiRequired: false,
589
+ cookies: COOKIE_PATTERNS_BY_CATEGORY["necessary"]
590
+ });
591
+ const enabled = finalConfig.enabledCategories || [];
592
+ const NAMES = {
593
+ analytics: { name: "Cookies Anal\xEDticos", description: "Medem uso e performance do site" },
594
+ functional: {
595
+ name: "Cookies Funcionais",
596
+ description: "Melhoram experi\xEAncia e funcionalidades"
597
+ },
598
+ marketing: { name: "Cookies de Marketing", description: "Publicidade direcionada e campanhas" },
599
+ social: { name: "Cookies de Redes Sociais", description: "Integra\xE7\xE3o com plataformas sociais" },
600
+ personalization: { name: "Cookies de Personaliza\xE7\xE3o", description: "Adapta\xE7\xE3o de conte\xFAdo" }
601
+ };
602
+ enabled.forEach((id) => {
603
+ const info = NAMES[id];
604
+ if (info) {
605
+ guidance.activeCategoriesInfo.push({
606
+ id,
607
+ name: info.name,
608
+ description: info.description,
609
+ essential: false,
610
+ uiRequired: true,
611
+ cookies: COOKIE_PATTERNS_BY_CATEGORY[id]
612
+ });
613
+ }
614
+ });
615
+ const custom = finalConfig.customCategories || [];
616
+ custom.forEach((cat) => {
617
+ if (!cat?.id || cat.id === "necessary") return;
618
+ guidance.activeCategoriesInfo.push({
619
+ id: cat.id,
620
+ name: cat.name,
621
+ description: cat.description,
622
+ essential: !!cat.essential,
623
+ uiRequired: !cat.essential,
624
+ cookies: cat.cookies
625
+ });
626
+ });
627
+ try {
628
+ const gt = globalThis;
629
+ const implied = (gt.__LGPD_REQUIRED_CATEGORIES__ || []).filter(Boolean);
630
+ implied.forEach((id) => {
631
+ if (!guidance.activeCategoriesInfo.find((c) => c.id === id)) {
632
+ const info = NAMES[id];
633
+ if (info) {
634
+ guidance.activeCategoriesInfo.push({
635
+ id,
636
+ name: info.name,
637
+ description: info.description,
638
+ essential: false,
639
+ uiRequired: true,
640
+ cookies: COOKIE_PATTERNS_BY_CATEGORY[id]
641
+ });
642
+ if (!enabled.includes(id)) {
643
+ addMessage(
644
+ "info",
645
+ `Integra\xE7\xF5es detectadas requerem a categoria '${id}'. Adicione-a em categories.enabledCategories.`,
646
+ "integration"
647
+ );
648
+ }
649
+ }
650
+ }
651
+ });
652
+ } catch {
653
+ }
654
+ try {
655
+ const gt2 = globalThis;
656
+ const used = gt2.__LGPD_USED_INTEGRATIONS__ || [];
657
+ guidance.activeCategoriesInfo = guidance.activeCategoriesInfo.map((c) => {
658
+ const info = getCookiesInfoForCategory(c.id, used);
659
+ const names = Array.from(/* @__PURE__ */ new Set([...c.cookies || [], ...info.map((d) => d.name)]));
660
+ return { ...c, cookies: names };
661
+ });
662
+ } catch {
663
+ }
664
+ const totalToggleable = guidance.activeCategoriesInfo.filter((c) => c.uiRequired).length;
665
+ if (totalToggleable === 0) {
666
+ addMessage(
667
+ "info",
668
+ 'Apenas cookies necess\xE1rios est\xE3o configurados. Para compliance LGPD, considere adicionar categorias como "analytics" ou "functional" conforme uso real.',
669
+ "compliance"
670
+ );
671
+ }
672
+ if (totalToggleable > 5) {
673
+ addMessage(
674
+ "warning",
675
+ `${totalToggleable} categorias opcionais detectadas. UI com muitas op\xE7\xF5es pode prejudicar a experi\xEAncia. Considere agrupar categorias similares.`,
676
+ "usability"
677
+ );
678
+ }
679
+ guidance.complianceScore = calculateComplianceScore(guidance);
680
+ return guidance;
681
+ }
682
+ var GUIDANCE_CACHE = /* @__PURE__ */ new Set();
683
+ var SESSION_LOGGED = {
684
+ intro: false,
685
+ bestPractices: false
686
+ };
687
+ function getComplianceScoreColor(score) {
688
+ if (score >= 80) return "#4caf50";
689
+ if (score >= 60) return "#ff9800";
690
+ return "#f44336";
691
+ }
692
+ function logComplianceScore(prefix, score) {
693
+ const color = getComplianceScoreColor(score);
694
+ console.log(
695
+ `%c${prefix} Score de Conformidade LGPD: ${score}/100`,
696
+ `color: ${color}; font-weight: bold; font-size: 14px;`
697
+ );
698
+ }
699
+ function logMessagesByType(prefix, messages, type, config) {
700
+ const filteredMessages = messages.filter((m) => m.severity === type);
701
+ if (filteredMessages.length === 0) return false;
702
+ const typeConfig = {
703
+ error: {
704
+ show: config.showWarnings,
705
+ title: "Erros Cr\xEDticos",
706
+ color: "#d32f2f",
707
+ method: console.error
708
+ },
709
+ warning: {
710
+ show: config.showWarnings,
711
+ title: "Avisos de Configura\xE7\xE3o",
712
+ color: "#f57c00",
713
+ method: console.warn
714
+ },
715
+ info: {
716
+ show: config.showSuggestions,
717
+ title: "Sugest\xF5es",
718
+ color: "#2196f3",
719
+ method: console.info
720
+ }
721
+ };
722
+ const typeSettings = typeConfig[type];
723
+ if (!typeSettings.show) return false;
724
+ console.group(
725
+ `%c${prefix} ${typeSettings.title}`,
726
+ `color: ${typeSettings.color}; font-weight: bold;`
727
+ );
728
+ filteredMessages.forEach(
729
+ (msg) => typeSettings.method(
730
+ `%c${prefix}%c ${msg.message}`,
731
+ `color: ${typeSettings.color};`,
732
+ "color: #333;"
733
+ )
734
+ );
735
+ console.groupEnd();
736
+ return true;
737
+ }
738
+ function getGuidanceHash(guidance) {
739
+ const sortedWarnings = [...guidance.warnings].sort((a, b) => a.localeCompare(b));
740
+ const sortedSuggestions = [...guidance.suggestions].sort(
741
+ (a, b) => a.localeCompare(b)
742
+ );
743
+ const sortedCategories = guidance.activeCategoriesInfo.map((c) => c.id).sort((a, b) => a.localeCompare(b));
744
+ return JSON.stringify({
745
+ warnings: sortedWarnings,
746
+ suggestions: sortedSuggestions,
747
+ categories: sortedCategories,
748
+ usingDefaults: guidance.usingDefaults
749
+ });
750
+ }
751
+ function logIntroOnce() {
752
+ if (SESSION_LOGGED.intro) return;
753
+ SESSION_LOGGED.intro = true;
754
+ console.log(
755
+ `%c\u{1F36A} LGPD-CONSENT %c- Sistema de Consentimento Ativo`,
756
+ "background: #4caf50; color: white; padding: 4px 8px; border-radius: 4px; font-weight: bold;",
757
+ "color: #2e7d32; font-weight: 500;"
758
+ );
759
+ }
760
+ function logServerSideIfAvailable(guidance) {
761
+ try {
762
+ const gt = globalThis;
763
+ if (gt.process?.stdout?.write) {
764
+ const prefix = "\x1B[36m[LGPD-CONSENT]\x1B[0m";
765
+ const warnings = guidance.warnings.length;
766
+ const suggestions = guidance.suggestions.length;
767
+ const stdout = gt.process.stdout;
768
+ if (warnings > 0 || suggestions > 0) {
769
+ stdout.write(`${prefix} \u{1F527} Config: ${warnings} avisos, ${suggestions} sugest\xF5es
770
+ `);
771
+ if (warnings > 0) {
772
+ guidance.warnings.forEach((w) => {
773
+ stdout.write(`${prefix} \x1B[33m\u26A0\uFE0F ${w}\x1B[0m
774
+ `);
775
+ });
776
+ }
777
+ if (suggestions > 0) {
778
+ guidance.suggestions.forEach((s) => {
779
+ stdout.write(`${prefix} \x1B[36m\u{1F4A1} ${s}\x1B[0m
780
+ `);
781
+ });
782
+ }
783
+ }
784
+ }
785
+ } catch {
786
+ }
787
+ }
788
+ function logDeveloperGuidance(guidance, disableGuidanceProp, config) {
789
+ const gt = globalThis;
790
+ const nodeEnv = typeof gt.process !== "undefined" ? gt.process?.env?.NODE_ENV : void 0;
791
+ const isProd = nodeEnv === "production" || gt.__LGPD_PRODUCTION__ === true;
792
+ if (isProd || disableGuidanceProp) return;
793
+ const guidanceHash = getGuidanceHash(guidance);
794
+ if (GUIDANCE_CACHE.has(guidanceHash)) return;
795
+ GUIDANCE_CACHE.add(guidanceHash);
796
+ logServerSideIfAvailable(guidance);
797
+ const guidanceConfig = {
798
+ showWarnings: true,
799
+ showSuggestions: true,
800
+ showCategoriesTable: true,
801
+ showBestPractices: true,
802
+ showComplianceScore: true,
803
+ minimumSeverity: "info",
804
+ ...config
805
+ };
806
+ if (guidanceConfig.messageProcessor) {
807
+ guidanceConfig.messageProcessor(guidance.messages);
808
+ return;
809
+ }
810
+ logIntroOnce();
811
+ const PREFIX = "\u{1F36A}";
812
+ let hasImportantInfo = false;
813
+ const filteredMessages = guidance.messages.filter((msg) => {
814
+ const severityLevels = { info: 0, warning: 1, error: 2 };
815
+ const minLevel = severityLevels[guidanceConfig.minimumSeverity || "info"];
816
+ const msgLevel = severityLevels[msg.severity];
817
+ return msgLevel >= minLevel;
818
+ });
819
+ hasImportantInfo = logMessagesByType(PREFIX, filteredMessages, "error", guidanceConfig) || hasImportantInfo;
820
+ hasImportantInfo = logMessagesByType(PREFIX, filteredMessages, "warning", guidanceConfig) || hasImportantInfo;
821
+ if (hasImportantInfo || guidance.usingDefaults) {
822
+ hasImportantInfo = logMessagesByType(PREFIX, filteredMessages, "info", guidanceConfig) || hasImportantInfo;
823
+ }
824
+ if (guidanceConfig.showComplianceScore && guidance.complianceScore !== void 0) {
825
+ logComplianceScore(PREFIX, guidance.complianceScore);
826
+ }
827
+ if (guidanceConfig.showCategoriesTable && (hasImportantInfo || guidance.usingDefaults)) {
828
+ const rows = guidance.activeCategoriesInfo.map((cat) => ({
829
+ "\u{1F4CA} Categoria": cat.id,
830
+ "\u{1F3F7}\uFE0F Nome": cat.name,
831
+ "\u{1F39B}\uFE0F UI": cat.uiRequired ? "\u2705" : "\u{1F512}",
832
+ "\u{1F36A} Cookies": (cat.cookies || []).slice(0, 3).join(", ") + (cat.cookies && cat.cookies.length > 3 ? ` (+${cat.cookies.length - 3})` : "")
833
+ }));
834
+ if (typeof console.table === "function") {
835
+ console.group(`%c${PREFIX} Configura\xE7\xE3o Ativa`, "color: #4caf50; font-weight: bold;");
836
+ console.table(rows);
837
+ console.groupEnd();
838
+ }
839
+ }
840
+ if (!SESSION_LOGGED.bestPractices && hasImportantInfo) {
841
+ SESSION_LOGGED.bestPractices = true;
842
+ console.group(`%c${PREFIX} LGPD - Boas Pr\xE1ticas`, "color: #9c27b0; font-weight: bold;");
843
+ console.info(
844
+ `%c${PREFIX}%c Necessary: sempre ativo \u2022 Demais: opt-out por padr\xE3o`,
845
+ "color: #9c27b0;",
846
+ "color: #7b1fa2;"
847
+ );
848
+ console.info(
849
+ `%c${PREFIX}%c Documente pol\xEDticas claras por categoria`,
850
+ "color: #9c27b0;",
851
+ "color: #7b1fa2;"
852
+ );
853
+ console.info(
854
+ `%c${PREFIX}%c Registre consentimento com data/hora/origem`,
855
+ "color: #9c27b0;",
856
+ "color: #7b1fa2;"
857
+ );
858
+ console.groupEnd();
859
+ }
860
+ }
861
+ function useDeveloperGuidance(config, disableGuidanceProp, guidanceConfig) {
862
+ const guidance = React.useMemo(() => analyzeDeveloperConfiguration(config), [config]);
863
+ React.useEffect(() => {
864
+ if (!disableGuidanceProp) logDeveloperGuidance(guidance, disableGuidanceProp, guidanceConfig);
865
+ }, [guidance, disableGuidanceProp, guidanceConfig]);
866
+ return guidance;
867
+ }
868
+ var GUIDANCE_PRESETS = {
869
+ /** Configuração completa para desenvolvimento */
870
+ development: {
871
+ showWarnings: true,
872
+ showSuggestions: true,
873
+ showCategoriesTable: true,
874
+ showBestPractices: true,
875
+ showComplianceScore: true,
876
+ minimumSeverity: "info"
877
+ },
878
+ /** Configuração silenciosa para produção */
879
+ production: {
880
+ showWarnings: false,
881
+ showSuggestions: false,
882
+ showCategoriesTable: false,
883
+ showBestPractices: false,
884
+ showComplianceScore: false,
885
+ minimumSeverity: "error"
886
+ },
887
+ /** Apenas erros críticos */
888
+ minimal: {
889
+ showWarnings: true,
890
+ showSuggestions: false,
891
+ showCategoriesTable: false,
892
+ showBestPractices: false,
893
+ showComplianceScore: false,
894
+ minimumSeverity: "error"
895
+ },
896
+ /** Focado em conformidade LGPD */
897
+ compliance: {
898
+ showWarnings: true,
899
+ showSuggestions: true,
900
+ showCategoriesTable: true,
901
+ showBestPractices: true,
902
+ showComplianceScore: true,
903
+ minimumSeverity: "warning"
904
+ }
905
+ };
906
+
907
+ // src/context/CategoriesContext.tsx
908
+ import { jsx } from "react/jsx-runtime";
909
+ var CategoriesContext = React2.createContext(null);
910
+ function CategoriesProvider({
911
+ children,
912
+ config,
913
+ disableDeveloperGuidance,
914
+ disableDiscoveryLog
915
+ }) {
916
+ const [impliedVersion, setImpliedVersion] = React2.useState(0);
917
+ React2.useEffect(() => {
918
+ const handler = () => setImpliedVersion((v) => v + 1);
919
+ if (typeof window !== "undefined" && typeof window.addEventListener === "function") {
920
+ window.addEventListener("lgpd:requiredCategories", handler);
921
+ return () => window.removeEventListener("lgpd:requiredCategories", handler);
922
+ }
923
+ return () => {
924
+ };
925
+ }, []);
926
+ const contextValue = React2.useMemo(() => {
927
+ const finalConfig = config || DEFAULT_PROJECT_CATEGORIES;
928
+ const guidance = analyzeDeveloperConfiguration(config);
929
+ const toggleableCategories = guidance.activeCategoriesInfo.filter((cat) => cat.uiRequired);
930
+ return {
931
+ config: finalConfig,
932
+ guidance,
933
+ toggleableCategories,
934
+ allCategories: guidance.activeCategoriesInfo
935
+ };
936
+ }, [config, impliedVersion]);
937
+ React2.useEffect(() => {
938
+ logDeveloperGuidance(contextValue.guidance, disableDeveloperGuidance);
939
+ }, [contextValue.guidance, disableDeveloperGuidance]);
940
+ React2.useEffect(() => {
941
+ try {
942
+ const gt = globalThis;
943
+ const env = typeof gt.process !== "undefined" ? gt.process?.env?.NODE_ENV : void 0;
944
+ const isDev = env === "development";
945
+ if (!isDev || gt.__LGPD_DISCOVERY_LOGGED__ === true || disableDiscoveryLog) return;
946
+ const discovered = discoverRuntimeCookies();
947
+ const consentName = detectConsentCookieName() || DEFAULT_COOKIE_OPTS.name;
948
+ const PREFIX = "[\u{1F36A} LGPD-CONSENT]";
949
+ if (typeof console !== "undefined") {
950
+ try {
951
+ console.group(`${PREFIX} \u{1F50E} Descoberta de cookies (experimental)`);
952
+ const names = Array.from(
953
+ new Set([consentName, ...discovered.map((d) => d.name)].filter(Boolean))
954
+ );
955
+ const rows = names.map((n) => ({ Cookie: n }));
956
+ if (typeof console.table === "function") console.table(rows);
957
+ else console.log(rows);
958
+ console.info(
959
+ `${PREFIX} \u2139\uFE0F Estes nomes s\xE3o detectados em tempo de execu\xE7\xE3o. Ajuste ou categorize via APIs de override se necess\xE1rio.`
960
+ );
961
+ console.groupEnd();
962
+ } catch {
963
+ }
964
+ }
965
+ gt.__LGPD_DISCOVERY_LOGGED__ = true;
966
+ } catch {
967
+ }
968
+ }, [disableDiscoveryLog]);
969
+ return /* @__PURE__ */ jsx(CategoriesContext.Provider, { value: contextValue, children });
970
+ }
971
+ function useCategories() {
972
+ const context = React2.useContext(CategoriesContext);
973
+ if (!context) {
974
+ throw new Error(
975
+ "useCategories deve ser usado dentro de CategoriesProvider. Certifique-se de que o ConsentProvider est\xE1 envolvendo seu componente."
976
+ );
977
+ }
978
+ return context;
979
+ }
980
+ function useCategoryStatus(categoryId) {
981
+ const { allCategories } = useCategories();
982
+ const category = allCategories.find((cat) => cat.id === categoryId);
983
+ return {
984
+ isActive: !!category,
985
+ isEssential: category?.essential || false,
986
+ needsToggle: category?.uiRequired || false,
987
+ name: category?.name,
988
+ description: category?.description
989
+ };
990
+ }
991
+
992
+ // src/context/DesignContext.tsx
993
+ import * as React3 from "react";
994
+ import { jsx as jsx2 } from "react/jsx-runtime";
995
+ var DesignContext = React3.createContext(void 0);
996
+ function DesignProvider({
997
+ tokens,
998
+ children
999
+ }) {
1000
+ return /* @__PURE__ */ jsx2(DesignContext.Provider, { value: tokens, children });
1001
+ }
1002
+ function useDesignTokens() {
1003
+ return React3.useContext(DesignContext);
1004
+ }
1005
+
1006
+ // src/context/ConsentContext.tsx
1007
+ import { ThemeProvider } from "@mui/material/styles";
1008
+ import * as React4 from "react";
1009
+
458
1010
  // src/utils/categoryUtils.ts
459
1011
  function createProjectPreferences(config, defaultValue = false) {
460
1012
  const preferences = {
@@ -467,6 +1019,12 @@ function createProjectPreferences(config, defaultValue = false) {
467
1019
  preferences[category] = defaultValue;
468
1020
  }
469
1021
  });
1022
+ const customCategories = config?.customCategories || [];
1023
+ customCategories.forEach((cat) => {
1024
+ if (cat.id && cat.id !== "necessary") {
1025
+ preferences[cat.id] = defaultValue;
1026
+ }
1027
+ });
470
1028
  return preferences;
471
1029
  }
472
1030
  function validateProjectPreferences(preferences, config) {
@@ -480,6 +1038,13 @@ function validateProjectPreferences(preferences, config) {
480
1038
  validPreferences[category] = preferences[category];
481
1039
  }
482
1040
  });
1041
+ const customCategories = config?.customCategories || [];
1042
+ customCategories.forEach((cat) => {
1043
+ const id = cat.id;
1044
+ if (id && id !== "necessary" && preferences[id] !== void 0) {
1045
+ validPreferences[id] = preferences[id];
1046
+ }
1047
+ });
483
1048
  return validPreferences;
484
1049
  }
485
1050
  function getAllProjectCategories(config) {
@@ -497,6 +1062,12 @@ function getAllProjectCategories(config) {
497
1062
  allCategories.push(getDefaultCategoryDefinition(category));
498
1063
  }
499
1064
  });
1065
+ const customCategories = config?.customCategories || [];
1066
+ customCategories.forEach((cat) => {
1067
+ if (cat.id && cat.id !== "necessary") {
1068
+ allCategories.push({ ...cat, essential: !!cat.essential });
1069
+ }
1070
+ });
500
1071
  return allCategories;
501
1072
  }
502
1073
  function getDefaultCategoryDefinition(category) {
@@ -541,20 +1112,6 @@ function getDefaultCategoryDefinition(category) {
541
1112
  return definitions[category];
542
1113
  }
543
1114
 
544
- // src/context/DesignContext.tsx
545
- import * as React3 from "react";
546
- import { jsx as jsx2 } from "react/jsx-runtime";
547
- var DesignContext = React3.createContext(void 0);
548
- function DesignProvider({
549
- tokens,
550
- children
551
- }) {
552
- return /* @__PURE__ */ jsx2(DesignContext.Provider, { value: tokens, children });
553
- }
554
- function useDesignTokens() {
555
- return React3.useContext(DesignContext);
556
- }
557
-
558
1115
  // src/components/CookieBanner.tsx
559
1116
  import Button from "@mui/material/Button";
560
1117
  import Box from "@mui/material/Box";
@@ -631,6 +1188,7 @@ function Branding({ variant, hidden = false }) {
631
1188
  import { Fragment, jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
632
1189
  function CookieBanner({
633
1190
  policyLinkUrl,
1191
+ termsLinkUrl,
634
1192
  debug,
635
1193
  blocking = true,
636
1194
  hideBranding = false,
@@ -650,15 +1208,15 @@ function CookieBanner({
650
1208
  hideBranding
651
1209
  });
652
1210
  if (!open) return null;
653
- const bannerStyle = {
1211
+ const bannerStyle = (theme) => ({
654
1212
  p: designTokens?.spacing?.padding?.banner ?? 2,
655
1213
  maxWidth: 720,
656
1214
  mx: "auto",
657
- backgroundColor: designTokens?.colors?.background,
658
- color: designTokens?.colors?.text,
1215
+ backgroundColor: designTokens?.colors?.background ?? theme.palette.background?.paper,
1216
+ color: designTokens?.colors?.text ?? theme.palette.text?.primary,
659
1217
  borderRadius: designTokens?.spacing?.borderRadius?.banner,
660
1218
  fontFamily: designTokens?.typography?.fontFamily
661
- };
1219
+ });
662
1220
  const bannerContent = /* @__PURE__ */ jsx4(Paper, { elevation: 3, sx: bannerStyle, ...PaperProps, children: /* @__PURE__ */ jsxs2(Stack, { spacing: 1, children: [
663
1221
  /* @__PURE__ */ jsxs2(Typography2, { variant: "body2", sx: { fontSize: designTokens?.typography?.fontSize?.banner }, children: [
664
1222
  texts.bannerMessage,
@@ -724,27 +1282,51 @@ function CookieBanner({
724
1282
  width: designTokens?.layout?.width?.desktop ?? "100%",
725
1283
  p: 2
726
1284
  };
727
- let backdropColor = "rgba(0, 0, 0, 0.4)";
728
1285
  const backdropToken = designTokens?.layout?.backdrop;
729
- if (backdropToken === false) {
730
- backdropColor = "transparent";
731
- } else if (typeof backdropToken === "string") {
732
- backdropColor = backdropToken;
733
- }
734
- if (blocking) {
1286
+ const resolveBackdropColor = (theme) => {
1287
+ if (backdropToken === false) return "transparent";
1288
+ if (typeof backdropToken === "string") {
1289
+ if (backdropToken.toLowerCase() === "auto") {
1290
+ const isDark2 = theme?.palette?.mode === "dark";
1291
+ return isDark2 ? "rgba(255, 255, 255, 0.12)" : "rgba(0, 0, 0, 0.4)";
1292
+ }
1293
+ return backdropToken;
1294
+ }
1295
+ const isDark = theme?.palette?.mode === "dark";
1296
+ return isDark ? "rgba(255, 255, 255, 0.12)" : "rgba(0, 0, 0, 0.4)";
1297
+ };
1298
+ const isSafeRoute = (() => {
1299
+ try {
1300
+ if (typeof window === "undefined") return false;
1301
+ const current = new URL(window.location.href);
1302
+ const safeUrls = [policyLinkUrl, termsLinkUrl].filter(Boolean);
1303
+ return safeUrls.some((u) => {
1304
+ try {
1305
+ const target = new URL(u, current.origin);
1306
+ return target.pathname === current.pathname;
1307
+ } catch {
1308
+ return false;
1309
+ }
1310
+ });
1311
+ } catch {
1312
+ return false;
1313
+ }
1314
+ })();
1315
+ const effectiveBlocking = blocking && !isSafeRoute;
1316
+ if (effectiveBlocking) {
735
1317
  return /* @__PURE__ */ jsxs2(Fragment, { children: [
736
1318
  /* @__PURE__ */ jsx4(
737
1319
  Box,
738
1320
  {
739
- sx: {
1321
+ sx: (theme) => ({
740
1322
  position: "fixed",
741
1323
  top: 0,
742
1324
  left: 0,
743
1325
  right: 0,
744
1326
  bottom: 0,
745
- backgroundColor: backdropColor,
1327
+ backgroundColor: resolveBackdropColor(theme),
746
1328
  zIndex: 1299
747
- }
1329
+ })
748
1330
  }
749
1331
  ),
750
1332
  /* @__PURE__ */ jsx4(Box, { sx: positionStyle, children: bannerContent })
@@ -855,7 +1437,7 @@ function FloatingPreferencesButton({
855
1437
  // src/context/ConsentContext.tsx
856
1438
  import { jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
857
1439
  var PreferencesModal = React4.lazy(
858
- () => import("./PreferencesModal-3KKTKVII.js").then((m) => ({
1440
+ () => import("./PreferencesModal-RNRD3JKB.js").then((m) => ({
859
1441
  default: m.PreferencesModal
860
1442
  }))
861
1443
  );
@@ -996,7 +1578,9 @@ function ConsentProvider({
996
1578
  onPreferencesSaved,
997
1579
  cookie: cookieOpts,
998
1580
  disableDeveloperGuidance,
999
- children
1581
+ guidanceConfig,
1582
+ children,
1583
+ disableDiscoveryLog
1000
1584
  }) {
1001
1585
  const texts = React4.useMemo(() => ({ ...DEFAULT_TEXTS, ...textsProp ?? {} }), [textsProp]);
1002
1586
  const cookie = React4.useMemo(
@@ -1008,7 +1592,15 @@ function ConsentProvider({
1008
1592
  if (categories) return categories;
1009
1593
  return DEFAULT_PROJECT_CATEGORIES;
1010
1594
  }, [categories]);
1011
- useDeveloperGuidance(finalCategoriesConfig, disableDeveloperGuidance);
1595
+ useDeveloperGuidance(finalCategoriesConfig, disableDeveloperGuidance, guidanceConfig);
1596
+ React4.useEffect(() => {
1597
+ const isProd = typeof process !== "undefined" && process.env?.NODE_ENV === "production";
1598
+ if (!isProd && PreferencesModalComponent) {
1599
+ console.info(
1600
+ "[LGPD-CONSENT] Dica: seu PreferencesModal \xE9 customizado. Garanta exibir os detalhes dos cookies por categoria (nome, finalidade, dura\xE7\xE3o) usando as APIs setCookieCatalogOverrides / setCookieCategoryOverrides e getCookiesInfoForCategory. Consulte QUICKSTART e INTEGRACOES.md."
1601
+ );
1602
+ }
1603
+ }, [PreferencesModalComponent]);
1012
1604
  const boot = React4.useMemo(() => {
1013
1605
  if (initialState) return { ...initialState, isModalOpen: false };
1014
1606
  return createFullConsentState(
@@ -1092,6 +1684,7 @@ function ConsentProvider({
1092
1684
  {
1093
1685
  config: finalCategoriesConfig,
1094
1686
  disableDeveloperGuidance,
1687
+ disableDiscoveryLog,
1095
1688
  children: [
1096
1689
  children,
1097
1690
  /* @__PURE__ */ jsx6(React4.Suspense, { fallback: null, children: PreferencesModalComponent ? /* @__PURE__ */ jsx6(
@@ -1206,26 +1799,31 @@ function useConsentTexts() {
1206
1799
  function useConsentHydration() {
1207
1800
  return useConsentHydrationInternal();
1208
1801
  }
1802
+ var globalOpenPreferences = null;
1803
+ function _registerGlobalOpenPreferences(openPreferences) {
1804
+ globalOpenPreferences = openPreferences;
1805
+ }
1806
+ function _unregisterGlobalOpenPreferences() {
1807
+ globalOpenPreferences = null;
1808
+ }
1209
1809
  function useOpenPreferencesModal() {
1210
- const { openPreferences } = useConsent();
1211
- return openPreferences;
1810
+ const actions = useConsentActionsInternal();
1811
+ if (!actions) {
1812
+ throw new Error(
1813
+ "[LGPD-CONSENT] useOpenPreferencesModal deve ser usado dentro do ConsentProvider. Envolva seu componente com <ConsentProvider>."
1814
+ );
1815
+ }
1816
+ return actions.openPreferences;
1212
1817
  }
1213
- var globalOpenPreferences = null;
1214
1818
  function openPreferencesModal() {
1215
1819
  if (globalOpenPreferences) {
1216
1820
  globalOpenPreferences();
1217
1821
  } else {
1218
1822
  logger.warn(
1219
- "openPreferencesModal: ConsentProvider n\xE3o foi inicializado ou n\xE3o est\xE1 dispon\xEDvel."
1823
+ "openPreferencesModal called but no ConsentProvider is mounted. Make sure ConsentProvider is rendered before calling this function."
1220
1824
  );
1221
1825
  }
1222
1826
  }
1223
- function _registerGlobalOpenPreferences(openPreferences) {
1224
- globalOpenPreferences = openPreferences;
1225
- }
1226
- function _unregisterGlobalOpenPreferences() {
1227
- globalOpenPreferences = null;
1228
- }
1229
1827
 
1230
1828
  // src/components/PreferencesModal.tsx
1231
1829
  import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
@@ -1236,8 +1834,8 @@ function PreferencesModal2({
1236
1834
  const { preferences, setPreferences, closePreferences, isModalOpen } = useConsent();
1237
1835
  const texts = useConsentTexts();
1238
1836
  const designTokens = useDesignTokens();
1239
- const { toggleableCategories } = useCategories();
1240
- const [tempPreferences, setTempPreferences] = useState2(() => {
1837
+ const { toggleableCategories, allCategories } = useCategories();
1838
+ const [tempPreferences, setTempPreferences] = useState3(() => {
1241
1839
  const initialPrefs = { necessary: true };
1242
1840
  toggleableCategories.forEach((category) => {
1243
1841
  initialPrefs[category.id] = preferences[category.id] ?? false;
@@ -1261,43 +1859,126 @@ function PreferencesModal2({
1261
1859
  setTempPreferences(preferences);
1262
1860
  closePreferences();
1263
1861
  };
1862
+ const modalTitleSx = (theme) => ({
1863
+ fontSize: designTokens?.typography?.fontSize?.modal ?? void 0,
1864
+ color: designTokens?.colors?.text ?? theme.palette.text.primary
1865
+ });
1866
+ const modalContentSx = (theme) => ({
1867
+ p: designTokens?.spacing?.padding?.modal ?? void 0,
1868
+ backgroundColor: designTokens?.colors?.background ?? theme.palette.background.paper,
1869
+ color: designTokens?.colors?.text ?? theme.palette.text.primary
1870
+ });
1264
1871
  return /* @__PURE__ */ jsxs4(Dialog, { "aria-labelledby": "cookie-pref-title", open, onClose: handleCancel, ...DialogProps2, children: [
1265
- /* @__PURE__ */ jsx7(
1266
- DialogTitle,
1267
- {
1268
- id: "cookie-pref-title",
1269
- sx: { fontSize: designTokens?.typography?.fontSize?.modal ?? void 0 },
1270
- children: texts.modalTitle
1271
- }
1272
- ),
1273
- /* @__PURE__ */ jsxs4(DialogContent, { dividers: true, sx: { p: designTokens?.spacing?.padding?.modal ?? void 0 }, children: [
1872
+ /* @__PURE__ */ jsx7(DialogTitle, { id: "cookie-pref-title", sx: modalTitleSx, children: texts.modalTitle }),
1873
+ /* @__PURE__ */ jsxs4(DialogContent, { dividers: true, sx: modalContentSx, children: [
1274
1874
  /* @__PURE__ */ jsx7(
1275
1875
  Typography3,
1276
1876
  {
1277
1877
  variant: "body2",
1278
- sx: { mb: 2, fontSize: designTokens?.typography?.fontSize?.modal ?? void 0 },
1878
+ sx: (theme) => ({
1879
+ mb: 2,
1880
+ fontSize: designTokens?.typography?.fontSize?.modal ?? void 0,
1881
+ color: designTokens?.colors?.text ?? theme.palette.text.primary
1882
+ }),
1279
1883
  children: texts.modalIntro
1280
1884
  }
1281
1885
  ),
1282
1886
  /* @__PURE__ */ jsxs4(FormGroup, { children: [
1283
- toggleableCategories.map((category) => /* @__PURE__ */ jsx7(
1284
- FormControlLabel,
1285
- {
1286
- control: /* @__PURE__ */ jsx7(
1287
- Switch,
1887
+ toggleableCategories.map((category) => {
1888
+ const full = allCategories.find((c) => c.id === category.id);
1889
+ const namesFromGuidance = full?.cookies ?? [];
1890
+ const used = globalThis.__LGPD_USED_INTEGRATIONS__ || [];
1891
+ const descriptors = getCookiesInfoForCategory(category.id, used);
1892
+ const enrichedDescriptors = descriptors.map((desc) => {
1893
+ if (desc.purpose && desc.duration && desc.provider) {
1894
+ return desc;
1895
+ }
1896
+ return {
1897
+ name: desc.name,
1898
+ purpose: desc.purpose || "-",
1899
+ duration: desc.duration || "-",
1900
+ provider: desc.provider || "-"
1901
+ };
1902
+ });
1903
+ const merged = [
1904
+ ...enrichedDescriptors,
1905
+ ...namesFromGuidance.filter((n) => !enrichedDescriptors.find((d) => d.name === n)).map((n) => ({ name: n, purpose: "-", duration: "-", provider: "-" }))
1906
+ ];
1907
+ let mergedFinal = merged;
1908
+ try {
1909
+ if (merged.length === 0) {
1910
+ const gmap = globalThis.__LGPD_INTEGRATIONS_MAP__ || {};
1911
+ const scriptRows = Object.entries(gmap).filter(([, cat]) => cat === category.id).map(([id]) => ({
1912
+ name: `(script) ${id}`,
1913
+ purpose: "Script de integra\xE7\xE3o ativo",
1914
+ duration: "-",
1915
+ provider: "-"
1916
+ }));
1917
+ if (scriptRows.length > 0) mergedFinal = scriptRows;
1918
+ }
1919
+ } catch {
1920
+ }
1921
+ return /* @__PURE__ */ jsxs4(Box2, { sx: { mb: 1 }, children: [
1922
+ /* @__PURE__ */ jsx7(
1923
+ FormControlLabel,
1288
1924
  {
1289
- checked: tempPreferences[category.id] ?? false,
1290
- onChange: (e) => setTempPreferences((prev) => ({
1291
- ...prev,
1292
- [category.id]: e.target.checked
1293
- }))
1925
+ control: /* @__PURE__ */ jsx7(
1926
+ Switch,
1927
+ {
1928
+ checked: tempPreferences[category.id] ?? false,
1929
+ onChange: (e) => setTempPreferences((prev) => ({
1930
+ ...prev,
1931
+ [category.id]: e.target.checked
1932
+ }))
1933
+ }
1934
+ ),
1935
+ label: `${category.name} - ${category.description}`
1294
1936
  }
1295
1937
  ),
1296
- label: `${category.name} - ${category.description}`
1297
- },
1298
- category.id
1299
- )),
1300
- /* @__PURE__ */ jsx7(FormControlLabel, { control: /* @__PURE__ */ jsx7(Switch, { checked: true, disabled: true }), label: texts.necessaryAlwaysOn })
1938
+ /* @__PURE__ */ jsxs4("details", { style: { marginLeft: 48 }, children: [
1939
+ /* @__PURE__ */ jsx7("summary", { children: "Ver detalhes" }),
1940
+ /* @__PURE__ */ jsx7(Box2, { sx: { mt: 1 }, children: /* @__PURE__ */ jsxs4("table", { style: { width: "100%", borderCollapse: "collapse" }, children: [
1941
+ /* @__PURE__ */ jsx7("thead", { children: /* @__PURE__ */ jsxs4("tr", { children: [
1942
+ /* @__PURE__ */ jsx7("th", { style: { textAlign: "left" }, children: "Cookie" }),
1943
+ /* @__PURE__ */ jsx7("th", { style: { textAlign: "left" }, children: "Finalidade" }),
1944
+ /* @__PURE__ */ jsx7("th", { style: { textAlign: "left" }, children: "Dura\xE7\xE3o" }),
1945
+ /* @__PURE__ */ jsx7("th", { style: { textAlign: "left" }, children: "Fornecedor" })
1946
+ ] }) }),
1947
+ /* @__PURE__ */ jsx7("tbody", { children: mergedFinal.map((d, idx) => /* @__PURE__ */ jsxs4("tr", { children: [
1948
+ /* @__PURE__ */ jsx7("td", { children: d.name }),
1949
+ /* @__PURE__ */ jsx7("td", { children: d.purpose }),
1950
+ /* @__PURE__ */ jsx7("td", { children: d.duration }),
1951
+ /* @__PURE__ */ jsx7("td", { children: d.provider })
1952
+ ] }, d.name + idx)) })
1953
+ ] }) })
1954
+ ] })
1955
+ ] }, category.id);
1956
+ }),
1957
+ /* @__PURE__ */ jsx7(FormControlLabel, { control: /* @__PURE__ */ jsx7(Switch, { checked: true, disabled: true }), label: texts.necessaryAlwaysOn }),
1958
+ /* @__PURE__ */ jsxs4("details", { style: { marginLeft: 48 }, children: [
1959
+ /* @__PURE__ */ jsx7("summary", { children: "Ver detalhes" }),
1960
+ /* @__PURE__ */ jsx7(Box2, { sx: { mt: 1 }, children: /* @__PURE__ */ jsxs4("table", { style: { width: "100%", borderCollapse: "collapse" }, children: [
1961
+ /* @__PURE__ */ jsx7("thead", { children: /* @__PURE__ */ jsxs4("tr", { children: [
1962
+ /* @__PURE__ */ jsx7("th", { style: { textAlign: "left" }, children: "Cookie" }),
1963
+ /* @__PURE__ */ jsx7("th", { style: { textAlign: "left" }, children: "Finalidade" }),
1964
+ /* @__PURE__ */ jsx7("th", { style: { textAlign: "left" }, children: "Dura\xE7\xE3o" }),
1965
+ /* @__PURE__ */ jsx7("th", { style: { textAlign: "left" }, children: "Fornecedor" })
1966
+ ] }) }),
1967
+ /* @__PURE__ */ jsx7("tbody", { children: (() => {
1968
+ const used = globalThis.__LGPD_USED_INTEGRATIONS__ || [];
1969
+ const necessaryCookies = getCookiesInfoForCategory(
1970
+ "necessary",
1971
+ used
1972
+ );
1973
+ return necessaryCookies.map((d, idx) => /* @__PURE__ */ jsxs4("tr", { children: [
1974
+ /* @__PURE__ */ jsx7("td", { children: d.name }),
1975
+ /* @__PURE__ */ jsx7("td", { children: d.purpose || "-" }),
1976
+ /* @__PURE__ */ jsx7("td", { children: d.duration || "-" }),
1977
+ /* @__PURE__ */ jsx7("td", { children: d.provider || "-" })
1978
+ ] }, d.name + idx));
1979
+ })() })
1980
+ ] }) })
1981
+ ] })
1301
1982
  ] })
1302
1983
  ] }),
1303
1984
  /* @__PURE__ */ jsxs4(DialogActions, { children: [
@@ -1309,13 +1990,22 @@ function PreferencesModal2({
1309
1990
  }
1310
1991
 
1311
1992
  export {
1993
+ setCookieCatalogOverrides,
1994
+ setCookieCategoryOverrides,
1995
+ getCookiesInfoForCategory,
1996
+ discoverRuntimeCookies,
1997
+ detectConsentCookieName,
1998
+ categorizeDiscoveredCookies,
1999
+ LogLevel,
2000
+ logger,
2001
+ setDebugLogging,
1312
2002
  DEFAULT_PROJECT_CATEGORIES,
1313
2003
  analyzeDeveloperConfiguration,
2004
+ logDeveloperGuidance,
2005
+ useDeveloperGuidance,
2006
+ GUIDANCE_PRESETS,
1314
2007
  useCategories,
1315
2008
  useCategoryStatus,
1316
- LogLevel,
1317
- logger,
1318
- setDebugLogging,
1319
2009
  createProjectPreferences,
1320
2010
  validateProjectPreferences,
1321
2011
  getAllProjectCategories,