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.
package/dist/index.cjs CHANGED
@@ -30,162 +30,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
30
30
  ));
31
31
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
32
32
 
33
- // src/utils/cookieUtils.ts
34
- function readConsentCookie(name = DEFAULT_COOKIE_OPTS.name) {
35
- if (typeof document === "undefined") return null;
36
- const raw = import_js_cookie.default.get(name);
37
- if (!raw) return null;
38
- try {
39
- const data = JSON.parse(raw);
40
- if (!data.version) {
41
- return migrateLegacyCookie(data);
42
- }
43
- if (data.version !== COOKIE_SCHEMA_VERSION) {
44
- console.warn(
45
- `[react-lgpd-consent] Cookie version mismatch: ${data.version} != ${COOKIE_SCHEMA_VERSION}`
46
- );
47
- return null;
48
- }
49
- return data;
50
- } catch {
51
- return null;
52
- }
53
- }
54
- function migrateLegacyCookie(legacyData) {
55
- try {
56
- const now = (/* @__PURE__ */ new Date()).toISOString();
57
- return {
58
- version: COOKIE_SCHEMA_VERSION,
59
- consented: legacyData.consented || false,
60
- preferences: legacyData.preferences || { necessary: true },
61
- consentDate: now,
62
- // Não temos o original, usar data atual
63
- lastUpdate: now,
64
- source: "banner",
65
- // Assumir origem banner
66
- isModalOpen: false
67
- // Nunca persistir estado de UI
68
- };
69
- } catch {
70
- return null;
71
- }
72
- }
73
- function writeConsentCookie(state, source = "banner", opts) {
74
- if (typeof document === "undefined") return;
75
- const now = (/* @__PURE__ */ new Date()).toISOString();
76
- const o = { ...DEFAULT_COOKIE_OPTS, ...opts };
77
- const cookieData = {
78
- version: COOKIE_SCHEMA_VERSION,
79
- consented: state.consented,
80
- preferences: state.preferences,
81
- consentDate: state.consentDate || now,
82
- // Preservar data original ou usar atual
83
- lastUpdate: now,
84
- source
85
- // isModalOpen NÃO é persistido (campo de UI apenas)
86
- };
87
- import_js_cookie.default.set(o.name, JSON.stringify(cookieData), {
88
- expires: o.maxAgeDays,
89
- sameSite: o.sameSite,
90
- secure: o.secure,
91
- path: o.path
92
- });
93
- }
94
- function removeConsentCookie(opts) {
95
- if (typeof document === "undefined") return;
96
- const o = { ...DEFAULT_COOKIE_OPTS, ...opts };
97
- import_js_cookie.default.remove(o.name, { path: o.path });
98
- }
99
- var import_js_cookie, DEFAULT_COOKIE_OPTS, COOKIE_SCHEMA_VERSION;
100
- var init_cookieUtils = __esm({
101
- "src/utils/cookieUtils.ts"() {
102
- "use strict";
103
- import_js_cookie = __toESM(require("js-cookie"), 1);
104
- DEFAULT_COOKIE_OPTS = {
105
- name: "cookieConsent",
106
- maxAgeDays: 365,
107
- sameSite: "Lax",
108
- secure: typeof window !== "undefined" ? window.location.protocol === "https:" : false,
109
- path: "/"
110
- };
111
- COOKIE_SCHEMA_VERSION = "1.0";
112
- }
113
- });
114
-
115
- // src/utils/theme.ts
116
- var import_styles, defaultConsentTheme;
117
- var init_theme = __esm({
118
- "src/utils/theme.ts"() {
119
- "use strict";
120
- import_styles = require("@mui/material/styles");
121
- defaultConsentTheme = (0, import_styles.createTheme)({
122
- palette: {
123
- primary: {
124
- main: "#1976d2",
125
- contrastText: "#ffffff"
126
- },
127
- secondary: {
128
- main: "#dc004e",
129
- contrastText: "#ffffff"
130
- },
131
- background: {
132
- default: "#fafafa",
133
- paper: "#ffffff"
134
- },
135
- text: {
136
- primary: "#333333",
137
- secondary: "#666666"
138
- },
139
- action: {
140
- hover: "rgba(25, 118, 210, 0.04)"
141
- }
142
- },
143
- typography: {
144
- fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif',
145
- body2: {
146
- fontSize: "0.875rem",
147
- lineHeight: 1.43
148
- },
149
- button: {
150
- fontWeight: 500,
151
- textTransform: "none"
152
- }
153
- },
154
- components: {
155
- MuiButton: {
156
- styleOverrides: {
157
- root: {
158
- borderRadius: 8,
159
- paddingX: 16,
160
- paddingY: 8
161
- },
162
- contained: {
163
- boxShadow: "0 2px 4px rgba(0,0,0,0.1)",
164
- "&:hover": {
165
- boxShadow: "0 4px 8px rgba(0,0,0,0.15)"
166
- }
167
- }
168
- }
169
- },
170
- MuiPaper: {
171
- styleOverrides: {
172
- root: {
173
- borderRadius: 12
174
- }
175
- }
176
- },
177
- MuiDialog: {
178
- styleOverrides: {
179
- paper: {
180
- borderRadius: 16
181
- }
182
- }
183
- }
184
- }
185
- });
186
- }
187
- });
188
-
189
33
  // src/utils/developerGuidance.ts
190
34
  function analyzeDeveloperConfiguration(config) {
191
35
  const guidance = {
@@ -244,17 +88,6 @@ function analyzeDeveloperConfiguration(config) {
244
88
  });
245
89
  }
246
90
  });
247
- const customCategories = finalConfig.customCategories || [];
248
- customCategories.forEach((category) => {
249
- guidance.activeCategoriesInfo.push({
250
- id: category.id,
251
- name: category.name,
252
- description: category.description,
253
- essential: category.essential === true,
254
- uiRequired: category.essential !== true
255
- // Apenas não-essenciais precisam toggle
256
- });
257
- });
258
91
  const totalToggleable = guidance.activeCategoriesInfo.filter(
259
92
  (c) => c.uiRequired
260
93
  ).length;
@@ -269,18 +102,10 @@ function analyzeDeveloperConfiguration(config) {
269
102
  'prejudicar experi\xEAncia do usu\xE1rio. Considere agrupar categorias similares.`
270
103
  );
271
104
  }
272
- const poorDescriptions = customCategories.filter(
273
- (c) => !c.description || c.description.length < 10
274
- );
275
- if (poorDescriptions.length > 0) {
276
- guidance.warnings.push(
277
- `Categorias customizadas com descri\xE7\xF5es inadequadas: ${poorDescriptions.map((c) => c.id).join(", ")}. Descri\xE7\xF5es claras s\xE3o obrigat\xF3rias para compliance LGPD.`
278
- );
279
- }
280
105
  return guidance;
281
106
  }
282
107
  function logDeveloperGuidance(guidance, disableGuidanceProp) {
283
- if (disableGuidanceProp === true) {
108
+ if (disableGuidanceProp) {
284
109
  return;
285
110
  }
286
111
  const isProduction = (
@@ -304,7 +129,8 @@ function logDeveloperGuidance(guidance, disableGuidanceProp) {
304
129
  console.groupEnd();
305
130
  }
306
131
  if (guidance.usingDefaults) {
307
- console.info(
132
+ console.warn(
133
+ // Changed from console.info to console.warn
308
134
  `${PREFIX} \u{1F4CB} Usando configura\xE7\xE3o padr\xE3o. Para personalizar, use a prop "categories" no ConsentProvider.`
309
135
  );
310
136
  }
@@ -329,6 +155,9 @@ function useDeveloperGuidance(config, disableGuidanceProp) {
329
155
  [config]
330
156
  );
331
157
  React.useEffect(() => {
158
+ if (disableGuidanceProp === true) {
159
+ return;
160
+ }
332
161
  logDeveloperGuidance(guidance, disableGuidanceProp);
333
162
  }, [guidance, stringifiedConfig, disableGuidanceProp]);
334
163
  return guidance;
@@ -339,9 +168,8 @@ var init_developerGuidance = __esm({
339
168
  "use strict";
340
169
  React = __toESM(require("react"), 1);
341
170
  DEFAULT_PROJECT_CATEGORIES = {
342
- enabledCategories: ["analytics"],
171
+ enabledCategories: ["analytics"]
343
172
  // Só analytics além de necessary
344
- customCategories: []
345
173
  };
346
174
  }
347
175
  });
@@ -349,24 +177,13 @@ var init_developerGuidance = __esm({
349
177
  // src/context/CategoriesContext.tsx
350
178
  function CategoriesProvider({
351
179
  children,
352
- categories,
353
- // LEGACY: prop antiga (apenas customCategories)
354
- config
180
+ config,
355
181
  // NOVO: configuração completa
182
+ disableDeveloperGuidance
356
183
  }) {
357
184
  const contextValue = React2.useMemo(() => {
358
- let finalConfig;
359
- if (categories && !config) {
360
- finalConfig = {
361
- enabledCategories: DEFAULT_PROJECT_CATEGORIES.enabledCategories,
362
- customCategories: categories
363
- };
364
- } else {
365
- finalConfig = config || DEFAULT_PROJECT_CATEGORIES;
366
- }
367
- const guidance = analyzeDeveloperConfiguration(
368
- config || (categories ? { customCategories: categories } : void 0)
369
- );
185
+ const finalConfig = config || DEFAULT_PROJECT_CATEGORIES;
186
+ const guidance = analyzeDeveloperConfiguration(config);
370
187
  const toggleableCategories = guidance.activeCategoriesInfo.filter(
371
188
  (cat) => cat.uiRequired
372
189
  );
@@ -374,14 +191,13 @@ function CategoriesProvider({
374
191
  config: finalConfig,
375
192
  guidance,
376
193
  toggleableCategories,
377
- allCategories: guidance.activeCategoriesInfo,
378
- legacyCategories: categories || []
194
+ allCategories: guidance.activeCategoriesInfo
379
195
  };
380
- }, [config, categories]);
196
+ }, [config]);
381
197
  React2.useEffect(() => {
382
- logDeveloperGuidance(contextValue.guidance);
383
- }, [contextValue.guidance]);
384
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CategoriesContext.Provider, { value: contextValue, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CategoriesCtx.Provider, { value: contextValue.legacyCategories, children }) });
198
+ logDeveloperGuidance(contextValue.guidance, disableDeveloperGuidance);
199
+ }, [contextValue.guidance, disableDeveloperGuidance]);
200
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CategoriesContext.Provider, { value: contextValue, children });
385
201
  }
