react-lgpd-consent 0.2.5 → 0.3.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.
@@ -0,0 +1,1380 @@
1
+ // src/components/PreferencesModal.tsx
2
+ import Button2 from "@mui/material/Button";
3
+ import Dialog from "@mui/material/Dialog";
4
+ import DialogActions from "@mui/material/DialogActions";
5
+ import DialogContent from "@mui/material/DialogContent";
6
+ import DialogTitle from "@mui/material/DialogTitle";
7
+ import FormControlLabel from "@mui/material/FormControlLabel";
8
+ import FormGroup from "@mui/material/FormGroup";
9
+ import Switch from "@mui/material/Switch";
10
+ import Typography3 from "@mui/material/Typography";
11
+ import { useEffect as useEffect4, useState as useState2 } from "react";
12
+
13
+ // src/context/CategoriesContext.tsx
14
+ import * as React2 from "react";
15
+
16
+ // src/utils/developerGuidance.ts
17
+ import * as React from "react";
18
+ var DEFAULT_PROJECT_CATEGORIES = {
19
+ enabledCategories: ["analytics"]
20
+ // Só analytics além de necessary
21
+ };
22
+ function analyzeDeveloperConfiguration(config) {
23
+ const guidance = {
24
+ warnings: [],
25
+ suggestions: [],
26
+ activeCategoriesInfo: [],
27
+ usingDefaults: !config
28
+ };
29
+ const finalConfig = config || DEFAULT_PROJECT_CATEGORIES;
30
+ if (!config) {
31
+ guidance.warnings.push(
32
+ '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".'
33
+ );
34
+ }
35
+ guidance.activeCategoriesInfo.push({
36
+ id: "necessary",
37
+ name: "Cookies Necess\xE1rios",
38
+ description: "Essenciais para funcionamento b\xE1sico do site",
39
+ essential: true,
40
+ uiRequired: false
41
+ // Não precisa de toggle (sempre ativo)
42
+ });
43
+ const enabledCategories = finalConfig.enabledCategories || [];
44
+ const categoryNames = {
45
+ analytics: {
46
+ name: "Cookies Anal\xEDticos",
47
+ description: "Medem uso e performance do site"
48
+ },
49
+ functional: {
50
+ name: "Cookies Funcionais",
51
+ description: "Melhoram experi\xEAncia e funcionalidades"
52
+ },
53
+ marketing: {
54
+ name: "Cookies de Marketing",
55
+ description: "Publicidade direcionada e campanhas"
56
+ },
57
+ social: {
58
+ name: "Cookies de Redes Sociais",
59
+ description: "Integra\xE7\xE3o com plataformas sociais"
60
+ },
61
+ personalization: {
62
+ name: "Cookies de Personaliza\xE7\xE3o",
63
+ description: "Adaptam conte\xFAdo \xE0s prefer\xEAncias do usu\xE1rio"
64
+ }
65
+ };
66
+ enabledCategories.forEach((categoryId) => {
67
+ const categoryInfo = categoryNames[categoryId];
68
+ if (categoryInfo) {
69
+ guidance.activeCategoriesInfo.push({
70
+ id: categoryId,
71
+ name: categoryInfo.name,
72
+ description: categoryInfo.description,
73
+ essential: false,
74
+ uiRequired: true
75
+ // Precisa de toggle na UI
76
+ });
77
+ }
78
+ });
79
+ const totalToggleable = guidance.activeCategoriesInfo.filter(
80
+ (c) => c.uiRequired
81
+ ).length;
82
+ if (totalToggleable === 0) {
83
+ guidance.suggestions.push(
84
+ 'Apenas cookies necess\xE1rios est\xE3o configurados. Para compliance completo LGPD, considere adicionar categorias como "analytics" ou "functional" conforme uso real.'
85
+ );
86
+ }
87
+ if (totalToggleable > 5) {
88
+ guidance.warnings.push(
89
+ `${totalToggleable} categorias opcionais detectadas. UI com muitas op\xE7\xF5es pode ' +
90
+ 'prejudicar experi\xEAncia do usu\xE1rio. Considere agrupar categorias similares.`
91
+ );
92
+ }
93
+ return guidance;
94
+ }
95
+ function logDeveloperGuidance(guidance, disableGuidanceProp) {
96
+ if (disableGuidanceProp) {
97
+ return;
98
+ }
99
+ const isProduction = (
100
+ // 1. NODE_ENV de bundlers (Vite, webpack, etc.)
101
+ typeof globalThis.process !== "undefined" && globalThis.process.env?.NODE_ENV === "production" || // 2. Flag customizada para desabilitar logs
102
+ typeof globalThis !== "undefined" && globalThis.__LGPD_PRODUCTION__ === true || // 3. Flag de desenvolvimento desabilitada via window global (legado)
103
+ typeof window !== "undefined" && window.__LGPD_DISABLE_GUIDANCE__ === true
104
+ );
105
+ if (isProduction) return;
106
+ const PREFIX = "[\u{1F36A} LGPD-CONSENT]";
107
+ if (guidance.warnings.length > 0) {
108
+ console.group(`${PREFIX} \u26A0\uFE0F Avisos de Configura\xE7\xE3o`);
109
+ guidance.warnings.forEach((warning) => console.warn(`${PREFIX} ${warning}`));
110
+ console.groupEnd();
111
+ }
112
+ if (guidance.suggestions.length > 0) {
113
+ console.group(`${PREFIX} \u{1F4A1} Sugest\xF5es`);
114
+ guidance.suggestions.forEach(
115
+ (suggestion) => console.info(`${PREFIX} ${suggestion}`)
116
+ );
117
+ console.groupEnd();
118
+ }
119
+ if (guidance.usingDefaults) {
120
+ console.warn(
121
+ // Changed from console.info to console.warn
122
+ `${PREFIX} \u{1F4CB} Usando configura\xE7\xE3o padr\xE3o. Para personalizar, use a prop "categories" no ConsentProvider.`
123
+ );
124
+ }
125
+ console.group(`${PREFIX} \u{1F527} Categorias Ativas (para UI customizada)`);
126
+ console.table(
127
+ guidance.activeCategoriesInfo.map((cat) => ({
128
+ ID: cat.id,
129
+ Nome: cat.name,
130
+ "Toggle UI?": cat.uiRequired ? "\u2705 SIM" : "\u274C N\xC3O (sempre ativo)",
131
+ "Essencial?": cat.essential ? "\u{1F512} SIM" : "\u2699\uFE0F N\xC3O"
132
+ }))
133
+ );
134
+ console.info(
135
+ `${PREFIX} \u2139\uFE0F Use estes dados para criar componentes customizados adequados.`
136
+ );
137
+ console.groupEnd();
138
+ }
139
+ function useDeveloperGuidance(config, disableGuidanceProp) {
140
+ const guidance = analyzeDeveloperConfiguration(config);
141
+ const stringifiedConfig = React.useMemo(
142
+ () => JSON.stringify(config),
143
+ [config]
144
+ );
145
+ React.useEffect(() => {
146
+ if (disableGuidanceProp === true) {
147
+ return;
148
+ }
149
+ logDeveloperGuidance(guidance, disableGuidanceProp);
150
+ }, [guidance, stringifiedConfig, disableGuidanceProp]);
151
+ return guidance;
152
+ }
153
+
154
+ // src/context/CategoriesContext.tsx
155
+ import { jsx } from "react/jsx-runtime";
156
+ var CategoriesContext = React2.createContext(
157
+ null
158
+ );
159
+ function CategoriesProvider({
160
+ children,
161
+ config,
162
+ // NOVO: configuração completa
163
+ disableDeveloperGuidance
164
+ }) {
165
+ const contextValue = React2.useMemo(() => {
166
+ const finalConfig = config || DEFAULT_PROJECT_CATEGORIES;
167
+ const guidance = analyzeDeveloperConfiguration(config);
168
+ const toggleableCategories = guidance.activeCategoriesInfo.filter(
169
+ (cat) => cat.uiRequired
170
+ );
171
+ return {
172
+ config: finalConfig,
173
+ guidance,
174
+ toggleableCategories,
175
+ allCategories: guidance.activeCategoriesInfo
176
+ };
177
+ }, [config]);
178
+ React2.useEffect(() => {
179
+ logDeveloperGuidance(contextValue.guidance, disableDeveloperGuidance);
180
+ }, [contextValue.guidance, disableDeveloperGuidance]);
181
+ return /* @__PURE__ */ jsx(CategoriesContext.Provider, { value: contextValue, children });
182
+ }
183
+ function useCategories() {
184
+ const context = React2.useContext(CategoriesContext);
185
+ if (!context) {
186
+ throw new Error(
187
+ "useCategories deve ser usado dentro de CategoriesProvider. Certifique-se de que o ConsentProvider est\xE1 envolvendo seu componente."
188
+ );
189
+ }
190
+ return context;
191
+ }
192
+ function useCategoryStatus(categoryId) {
193
+ const { allCategories } = useCategories();
194
+ const category = allCategories.find((cat) => cat.id === categoryId);
195
+ return {
196
+ isActive: !!category,
197
+ isEssential: category?.essential || false,
198
+ needsToggle: category?.uiRequired || false,
199
+ name: category?.name,
200
+ description: category?.description
201
+ };
202
+ }
203
+
204
+ // src/context/ConsentContext.tsx
205
+ import * as React5 from "react";
206
+
207
+ // src/utils/SafeThemeProvider.tsx
208
+ import * as React3 from "react";
209
+ import { ThemeProvider, createTheme } from "@mui/material/styles";
210
+ import { jsx as jsx2 } from "react/jsx-runtime";
211
+ var createSafeTheme = (userTheme) => {
212
+ const baseTheme = createTheme({
213
+ palette: {
214
+ primary: {
215
+ main: "#1976d2",
216
+ dark: "#1565c0",
217
+ light: "#42a5f5",
218
+ contrastText: "#ffffff"
219
+ },
220
+ secondary: {
221
+ main: "#dc004e",
222
+ dark: "#9a0036",
223
+ light: "#e33371",
224
+ contrastText: "#ffffff"
225
+ },
226
+ background: {
227
+ default: "#fafafa",
228
+ paper: "#ffffff"
229
+ },
230
+ text: {
231
+ primary: "#333333",
232
+ secondary: "#666666"
233
+ }
234
+ },
235
+ transitions: {
236
+ duration: {
237
+ shortest: 150,
238
+ shorter: 200,
239
+ short: 250,
240
+ standard: 300,
241
+ complex: 375,
242
+ enteringScreen: 225,
243
+ leavingScreen: 195
244
+ }
245
+ }
246
+ });
247
+ if (!userTheme) {
248
+ return baseTheme;
249
+ }
250
+ return createTheme({
251
+ ...baseTheme,
252
+ ...userTheme,
253
+ palette: {
254
+ ...baseTheme.palette,
255
+ ...userTheme.palette,
256
+ primary: {
257
+ ...baseTheme.palette.primary,
258
+ ...userTheme.palette?.primary
259
+ },
260
+ secondary: {
261
+ ...baseTheme.palette.secondary,
262
+ ...userTheme.palette?.secondary
263
+ },
264
+ background: {
265
+ ...baseTheme.palette.background,
266
+ ...userTheme.palette?.background
267
+ },
268
+ text: {
269
+ ...baseTheme.palette.text,
270
+ ...userTheme.palette?.text
271
+ }
272
+ },
273
+ transitions: {
274
+ ...baseTheme.transitions,
275
+ ...userTheme.transitions,
276
+ duration: {
277
+ ...baseTheme.transitions.duration,
278
+ ...userTheme.transitions?.duration
279
+ }
280
+ }
281
+ });
282
+ };
283
+ function SafeThemeProvider({
284
+ theme,
285
+ children
286
+ }) {
287
+ const safeTheme = React3.useMemo(() => createSafeTheme(theme), [theme]);
288
+ return /* @__PURE__ */ jsx2(ThemeProvider, { theme: safeTheme, children });
289
+ }
290
+
291
+ // src/utils/cookieUtils.ts
292
+ import Cookies from "js-cookie";
293
+
294
+ // src/utils/logger.ts
295
+ var IS_DEVELOPMENT = typeof window !== "undefined" && window.__REACT_DEVTOOLS_GLOBAL_HOOK__ || typeof globalThis !== "undefined" && globalThis.process?.env?.NODE_ENV === "development";
296
+ var LOG_PREFIX = "[react-lgpd-consent]";
297
+ var LogLevel = /* @__PURE__ */ ((LogLevel2) => {
298
+ LogLevel2[LogLevel2["ERROR"] = 0] = "ERROR";
299
+ LogLevel2[LogLevel2["WARN"] = 1] = "WARN";
300
+ LogLevel2[LogLevel2["INFO"] = 2] = "INFO";
301
+ LogLevel2[LogLevel2["DEBUG"] = 3] = "DEBUG";
302
+ return LogLevel2;
303
+ })(LogLevel || {});
304
+ var ConsentLogger = class {
305
+ constructor() {
306
+ this.enabled = IS_DEVELOPMENT;
307
+ this.level = 2 /* INFO */;
308
+ }
309
+ setEnabled(enabled) {
310
+ this.enabled = enabled;
311
+ }
312
+ setLevel(level) {
313
+ this.level = level;
314
+ }
315
+ error(...args) {
316
+ if (this.enabled && this.level >= 0 /* ERROR */) {
317
+ console.error(LOG_PREFIX, "[ERROR]", ...args);
318
+ }
319
+ }
320
+ warn(...args) {
321
+ if (this.enabled && this.level >= 1 /* WARN */) {
322
+ console.warn(LOG_PREFIX, "[WARN]", ...args);
323
+ }
324
+ }
325
+ info(...args) {
326
+ if (this.enabled && this.level >= 2 /* INFO */) {
327
+ console.info(LOG_PREFIX, "[INFO]", ...args);
328
+ }
329
+ }
330
+ debug(...args) {
331
+ if (this.enabled && this.level >= 3 /* DEBUG */) {
332
+ console.debug(LOG_PREFIX, "[DEBUG]", ...args);
333
+ }
334
+ }
335
+ // Logs específicos para troubleshooting
336
+ themeCompatibility(themeInfo) {
337
+ this.debug("Theme compatibility check:", {
338
+ hasTheme: !!themeInfo,
339
+ hasPalette: !!themeInfo?.palette,
340
+ hasPrimary: !!themeInfo?.palette?.primary,
341
+ hasTransitions: !!themeInfo?.transitions,
342
+ hasDuration: !!themeInfo?.transitions?.duration
343
+ });
344
+ }
345
+ consentState(action, state) {
346
+ this.debug(`Consent state change [${action}]:`, {
347
+ consented: state.consented,
348
+ isModalOpen: state.isModalOpen,
349
+ preferencesCount: Object.keys(state.preferences || {}).length
350
+ });
351
+ }
352
+ cookieOperation(operation, cookieName, data) {
353
+ this.debug(`Cookie ${operation}:`, {
354
+ name: cookieName,
355
+ hasData: !!data,
356
+ dataSize: data ? JSON.stringify(data).length : 0
357
+ });
358
+ }
359
+ componentRender(componentName, props) {
360
+ this.debug(`Component render [${componentName}]:`, {
361
+ hasProps: !!props,
362
+ propsKeys: props ? Object.keys(props) : []
363
+ });
364
+ }
365
+ scriptIntegration(scriptName, action, success) {
366
+ this.info(
367
+ `Script ${action} [${scriptName}]:`,
368
+ success ? "SUCCESS" : "FAILED"
369
+ );
370
+ }
371
+ apiUsage(method, params) {
372
+ this.debug(`API call [${method}]:`, params);
373
+ }
374
+ };
375
+ var logger = new ConsentLogger();
376
+ function setDebugLogging(enabled, level = 2 /* INFO */) {
377
+ logger.setEnabled(enabled);
378
+ logger.setLevel(level);
379
+ logger.info(
380
+ `Debug logging ${enabled ? "enabled" : "disabled"} with level ${LogLevel[level]}`
381
+ );
382
+ }
383
+
384
+ // src/utils/cookieUtils.ts
385
+ var DEFAULT_COOKIE_OPTS = {
386
+ name: "cookieConsent",
387
+ maxAgeDays: 365,
388
+ sameSite: "Lax",
389
+ secure: typeof window !== "undefined" ? window.location.protocol === "https:" : false,
390
+ path: "/"
391
+ };
392
+ var COOKIE_SCHEMA_VERSION = "1.0";
393
+ function readConsentCookie(name = DEFAULT_COOKIE_OPTS.name) {
394
+ logger.debug("Reading consent cookie", { name });
395
+ if (typeof document === "undefined") {
396
+ logger.debug("Cookie read skipped: server-side environment");
397
+ return null;
398
+ }
399
+ const raw = Cookies.get(name);
400
+ if (!raw) {
401
+ logger.debug("No consent cookie found");
402
+ return null;
403
+ }
404
+ try {
405
+ const data = JSON.parse(raw);
406
+ logger.cookieOperation("read", name, data);
407
+ if (!data.version) {
408
+ logger.debug("Migrating legacy cookie format");
409
+ return migrateLegacyCookie(data);
410
+ }
411
+ if (data.version !== COOKIE_SCHEMA_VERSION) {
412
+ logger.warn(
413
+ `Cookie version mismatch: ${data.version} != ${COOKIE_SCHEMA_VERSION}`
414
+ );
415
+ return null;
416
+ }
417
+ return data;
418
+ } catch (error) {
419
+ logger.error("Error parsing consent cookie", error);
420
+ return null;
421
+ }
422
+ }
423
+ function migrateLegacyCookie(legacyData) {
424
+ try {
425
+ const now = (/* @__PURE__ */ new Date()).toISOString();
426
+ return {
427
+ version: COOKIE_SCHEMA_VERSION,
428
+ consented: legacyData.consented || false,
429
+ preferences: legacyData.preferences || { necessary: true },
430
+ consentDate: now,
431
+ // Não temos o original, usar data atual
432
+ lastUpdate: now,
433
+ source: "banner",
434
+ // Assumir origem banner
435
+ isModalOpen: false
436
+ // Nunca persistir estado de UI
437
+ };
438
+ } catch {
439
+ return null;
440
+ }
441
+ }
442
+ function writeConsentCookie(state, config, opts, source = "banner") {
443
+ if (typeof document === "undefined") {
444
+ logger.debug("Cookie write skipped: server-side environment");
445
+ return;
446
+ }
447
+ const now = (/* @__PURE__ */ new Date()).toISOString();
448
+ const o = { ...DEFAULT_COOKIE_OPTS, ...opts };
449
+ const cookieData = {
450
+ version: COOKIE_SCHEMA_VERSION,
451
+ consented: state.consented,
452
+ preferences: state.preferences,
453
+ consentDate: state.consentDate || now,
454
+ // Preservar data original ou usar atual
455
+ lastUpdate: now,
456
+ source,
457
+ projectConfig: config
458
+ // isModalOpen NÃO é persistido (campo de UI apenas)
459
+ };
460
+ logger.cookieOperation("write", o.name, cookieData);
461
+ Cookies.set(o.name, JSON.stringify(cookieData), {
462
+ expires: o.maxAgeDays,
463
+ sameSite: o.sameSite,
464
+ secure: o.secure,
465
+ path: o.path
466
+ });
467
+ logger.info("Consent cookie saved", {
468
+ consented: cookieData.consented,
469
+ source: cookieData.source,
470
+ preferencesCount: Object.keys(cookieData.preferences).length
471
+ });
472
+ }
473
+ function removeConsentCookie(opts) {
474
+ if (typeof document === "undefined") {
475
+ logger.debug("Cookie removal skipped: server-side environment");
476
+ return;
477
+ }
478
+ const o = { ...DEFAULT_COOKIE_OPTS, ...opts };
479
+ logger.cookieOperation("delete", o.name);
480
+ Cookies.remove(o.name, { path: o.path });
481
+ logger.info("Consent cookie removed");
482
+ }
483
+
484
+ // src/utils/categoryUtils.ts
485
+ function createProjectPreferences(config, defaultValue = false) {
486
+ const preferences = {
487
+ necessary: true
488
+ // Sempre presente e true (essencial)
489
+ };
490
+ const enabledCategories = config?.enabledCategories || [];
491
+ enabledCategories.forEach((category) => {
492
+ if (category !== "necessary") {
493
+ preferences[category] = defaultValue;
494
+ }
495
+ });
496
+ return preferences;
497
+ }
498
+ function validateProjectPreferences(preferences, config) {
499
+ const validPreferences = {
500
+ necessary: true
501
+ // Sempre válida
502
+ };
503
+ const enabledCategories = config?.enabledCategories || [];
504
+ enabledCategories.forEach((category) => {
505
+ if (category !== "necessary" && preferences[category] !== void 0) {
506
+ validPreferences[category] = preferences[category];
507
+ }
508
+ });
509
+ return validPreferences;
510
+ }
511
+
512
+ // src/utils/theme.ts
513
+ import { createTheme as createTheme2 } from "@mui/material/styles";
514
+ var defaultConsentTheme = createTheme2({
515
+ palette: {
516
+ primary: {
517
+ main: "#1976d2",
518
+ contrastText: "#ffffff"
519
+ },
520
+ secondary: {
521
+ main: "#dc004e",
522
+ contrastText: "#ffffff"
523
+ },
524
+ background: {
525
+ default: "#fafafa",
526
+ paper: "#ffffff"
527
+ },
528
+ text: {
529
+ primary: "#333333",
530
+ secondary: "#666666"
531
+ },
532
+ action: {
533
+ hover: "rgba(25, 118, 210, 0.04)"
534
+ }
535
+ },
536
+ typography: {
537
+ fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif',
538
+ body2: {
539
+ fontSize: "0.875rem",
540
+ lineHeight: 1.43
541
+ },
542
+ button: {
543
+ fontWeight: 500,
544
+ textTransform: "none"
545
+ }
546
+ },
547
+ components: {
548
+ MuiButton: {
549
+ styleOverrides: {
550
+ root: {
551
+ borderRadius: 8,
552
+ paddingX: 16,
553
+ paddingY: 8
554
+ },
555
+ contained: {
556
+ boxShadow: "0 2px 4px rgba(0,0,0,0.1)",
557
+ "&:hover": {
558
+ boxShadow: "0 4px 8px rgba(0,0,0,0.15)"
559
+ }
560
+ }
561
+ }
562
+ },
563
+ MuiPaper: {
564
+ styleOverrides: {
565
+ root: {
566
+ borderRadius: 12
567
+ }
568
+ }
569
+ },
570
+ MuiDialog: {
571
+ styleOverrides: {
572
+ paper: {
573
+ borderRadius: 16
574
+ }
575
+ }
576
+ }
577
+ }
578
+ });
579
+
580
+ // src/context/DesignContext.tsx
581
+ import * as React4 from "react";
582
+ import { jsx as jsx3 } from "react/jsx-runtime";
583
+ var DesignContext = React4.createContext(void 0);
584
+ function DesignProvider({
585
+ tokens,
586
+ children
587
+ }) {
588
+ return /* @__PURE__ */ jsx3(DesignContext.Provider, { value: tokens, children });
589
+ }
590
+ function useDesignTokens() {
591
+ return React4.useContext(DesignContext);
592
+ }
593
+
594
+ // src/components/CookieBanner.tsx
595
+ import Button from "@mui/material/Button";
596
+ import Box from "@mui/material/Box";
597
+ import Paper from "@mui/material/Paper";
598
+ import Snackbar from "@mui/material/Snackbar";
599
+ import Stack from "@mui/material/Stack";
600
+ import Typography2 from "@mui/material/Typography";
601
+ import Link2 from "@mui/material/Link";
602
+
603
+ // src/components/Branding.tsx
604
+ import Link from "@mui/material/Link";
605
+ import Typography from "@mui/material/Typography";
606
+ import { jsx as jsx4, jsxs } from "react/jsx-runtime";
607
+ var brandingStyles = {
608
+ banner: {
609
+ fontSize: "0.65rem",
610
+ textAlign: "right",
611
+ mt: 1,
612
+ opacity: 0.7,
613
+ fontStyle: "italic",
614
+ width: "100%"
615
+ },
616
+ modal: {
617
+ fontSize: "0.65rem",
618
+ textAlign: "right",
619
+ px: 3,
620
+ pb: 1,
621
+ opacity: 0.7,
622
+ fontStyle: "italic",
623
+ width: "100%"
624
+ }
625
+ };
626
+ var linkStyles = {
627
+ textDecoration: "none",
628
+ fontWeight: 500,
629
+ "&:hover": {
630
+ textDecoration: "underline"
631
+ }
632
+ };
633
+ function Branding({ variant, hidden = false }) {
634
+ const texts = useConsentTexts();
635
+ if (hidden) return null;
636
+ return /* @__PURE__ */ jsxs(
637
+ Typography,
638
+ {
639
+ variant: "caption",
640
+ sx: (theme) => ({
641
+ ...brandingStyles[variant],
642
+ color: theme.palette.text.secondary
643
+ }),
644
+ children: [
645
+ texts.brandingPoweredBy || "fornecido por",
646
+ " ",
647
+ /* @__PURE__ */ jsx4(
648
+ Link,
649
+ {
650
+ href: "https://www.ledipo.eti.br",
651
+ target: "_blank",
652
+ rel: "noopener noreferrer",
653
+ sx: (theme) => ({
654
+ ...linkStyles,
655
+ color: theme.palette.primary.main
656
+ }),
657
+ children: "L\xC9dipO.eti.br"
658
+ }
659
+ )
660
+ ]
661
+ }
662
+ );
663
+ }
664
+
665
+ // src/components/CookieBanner.tsx
666
+ import { Fragment, jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
667
+ function CookieBanner({
668
+ policyLinkUrl,
669
+ debug,
670
+ blocking = true,
671
+ hideBranding = false,
672
+ SnackbarProps,
673
+ PaperProps
674
+ }) {
675
+ const { consented, acceptAll, rejectAll, openPreferences } = useConsent();
676
+ const texts = useConsentTexts();
677
+ const isHydrated = useConsentHydration();
678
+ const designTokens = useDesignTokens();
679
+ const open = debug ? true : isHydrated && !consented;
680
+ logger.componentRender("CookieBanner", {
681
+ open,
682
+ consented,
683
+ isHydrated,
684
+ blocking,
685
+ hideBranding
686
+ });
687
+ if (!open) return null;
688
+ const bannerStyle = {
689
+ p: designTokens?.spacing?.padding?.banner ?? 2,
690
+ maxWidth: 720,
691
+ mx: "auto",
692
+ backgroundColor: designTokens?.colors?.background,
693
+ color: designTokens?.colors?.text,
694
+ borderRadius: designTokens?.spacing?.borderRadius?.banner,
695
+ fontFamily: designTokens?.typography?.fontFamily
696
+ };
697
+ const bannerContent = /* @__PURE__ */ jsx5(Paper, { elevation: 3, sx: bannerStyle, ...PaperProps, children: /* @__PURE__ */ jsxs2(Stack, { spacing: 1, children: [
698
+ /* @__PURE__ */ jsxs2(
699
+ Typography2,
700
+ {
701
+ variant: "body2",
702
+ sx: { fontSize: designTokens?.typography?.fontSize?.banner },
703
+ children: [
704
+ texts.bannerMessage,
705
+ " ",
706
+ policyLinkUrl && /* @__PURE__ */ jsx5(
707
+ Link2,
708
+ {
709
+ href: policyLinkUrl,
710
+ underline: "hover",
711
+ target: "_blank",
712
+ rel: "noopener noreferrer",
713
+ sx: { color: designTokens?.colors?.primary },
714
+ children: texts.policyLink ?? "Saiba mais"
715
+ }
716
+ )
717
+ ]
718
+ }
719
+ ),
720
+ /* @__PURE__ */ jsxs2(
721
+ Stack,
722
+ {
723
+ direction: { xs: "column", sm: "row" },
724
+ spacing: 1,
725
+ justifyContent: "flex-end",
726
+ children: [
727
+ /* @__PURE__ */ jsx5(
728
+ Button,
729
+ {
730
+ variant: "outlined",
731
+ onClick: () => {
732
+ logger.apiUsage("rejectAll", { source: "banner" });
733
+ rejectAll();
734
+ },
735
+ sx: { color: designTokens?.colors?.secondary },
736
+ children: texts.declineAll
737
+ }
738
+ ),
739
+ /* @__PURE__ */ jsx5(
740
+ Button,
741
+ {
742
+ variant: "contained",
743
+ onClick: () => {
744
+ logger.apiUsage("acceptAll", { source: "banner" });
745
+ acceptAll();
746
+ },
747
+ sx: { backgroundColor: designTokens?.colors?.primary },
748
+ children: texts.acceptAll
749
+ }
750
+ ),
751
+ /* @__PURE__ */ jsx5(
752
+ Button,
753
+ {
754
+ variant: "text",
755
+ onClick: () => {
756
+ logger.apiUsage("openPreferences", { source: "banner" });
757
+ openPreferences();
758
+ },
759
+ sx: { color: designTokens?.colors?.text },
760
+ children: texts.preferences
761
+ }
762
+ )
763
+ ]
764
+ }
765
+ ),
766
+ !hideBranding && /* @__PURE__ */ jsx5(Branding, { variant: "banner" })
767
+ ] }) });
768
+ const positionStyle = {
769
+ position: "fixed",
770
+ zIndex: 1300,
771
+ ...designTokens?.layout?.position === "top" ? { top: 0 } : { bottom: 0 },
772
+ left: 0,
773
+ right: 0,
774
+ width: designTokens?.layout?.width?.desktop ?? "100%",
775
+ p: 2
776
+ };
777
+ if (blocking) {
778
+ return /* @__PURE__ */ jsxs2(Fragment, { children: [
779
+ /* @__PURE__ */ jsx5(
780
+ Box,
781
+ {
782
+ sx: {
783
+ position: "fixed",
784
+ top: 0,
785
+ left: 0,
786
+ right: 0,
787
+ bottom: 0,
788
+ backgroundColor: designTokens?.layout?.backdrop ? "rgba(0, 0, 0, 0.5)" : "transparent",
789
+ zIndex: 1299
790
+ }
791
+ }
792
+ ),
793
+ /* @__PURE__ */ jsx5(Box, { sx: positionStyle, children: bannerContent })
794
+ ] });
795
+ }
796
+ return /* @__PURE__ */ jsx5(
797
+ Snackbar,
798
+ {
799
+ open,
800
+ anchorOrigin: {
801
+ vertical: designTokens?.layout?.position === "top" ? "top" : "bottom",
802
+ horizontal: "center"
803
+ },
804
+ ...SnackbarProps,
805
+ children: bannerContent
806
+ }
807
+ );
808
+ }
809
+
810
+ // src/components/FloatingPreferencesButton.tsx
811
+ import CookieOutlined from "@mui/icons-material/CookieOutlined";
812
+ import Fab from "@mui/material/Fab";
813
+ import Tooltip from "@mui/material/Tooltip";
814
+ import { useTheme } from "@mui/material/styles";
815
+ import { jsx as jsx6 } from "react/jsx-runtime";
816
+ function useThemeWithFallbacks() {
817
+ const theme = useTheme();
818
+ logger.themeCompatibility(theme);
819
+ return {
820
+ palette: {
821
+ primary: {
822
+ main: theme?.palette?.primary?.main || "#1976d2",
823
+ dark: theme?.palette?.primary?.dark || "#1565c0"
824
+ }
825
+ },
826
+ transitions: {
827
+ duration: {
828
+ shortest: theme?.transitions?.duration?.shortest || 150,
829
+ short: theme?.transitions?.duration?.short || 250
830
+ }
831
+ }
832
+ };
833
+ }
834
+ function FloatingPreferencesButton({
835
+ position = "bottom-right",
836
+ offset = 24,
837
+ icon = /* @__PURE__ */ jsx6(CookieOutlined, {}),
838
+ tooltip,
839
+ FabProps,
840
+ hideWhenConsented = false
841
+ }) {
842
+ const { openPreferences, consented } = useConsent();
843
+ const texts = useConsentTexts();
844
+ const safeTheme = useThemeWithFallbacks();
845
+ logger.componentRender("FloatingPreferencesButton", {
846
+ position,
847
+ offset,
848
+ hideWhenConsented,
849
+ consented
850
+ });
851
+ if (hideWhenConsented && consented) {
852
+ logger.debug(
853
+ "FloatingPreferencesButton: Hidden due to hideWhenConsented=true and consented=true"
854
+ );
855
+ return null;
856
+ }
857
+ const tooltipText = tooltip ?? texts.preferencesButton ?? "Gerenciar Prefer\xEAncias de Cookies";
858
+ const getPosition = () => {
859
+ const styles = {
860
+ position: "fixed",
861
+ zIndex: 1200
862
+ };
863
+ switch (position) {
864
+ case "bottom-left":
865
+ return { ...styles, bottom: offset, left: offset };
866
+ case "bottom-right":
867
+ return { ...styles, bottom: offset, right: offset };
868
+ case "top-left":
869
+ return { ...styles, top: offset, left: offset };
870
+ case "top-right":
871
+ return { ...styles, top: offset, right: offset };
872
+ default:
873
+ return { ...styles, bottom: offset, right: offset };
874
+ }
875
+ };
876
+ return /* @__PURE__ */ jsx6(Tooltip, { title: tooltipText, placement: "top", children: /* @__PURE__ */ jsx6(
877
+ Fab,
878
+ {
879
+ size: "medium",
880
+ color: "primary",
881
+ onClick: openPreferences,
882
+ sx: {
883
+ ...getPosition(),
884
+ backgroundColor: safeTheme.palette.primary.main,
885
+ "&:hover": {
886
+ backgroundColor: safeTheme.palette.primary.dark
887
+ },
888
+ transition: `all ${safeTheme.transitions.duration.short}ms`
889
+ },
890
+ "aria-label": tooltipText,
891
+ ...FabProps,
892
+ children: icon
893
+ }
894
+ ) });
895
+ }
896
+
897
+ // src/context/ConsentContext.tsx
898
+ import { jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
899
+ var log = {
900
+ debug: (message, data) => {
901
+ if (typeof window !== "undefined" && window.__REACT_DEVTOOLS_GLOBAL_HOOK__) {
902
+ console.debug("[react-lgpd-consent] [DEBUG]", message, data);
903
+ }
904
+ },
905
+ info: (message, data) => {
906
+ if (typeof window !== "undefined" && window.__REACT_DEVTOOLS_GLOBAL_HOOK__) {
907
+ console.info("[react-lgpd-consent] [INFO]", message, data);
908
+ }
909
+ }
910
+ };
911
+ var PreferencesModal = React5.lazy(
912
+ () => import("./PreferencesModal-J27W5XAJ.js").then((m) => ({
913
+ default: m.PreferencesModal
914
+ }))
915
+ );
916
+ function createFullConsentState(consented, preferences, source, projectConfig, isModalOpen = false, existingState) {
917
+ const now = (/* @__PURE__ */ new Date()).toISOString();
918
+ return {
919
+ version: "1.0",
920
+ consented,
921
+ preferences,
922
+ consentDate: existingState?.consentDate || now,
923
+ lastUpdate: now,
924
+ source,
925
+ projectConfig,
926
+ isModalOpen
927
+ };
928
+ }
929
+ var DEFAULT_TEXTS = {
930
+ // Textos básicos
931
+ bannerMessage: "Utilizamos cookies para melhorar sua experi\xEAncia.",
932
+ acceptAll: "Aceitar todos",
933
+ declineAll: "Recusar",
934
+ preferences: "Prefer\xEAncias",
935
+ policyLink: "Saiba mais",
936
+ modalTitle: "Prefer\xEAncias de Cookies",
937
+ modalIntro: "Ajuste as categorias de cookies. Cookies necess\xE1rios s\xE3o sempre utilizados para funcionalidades b\xE1sicas.",
938
+ save: "Salvar prefer\xEAncias",
939
+ necessaryAlwaysOn: "Cookies necess\xE1rios (sempre ativos)",
940
+ // Textos adicionais para UI customizada
941
+ preferencesButton: "Configurar Cookies",
942
+ preferencesTitle: "Gerenciar Prefer\xEAncias de Cookies",
943
+ preferencesDescription: "Escolha quais tipos de cookies voc\xEA permite que sejam utilizados.",
944
+ close: "Fechar",
945
+ accept: "Aceitar",
946
+ reject: "Rejeitar",
947
+ // Textos ANPD expandidos (opcionais)
948
+ brandingPoweredBy: "fornecido por",
949
+ controllerInfo: void 0,
950
+ // Exibido se definido
951
+ dataTypes: void 0,
952
+ // Exibido se definido
953
+ thirdPartySharing: void 0,
954
+ // Exibido se definido
955
+ userRights: void 0,
956
+ // Exibido se definido
957
+ contactInfo: void 0,
958
+ // Exibido se definido
959
+ retentionPeriod: void 0,
960
+ // Exibido se definido
961
+ lawfulBasis: void 0,
962
+ // Exibido se definido
963
+ transferCountries: void 0
964
+ // Exibido se definido
965
+ };
966
+ function reducer(state, action) {
967
+ log.debug("State transition:", {
968
+ action: action.type,
969
+ currentState: state.consented
970
+ });
971
+ switch (action.type) {
972
+ case "ACCEPT_ALL": {
973
+ const prefs = createProjectPreferences(action.config, true);
974
+ const newState = createFullConsentState(
975
+ true,
976
+ prefs,
977
+ "banner",
978
+ action.config,
979
+ false,
980
+ state
981
+ );
982
+ log.info("User accepted all cookies", {
983
+ preferences: newState.preferences
984
+ });
985
+ return newState;
986
+ }
987
+ case "REJECT_ALL": {
988
+ const prefs = createProjectPreferences(action.config, false);
989
+ const newState = createFullConsentState(
990
+ true,
991
+ prefs,
992
+ "banner",
993
+ action.config,
994
+ false,
995
+ state
996
+ );
997
+ log.info("User rejected all cookies", {
998
+ preferences: newState.preferences
999
+ });
1000
+ return newState;
1001
+ }
1002
+ case "SET_CATEGORY":
1003
+ log.debug("Category preference changed", {
1004
+ category: action.category,
1005
+ value: action.value
1006
+ });
1007
+ return {
1008
+ ...state,
1009
+ preferences: {
1010
+ ...state.preferences,
1011
+ [action.category]: action.value
1012
+ },
1013
+ lastUpdate: (/* @__PURE__ */ new Date()).toISOString()
1014
+ };
1015
+ case "SET_PREFERENCES":
1016
+ log.info("Preferences saved", { preferences: action.preferences });
1017
+ return createFullConsentState(
1018
+ true,
1019
+ action.preferences,
1020
+ "modal",
1021
+ action.config,
1022
+ false,
1023
+ state
1024
+ );
1025
+ case "OPEN_MODAL":
1026
+ return { ...state, isModalOpen: true };
1027
+ case "CLOSE_MODAL":
1028
+ return createFullConsentState(
1029
+ true,
1030
+ state.preferences,
1031
+ "modal",
1032
+ action.config,
1033
+ false,
1034
+ state
1035
+ );
1036
+ case "RESET": {
1037
+ return createFullConsentState(
1038
+ false,
1039
+ createProjectPreferences(action.config),
1040
+ "programmatic",
1041
+ action.config,
1042
+ false
1043
+ );
1044
+ }
1045
+ case "HYDRATE": {
1046
+ const validatedPreferences = validateProjectPreferences(
1047
+ action.state.preferences,
1048
+ action.config
1049
+ );
1050
+ return {
1051
+ ...action.state,
1052
+ preferences: validatedPreferences,
1053
+ isModalOpen: false
1054
+ };
1055
+ }
1056
+ default:
1057
+ return state;
1058
+ }
1059
+ }
1060
+ var StateCtx = React5.createContext(null);
1061
+ var ActionsCtx = React5.createContext(null);
1062
+ var TextsCtx = React5.createContext(DEFAULT_TEXTS);
1063
+ var HydrationCtx = React5.createContext(false);
1064
+ function ConsentProvider({
1065
+ initialState,
1066
+ categories,
1067
+ // Nova prop para configuração de categorias
1068
+ texts: textsProp,
1069
+ theme,
1070
+ designTokens,
1071
+ scriptIntegrations,
1072
+ // eslint-disable-line no-unused-vars
1073
+ PreferencesModalComponent,
1074
+ preferencesModalProps = {},
1075
+ CookieBannerComponent,
1076
+ cookieBannerProps = {},
1077
+ FloatingPreferencesButtonComponent,
1078
+ floatingPreferencesButtonProps = {},
1079
+ disableFloatingPreferencesButton = false,
1080
+ hideBranding = false,
1081
+ onConsentGiven,
1082
+ onPreferencesSaved,
1083
+ cookie: cookieOpts,
1084
+ disableDeveloperGuidance,
1085
+ children
1086
+ }) {
1087
+ const texts = React5.useMemo(
1088
+ () => ({ ...DEFAULT_TEXTS, ...textsProp ?? {} }),
1089
+ [textsProp]
1090
+ );
1091
+ const cookie = React5.useMemo(
1092
+ () => ({ ...DEFAULT_COOKIE_OPTS, ...cookieOpts ?? {} }),
1093
+ [cookieOpts]
1094
+ );
1095
+ const appliedTheme = React5.useMemo(
1096
+ () => theme || defaultConsentTheme,
1097
+ [theme]
1098
+ );
1099
+ const finalCategoriesConfig = React5.useMemo(() => {
1100
+ if (categories) return categories;
1101
+ return DEFAULT_PROJECT_CATEGORIES;
1102
+ }, [categories]);
1103
+ useDeveloperGuidance(finalCategoriesConfig, disableDeveloperGuidance);
1104
+ const boot = React5.useMemo(() => {
1105
+ if (initialState) return { ...initialState, isModalOpen: false };
1106
+ return createFullConsentState(
1107
+ false,
1108
+ createProjectPreferences(finalCategoriesConfig),
1109
+ "banner",
1110
+ finalCategoriesConfig,
1111
+ false
1112
+ );
1113
+ }, [initialState, finalCategoriesConfig]);
1114
+ const [state, dispatch] = React5.useReducer(reducer, boot);
1115
+ const [isHydrated, setIsHydrated] = React5.useState(false);
1116
+ React5.useEffect(() => {
1117
+ if (!initialState) {
1118
+ const saved = readConsentCookie(cookie.name);
1119
+ if (saved?.consented) {
1120
+ dispatch({
1121
+ type: "HYDRATE",
1122
+ state: saved,
1123
+ config: finalCategoriesConfig
1124
+ });
1125
+ }
1126
+ }
1127
+ setIsHydrated(true);
1128
+ }, [cookie.name, initialState, finalCategoriesConfig]);
1129
+ React5.useEffect(() => {
1130
+ if (state.consented)
1131
+ writeConsentCookie(state, finalCategoriesConfig, cookie);
1132
+ }, [state, cookie, finalCategoriesConfig]);
1133
+ const prevConsented = React5.useRef(state.consented);
1134
+ React5.useEffect(() => {
1135
+ if (!prevConsented.current && state.consented && onConsentGiven) {
1136
+ setTimeout(() => onConsentGiven(state), 150);
1137
+ }
1138
+ prevConsented.current = state.consented;
1139
+ }, [state, onConsentGiven]);
1140
+ const api = React5.useMemo(() => {
1141
+ const acceptAll = () => dispatch({ type: "ACCEPT_ALL", config: finalCategoriesConfig });
1142
+ const rejectAll = () => dispatch({ type: "REJECT_ALL", config: finalCategoriesConfig });
1143
+ const setPreference = (category, value) => dispatch({ type: "SET_CATEGORY", category, value });
1144
+ const setPreferences = (preferences) => {
1145
+ dispatch({
1146
+ type: "SET_PREFERENCES",
1147
+ preferences,
1148
+ config: finalCategoriesConfig
1149
+ });
1150
+ if (onPreferencesSaved) {
1151
+ setTimeout(() => onPreferencesSaved(preferences), 150);
1152
+ }
1153
+ };
1154
+ const openPreferences = () => dispatch({ type: "OPEN_MODAL" });
1155
+ const closePreferences = () => dispatch({ type: "CLOSE_MODAL", config: finalCategoriesConfig });
1156
+ const resetConsent = () => {
1157
+ removeConsentCookie(cookie);
1158
+ dispatch({ type: "RESET", config: finalCategoriesConfig });
1159
+ };
1160
+ return {
1161
+ consented: !!state.consented,
1162
+ preferences: state.preferences,
1163
+ isModalOpen: state.isModalOpen,
1164
+ acceptAll,
1165
+ rejectAll,
1166
+ setPreference,
1167
+ setPreferences,
1168
+ openPreferences,
1169
+ closePreferences,
1170
+ resetConsent
1171
+ };
1172
+ }, [state, cookie, finalCategoriesConfig, onPreferencesSaved]);
1173
+ React5.useEffect(() => {
1174
+ _registerGlobalOpenPreferences(api.openPreferences);
1175
+ return () => _unregisterGlobalOpenPreferences();
1176
+ }, [api.openPreferences]);
1177
+ return /* @__PURE__ */ jsx7(SafeThemeProvider, { theme: appliedTheme, children: /* @__PURE__ */ jsx7(StateCtx.Provider, { value: state, children: /* @__PURE__ */ jsx7(ActionsCtx.Provider, { value: api, children: /* @__PURE__ */ jsx7(TextsCtx.Provider, { value: texts, children: /* @__PURE__ */ jsx7(HydrationCtx.Provider, { value: isHydrated, children: /* @__PURE__ */ jsx7(DesignProvider, { tokens: designTokens, children: /* @__PURE__ */ jsxs3(
1178
+ CategoriesProvider,
1179
+ {
1180
+ config: finalCategoriesConfig,
1181
+ disableDeveloperGuidance,
1182
+ children: [
1183
+ children,
1184
+ /* @__PURE__ */ jsx7(React5.Suspense, { fallback: null, children: PreferencesModalComponent ? /* @__PURE__ */ jsx7(
1185
+ PreferencesModalComponent,
1186
+ {
1187
+ preferences: api.preferences,
1188
+ setPreferences: api.setPreferences,
1189
+ closePreferences: api.closePreferences,
1190
+ isModalOpen: api.isModalOpen,
1191
+ texts,
1192
+ ...preferencesModalProps
1193
+ }
1194
+ ) : /* @__PURE__ */ jsx7(PreferencesModal, { hideBranding }) }),
1195
+ !state.consented && isHydrated && (CookieBannerComponent ? /* @__PURE__ */ jsx7(
1196
+ CookieBannerComponent,
1197
+ {
1198
+ consented: api.consented,
1199
+ acceptAll: api.acceptAll,
1200
+ rejectAll: api.rejectAll,
1201
+ openPreferences: api.openPreferences,
1202
+ texts,
1203
+ ...cookieBannerProps
1204
+ }
1205
+ ) : /* @__PURE__ */ jsx7(CookieBanner, {})),
1206
+ state.consented && !disableFloatingPreferencesButton && (FloatingPreferencesButtonComponent ? /* @__PURE__ */ jsx7(
1207
+ FloatingPreferencesButtonComponent,
1208
+ {
1209
+ openPreferences: api.openPreferences,
1210
+ consented: api.consented,
1211
+ ...floatingPreferencesButtonProps
1212
+ }
1213
+ ) : /* @__PURE__ */ jsx7(FloatingPreferencesButton, {}))
1214
+ ]
1215
+ }
1216
+ ) }) }) }) }) }) });
1217
+ }
1218
+ function useConsentStateInternal() {
1219
+ const ctx = React5.useContext(StateCtx);
1220
+ if (!ctx)
1221
+ throw new Error("useConsentState must be used within ConsentProvider");
1222
+ return ctx;
1223
+ }
1224
+ function useConsentActionsInternal() {
1225
+ const ctx = React5.useContext(ActionsCtx);
1226
+ if (!ctx)
1227
+ throw new Error("useConsentActions must be used within ConsentProvider");
1228
+ return ctx;
1229
+ }
1230
+ function useConsentTextsInternal() {
1231
+ const ctx = React5.useContext(TextsCtx);
1232
+ return ctx;
1233
+ }
1234
+ function useConsentHydrationInternal() {
1235
+ return React5.useContext(HydrationCtx);
1236
+ }
1237
+
1238
+ // src/hooks/useConsent.ts
1239
+ function useConsent() {
1240
+ const state = useConsentStateInternal();
1241
+ const actions = useConsentActionsInternal();
1242
+ return {
1243
+ consented: state.consented,
1244
+ preferences: state.preferences,
1245
+ isModalOpen: state.isModalOpen,
1246
+ acceptAll: actions.acceptAll,
1247
+ rejectAll: actions.rejectAll,
1248
+ setPreference: actions.setPreference,
1249
+ setPreferences: actions.setPreferences,
1250
+ openPreferences: actions.openPreferences,
1251
+ closePreferences: actions.closePreferences,
1252
+ resetConsent: actions.resetConsent
1253
+ };
1254
+ }
1255
+ function useConsentTexts() {
1256
+ return useConsentTextsInternal();
1257
+ }
1258
+ function useConsentHydration() {
1259
+ return useConsentHydrationInternal();
1260
+ }
1261
+ function useOpenPreferencesModal() {
1262
+ const { openPreferences } = useConsent();
1263
+ return openPreferences;
1264
+ }
1265
+ var globalOpenPreferences = null;
1266
+ function openPreferencesModal() {
1267
+ if (globalOpenPreferences) {
1268
+ globalOpenPreferences();
1269
+ } else {
1270
+ console.warn(
1271
+ "openPreferencesModal: ConsentProvider n\xE3o foi inicializado ou n\xE3o est\xE1 dispon\xEDvel."
1272
+ );
1273
+ }
1274
+ }
1275
+ function _registerGlobalOpenPreferences(openPreferences) {
1276
+ globalOpenPreferences = openPreferences;
1277
+ }
1278
+ function _unregisterGlobalOpenPreferences() {
1279
+ globalOpenPreferences = null;
1280
+ }
1281
+
1282
+ // src/components/PreferencesModal.tsx
1283
+ import { jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
1284
+ function PreferencesModal2({
1285
+ DialogProps: DialogProps2,
1286
+ hideBranding = false
1287
+ }) {
1288
+ const { preferences, setPreferences, closePreferences, isModalOpen } = useConsent();
1289
+ const texts = useConsentTexts();
1290
+ const { toggleableCategories } = useCategories();
1291
+ const [tempPreferences, setTempPreferences] = useState2(
1292
+ () => {
1293
+ const initialPrefs = { necessary: true };
1294
+ toggleableCategories.forEach((category) => {
1295
+ initialPrefs[category.id] = preferences[category.id] ?? false;
1296
+ });
1297
+ return initialPrefs;
1298
+ }
1299
+ );
1300
+ useEffect4(() => {
1301
+ if (isModalOpen) {
1302
+ const syncedPrefs = { necessary: true };
1303
+ toggleableCategories.forEach((category) => {
1304
+ syncedPrefs[category.id] = preferences[category.id] ?? false;
1305
+ });
1306
+ setTempPreferences(syncedPrefs);
1307
+ }
1308
+ }, [isModalOpen, preferences, toggleableCategories]);
1309
+ const open = DialogProps2?.open ?? isModalOpen ?? false;
1310
+ const handleSave = () => {
1311
+ setPreferences(tempPreferences);
1312
+ };
1313
+ const handleCancel = () => {
1314
+ setTempPreferences(preferences);
1315
+ closePreferences();
1316
+ };
1317
+ return /* @__PURE__ */ jsxs4(
1318
+ Dialog,
1319
+ {
1320
+ "aria-labelledby": "cookie-pref-title",
1321
+ open,
1322
+ onClose: handleCancel,
1323
+ ...DialogProps2,
1324
+ children: [
1325
+ /* @__PURE__ */ jsx8(DialogTitle, { id: "cookie-pref-title", children: texts.modalTitle }),
1326
+ /* @__PURE__ */ jsxs4(DialogContent, { dividers: true, children: [
1327
+ /* @__PURE__ */ jsx8(Typography3, { variant: "body2", sx: { mb: 2 }, children: texts.modalIntro }),
1328
+ /* @__PURE__ */ jsxs4(FormGroup, { children: [
1329
+ toggleableCategories.map((category) => /* @__PURE__ */ jsx8(
1330
+ FormControlLabel,
1331
+ {
1332
+ control: /* @__PURE__ */ jsx8(
1333
+ Switch,
1334
+ {
1335
+ checked: tempPreferences[category.id] ?? false,
1336
+ onChange: (e) => setTempPreferences((prev) => ({
1337
+ ...prev,
1338
+ [category.id]: e.target.checked
1339
+ }))
1340
+ }
1341
+ ),
1342
+ label: `${category.name} - ${category.description}`
1343
+ },
1344
+ category.id
1345
+ )),
1346
+ /* @__PURE__ */ jsx8(
1347
+ FormControlLabel,
1348
+ {
1349
+ control: /* @__PURE__ */ jsx8(Switch, { checked: true, disabled: true }),
1350
+ label: texts.necessaryAlwaysOn
1351
+ }
1352
+ )
1353
+ ] })
1354
+ ] }),
1355
+ /* @__PURE__ */ jsxs4(DialogActions, { children: [
1356
+ /* @__PURE__ */ jsx8(Button2, { variant: "outlined", onClick: handleCancel, children: texts.close }),
1357
+ /* @__PURE__ */ jsx8(Button2, { variant: "contained", onClick: handleSave, children: texts.save })
1358
+ ] }),
1359
+ !hideBranding && /* @__PURE__ */ jsx8(Branding, { variant: "modal" })
1360
+ ]
1361
+ }
1362
+ );
1363
+ }
1364
+
1365
+ export {
1366
+ DEFAULT_PROJECT_CATEGORIES,
1367
+ analyzeDeveloperConfiguration,
1368
+ useCategories,
1369
+ useCategoryStatus,
1370
+ LogLevel,
1371
+ setDebugLogging,
1372
+ defaultConsentTheme,
1373
+ ConsentProvider,
1374
+ useConsent,
1375
+ useConsentTexts,
1376
+ useConsentHydration,
1377
+ useOpenPreferencesModal,
1378
+ openPreferencesModal,
1379
+ PreferencesModal2 as PreferencesModal
1380
+ };