386
202
  function useCategories() {
387
203
  const context = React2.useContext(CategoriesContext);
@@ -403,10 +219,7 @@ function useCategoryStatus(categoryId) {
403
219
  description: category?.description
404
220
  };
405
221
  }
406
- function useCustomCategories() {
407
- return React2.useContext(CategoriesCtx);
408
- }
409
- var React2, import_jsx_runtime, CategoriesContext, CategoriesCtx;
222
+ var React2, import_jsx_runtime, CategoriesContext;
410
223
  var init_CategoriesContext = __esm({
411
224
  "src/context/CategoriesContext.tsx"() {
412
225
  "use strict";
@@ -416,192 +229,758 @@ var init_CategoriesContext = __esm({
416
229
  CategoriesContext = React2.createContext(
417
230
  null
418
231
  );
419
- CategoriesCtx = React2.createContext([]);
420
232
  }
421
233
  });
422
234
 
423
- // src/components/Branding.tsx
424
- function Branding({ variant, hidden = false }) {
425
- if (hidden) return null;
426
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
427
- import_Typography.default,
428
- {
429
- variant: "caption",
430
- sx: (theme) => ({
431
- ...brandingStyles[variant],
432
- color: theme.palette.text.secondary
433
- }),
434
- children: [
435
- "fornecido por",
436
- " ",
437
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
438
- import_Link.default,
439
- {
440
- href: "https://www.ledipo.eti.br",
441
- target: "_blank",
442
- rel: "noopener noreferrer",
443
- sx: (theme) => ({
444
- ...linkStyles,
445
- color: theme.palette.primary.main
446
- }),
447
- children: "L\xC9dipO.eti.br"
448
- }
449
- )
450
- ]
451
- }
452
- );
235
+ // src/utils/SafeThemeProvider.tsx
236
+ function SafeThemeProvider({
237
+ theme,
238
+ children
239
+ }) {
240
+ const safeTheme = React3.useMemo(() => createSafeTheme(theme), [theme]);
241
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_styles.ThemeProvider, { theme: safeTheme, children });
453
242
  }
454
- var import_Link, import_Typography, import_jsx_runtime2, brandingStyles, linkStyles;
455
- var init_Branding = __esm({
456
- "src/components/Branding.tsx"() {
243
+ var React3, import_styles, import_jsx_runtime2, createSafeTheme;
244
+ var init_SafeThemeProvider = __esm({
245
+ "src/utils/SafeThemeProvider.tsx"() {
457
246
  "use strict";
458
- import_Link = __toESM(require("@mui/material/Link"), 1);
459
- import_Typography = __toESM(require("@mui/material/Typography"), 1);
247
+ React3 = __toESM(require("react"), 1);
248
+ import_styles = require("@mui/material/styles");
460
249
  import_jsx_runtime2 = require("react/jsx-runtime");
461
- brandingStyles = {
462
- banner: {
463
- fontSize: "0.65rem",
464
- textAlign: "center",
465
- mt: 1,
466
- opacity: 0.7,
467
- fontStyle: "italic"
468
- },
469
- modal: {
470
- fontSize: "0.65rem",
471
- textAlign: "center",
472
- px: 3,
473
- pb: 1,
474
- opacity: 0.7,
475
- fontStyle: "italic"
250
+ createSafeTheme = (userTheme) => {
251
+ const baseTheme = (0, import_styles.createTheme)({
252
+ palette: {
253
+ primary: {
254
+ main: "#1976d2",
255
+ dark: "#1565c0",
256
+ light: "#42a5f5",
257
+ contrastText: "#ffffff"
258
+ },
259
+ secondary: {
260
+ main: "#dc004e",
261
+ dark: "#9a0036",
262
+ light: "#e33371",
263
+ contrastText: "#ffffff"
264
+ },
265
+ background: {
266
+ default: "#fafafa",
267
+ paper: "#ffffff"
268
+ },
269
+ text: {
270
+ primary: "#333333",
271
+ secondary: "#666666"
272
+ }
273
+ },
274
+ transitions: {
275
+ duration: {
276
+ shortest: 150,
277
+ shorter: 200,
278
+ short: 250,
279
+ standard: 300,
280
+ complex: 375,
281
+ enteringScreen: 225,
282
+ leavingScreen: 195
283
+ }
284
+ }
285
+ });
286
+ if (!userTheme) {
287
+ return baseTheme;
476
288
  }
289
+ return (0, import_styles.createTheme)({
290
+ ...baseTheme,
291
+ ...userTheme,
292
+ palette: {
293
+ ...baseTheme.palette,
294
+ ...userTheme.palette,
295
+ primary: {
296
+ ...baseTheme.palette.primary,
297
+ ...userTheme.palette?.primary
298
+ },
299
+ secondary: {
300
+ ...baseTheme.palette.secondary,
301
+ ...userTheme.palette?.secondary
302
+ },
303
+ background: {
304
+ ...baseTheme.palette.background,
305
+ ...userTheme.palette?.background
306
+ },
307
+ text: {
308
+ ...baseTheme.palette.text,
309
+ ...userTheme.palette?.text
310
+ }
311
+ },
312
+ transitions: {
313
+ ...baseTheme.transitions,
314
+ ...userTheme.transitions,
315
+ duration: {
316
+ ...baseTheme.transitions.duration,
317
+ ...userTheme.transitions?.duration
318
+ }
319
+ }
320
+ });
477
321
  };
478
- linkStyles = {
479
- textDecoration: "none",
480
- fontWeight: 500,
481
- "&:hover": {
482
- textDecoration: "underline"
322
+ }
323
+ });
324
+
325
+ // src/utils/logger.ts
326
+ function setDebugLogging(enabled, level = 2 /* INFO */) {
327
+ logger.setEnabled(enabled);
328
+ logger.setLevel(level);
329
+ logger.info(
330
+ `Debug logging ${enabled ? "enabled" : "disabled"} with level ${LogLevel[level]}`
331
+ );
332
+ }
333
+ var IS_DEVELOPMENT, LOG_PREFIX, LogLevel, ConsentLogger, logger;
334
+ var init_logger = __esm({
335
+ "src/utils/logger.ts"() {
336
+ "use strict";
337
+ IS_DEVELOPMENT = typeof window !== "undefined" && window.__REACT_DEVTOOLS_GLOBAL_HOOK__ || typeof globalThis !== "undefined" && globalThis.process?.env?.NODE_ENV === "development";
338
+ LOG_PREFIX = "[react-lgpd-consent]";
339
+ LogLevel = /* @__PURE__ */ ((LogLevel2) => {
340
+ LogLevel2[LogLevel2["ERROR"] = 0] = "ERROR";
341
+ LogLevel2[LogLevel2["WARN"] = 1] = "WARN";
342
+ LogLevel2[LogLevel2["INFO"] = 2] = "INFO";
343
+ LogLevel2[LogLevel2["DEBUG"] = 3] = "DEBUG";
344
+ return LogLevel2;
345
+ })(LogLevel || {});
346
+ ConsentLogger = class {
347
+ constructor() {
348
+ this.enabled = IS_DEVELOPMENT;
349
+ this.level = 2 /* INFO */;
350
+ }
351
+ setEnabled(enabled) {
352
+ this.enabled = enabled;
353
+ }
354
+ setLevel(level) {
355
+ this.level = level;
356
+ }
357
+ error(...args) {
358
+ if (this.enabled && this.level >= 0 /* ERROR */) {
359
+ console.error(LOG_PREFIX, "[ERROR]", ...args);
360
+ }
361
+ }
362
+ warn(...args) {
363
+ if (this.enabled && this.level >= 1 /* WARN */) {
364
+ console.warn(LOG_PREFIX, "[WARN]", ...args);
365
+ }
366
+ }
367
+ info(...args) {
368
+ if (this.enabled && this.level >= 2 /* INFO */) {
369
+ console.info(LOG_PREFIX, "[INFO]", ...args);
370
+ }
371
+ }
372
+ debug(...args) {
373
+ if (this.enabled && this.level >= 3 /* DEBUG */) {
374
+ console.debug(LOG_PREFIX, "[DEBUG]", ...args);
375
+ }
376
+ }
377
+ // Logs específicos para troubleshooting
378
+ themeCompatibility(themeInfo) {
379
+ this.debug("Theme compatibility check:", {
380
+ hasTheme: !!themeInfo,
381
+ hasPalette: !!themeInfo?.palette,
382
+ hasPrimary: !!themeInfo?.palette?.primary,
383
+ hasTransitions: !!themeInfo?.transitions,
384
+ hasDuration: !!themeInfo?.transitions?.duration
385
+ });
386
+ }
387
+ consentState(action, state) {
388
+ this.debug(`Consent state change [${action}]:`, {
389
+ consented: state.consented,
390
+ isModalOpen: state.isModalOpen,
391
+ preferencesCount: Object.keys(state.preferences || {}).length
392
+ });
393
+ }
394
+ cookieOperation(operation, cookieName, data) {
395
+ this.debug(`Cookie ${operation}:`, {
396
+ name: cookieName,
397
+ hasData: !!data,
398
+ dataSize: data ? JSON.stringify(data).length : 0
399
+ });
400
+ }
401
+ componentRender(componentName, props) {
402
+ this.debug(`Component render [${componentName}]:`, {
403
+ hasProps: !!props,
404
+ propsKeys: props ? Object.keys(props) : []
405
+ });
406
+ }
407
+ scriptIntegration(scriptName, action, success) {
408
+ this.info(
409
+ `Script ${action} [${scriptName}]:`,
410
+ success ? "SUCCESS" : "FAILED"
411
+ );
412
+ }
413
+ apiUsage(method, params) {
414
+ this.debug(`API call [${method}]:`, params);
483
415
  }
484
416
  };
417
+ logger = new ConsentLogger();
485
418
  }
486
419
  });
487
420
 
488
- // src/components/PreferencesModal.tsx
489
- var PreferencesModal_exports = {};
490
- __export(PreferencesModal_exports, {
491
- PreferencesModal: () => PreferencesModal
421
+ // src/utils/cookieUtils.ts
422
+ function readConsentCookie(name = DEFAULT_COOKIE_OPTS.name) {
423
+ logger.debug("Reading consent cookie", { name });
424
+ if (typeof document === "undefined") {
425
+ logger.debug("Cookie read skipped: server-side environment");
426
+ return null;
427
+ }
428
+ const raw = import_js_cookie.default.get(name);
429
+ if (!raw) {
430
+ logger.debug("No consent cookie found");
431
+ return null;
432
+ }
433
+ try {
434
+ const data = JSON.parse(raw);
435
+ logger.cookieOperation("read", name, data);
436
+ if (!data.version) {
437
+ logger.debug("Migrating legacy cookie format");
438
+ return migrateLegacyCookie(data);
439
+ }
440
+ if (data.version !== COOKIE_SCHEMA_VERSION) {
441
+ logger.warn(
442
+ `Cookie version mismatch: ${data.version} != ${COOKIE_SCHEMA_VERSION}`
443
+ );
444
+ return null;
445
+ }
446
+ return data;
447
+ } catch (error) {
448
+ logger.error("Error parsing consent cookie", error);
449
+ return null;
450
+ }
451
+ }
452
+ function migrateLegacyCookie(legacyData) {
453
+ try {
454
+ const now = (/* @__PURE__ */ new Date()).toISOString();
455
+ return {
456
+ version: COOKIE_SCHEMA_VERSION,
457
+ consented: legacyData.consented || false,
458
+ preferences: legacyData.preferences || { necessary: true },
459
+ consentDate: now,
460
+ // Não temos o original, usar data atual
461
+ lastUpdate: now,
462
+ source: "banner",
463
+ // Assumir origem banner
464
+ isModalOpen: false
465
+ // Nunca persistir estado de UI
466
+ };
467
+ } catch {
468
+ return null;
469
+ }
470
+ }
471
+ function writeConsentCookie(state, config, opts, source = "banner") {
472
+ if (typeof document === "undefined") {
473
+ logger.debug("Cookie write skipped: server-side environment");
474
+ return;
475
+ }
476
+ const now = (/* @__PURE__ */ new Date()).toISOString();
477
+ const o = { ...DEFAULT_COOKIE_OPTS, ...opts };
478
+ const cookieData = {
479
+ version: COOKIE_SCHEMA_VERSION,
480
+ consented: state.consented,
481
+ preferences: state.preferences,
482
+ consentDate: state.consentDate || now,
483
+ // Preservar data original ou usar atual
484
+ lastUpdate: now,
485
+ source,
486
+ projectConfig: config
487
+ // isModalOpen NÃO é persistido (campo de UI apenas)
488
+ };
489
+ logger.cookieOperation("write", o.name, cookieData);
490
+ import_js_cookie.default.set(o.name, JSON.stringify(cookieData), {
491
+ expires: o.maxAgeDays,
492
+ sameSite: o.sameSite,
493
+ secure: o.secure,
494
+ path: o.path
495
+ });
496
+ logger.info("Consent cookie saved", {
497
+ consented: cookieData.consented,
498
+ source: cookieData.source,
499
+ preferencesCount: Object.keys(cookieData.preferences).length
500
+ });
501
+ }
502
+ function removeConsentCookie(opts) {
503
+ if (typeof document === "undefined") {
504
+ logger.debug("Cookie removal skipped: server-side environment");
505
+ return;
506
+ }
507
+ const o = { ...DEFAULT_COOKIE_OPTS, ...opts };
508
+ logger.cookieOperation("delete", o.name);
509
+ import_js_cookie.default.remove(o.name, { path: o.path });
510
+ logger.info("Consent cookie removed");
511
+ }
512
+ var import_js_cookie, DEFAULT_COOKIE_OPTS, COOKIE_SCHEMA_VERSION;
513
+ var init_cookieUtils = __esm({
514
+ "src/utils/cookieUtils.ts"() {
515
+ "use strict";
516
+ import_js_cookie = __toESM(require("js-cookie"), 1);
517
+ init_logger();
518
+ DEFAULT_COOKIE_OPTS = {
519
+ name: "cookieConsent",
520
+ maxAgeDays: 365,
521
+ sameSite: "Lax",
522
+ secure: typeof window !== "undefined" ? window.location.protocol === "https:" : false,
523
+ path: "/"
524
+ };
525
+ COOKIE_SCHEMA_VERSION = "1.0";
526
+ }
492
527
  });
493
- function PreferencesModal({
494
- DialogProps: DialogProps2,
495
- hideBranding = false
528
+
529
+ // src/utils/categoryUtils.ts
530
+ function createProjectPreferences(config, defaultValue = false) {
531
+ const preferences = {
532
+ necessary: true
533
+ // Sempre presente e true (essencial)
534
+ };
535
+ const enabledCategories = config?.enabledCategories || [];
536
+ enabledCategories.forEach((category) => {
537
+ if (category !== "necessary") {
538
+ preferences[category] = defaultValue;
539
+ }
540
+ });
541
+ return preferences;
542
+ }
543
+ function validateProjectPreferences(preferences, config) {
544
+ const validPreferences = {
545
+ necessary: true
546
+ // Sempre válida
547
+ };
548
+ const enabledCategories = config?.enabledCategories || [];
549
+ enabledCategories.forEach((category) => {
550
+ if (category !== "necessary" && preferences[category] !== void 0) {
551
+ validPreferences[category] = preferences[category];
552
+ }
553
+ });
554
+ return validPreferences;
555
+ }
556
+ var init_categoryUtils = __esm({
557
+ "src/utils/categoryUtils.ts"() {
558
+ "use strict";
559
+ }
560
+ });
561
+
562
+ // src/utils/theme.ts
563
+ var import_styles2, defaultConsentTheme;
564
+ var init_theme = __esm({
565
+ "src/utils/theme.ts"() {
566
+ "use strict";
567
+ import_styles2 = require("@mui/material/styles");
568
+ defaultConsentTheme = (0, import_styles2.createTheme)({
569
+ palette: {
570
+ primary: {
571
+ main: "#1976d2",
572
+ contrastText: "#ffffff"
573
+ },
574
+ secondary: {
575
+ main: "#dc004e",
576
+ contrastText: "#ffffff"
577
+ },
578
+ background: {
579
+ default: "#fafafa",
580
+ paper: "#ffffff"
581
+ },
582
+ text: {
583
+ primary: "#333333",
584
+ secondary: "#666666"
585
+ },
586
+ action: {
587
+ hover: "rgba(25, 118, 210, 0.04)"
588
+ }
589
+ },
590
+ typography: {
591
+ fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif',
592
+ body2: {
593
+ fontSize: "0.875rem",
594
+ lineHeight: 1.43
595
+ },
596
+ button: {
597
+ fontWeight: 500,
598
+ textTransform: "none"
599
+ }
600
+ },
601
+ components: {
602
+ MuiButton: {
603
+ styleOverrides: {
604
+ root: {
605
+ borderRadius: 8,
606
+ paddingX: 16,
607
+ paddingY: 8
608
+ },
609
+ contained: {
610
+ boxShadow: "0 2px 4px rgba(0,0,0,0.1)",
611
+ "&:hover": {
612
+ boxShadow: "0 4px 8px rgba(0,0,0,0.15)"
613
+ }
614
+ }
615
+ }
616
+ },
617
+ MuiPaper: {
618
+ styleOverrides: {
619
+ root: {
620
+ borderRadius: 12
621
+ }
622
+ }
623
+ },
624
+ MuiDialog: {
625
+ styleOverrides: {
626
+ paper: {
627
+ borderRadius: 16
628
+ }
629
+ }
630
+ }
631
+ }
632
+ });
633
+ }
634
+ });
635
+
636
+ // src/context/DesignContext.tsx
637
+ function DesignProvider({
638
+ tokens,
639
+ children
496
640
  }) {
497
- const { preferences, setPreferences, closePreferences, isModalOpen } = useConsent();
641
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(DesignContext.Provider, { value: tokens, children });
642
+ }
643
+ function useDesignTokens() {
644
+ return React4.useContext(DesignContext);
645
+ }
646
+ var React4, import_jsx_runtime3, DesignContext;
647
+ var init_DesignContext = __esm({
648
+ "src/context/DesignContext.tsx"() {
649
+ "use strict";
650
+ React4 = __toESM(require("react"), 1);
651
+ import_jsx_runtime3 = require("react/jsx-runtime");
652
+ DesignContext = React4.createContext(void 0);
653
+ }
654
+ });
655
+
656
+ // src/components/Branding.tsx
657
+ function Branding({ variant, hidden = false }) {
498
658
  const texts = useConsentTexts();
499
- const { toggleableCategories } = useCategories();
500
- const [tempPreferences, setTempPreferences] = (0, import_react.useState)(
501
- () => {
502
- const initialPrefs = { necessary: true };
503
- toggleableCategories.forEach((category) => {
504
- initialPrefs[category.id] = preferences[category.id] ?? false;
505
- });
506
- return initialPrefs;
659
+ if (hidden) return null;
660
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
661
+ import_Typography.default,
662
+ {
663
+ variant: "caption",
664
+ sx: (theme) => ({
665
+ ...brandingStyles[variant],
666
+ color: theme.palette.text.secondary
667
+ }),
668
+ children: [
669
+ texts.brandingPoweredBy || "fornecido por",
670
+ " ",
671
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
672
+ import_Link.default,
673
+ {
674
+ href: "https://www.ledipo.eti.br",
675
+ target: "_blank",
676
+ rel: "noopener noreferrer",
677
+ sx: (theme) => ({
678
+ ...linkStyles,
679
+ color: theme.palette.primary.main
680
+ }),
681
+ children: "L\xC9dipO.eti.br"
682
+ }
683
+ )
684
+ ]
507
685
  }
508
686
  );
509
- (0, import_react.useEffect)(() => {
510
- if (isModalOpen) {
511
- const syncedPrefs = { necessary: true };
512
- toggleableCategories.forEach((category) => {
513
- syncedPrefs[category.id] = preferences[category.id] ?? false;
514
- });
515
- setTempPreferences(syncedPrefs);
516
- }
517
- }, [isModalOpen, preferences, toggleableCategories]);
518
- const open = DialogProps2?.open ?? isModalOpen ?? false;
519
- const handleSave = () => {
520
- setPreferences(tempPreferences);
687
+ }
688
+ var import_Link, import_Typography, import_jsx_runtime4, brandingStyles, linkStyles;
689
+ var init_Branding = __esm({
690
+ "src/components/Branding.tsx"() {
691
+ "use strict";
692
+ init_useConsent();
693
+ import_Link = __toESM(require("@mui/material/Link"), 1);
694
+ import_Typography = __toESM(require("@mui/material/Typography"), 1);
695
+ import_jsx_runtime4 = require("react/jsx-runtime");
696
+ brandingStyles = {
697
+ banner: {
698
+ fontSize: "0.65rem",
699
+ textAlign: "right",
700
+ mt: 1,
701
+ opacity: 0.7,
702
+ fontStyle: "italic",
703
+ width: "100%"
704
+ },
705
+ modal: {
706
+ fontSize: "0.65rem",
707
+ textAlign: "right",
708
+ px: 3,
709
+ pb: 1,
710
+ opacity: 0.7,
711
+ fontStyle: "italic",
712
+ width: "100%"
713
+ }
714
+ };
715
+ linkStyles = {
716
+ textDecoration: "none",
717
+ fontWeight: 500,
718
+ "&:hover": {
719
+ textDecoration: "underline"
720
+ }
721
+ };
722
+ }
723
+ });
724
+
725
+ // src/components/CookieBanner.tsx
726
+ function CookieBanner({
727
+ policyLinkUrl,
728
+ debug,
729
+ blocking = true,
730
+ hideBranding = false,
731
+ SnackbarProps,
732
+ PaperProps
733
+ }) {
734
+ const { consented, acceptAll, rejectAll, openPreferences } = useConsent();
735
+ const texts = useConsentTexts();
736
+ const isHydrated = useConsentHydration();
737
+ const designTokens = useDesignTokens();
738
+ const open = debug ? true : isHydrated && !consented;
739
+ logger.componentRender("CookieBanner", {
740
+ open,
741
+ consented,
742
+ isHydrated,
743
+ blocking,
744
+ hideBranding
745
+ });
746
+ if (!open) return null;
747
+ const bannerStyle = {
748
+ p: designTokens?.spacing?.padding?.banner ?? 2,
749
+ maxWidth: 720,
750
+ mx: "auto",
751
+ backgroundColor: designTokens?.colors?.background,
752
+ color: designTokens?.colors?.text,
753
+ borderRadius: designTokens?.spacing?.borderRadius?.banner,
754
+ fontFamily: designTokens?.typography?.fontFamily
521
755
  };
522
- const handleCancel = () => {
523
- setTempPreferences(preferences);
524
- closePreferences();
756
+ const bannerContent = /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_Paper.default, { elevation: 3, sx: bannerStyle, ...PaperProps, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_Stack.default, { spacing: 1, children: [
757
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
758
+ import_Typography2.default,
759
+ {
760
+ variant: "body2",
761
+ sx: { fontSize: designTokens?.typography?.fontSize?.banner },
762
+ children: [
763
+ texts.bannerMessage,
764
+ " ",
765
+ policyLinkUrl && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
766
+ import_Link2.default,
767
+ {
768
+ href: policyLinkUrl,
769
+ underline: "hover",
770
+ target: "_blank",
771
+ rel: "noopener noreferrer",
772
+ sx: { color: designTokens?.colors?.primary },
773
+ children: texts.policyLink ?? "Saiba mais"
774
+ }
775
+ )
776
+ ]
777
+ }
778
+ ),
779
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
780
+ import_Stack.default,
781
+ {
782
+ direction: { xs: "column", sm: "row" },
783
+ spacing: 1,
784
+ justifyContent: "flex-end",
785
+ children: [
786
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
787
+ import_Button.default,
788
+ {
789
+ variant: "outlined",
790
+ onClick: () => {
791
+ logger.apiUsage("rejectAll", { source: "banner" });
792
+ rejectAll();
793
+ },
794
+ sx: { color: designTokens?.colors?.secondary },
795
+ children: texts.declineAll
796
+ }
797
+ ),
798
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
799
+ import_Button.default,
800
+ {
801
+ variant: "contained",
802
+ onClick: () => {
803
+ logger.apiUsage("acceptAll", { source: "banner" });
804
+ acceptAll();
805
+ },
806
+ sx: { backgroundColor: designTokens?.colors?.primary },
807
+ children: texts.acceptAll
808
+ }
809
+ ),
810
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
811
+ import_Button.default,
812
+ {
813
+ variant: "text",
814
+ onClick: () => {
815
+ logger.apiUsage("openPreferences", { source: "banner" });
816
+ openPreferences();
817
+ },
818
+ sx: { color: designTokens?.colors?.text },
819
+ children: texts.preferences
820
+ }
821
+ )
822
+ ]
823
+ }
824
+ ),
825
+ !hideBranding && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Branding, { variant: "banner" })
826
+ ] }) });
827
+ const positionStyle = {
828
+ position: "fixed",
829
+ zIndex: 1300,
830
+ ...designTokens?.layout?.position === "top" ? { top: 0 } : { bottom: 0 },
831
+ left: 0,
832
+ right: 0,
833
+ width: designTokens?.layout?.width?.desktop ?? "100%",
834
+ p: 2
525
835
  };
526
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
527
- import_Dialog.default,
836
+ if (blocking) {
837
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
838
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
839
+ import_Box.default,
840
+ {
841
+ sx: {
842
+ position: "fixed",
843
+ top: 0,
844
+ left: 0,
845
+ right: 0,
846
+ bottom: 0,
847
+ backgroundColor: designTokens?.layout?.backdrop ? "rgba(0, 0, 0, 0.5)" : "transparent",
848
+ zIndex: 1299
849
+ }
850
+ }
851
+ ),
852
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_Box.default, { sx: positionStyle, children: bannerContent })
853
+ ] });
854
+ }
855
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
856
+ import_Snackbar.default,
528
857
  {
529
- "aria-labelledby": "cookie-pref-title",
530
858
  open,
531
- onClose: handleCancel,
532
- ...DialogProps2,
533
- children: [
534
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_DialogTitle.default, { id: "cookie-pref-title", children: texts.modalTitle }),
535
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_DialogContent.default, { dividers: true, children: [
536
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_Typography2.default, { variant: "body2", sx: { mb: 2 }, children: texts.modalIntro }),
537
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_FormGroup.default, { children: [
538
- toggleableCategories.map((category) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
539
- import_FormControlLabel.default,
540
- {
541
- control: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
542
- import_Switch.default,
543
- {
544
- checked: tempPreferences[category.id] ?? false,
545
- onChange: (e) => setTempPreferences((prev) => ({
546
- ...prev,
547
- [category.id]: e.target.checked
548
- }))
549
- }
550
- ),
551
- label: `${category.name} - ${category.description}`
552
- },
553
- category.id
554
- )),
555
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
556
- import_FormControlLabel.default,
557
- {
558
- control: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_Switch.default, { checked: true, disabled: true }),
559
- label: texts.necessaryAlwaysOn
560
- }
561
- )
562
- ] })
563
- ] }),
564
- !hideBranding && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Branding, { variant: "modal" }),
565
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_DialogActions.default, { children: [
566
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_Button.default, { variant: "outlined", onClick: handleCancel, children: "Cancelar" }),
567
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_Button.default, { variant: "contained", onClick: handleSave, children: texts.save })
568
- ] })
569
- ]
859
+ anchorOrigin: {
860
+ vertical: designTokens?.layout?.position === "top" ? "top" : "bottom",
861
+ horizontal: "center"
862
+ },
863
+ ...SnackbarProps,
864
+ children: bannerContent
570
865
  }
571
866
  );
572
867
  }
573
- var import_Button, import_Dialog, import_DialogActions, import_DialogContent, import_DialogTitle, import_FormControlLabel, import_FormGroup, import_Switch, import_Typography2, import_react, import_jsx_runtime3;
574
- var init_PreferencesModal = __esm({
575
- "src/components/PreferencesModal.tsx"() {
868
+ var import_Button, import_Box, import_Paper, import_Snackbar, import_Stack, import_Typography2, import_Link2, import_jsx_runtime5;
869
+ var init_CookieBanner = __esm({
870
+ "src/components/CookieBanner.tsx"() {
576
871
  "use strict";
577
872
  import_Button = __toESM(require("@mui/material/Button"), 1);
578
- import_Dialog = __toESM(require("@mui/material/Dialog"), 1);
579
- import_DialogActions = __toESM(require("@mui/material/DialogActions"), 1);
580
- import_DialogContent = __toESM(require("@mui/material/DialogContent"), 1);
581
- import_DialogTitle = __toESM(require("@mui/material/DialogTitle"), 1);
582
- import_FormControlLabel = __toESM(require("@mui/material/FormControlLabel"), 1);
583
- import_FormGroup = __toESM(require("@mui/material/FormGroup"), 1);
584
- import_Switch = __toESM(require("@mui/material/Switch"), 1);
873
+ import_Box = __toESM(require("@mui/material/Box"), 1);
874
+ import_Paper = __toESM(require("@mui/material/Paper"), 1);
875
+ import_Snackbar = __toESM(require("@mui/material/Snackbar"), 1);
876
+ import_Stack = __toESM(require("@mui/material/Stack"), 1);
585
877
  import_Typography2 = __toESM(require("@mui/material/Typography"), 1);
586
- import_react = require("react");
587
- init_CategoriesContext();
878
+ import_Link2 = __toESM(require("@mui/material/Link"), 1);
588
879
  init_useConsent();
880
+ init_DesignContext();
589
881
  init_Branding();
590
- import_jsx_runtime3 = require("react/jsx-runtime");
882
+ init_logger();
883
+ import_jsx_runtime5 = require("react/jsx-runtime");
591
884
  }
592
885
  });
593
886
 
594
- // src/context/ConsentContext.tsx
595
- function createInitialPreferences(customCategories) {
596
- const prefs = { ...DEFAULT_PREFERENCES };
597
- if (customCategories) {
598
- customCategories.forEach((category) => {
599
- prefs[category.id] = category.essential === true;
600
- });
887
+ // src/components/FloatingPreferencesButton.tsx
888
+ function useThemeWithFallbacks() {
889
+ const theme = (0, import_styles3.useTheme)();
890
+ logger.themeCompatibility(theme);
891
+ return {
892
+ palette: {
893
+ primary: {
894
+ main: theme?.palette?.primary?.main || "#1976d2",
895
+ dark: theme?.palette?.primary?.dark || "#1565c0"
896
+ }
897
+ },
898
+ transitions: {
899
+ duration: {
900
+ shortest: theme?.transitions?.duration?.shortest || 150,
901
+ short: theme?.transitions?.duration?.short || 250
902
+ }
903
+ }
904
+ };
905
+ }
906
+ function FloatingPreferencesButton({
907
+ position = "bottom-right",
908
+ offset = 24,
909
+ icon = /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_CookieOutlined.default, {}),
910
+ tooltip,
911
+ FabProps,
912
+ hideWhenConsented = false
913
+ }) {
914
+ const { openPreferences, consented } = useConsent();
915
+ const texts = useConsentTexts();
916
+ const safeTheme = useThemeWithFallbacks();
917
+ logger.componentRender("FloatingPreferencesButton", {
918
+ position,
919
+ offset,
920
+ hideWhenConsented,
921
+ consented
922
+ });
923
+ if (hideWhenConsented && consented) {
924
+ logger.debug(
925
+ "FloatingPreferencesButton: Hidden due to hideWhenConsented=true and consented=true"
926
+ );
927
+ return null;
601
928
  }
602
- return prefs;
929
+ const tooltipText = tooltip ?? texts.preferencesButton ?? "Gerenciar Prefer\xEAncias de Cookies";
930
+ const getPosition = () => {
931
+ const styles = {
932
+ position: "fixed",
933
+ zIndex: 1200
934
+ };
935
+ switch (position) {
936
+ case "bottom-left":
937
+ return { ...styles, bottom: offset, left: offset };
938
+ case "bottom-right":
939
+ return { ...styles, bottom: offset, right: offset };
940
+ case "top-left":
941
+ return { ...styles, top: offset, left: offset };
942
+ case "top-right":
943
+ return { ...styles, top: offset, right: offset };
944
+ default:
945
+ return { ...styles, bottom: offset, right: offset };
946
+ }
947
+ };
948
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_Tooltip.default, { title: tooltipText, placement: "top", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
949
+ import_Fab.default,
950
+ {
951
+ size: "medium",
952
+ color: "primary",
953
+ onClick: openPreferences,
954
+ sx: {
955
+ ...getPosition(),
956
+ backgroundColor: safeTheme.palette.primary.main,
957
+ "&:hover": {
958
+ backgroundColor: safeTheme.palette.primary.dark
959
+ },
960
+ transition: `all ${safeTheme.transitions.duration.short}ms`
961
+ },
962
+ "aria-label": tooltipText,
963
+ ...FabProps,
964
+ children: icon
965
+ }
966
+ ) });
603
967
  }
604
- function createFullConsentState(consented, preferences, source, isModalOpen = false, existingState) {
968
+ var import_CookieOutlined, import_Fab, import_Tooltip, import_styles3, import_jsx_runtime6;
969
+ var init_FloatingPreferencesButton = __esm({
970
+ "src/components/FloatingPreferencesButton.tsx"() {
971
+ "use strict";
972
+ import_CookieOutlined = __toESM(require("@mui/icons-material/CookieOutlined"), 1);
973
+ import_Fab = __toESM(require("@mui/material/Fab"), 1);
974
+ import_Tooltip = __toESM(require("@mui/material/Tooltip"), 1);
975
+ import_styles3 = require("@mui/material/styles");
976
+ init_useConsent();
977
+ init_logger();
978
+ import_jsx_runtime6 = require("react/jsx-runtime");
979
+ }
980
+ });
981
+
982
+ // src/context/ConsentContext.tsx
983
+ function createFullConsentState(consented, preferences, source, projectConfig, isModalOpen = false, existingState) {
605
984
  const now = (/* @__PURE__ */ new Date()).toISOString();
606
985
  return {
607
986
  version: "1.0",
@@ -610,30 +989,51 @@ function createFullConsentState(consented, preferences, source, isModalOpen = fa
610
989
  consentDate: existingState?.consentDate || now,
611
990
  lastUpdate: now,
612
991
  source,
992
+ projectConfig,
613
993
  isModalOpen
614
994
  };
615
995
  }
616
996
  function reducer(state, action) {
997
+ log.debug("State transition:", {
998
+ action: action.type,
999
+ currentState: state.consented
1000
+ });
617
1001
  switch (action.type) {
618
1002
  case "ACCEPT_ALL": {
619
- const prefs = createInitialPreferences(action.customCategories);
620
- Object.keys(prefs).forEach((key) => {
621
- prefs[key] = true;
1003
+ const prefs = createProjectPreferences(action.config, true);
1004
+ const newState = createFullConsentState(
1005
+ true,
1006
+ prefs,
1007
+ "banner",
1008
+ action.config,
1009
+ false,
1010
+ state
1011
+ );
1012
+ log.info("User accepted all cookies", {
1013
+ preferences: newState.preferences
1014
+ });
1015
+ return newState;
1016
+ }
1017
+ case "REJECT_ALL": {
1018
+ const prefs = createProjectPreferences(action.config, false);
1019
+ const newState = createFullConsentState(
1020
+ true,
1021
+ prefs,
1022
+ "banner",
1023
+ action.config,
1024
+ false,
1025
+ state
1026
+ );
1027
+ log.info("User rejected all cookies", {
1028
+ preferences: newState.preferences
622
1029
  });
623
- return createFullConsentState(true, prefs, "banner", false, state);
624
- }
625
- case "REJECT_ALL": {
626
- const prefs = createInitialPreferences(action.customCategories);
627
- if (action.customCategories) {
628
- action.customCategories.forEach((category) => {
629
- if (category.essential) {
630
- prefs[category.id] = true;
631
- }
632
- });
633
- }
634
- return createFullConsentState(true, prefs, "banner", false, state);
1030
+ return newState;
635
1031
  }
636
1032
  case "SET_CATEGORY":
1033
+ log.debug("Category preference changed", {
1034
+ category: action.category,
1035
+ value: action.value
1036
+ });
637
1037
  return {
638
1038
  ...state,
639
1039
  preferences: {
@@ -643,10 +1043,12 @@ function reducer(state, action) {
643
1043
  lastUpdate: (/* @__PURE__ */ new Date()).toISOString()
644
1044
  };
645
1045
  case "SET_PREFERENCES":
1046
+ log.info("Preferences saved", { preferences: action.preferences });
646
1047
  return createFullConsentState(
647
1048
  true,
648
1049
  action.preferences,
649
1050
  "modal",
1051
+ action.config,
650
1052
  false,
651
1053
  state
652
1054
  );
@@ -657,20 +1059,30 @@ function reducer(state, action) {
657
1059
  true,
658
1060
  state.preferences,
659
1061
  "modal",
1062
+ action.config,
660
1063
  false,
661
1064
  state
662
1065
  );
663
1066
  case "RESET": {
664
1067
  return createFullConsentState(
665
1068
  false,
666
- createInitialPreferences(action.customCategories),
1069
+ createProjectPreferences(action.config),
667
1070
  "programmatic",
1071
+ action.config,
668
1072
  false
669
1073
  );
670
1074
  }
671
- case "HYDRATE":
672
- return { ...action.state, isModalOpen: false };
673
- // Nunca hidratar com modal aberto
1075
+ case "HYDRATE": {
1076
+ const validatedPreferences = validateProjectPreferences(
1077
+ action.state.preferences,
1078
+ action.config
1079
+ );
1080
+ return {
1081
+ ...action.state,
1082
+ preferences: validatedPreferences,
1083
+ isModalOpen: false
1084
+ };
1085
+ }
674
1086
  default:
675
1087
  return state;
676
1088
  }
@@ -678,96 +1090,98 @@ function reducer(state, action) {
678
1090
  function ConsentProvider({
679
1091
  initialState,
680
1092
  categories,
681
- // NOVO: configuração completa de categorias
1093
+ // Nova prop para configuração de categorias
682
1094
  texts: textsProp,
683
1095
  theme,
684
- customCategories,
685
- // LEGACY: compatibilidade
1096
+ designTokens,
686
1097
  scriptIntegrations,
687
1098
  // eslint-disable-line no-unused-vars
688
1099
  PreferencesModalComponent,
689
1100
  preferencesModalProps = {},
690
- disableAutomaticModal = false,
1101
+ CookieBannerComponent,
1102
+ cookieBannerProps = {},
1103
+ FloatingPreferencesButtonComponent,
1104
+ floatingPreferencesButtonProps = {},
1105
+ disableFloatingPreferencesButton = false,
691
1106
  hideBranding = false,
692
1107
  onConsentGiven,
693
1108
  onPreferencesSaved,
694
1109
  cookie: cookieOpts,
695
1110
  disableDeveloperGuidance,
696
- // NOVO: desabilita avisos de dev
697
1111
  children
698
1112
  }) {
699
- const texts = React3.useMemo(
1113
+ const texts = React5.useMemo(
700
1114
  () => ({ ...DEFAULT_TEXTS, ...textsProp ?? {} }),
701
1115
  [textsProp]
702
1116
  );
703
- const cookie = React3.useMemo(
1117
+ const cookie = React5.useMemo(
704
1118
  () => ({ ...DEFAULT_COOKIE_OPTS, ...cookieOpts ?? {} }),
705
1119
  [cookieOpts]
706
1120
  );
707
- const appliedTheme = React3.useMemo(
1121
+ const appliedTheme = React5.useMemo(
708
1122
  () => theme || defaultConsentTheme,
709
1123
  [theme]
710
1124
  );
711
- const finalCategoriesConfig = React3.useMemo(() => {
1125
+ const finalCategoriesConfig = React5.useMemo(() => {
712
1126
  if (categories) return categories;
713
- if (customCategories) {
714
- return {
715
- enabledCategories: ["analytics"],
716
- // padrão quando usando API antiga
717
- customCategories
718
- };
719
- }
720
- return void 0;
721
- }, [categories, customCategories]);
1127
+ return DEFAULT_PROJECT_CATEGORIES;
1128
+ }, [categories]);
722
1129
  useDeveloperGuidance(finalCategoriesConfig, disableDeveloperGuidance);
723
- const boot = React3.useMemo(() => {
1130
+ const boot = React5.useMemo(() => {
724
1131
  if (initialState) return { ...initialState, isModalOpen: false };
725
1132
  return createFullConsentState(
726
1133
  false,
727
- createInitialPreferences(customCategories),
1134
+ createProjectPreferences(finalCategoriesConfig),
728
1135
  "banner",
1136
+ finalCategoriesConfig,
729
1137
  false
730
1138
  );
731
- }, [initialState, customCategories]);
732
- const [state, dispatch] = React3.useReducer(reducer, boot);
733
- const [isHydrated, setIsHydrated] = React3.useState(false);
734
- React3.useEffect(() => {
1139
+ }, [initialState, finalCategoriesConfig]);
1140
+ const [state, dispatch] = React5.useReducer(reducer, boot);
1141
+ const [isHydrated, setIsHydrated] = React5.useState(false);
1142
+ React5.useEffect(() => {
735
1143
  if (!initialState) {
736
1144
  const saved = readConsentCookie(cookie.name);
737
1145
  if (saved?.consented) {
738
- console.log("\u{1F680} Immediate hydration: Cookie found", saved);
739
- dispatch({ type: "HYDRATE", state: saved });
1146
+ dispatch({
1147
+ type: "HYDRATE",
1148
+ state: saved,
1149
+ config: finalCategoriesConfig
1150
+ });
740
1151
  }
741
1152
  }
742
1153
  setIsHydrated(true);
743
- }, [cookie.name, initialState]);
744
- React3.useEffect(() => {
745
- if (state.consented) writeConsentCookie(state, state.source, cookie);
746
- }, [state, cookie]);
747
- const prevConsented = React3.useRef(state.consented);
748
- React3.useEffect(() => {
1154
+ }, [cookie.name, initialState, finalCategoriesConfig]);
1155
+ React5.useEffect(() => {
1156
+ if (state.consented)
1157
+ writeConsentCookie(state, finalCategoriesConfig, cookie);
1158
+ }, [state, cookie, finalCategoriesConfig]);
1159
+ const prevConsented = React5.useRef(state.consented);
1160
+ React5.useEffect(() => {
749
1161
  if (!prevConsented.current && state.consented && onConsentGiven) {
750
1162
  setTimeout(() => onConsentGiven(state), 150);
751
1163
  }
752
1164
  prevConsented.current = state.consented;
753
1165
  }, [state, onConsentGiven]);
754
- const prevPrefs = React3.useRef(state.preferences);
755
- React3.useEffect(() => {
756
- if (state.consented && onPreferencesSaved && prevPrefs.current !== state.preferences) {
757
- setTimeout(() => onPreferencesSaved(state.preferences), 150);
758
- prevPrefs.current = state.preferences;
759
- }
760
- }, [state, onPreferencesSaved]);
761
- const api = React3.useMemo(() => {
762
- const acceptAll = () => dispatch({ type: "ACCEPT_ALL", customCategories });
763
- const rejectAll = () => dispatch({ type: "REJECT_ALL", customCategories });
1166
+ const api = React5.useMemo(() => {
1167
+ const acceptAll = () => dispatch({ type: "ACCEPT_ALL", config: finalCategoriesConfig });
1168
+ const rejectAll = () => dispatch({ type: "REJECT_ALL", config: finalCategoriesConfig });
764
1169
  const setPreference = (category, value) => dispatch({ type: "SET_CATEGORY", category, value });
765
- const setPreferences = (preferences) => dispatch({ type: "SET_PREFERENCES", preferences });
1170
+ const setPreferences = (preferences) => {
1171
+ dispatch({
1172
+ type: "SET_PREFERENCES",
1173
+ preferences,
1174
+ config: finalCategoriesConfig
1175
+ });
1176
+ if (onPreferencesSaved) {
1177
+ setTimeout(() => onPreferencesSaved(preferences), 150);
1178
+ }
1179
+ };
766
1180
  const openPreferences = () => dispatch({ type: "OPEN_MODAL" });
767
- const closePreferences = () => dispatch({ type: "CLOSE_MODAL" });
1181
+ const closePreferences = () => dispatch({ type: "CLOSE_MODAL", config: finalCategoriesConfig });
768
1182
  const resetConsent = () => {
769
1183
  removeConsentCookie(cookie);
770
- dispatch({ type: "RESET", customCategories });
1184
+ dispatch({ type: "RESET", config: finalCategoriesConfig });
771
1185
  };
772
1186
  return {
773
1187
  consented: !!state.consented,
@@ -781,58 +1195,104 @@ function ConsentProvider({
781
1195
  closePreferences,
782
1196
  resetConsent
783
1197
  };
784
- }, [state, cookie, customCategories]);
785
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_styles2.ThemeProvider, { theme: appliedTheme, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(StateCtx.Provider, { value: state, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ActionsCtx.Provider, { value: api, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(TextsCtx.Provider, { value: texts, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(HydrationCtx.Provider, { value: isHydrated, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
1198
+ }, [state, cookie, finalCategoriesConfig, onPreferencesSaved]);
1199
+ React5.useEffect(() => {
1200
+ _registerGlobalOpenPreferences(api.openPreferences);
1201
+ return () => _unregisterGlobalOpenPreferences();
1202
+ }, [api.openPreferences]);
1203
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SafeThemeProvider, { theme: appliedTheme, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(StateCtx.Provider, { value: state, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ActionsCtx.Provider, { value: api, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(TextsCtx.Provider, { value: texts, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(HydrationCtx.Provider, { value: isHydrated, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(DesignProvider, { tokens: designTokens, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
786
1204
  CategoriesProvider,
787
1205
  {
788
1206
  config: finalCategoriesConfig,
789
- categories: customCategories,
1207
+ disableDeveloperGuidance,
790
1208
  children: [
791
1209
  children,
792
- !disableAutomaticModal && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(React3.Suspense, { fallback: null, children: PreferencesModalComponent ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PreferencesModalComponent, { ...preferencesModalProps }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PreferencesModal2, { hideBranding }) })
1210
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(React5.Suspense, { fallback: null, children: PreferencesModalComponent ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1211
+ PreferencesModalComponent,
1212
+ {
1213
+ preferences: api.preferences,
1214
+ setPreferences: api.setPreferences,
1215
+ closePreferences: api.closePreferences,
1216
+ isModalOpen: api.isModalOpen,
1217
+ texts,
1218
+ ...preferencesModalProps
1219
+ }
1220
+ ) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(PreferencesModal, { hideBranding }) }),
1221
+ !state.consented && isHydrated && (CookieBannerComponent ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1222
+ CookieBannerComponent,
1223
+ {
1224
+ consented: api.consented,
1225
+ acceptAll: api.acceptAll,
1226
+ rejectAll: api.rejectAll,
1227
+ openPreferences: api.openPreferences,
1228
+ texts,
1229
+ ...cookieBannerProps
1230
+ }
1231
+ ) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CookieBanner, {})),
1232
+ state.consented && !disableFloatingPreferencesButton && (FloatingPreferencesButtonComponent ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1233
+ FloatingPreferencesButtonComponent,
1234
+ {
1235
+ openPreferences: api.openPreferences,
1236
+ consented: api.consented,
1237
+ ...floatingPreferencesButtonProps
1238
+ }
1239
+ ) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(FloatingPreferencesButton, {}))
793
1240
  ]
794
1241
  }
795
- ) }) }) }) }) });
1242
+ ) }) }) }) }) }) });
796
1243
  }
797
1244
  function useConsentStateInternal() {
798
- const ctx = React3.useContext(StateCtx);
1245
+ const ctx = React5.useContext(StateCtx);
799
1246
  if (!ctx)
800
1247
  throw new Error("useConsentState must be used within ConsentProvider");
801
1248
  return ctx;
802
1249
  }
803
1250
  function useConsentActionsInternal() {
804
- const ctx = React3.useContext(ActionsCtx);
1251
+ const ctx = React5.useContext(ActionsCtx);
805
1252
  if (!ctx)
806
1253
  throw new Error("useConsentActions must be used within ConsentProvider");
807
1254
  return ctx;
808
1255
  }
809
1256
  function useConsentTextsInternal() {
810
- const ctx = React3.useContext(TextsCtx);
1257
+ const ctx = React5.useContext(TextsCtx);
811
1258
  return ctx;
812
1259
  }
813
1260
  function useConsentHydrationInternal() {
814
- return React3.useContext(HydrationCtx);
1261
+ return React5.useContext(HydrationCtx);
815
1262
  }
816
- var React3, import_styles2, import_jsx_runtime4, PreferencesModal2, DEFAULT_PREFERENCES, DEFAULT_TEXTS, StateCtx, ActionsCtx, TextsCtx, HydrationCtx;
1263
+ var React5, import_jsx_runtime7, log, PreferencesModal, DEFAULT_TEXTS, StateCtx, ActionsCtx, TextsCtx, HydrationCtx;
817
1264
  var init_ConsentContext = __esm({
818
1265
  "src/context/ConsentContext.tsx"() {
819
1266
  "use strict";
820
- React3 = __toESM(require("react"), 1);
821
- import_styles2 = require("@mui/material/styles");
1267
+ React5 = __toESM(require("react"), 1);
1268
+ init_SafeThemeProvider();
822
1269
  init_cookieUtils();
1270
+ init_categoryUtils();
823
1271
  init_theme();
824
1272
  init_CategoriesContext();
1273
+ init_DesignContext();
825
1274
  init_developerGuidance();
826
- import_jsx_runtime4 = require("react/jsx-runtime");
827
- PreferencesModal2 = React3.lazy(
1275
+ init_useConsent();
1276
+ init_CookieBanner();
1277
+ init_FloatingPreferencesButton();
1278
+ import_jsx_runtime7 = require("react/jsx-runtime");
1279
+ log = {
1280
+ debug: (message, data) => {
1281
+ if (typeof window !== "undefined" && window.__REACT_DEVTOOLS_GLOBAL_HOOK__) {
1282
+ console.debug("[react-lgpd-consent] [DEBUG]", message, data);
1283
+ }
1284
+ },
1285
+ info: (message, data) => {
1286
+ if (typeof window !== "undefined" && window.__REACT_DEVTOOLS_GLOBAL_HOOK__) {
1287
+ console.info("[react-lgpd-consent] [INFO]", message, data);
1288
+ }
1289
+ }
1290
+ };
1291
+ PreferencesModal = React5.lazy(
828
1292
  () => Promise.resolve().then(() => (init_PreferencesModal(), PreferencesModal_exports)).then((m) => ({
829
1293
  default: m.PreferencesModal
830
1294
  }))
831
1295
  );
832
- DEFAULT_PREFERENCES = {
833
- necessary: true
834
- // Sempre ativo (essencial)
835
- };
836
1296
  DEFAULT_TEXTS = {
837
1297
  // Textos básicos
838
1298
  bannerMessage: "Utilizamos cookies para melhorar sua experi\xEAncia.",
@@ -844,7 +1304,15 @@ var init_ConsentContext = __esm({
844
1304
  modalIntro: "Ajuste as categorias de cookies. Cookies necess\xE1rios s\xE3o sempre utilizados para funcionalidades b\xE1sicas.",
845
1305
  save: "Salvar prefer\xEAncias",
846
1306
  necessaryAlwaysOn: "Cookies necess\xE1rios (sempre ativos)",
1307
+ // Textos adicionais para UI customizada
1308
+ preferencesButton: "Configurar Cookies",
1309
+ preferencesTitle: "Gerenciar Prefer\xEAncias de Cookies",
1310
+ preferencesDescription: "Escolha quais tipos de cookies voc\xEA permite que sejam utilizados.",
1311
+ close: "Fechar",
1312
+ accept: "Aceitar",
1313
+ reject: "Rejeitar",
847
1314
  // Textos ANPD expandidos (opcionais)
1315
+ brandingPoweredBy: "fornecido por",
848
1316
  controllerInfo: void 0,
849
1317
  // Exibido se definido
850
1318
  dataTypes: void 0,
@@ -862,10 +1330,10 @@ var init_ConsentContext = __esm({
862
1330
  transferCountries: void 0
863
1331
  // Exibido se definido
864
1332
  };
865
- StateCtx = React3.createContext(null);
866
- ActionsCtx = React3.createContext(null);
867
- TextsCtx = React3.createContext(DEFAULT_TEXTS);
868
- HydrationCtx = React3.createContext(false);
1333
+ StateCtx = React5.createContext(null);
1334
+ ActionsCtx = React5.createContext(null);
1335
+ TextsCtx = React5.createContext(DEFAULT_TEXTS);
1336
+ HydrationCtx = React5.createContext(false);
869
1337
  }
870
1338
  });
871
1339
 
@@ -892,10 +1360,137 @@ function useConsentTexts() {
892
1360
  function useConsentHydration() {
893
1361
  return useConsentHydrationInternal();
894
1362
  }
1363
+ function useOpenPreferencesModal() {
1364
+ const { openPreferences } = useConsent();
1365
+ return openPreferences;
1366
+ }
1367
+ function openPreferencesModal() {
1368
+ if (globalOpenPreferences) {
1369
+ globalOpenPreferences();
1370
+ } else {
1371
+ console.warn(
1372
+ "openPreferencesModal: ConsentProvider n\xE3o foi inicializado ou n\xE3o est\xE1 dispon\xEDvel."
1373
+ );
1374
+ }
1375
+ }
1376
+ function _registerGlobalOpenPreferences(openPreferences) {
1377
+ globalOpenPreferences = openPreferences;
1378
+ }
1379
+ function _unregisterGlobalOpenPreferences() {
1380
+ globalOpenPreferences = null;
1381
+ }
1382
+ var globalOpenPreferences;
895
1383
  var init_useConsent = __esm({
896
1384
  "src/hooks/useConsent.ts"() {
897
1385
  "use strict";
898
1386
  init_ConsentContext();
1387
+ globalOpenPreferences = null;
1388
+ }
1389
+ });
1390
+
1391
+ // src/components/PreferencesModal.tsx
1392
+ var PreferencesModal_exports = {};
1393
+ __export(PreferencesModal_exports, {
1394
+ PreferencesModal: () => PreferencesModal2
1395
+ });
1396
+ function PreferencesModal2({
1397
+ DialogProps: DialogProps2,
1398
+ hideBranding = false
1399
+ }) {
1400
+ const { preferences, setPreferences, closePreferences, isModalOpen } = useConsent();
1401
+ const texts = useConsentTexts();
1402
+ const { toggleableCategories } = useCategories();
1403
+ const [tempPreferences, setTempPreferences] = (0, import_react.useState)(
1404
+ () => {
1405
+ const initialPrefs = { necessary: true };
1406
+ toggleableCategories.forEach((category) => {
1407
+ initialPrefs[category.id] = preferences[category.id] ?? false;
1408
+ });
1409
+ return initialPrefs;
1410
+ }
1411
+ );
1412
+ (0, import_react.useEffect)(() => {
1413
+ if (isModalOpen) {
1414
+ const syncedPrefs = { necessary: true };
1415
+ toggleableCategories.forEach((category) => {
1416
+ syncedPrefs[category.id] = preferences[category.id] ?? false;
1417
+ });
1418
+ setTempPreferences(syncedPrefs);
1419
+ }
1420
+ }, [isModalOpen, preferences, toggleableCategories]);
1421
+ const open = DialogProps2?.open ?? isModalOpen ?? false;
1422
+ const handleSave = () => {
1423
+ setPreferences(tempPreferences);
1424
+ };
1425
+ const handleCancel = () => {
1426
+ setTempPreferences(preferences);
1427
+ closePreferences();
1428
+ };
1429
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1430
+ import_Dialog.default,
1431
+ {
1432
+ "aria-labelledby": "cookie-pref-title",
1433
+ open,
1434
+ onClose: handleCancel,
1435
+ ...DialogProps2,
1436
+ children: [
1437
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_DialogTitle.default, { id: "cookie-pref-title", children: texts.modalTitle }),
1438
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_DialogContent.default, { dividers: true, children: [
1439
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_Typography3.default, { variant: "body2", sx: { mb: 2 }, children: texts.modalIntro }),
1440
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_FormGroup.default, { children: [
1441
+ toggleableCategories.map((category) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1442
+ import_FormControlLabel.default,
1443
+ {
1444
+ control: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1445
+ import_Switch.default,
1446
+ {
1447
+ checked: tempPreferences[category.id] ?? false,
1448
+ onChange: (e) => setTempPreferences((prev) => ({
1449
+ ...prev,
1450
+ [category.id]: e.target.checked
1451
+ }))
1452
+ }
1453
+ ),
1454
+ label: `${category.name} - ${category.description}`
1455
+ },
1456
+ category.id
1457
+ )),
1458
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1459
+ import_FormControlLabel.default,
1460
+ {
1461
+ control: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_Switch.default, { checked: true, disabled: true }),
1462
+ label: texts.necessaryAlwaysOn
1463
+ }
1464
+ )
1465
+ ] })
1466
+ ] }),
1467
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_DialogActions.default, { children: [
1468
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_Button2.default, { variant: "outlined", onClick: handleCancel, children: texts.close }),
1469
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_Button2.default, { variant: "contained", onClick: handleSave, children: texts.save })
1470
+ ] }),
1471
+ !hideBranding && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Branding, { variant: "modal" })
1472
+ ]
1473
+ }
1474
+ );
1475
+ }
1476
+ var import_Button2, import_Dialog, import_DialogActions, import_DialogContent, import_DialogTitle, import_FormControlLabel, import_FormGroup, import_Switch, import_Typography3, import_react, import_jsx_runtime8;
1477
+ var init_PreferencesModal = __esm({
1478
+ "src/components/PreferencesModal.tsx"() {
1479
+ "use strict";
1480
+ import_Button2 = __toESM(require("@mui/material/Button"), 1);
1481
+ import_Dialog = __toESM(require("@mui/material/Dialog"), 1);
1482
+ import_DialogActions = __toESM(require("@mui/material/DialogActions"), 1);
1483
+ import_DialogContent = __toESM(require("@mui/material/DialogContent"), 1);
1484
+ import_DialogTitle = __toESM(require("@mui/material/DialogTitle"), 1);
1485
+ import_FormControlLabel = __toESM(require("@mui/material/FormControlLabel"), 1);
1486
+ import_FormGroup = __toESM(require("@mui/material/FormGroup"), 1);
1487
+ import_Switch = __toESM(require("@mui/material/Switch"), 1);
1488
+ import_Typography3 = __toESM(require("@mui/material/Typography"), 1);
1489
+ import_react = require("react");
1490
+ init_CategoriesContext();
1491
+ init_useConsent();
1492
+ init_Branding();
1493
+ import_jsx_runtime8 = require("react/jsx-runtime");
899
1494
  }
900
1495
  });
901
1496
 
@@ -906,208 +1501,38 @@ __export(index_exports, {
906
1501
  ConsentGate: () => ConsentGate,
907
1502
  ConsentProvider: () => ConsentProvider,
908
1503
  ConsentScriptLoader: () => ConsentScriptLoader,
909
- CookieBanner: () => CookieBanner,
910
1504
  DEFAULT_PROJECT_CATEGORIES: () => DEFAULT_PROJECT_CATEGORIES,
911
- FloatingPreferencesButton: () => FloatingPreferencesButton,
912
- PreferencesModal: () => PreferencesModal,
1505
+ LogLevel: () => LogLevel,
1506
+ PreferencesModal: () => PreferencesModal2,
913
1507
  analyzeDeveloperConfiguration: () => analyzeDeveloperConfiguration,
914
1508
  createGoogleAnalyticsIntegration: () => createGoogleAnalyticsIntegration,
915
1509
  createGoogleTagManagerIntegration: () => createGoogleTagManagerIntegration,
916
1510
  createUserWayIntegration: () => createUserWayIntegration,
917
1511
  defaultConsentTheme: () => defaultConsentTheme,
918
1512
  loadScript: () => loadScript,
1513
+ openPreferencesModal: () => openPreferencesModal,
1514
+ setDebugLogging: () => setDebugLogging,
919
1515
  useCategories: () => useCategories,
920
1516
  useCategoryStatus: () => useCategoryStatus,
921
1517
  useConsent: () => useConsent,
922
1518
  useConsentHydration: () => useConsentHydration,
923
1519
  useConsentScriptLoader: () => useConsentScriptLoader,
924
1520
  useConsentTexts: () => useConsentTexts,
925
- useCustomCategories: () => useCustomCategories
1521
+ useOpenPreferencesModal: () => useOpenPreferencesModal
926
1522
  });
927
1523
  module.exports = __toCommonJS(index_exports);
928
-
929
- // src/components/CookieBanner.tsx
930
- var import_Button2 = __toESM(require("@mui/material/Button"), 1);
931
- var import_Box = __toESM(require("@mui/material/Box"), 1);
932
- var import_Paper = __toESM(require("@mui/material/Paper"), 1);
933
- var import_Snackbar = __toESM(require("@mui/material/Snackbar"), 1);
934
- var import_Stack = __toESM(require("@mui/material/Stack"), 1);
935
- var import_Typography3 = __toESM(require("@mui/material/Typography"), 1);
936
- var import_Link2 = __toESM(require("@mui/material/Link"), 1);
937
- init_useConsent();
938
- init_Branding();
939
- var import_jsx_runtime5 = require("react/jsx-runtime");
940
- function CookieBanner({
941
- policyLinkUrl,
942
- debug,
943
- blocking = true,
944
- // Por padrão, bloqueia até decisão
945
- hideBranding = false,
946
- SnackbarProps,
947
- PaperProps
948
- }) {
949
- const { consented, acceptAll, rejectAll, openPreferences } = useConsent();
950
- const texts = useConsentTexts();
951
- const isHydrated = useConsentHydration();
952
- const open = debug ? true : isHydrated && !consented;
953
- if (!open) return null;
954
- const bannerContent = /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
955
- import_Paper.default,
956
- {
957
- elevation: 3,
958
- sx: { p: 2, maxWidth: 720, mx: "auto" },
959
- ...PaperProps,
960
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_Stack.default, { spacing: 1, children: [
961
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_Typography3.default, { variant: "body2", children: [
962
- texts.bannerMessage,
963
- " ",
964
- policyLinkUrl && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
965
- import_Link2.default,
966
- {
967
- href: policyLinkUrl,
968
- underline: "hover",
969
- target: "_blank",
970
- rel: "noopener noreferrer",
971
- children: texts.policyLink ?? "Saiba mais"
972
- }
973
- )
974
- ] }),
975
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
976
- import_Stack.default,
977
- {
978
- direction: { xs: "column", sm: "row" },
979
- spacing: 1,
980
- justifyContent: "flex-end",
981
- children: [
982
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_Button2.default, { variant: "outlined", onClick: rejectAll, children: texts.declineAll }),
983
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_Button2.default, { variant: "contained", onClick: acceptAll, children: texts.acceptAll }),
984
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_Button2.default, { variant: "text", onClick: openPreferences, children: texts.preferences })
985
- ]
986
- }
987
- ),
988
- !hideBranding && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Branding, { variant: "banner" })
989
- ] })
990
- }
991
- );
992
- if (blocking) {
993
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
994
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
995
- import_Box.default,
996
- {
997
- sx: {
998
- position: "fixed",
999
- top: 0,
1000
- left: 0,
1001
- right: 0,
1002
- bottom: 0,
1003
- backgroundColor: "rgba(0, 0, 0, 0.5)",
1004
- zIndex: 1299
1005
- // Abaixo do banner mas acima do conteúdo
1006
- }
1007
- }
1008
- ),
1009
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1010
- import_Box.default,
1011
- {
1012
- sx: {
1013
- position: "fixed",
1014
- bottom: 0,
1015
- left: 0,
1016
- right: 0,
1017
- zIndex: 1300,
1018
- // Acima do overlay
1019
- p: 2
1020
- },
1021
- children: bannerContent
1022
- }
1023
- )
1024
- ] });
1025
- }
1026
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1027
- import_Snackbar.default,
1028
- {
1029
- open,
1030
- anchorOrigin: { vertical: "bottom", horizontal: "center" },
1031
- ...SnackbarProps,
1032
- children: bannerContent
1033
- }
1034
- );
1035
- }
1036
-
1037
- // src/index.ts
1038
1524
  init_PreferencesModal();
1039
-
1040
- // src/components/FloatingPreferencesButton.tsx
1041
- var import_CookieOutlined = __toESM(require("@mui/icons-material/CookieOutlined"), 1);
1042
- var import_Fab = __toESM(require("@mui/material/Fab"), 1);
1043
- var import_Tooltip = __toESM(require("@mui/material/Tooltip"), 1);
1044
- var import_styles3 = require("@mui/material/styles");
1045
- init_useConsent();
1046
- var import_jsx_runtime6 = require("react/jsx-runtime");
1047
- function FloatingPreferencesButton({
1048
- position = "bottom-right",
1049
- offset = 24,
1050
- icon = /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_CookieOutlined.default, {}),
1051
- tooltip,
1052
- FabProps,
1053
- hideWhenConsented = false
1054
- }) {
1055
- const { openPreferences, consented } = useConsent();
1056
- const theme = (0, import_styles3.useTheme)();
1057
- if (hideWhenConsented && consented) {
1058
- return null;
1059
- }
1060
- const tooltipText = tooltip ?? "Gerenciar Prefer\xEAncias de Cookies";
1061
- const getPosition = () => {
1062
- const styles = {
1063
- position: "fixed",
1064
- zIndex: 1200
1065
- };
1066
- switch (position) {
1067
- case "bottom-left":
1068
- return { ...styles, bottom: offset, left: offset };
1069
- case "bottom-right":
1070
- return { ...styles, bottom: offset, right: offset };
1071
- case "top-left":
1072
- return { ...styles, top: offset, left: offset };
1073
- case "top-right":
1074
- return { ...styles, top: offset, right: offset };
1075
- default:
1076
- return { ...styles, bottom: offset, right: offset };
1077
- }
1078
- };
1079
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_Tooltip.default, { title: tooltipText, placement: "top", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1080
- import_Fab.default,
1081
- {
1082
- size: "medium",
1083
- color: "primary",
1084
- onClick: openPreferences,
1085
- sx: {
1086
- ...getPosition(),
1087
- backgroundColor: theme.palette.primary.main,
1088
- "&:hover": {
1089
- backgroundColor: theme.palette.primary.dark
1090
- }
1091
- },
1092
- "aria-label": tooltipText,
1093
- ...FabProps,
1094
- children: icon
1095
- }
1096
- ) });
1097
- }
1098
-
1099
- // src/index.ts
1100
1525
  init_ConsentContext();
1101
1526
  init_useConsent();
1102
1527
  init_CategoriesContext();
1103
1528
 
1104
1529
  // src/utils/ConsentGate.tsx
1105
1530
  init_useConsent();
1106
- var import_jsx_runtime7 = require("react/jsx-runtime");
1531
+ var import_jsx_runtime9 = require("react/jsx-runtime");
1107
1532
  function ConsentGate(props) {
1108
1533
  const { preferences } = useConsent();
1109
1534
  if (!preferences[props.category]) return null;
1110
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_jsx_runtime7.Fragment, { children: props.children });
1535
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_jsx_runtime9.Fragment, { children: props.children });
1111
1536
  }
1112
1537
 
1113
1538
  // src/utils/scriptLoader.ts
@@ -1151,15 +1576,15 @@ function loadScript(id, src, category = null, attrs = {}) {
1151
1576
  init_theme();
1152
1577
 
1153
1578
  // src/utils/ConsentScriptLoader.tsx
1154
- var React4 = __toESM(require("react"), 1);
1579
+ var React6 = __toESM(require("react"), 1);
1155
1580
  init_useConsent();
1156
1581
  function ConsentScriptLoader({
1157
1582
  integrations,
1158
1583
  reloadOnChange = false
1159
1584
  }) {
1160
1585
  const { preferences, consented } = useConsent();
1161
- const loadedScripts = React4.useRef(/* @__PURE__ */ new Set());
1162
- React4.useEffect(() => {
1586
+ const loadedScripts = React6.useRef(/* @__PURE__ */ new Set());
1587
+ React6.useEffect(() => {
1163
1588
  if (!consented) return;
1164
1589
  integrations.forEach(async (integration) => {
1165
1590
  const shouldLoad = preferences[integration.category];
@@ -1177,9 +1602,6 @@ function ConsentScriptLoader({
1177
1602
  integration.init();
1178
1603
  }
1179
1604
  loadedScripts.current.add(integration.id);
1180
- console.log(
1181
- `\u2705 Script loaded: ${integration.id} (${integration.category})`
1182
- );
1183
1605
  } catch (error) {
1184
1606
  console.error(`\u274C Failed to load script: ${integration.id}`, error);
1185
1607
  }
@@ -1190,7 +1612,7 @@ function ConsentScriptLoader({
1190
1612
  }
1191
1613
  function useConsentScriptLoader() {
1192
1614
  const { preferences, consented } = useConsent();
1193
- return React4.useCallback(
1615
+ return React6.useCallback(
1194
1616
  async (integration) => {
1195
1617
  if (!consented) {
1196
1618
  console.warn(
@@ -1216,9 +1638,6 @@ function useConsentScriptLoader() {
1216
1638
  if (integration.init) {
1217
1639
  integration.init();
1218
1640
  }
1219
- console.log(
1220
- `\u2705 Script loaded: ${integration.id} (${integration.category})`
1221
- );
1222
1641
  return true;
1223
1642
  } catch (error) {
1224
1643
  console.error(`\u274C Failed to load script: ${integration.id}`, error);
@@ -1270,8 +1689,8 @@ function createGoogleTagManagerIntegration(config) {
1270
1689
  function createUserWayIntegration(config) {
1271
1690
  return {
1272
1691
  id: "userway",
1273
- category: "marketing",
1274
- // ou poderia ser uma categoria 'accessibility'
1692
+ category: "functional",
1693
+ // Categoria mais apropriada para acessibilidade
1275
1694
  src: `https://cdn.userway.org/widget.js`,
1276
1695
  init: () => {
1277
1696
  if (typeof window !== "undefined") {
@@ -1290,15 +1709,15 @@ var COMMON_INTEGRATIONS = {
1290
1709
 
1291
1710
  // src/index.ts
1292
1711
  init_developerGuidance();
1712
+ init_logger();
1293
1713
  // Annotate the CommonJS export names for ESM import in node:
1294
1714
  0 && (module.exports = {
1295
1715
  COMMON_INTEGRATIONS,
1296
1716
  ConsentGate,
1297
1717
  ConsentProvider,
1298
1718
  ConsentScriptLoader,
1299
- CookieBanner,
1300
1719
  DEFAULT_PROJECT_CATEGORIES,
1301
- FloatingPreferencesButton,
1720
+ LogLevel,
1302
1721
  PreferencesModal,
1303
1722
  analyzeDeveloperConfiguration,
1304
1723
  createGoogleAnalyticsIntegration,
@@ -1306,11 +1725,13 @@ init_developerGuidance();
1306
1725
  createUserWayIntegration,
1307
1726
  defaultConsentTheme,
1308
1727
  loadScript,
1728
+ openPreferencesModal,
1729
+ setDebugLogging,
1309
1730
  useCategories,
1310
1731
  useCategoryStatus,
1311
1732
  useConsent,
1312
1733
  useConsentHydration,
1313
1734
  useConsentScriptLoader,
1314
1735
  useConsentTexts,
1315
- useCustomCategories
1736
+ useOpenPreferencesModal
1316
1737
  });