react-lgpd-consent 0.2.4 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -30,6 +30,208 @@ 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/developerGuidance.ts
34
+ function analyzeDeveloperConfiguration(config) {
35
+ const guidance = {
36
+ warnings: [],
37
+ suggestions: [],
38
+ activeCategoriesInfo: [],
39
+ usingDefaults: !config
40
+ };
41
+ const finalConfig = config || DEFAULT_PROJECT_CATEGORIES;
42
+ if (!config) {
43
+ guidance.warnings.push(
44
+ '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".'
45
+ );
46
+ }
47
+ guidance.activeCategoriesInfo.push({
48
+ id: "necessary",
49
+ name: "Cookies Necess\xE1rios",
50
+ description: "Essenciais para funcionamento b\xE1sico do site",
51
+ essential: true,
52
+ uiRequired: false
53
+ // Não precisa de toggle (sempre ativo)
54
+ });
55
+ const enabledCategories = finalConfig.enabledCategories || [];
56
+ const categoryNames = {
57
+ analytics: {
58
+ name: "Cookies Anal\xEDticos",
59
+ description: "Medem uso e performance do site"
60
+ },
61
+ functional: {
62
+ name: "Cookies Funcionais",
63
+ description: "Melhoram experi\xEAncia e funcionalidades"
64
+ },
65
+ marketing: {
66
+ name: "Cookies de Marketing",
67
+ description: "Publicidade direcionada e campanhas"
68
+ },
69
+ social: {
70
+ name: "Cookies de Redes Sociais",
71
+ description: "Integra\xE7\xE3o com plataformas sociais"
72
+ },
73
+ personalization: {
74
+ name: "Cookies de Personaliza\xE7\xE3o",
75
+ description: "Adaptam conte\xFAdo \xE0s prefer\xEAncias do usu\xE1rio"
76
+ }
77
+ };
78
+ enabledCategories.forEach((categoryId) => {
79
+ const categoryInfo = categoryNames[categoryId];
80
+ if (categoryInfo) {
81
+ guidance.activeCategoriesInfo.push({
82
+ id: categoryId,
83
+ name: categoryInfo.name,
84
+ description: categoryInfo.description,
85
+ essential: false,
86
+ uiRequired: true
87
+ // Precisa de toggle na UI
88
+ });
89
+ }
90
+ });
91
+ const totalToggleable = guidance.activeCategoriesInfo.filter(
92
+ (c) => c.uiRequired
93
+ ).length;
94
+ if (totalToggleable === 0) {
95
+ guidance.suggestions.push(
96
+ 'Apenas cookies necess\xE1rios est\xE3o configurados. Para compliance completo LGPD, considere adicionar categorias como "analytics" ou "functional" conforme uso real.'
97
+ );
98
+ }
99
+ if (totalToggleable > 5) {
100
+ guidance.warnings.push(
101
+ `${totalToggleable} categorias opcionais detectadas. UI com muitas op\xE7\xF5es pode ' +
102
+ 'prejudicar experi\xEAncia do usu\xE1rio. Considere agrupar categorias similares.`
103
+ );
104
+ }
105
+ return guidance;
106
+ }
107
+ function logDeveloperGuidance(guidance, disableGuidanceProp) {
108
+ if (disableGuidanceProp) {
109
+ return;
110
+ }
111
+ const isProduction = (
112
+ // 1. NODE_ENV de bundlers (Vite, webpack, etc.)
113
+ typeof globalThis.process !== "undefined" && globalThis.process.env?.NODE_ENV === "production" || // 2. Flag customizada para desabilitar logs
114
+ typeof globalThis !== "undefined" && globalThis.__LGPD_PRODUCTION__ === true || // 3. Flag de desenvolvimento desabilitada via window global (legado)
115
+ typeof window !== "undefined" && window.__LGPD_DISABLE_GUIDANCE__ === true
116
+ );
117
+ if (isProduction) return;
118
+ const PREFIX = "[\u{1F36A} LGPD-CONSENT]";
119
+ if (guidance.warnings.length > 0) {
120
+ console.group(`${PREFIX} \u26A0\uFE0F Avisos de Configura\xE7\xE3o`);
121
+ guidance.warnings.forEach((warning) => console.warn(`${PREFIX} ${warning}`));
122
+ console.groupEnd();
123
+ }
124
+ if (guidance.suggestions.length > 0) {
125
+ console.group(`${PREFIX} \u{1F4A1} Sugest\xF5es`);
126
+ guidance.suggestions.forEach(
127
+ (suggestion) => console.info(`${PREFIX} ${suggestion}`)
128
+ );
129
+ console.groupEnd();
130
+ }
131
+ if (guidance.usingDefaults) {
132
+ console.warn(
133
+ // Changed from console.info to console.warn
134
+ `${PREFIX} \u{1F4CB} Usando configura\xE7\xE3o padr\xE3o. Para personalizar, use a prop "categories" no ConsentProvider.`
135
+ );
136
+ }
137
+ console.group(`${PREFIX} \u{1F527} Categorias Ativas (para UI customizada)`);
138
+ console.table(
139
+ guidance.activeCategoriesInfo.map((cat) => ({
140
+ ID: cat.id,
141
+ Nome: cat.name,
142
+ "Toggle UI?": cat.uiRequired ? "\u2705 SIM" : "\u274C N\xC3O (sempre ativo)",
143
+ "Essencial?": cat.essential ? "\u{1F512} SIM" : "\u2699\uFE0F N\xC3O"
144
+ }))
145
+ );
146
+ console.info(
147
+ `${PREFIX} \u2139\uFE0F Use estes dados para criar componentes customizados adequados.`
148
+ );
149
+ console.groupEnd();
150
+ }
151
+ function useDeveloperGuidance(config, disableGuidanceProp) {
152
+ const guidance = analyzeDeveloperConfiguration(config);
153
+ const stringifiedConfig = React.useMemo(
154
+ () => JSON.stringify(config),
155
+ [config]
156
+ );
157
+ React.useEffect(() => {
158
+ if (disableGuidanceProp === true) {
159
+ return;
160
+ }
161
+ logDeveloperGuidance(guidance, disableGuidanceProp);
162
+ }, [guidance, stringifiedConfig, disableGuidanceProp]);
163
+ return guidance;
164
+ }
165
+ var React, DEFAULT_PROJECT_CATEGORIES;
166
+ var init_developerGuidance = __esm({
167
+ "src/utils/developerGuidance.ts"() {
168
+ "use strict";
169
+ React = __toESM(require("react"), 1);
170
+ DEFAULT_PROJECT_CATEGORIES = {
171
+ enabledCategories: ["analytics"]
172
+ // Só analytics além de necessary
173
+ };
174
+ }
175
+ });
176
+
177
+ // src/context/CategoriesContext.tsx
178
+ function CategoriesProvider({
179
+ children,
180
+ config,
181
+ // NOVO: configuração completa
182
+ disableDeveloperGuidance
183
+ }) {
184
+ const contextValue = React2.useMemo(() => {
185
+ const finalConfig = config || DEFAULT_PROJECT_CATEGORIES;
186
+ const guidance = analyzeDeveloperConfiguration(config);
187
+ const toggleableCategories = guidance.activeCategoriesInfo.filter(
188
+ (cat) => cat.uiRequired
189
+ );
190
+ return {
191
+ config: finalConfig,
192
+ guidance,
193
+ toggleableCategories,
194
+ allCategories: guidance.activeCategoriesInfo
195
+ };
196
+ }, [config]);
197
+ React2.useEffect(() => {
198
+ logDeveloperGuidance(contextValue.guidance, disableDeveloperGuidance);
199
+ }, [contextValue.guidance, disableDeveloperGuidance]);
200
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CategoriesContext.Provider, { value: contextValue, children });
201
+ }
202
+ function useCategories() {
203
+ const context = React2.useContext(CategoriesContext);
204
+ if (!context) {
205
+ throw new Error(
206
+ "useCategories deve ser usado dentro de CategoriesProvider. Certifique-se de que o ConsentProvider est\xE1 envolvendo seu componente."
207
+ );
208
+ }
209
+ return context;
210
+ }
211
+ function useCategoryStatus(categoryId) {
212
+ const { allCategories } = useCategories();
213
+ const category = allCategories.find((cat) => cat.id === categoryId);
214
+ return {
215
+ isActive: !!category,
216
+ isEssential: category?.essential || false,
217
+ needsToggle: category?.uiRequired || false,
218
+ name: category?.name,
219
+ description: category?.description
220
+ };
221
+ }
222
+ var React2, import_jsx_runtime, CategoriesContext;
223
+ var init_CategoriesContext = __esm({
224
+ "src/context/CategoriesContext.tsx"() {
225
+ "use strict";
226
+ React2 = __toESM(require("react"), 1);
227
+ init_developerGuidance();
228
+ import_jsx_runtime = require("react/jsx-runtime");
229
+ CategoriesContext = React2.createContext(
230
+ null
231
+ );
232
+ }
233
+ });
234
+
33
235
  // src/utils/cookieUtils.ts
34
236
  function readConsentCookie(name = DEFAULT_COOKIE_OPTS.name) {
35
237
  if (typeof document === "undefined") return null;
@@ -70,7 +272,7 @@ function migrateLegacyCookie(legacyData) {
70
272
  return null;
71
273
  }
72
274
  }
73
- function writeConsentCookie(state, source = "banner", opts) {
275
+ function writeConsentCookie(state, config, opts, source = "banner") {
74
276
  if (typeof document === "undefined") return;
75
277
  const now = (/* @__PURE__ */ new Date()).toISOString();
76
278
  const o = { ...DEFAULT_COOKIE_OPTS, ...opts };
@@ -81,7 +283,8 @@ function writeConsentCookie(state, source = "banner", opts) {
81
283
  consentDate: state.consentDate || now,
82
284
  // Preservar data original ou usar atual
83
285
  lastUpdate: now,
84
- source
286
+ source,
287
+ projectConfig: config
85
288
  // isModalOpen NÃO é persistido (campo de UI apenas)
86
289
  };
87
290
  import_js_cookie.default.set(o.name, JSON.stringify(cookieData), {
@@ -112,6 +315,39 @@ var init_cookieUtils = __esm({
112
315
  }
113
316
  });
114
317
 
318
+ // src/utils/categoryUtils.ts
319
+ function createProjectPreferences(config, defaultValue = false) {
320
+ const preferences = {
321
+ necessary: true
322
+ // Sempre presente e true (essencial)
323
+ };
324
+ const enabledCategories = config?.enabledCategories || [];
325
+ enabledCategories.forEach((category) => {
326
+ if (category !== "necessary") {
327
+ preferences[category] = defaultValue;
328
+ }
329
+ });
330
+ return preferences;
331
+ }
332
+ function validateProjectPreferences(preferences, config) {
333
+ const validPreferences = {
334
+ necessary: true
335
+ // Sempre válida
336
+ };
337
+ const enabledCategories = config?.enabledCategories || [];
338
+ enabledCategories.forEach((category) => {
339
+ if (category !== "necessary" && preferences[category] !== void 0) {
340
+ validPreferences[category] = preferences[category];
341
+ }
342
+ });
343
+ return validPreferences;
344
+ }
345
+ var init_categoryUtils = __esm({
346
+ "src/utils/categoryUtils.ts"() {
347
+ "use strict";
348
+ }
349
+ });
350
+
115
351
  // src/utils/theme.ts
116
352
  var import_styles, defaultConsentTheme;
117
353
  var init_theme = __esm({
@@ -186,300 +422,81 @@ var init_theme = __esm({
186
422
  }
187
423
  });
188
424
 
189
- // src/utils/developerGuidance.ts
190
- function analyzeDeveloperConfiguration(config) {
191
- const guidance = {
192
- warnings: [],
193
- suggestions: [],
194
- activeCategoriesInfo: [],
195
- usingDefaults: !config
196
- };
197
- const finalConfig = config || DEFAULT_PROJECT_CATEGORIES;
198
- if (!config) {
199
- guidance.warnings.push(
200
- 'LGPD-CONSENT: Nenhuma configura\xE7\xE3o de categorias especificada. Usando padr\xE3o: necessary + analytics. Para produ\xE7\xE3o, recomenda-se especificar explicitamente as categorias via prop "categories".'
201
- );
425
+ // src/context/DesignContext.tsx
426
+ function DesignProvider({
427
+ tokens,
428
+ children
429
+ }) {
430
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(DesignContext.Provider, { value: tokens, children });
431
+ }
432
+ function useDesignTokens() {
433
+ return React3.useContext(DesignContext);
434
+ }
435
+ var React3, import_jsx_runtime2, DesignContext;
436
+ var init_DesignContext = __esm({
437
+ "src/context/DesignContext.tsx"() {
438
+ "use strict";
439
+ React3 = __toESM(require("react"), 1);
440
+ import_jsx_runtime2 = require("react/jsx-runtime");
441
+ DesignContext = React3.createContext(void 0);
202
442
  }
203
- guidance.activeCategoriesInfo.push({
204
- id: "necessary",
205
- name: "Cookies Necess\xE1rios",
206
- description: "Essenciais para funcionamento b\xE1sico do site",
207
- essential: true,
208
- uiRequired: false
209
- // Não precisa de toggle (sempre ativo)
210
- });
211
- const enabledCategories = finalConfig.enabledCategories || [];
212
- const categoryNames = {
213
- analytics: {
214
- name: "Cookies Anal\xEDticos",
215
- description: "Medem uso e performance do site"
216
- },
217
- functional: {
218
- name: "Cookies Funcionais",
219
- description: "Melhoram experi\xEAncia e funcionalidades"
220
- },
221
- marketing: {
222
- name: "Cookies de Marketing",
223
- description: "Publicidade direcionada e campanhas"
224
- },
225
- social: {
226
- name: "Cookies de Redes Sociais",
227
- description: "Integra\xE7\xE3o com plataformas sociais"
228
- },
229
- personalization: {
230
- name: "Cookies de Personaliza\xE7\xE3o",
231
- description: "Adaptam conte\xFAdo \xE0s prefer\xEAncias do usu\xE1rio"
443
+ });
444
+
445
+ // src/components/Branding.tsx
446
+ function Branding({ variant, hidden = false }) {
447
+ if (hidden) return null;
448
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
449
+ import_Typography.default,
450
+ {
451
+ variant: "caption",
452
+ sx: (theme) => ({
453
+ ...brandingStyles[variant],
454
+ color: theme.palette.text.secondary
455
+ }),
456
+ children: [
457
+ "fornecido por",
458
+ " ",
459
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
460
+ import_Link.default,
461
+ {
462
+ href: "https://www.ledipo.eti.br",
463
+ target: "_blank",
464
+ rel: "noopener noreferrer",
465
+ sx: (theme) => ({
466
+ ...linkStyles,
467
+ color: theme.palette.primary.main
468
+ }),
469
+ children: "L\xC9dipO.eti.br"
470
+ }
471
+ )
472
+ ]
232
473
  }
233
- };
234
- enabledCategories.forEach((categoryId) => {
235
- const categoryInfo = categoryNames[categoryId];
236
- if (categoryInfo) {
237
- guidance.activeCategoriesInfo.push({
238
- id: categoryId,
239
- name: categoryInfo.name,
240
- description: categoryInfo.description,
241
- essential: false,
242
- uiRequired: true
243
- // Precisa de toggle na UI
244
- });
245
- }
246
- });
247
- const customCategories = finalConfig.customCategories || [];
248
- customCategories.forEach((category) => {
249
- guidance.activeCategoriesInfo.push({
250
- id: category.id,
251
- name: category.name,
252
- description: category.description,
253
- essential: category.essential === true,
254
- uiRequired: category.essential !== true
255
- // Apenas não-essenciais precisam toggle
256
- });
257
- });
258
- const totalToggleable = guidance.activeCategoriesInfo.filter(
259
- (c) => c.uiRequired
260
- ).length;
261
- if (totalToggleable === 0) {
262
- guidance.suggestions.push(
263
- 'Apenas cookies necess\xE1rios est\xE3o configurados. Para compliance completo LGPD, considere adicionar categorias como "analytics" ou "functional" conforme uso real.'
264
- );
265
- }
266
- if (totalToggleable > 5) {
267
- guidance.warnings.push(
268
- `${totalToggleable} categorias opcionais detectadas. UI com muitas op\xE7\xF5es pode ' +
269
- 'prejudicar experi\xEAncia do usu\xE1rio. Considere agrupar categorias similares.`
270
- );
271
- }
272
- const poorDescriptions = customCategories.filter(
273
- (c) => !c.description || c.description.length < 10
274
474
  );
275
- if (poorDescriptions.length > 0) {
276
- guidance.warnings.push(
277
- `Categorias customizadas com descri\xE7\xF5es inadequadas: ${poorDescriptions.map((c) => c.id).join(", ")}. Descri\xE7\xF5es claras s\xE3o obrigat\xF3rias para compliance LGPD.`
278
- );
279
- }
280
- return guidance;
281
475
  }
282
- function logDeveloperGuidance(guidance, disableGuidanceProp) {
283
- try {
284
- const isProduction = (
285
- // 1. NODE_ENV de bundlers (Vite, webpack, etc.)
286
- typeof globalThis.process !== "undefined" && globalThis.process.env?.NODE_ENV === "production" || // 2. Vite/bundler env vars (apenas em ESM)
287
- typeof globalThis !== "undefined" && typeof globalThis.import !== "undefined" && globalThis.import.meta?.env?.PROD === true || // 3. Flag customizada para desabilitar logs
288
- typeof globalThis !== "undefined" && globalThis.__LGPD_PRODUCTION__ || // 4. Flag de desenvolvimento desabilitada via window global (legado)
289
- typeof window !== "undefined" && window.__LGPD_DISABLE_GUIDANCE__ || // 5. Flag de desenvolvimento desabilitada via prop do ConsentProvider (preferencial)
290
- disableGuidanceProp
291
- );
292
- if (isProduction) return;
293
- const PREFIX = "[\u{1F36A} LGPD-CONSENT]";
294
- if (guidance.warnings.length > 0) {
295
- console.group(`${PREFIX} \u26A0\uFE0F Avisos de Configura\xE7\xE3o`);
296
- guidance.warnings.forEach(
297
- (warning) => console.warn(`${PREFIX} ${warning}`)
298
- );
299
- console.groupEnd();
300
- }
301
- if (guidance.suggestions.length > 0) {
302
- console.group(`${PREFIX} \u{1F4A1} Sugest\xF5es`);
303
- guidance.suggestions.forEach(
304
- (suggestion) => console.info(`${PREFIX} ${suggestion}`)
305
- );
306
- console.groupEnd();
307
- }
308
- if (guidance.usingDefaults) {
309
- console.info(
310
- `${PREFIX} \u{1F4CB} Usando configura\xE7\xE3o padr\xE3o. Para personalizar, use a prop "categories" no ConsentProvider.`
311
- );
312
- }
313
- console.group(`${PREFIX} \u{1F527} Categorias Ativas (para UI customizada)`);
314
- console.table(
315
- guidance.activeCategoriesInfo.map((cat) => ({
316
- ID: cat.id,
317
- Nome: cat.name,
318
- "Toggle UI?": cat.uiRequired ? "\u2705 SIM" : "\u274C N\xC3O (sempre ativo)",
319
- "Essencial?": cat.essential ? "\u{1F512} SIM" : "\u2699\uFE0F N\xC3O"
320
- }))
321
- );
322
- console.info(
323
- `${PREFIX} \u2139\uFE0F Use estes dados para criar componentes customizados adequados.`
324
- );
325
- console.groupEnd();
326
- } catch (error) {
327
- if (typeof console !== "undefined" && console.warn) {
328
- console.warn(
329
- "[\u{1F36A} LGPD-CONSENT] Sistema de orienta\xE7\xF5es encontrou erro:",
330
- error
331
- );
332
- }
333
- }
334
- }
335
- function useDeveloperGuidance(config, disableGuidanceProp) {
336
- const guidance = analyzeDeveloperConfiguration(config);
337
- const stringifiedConfig = React.useMemo(() => JSON.stringify(config), [config]);
338
- React.useEffect(() => {
339
- logDeveloperGuidance(guidance, disableGuidanceProp);
340
- }, [guidance, stringifiedConfig, disableGuidanceProp]);
341
- return guidance;
342
- }
343
- var React, DEFAULT_PROJECT_CATEGORIES;
344
- var init_developerGuidance = __esm({
345
- "src/utils/developerGuidance.ts"() {
346
- "use strict";
347
- React = __toESM(require("react"), 1);
348
- DEFAULT_PROJECT_CATEGORIES = {
349
- enabledCategories: ["analytics"],
350
- // Só analytics além de necessary
351
- customCategories: []
352
- };
353
- }
354
- });
355
-
356
- // src/context/CategoriesContext.tsx
357
- function CategoriesProvider({
358
- children,
359
- categories,
360
- // LEGACY: prop antiga (apenas customCategories)
361
- config
362
- // NOVO: configuração completa
363
- }) {
364
- const contextValue = React2.useMemo(() => {
365
- let finalConfig;
366
- if (categories && !config) {
367
- finalConfig = {
368
- enabledCategories: DEFAULT_PROJECT_CATEGORIES.enabledCategories,
369
- customCategories: categories
370
- };
371
- } else {
372
- finalConfig = config || DEFAULT_PROJECT_CATEGORIES;
373
- }
374
- const guidance = analyzeDeveloperConfiguration(
375
- config || (categories ? { customCategories: categories } : void 0)
376
- );
377
- const toggleableCategories = guidance.activeCategoriesInfo.filter(
378
- (cat) => cat.uiRequired
379
- );
380
- return {
381
- config: finalConfig,
382
- guidance,
383
- toggleableCategories,
384
- allCategories: guidance.activeCategoriesInfo,
385
- legacyCategories: categories || []
386
- };
387
- }, [config, categories]);
388
- React2.useEffect(() => {
389
- logDeveloperGuidance(contextValue.guidance);
390
- }, [contextValue.guidance]);
391
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CategoriesContext.Provider, { value: contextValue, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CategoriesCtx.Provider, { value: contextValue.legacyCategories, children }) });
392
- }
393
- function useCategories() {
394
- const context = React2.useContext(CategoriesContext);
395
- if (!context) {
396
- throw new Error(
397
- "useCategories deve ser usado dentro de CategoriesProvider. Certifique-se de que o ConsentProvider est\xE1 envolvendo seu componente."
398
- );
399
- }
400
- return context;
401
- }
402
- function useCategoryStatus(categoryId) {
403
- const { allCategories } = useCategories();
404
- const category = allCategories.find((cat) => cat.id === categoryId);
405
- return {
406
- isActive: !!category,
407
- isEssential: category?.essential || false,
408
- needsToggle: category?.uiRequired || false,
409
- name: category?.name,
410
- description: category?.description
411
- };
412
- }
413
- function useCustomCategories() {
414
- return React2.useContext(CategoriesCtx);
415
- }
416
- var React2, import_jsx_runtime, CategoriesContext, CategoriesCtx;
417
- var init_CategoriesContext = __esm({
418
- "src/context/CategoriesContext.tsx"() {
419
- "use strict";
420
- React2 = __toESM(require("react"), 1);
421
- init_developerGuidance();
422
- import_jsx_runtime = require("react/jsx-runtime");
423
- CategoriesContext = React2.createContext(
424
- null
425
- );
426
- CategoriesCtx = React2.createContext([]);
427
- }
428
- });
429
-
430
- // src/components/Branding.tsx
431
- function Branding({ variant, hidden = false }) {
432
- if (hidden) return null;
433
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
434
- import_Typography.default,
435
- {
436
- variant: "caption",
437
- sx: (theme) => ({
438
- ...brandingStyles[variant],
439
- color: theme.palette.text.secondary
440
- }),
441
- children: [
442
- "fornecido por",
443
- " ",
444
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
445
- import_Link.default,
446
- {
447
- href: "https://www.ledipo.eti.br",
448
- target: "_blank",
449
- rel: "noopener noreferrer",
450
- sx: (theme) => ({
451
- ...linkStyles,
452
- color: theme.palette.primary.main
453
- }),
454
- children: "L\xC9dipO.eti.br"
455
- }
456
- )
457
- ]
458
- }
459
- );
460
- }
461
- var import_Link, import_Typography, import_jsx_runtime2, brandingStyles, linkStyles;
476
+ var import_Link, import_Typography, import_jsx_runtime3, brandingStyles, linkStyles;
462
477
  var init_Branding = __esm({
463
478
  "src/components/Branding.tsx"() {
464
479
  "use strict";
465
480
  import_Link = __toESM(require("@mui/material/Link"), 1);
466
481
  import_Typography = __toESM(require("@mui/material/Typography"), 1);
467
- import_jsx_runtime2 = require("react/jsx-runtime");
482
+ import_jsx_runtime3 = require("react/jsx-runtime");
468
483
  brandingStyles = {
469
484
  banner: {
470
485
  fontSize: "0.65rem",
471
- textAlign: "center",
486
+ textAlign: "right",
472
487
  mt: 1,
473
488
  opacity: 0.7,
474
- fontStyle: "italic"
489
+ fontStyle: "italic",
490
+ width: "100%"
475
491
  },
476
492
  modal: {
477
493
  fontSize: "0.65rem",
478
- textAlign: "center",
494
+ textAlign: "right",
479
495
  px: 3,
480
496
  pb: 1,
481
497
  opacity: 0.7,
482
- fontStyle: "italic"
498
+ fontStyle: "italic",
499
+ width: "100%"
483
500
  }
484
501
  };
485
502
  linkStyles = {
@@ -492,123 +509,218 @@ var init_Branding = __esm({
492
509
  }
493
510
  });
494
511
 
495
- // src/components/PreferencesModal.tsx
496
- var PreferencesModal_exports = {};
497
- __export(PreferencesModal_exports, {
498
- PreferencesModal: () => PreferencesModal
499
- });
500
- function PreferencesModal({
501
- DialogProps: DialogProps2,
502
- hideBranding = false
512
+ // src/components/CookieBanner.tsx
513
+ function CookieBanner({
514
+ policyLinkUrl,
515
+ debug,
516
+ blocking = true,
517
+ hideBranding = false,
518
+ SnackbarProps,
519
+ PaperProps
503
520
  }) {
504
- const { preferences, setPreferences, closePreferences, isModalOpen } = useConsent();
521
+ const { consented, acceptAll, rejectAll, openPreferences } = useConsent();
505
522
  const texts = useConsentTexts();
506
- const { toggleableCategories } = useCategories();
507
- const [tempPreferences, setTempPreferences] = (0, import_react.useState)(
508
- () => {
509
- const initialPrefs = { necessary: true };
510
- toggleableCategories.forEach((category) => {
511
- initialPrefs[category.id] = preferences[category.id] ?? false;
512
- });
513
- return initialPrefs;
514
- }
515
- );
516
- (0, import_react.useEffect)(() => {
517
- if (isModalOpen) {
518
- const syncedPrefs = { necessary: true };
519
- toggleableCategories.forEach((category) => {
520
- syncedPrefs[category.id] = preferences[category.id] ?? false;
521
- });
522
- setTempPreferences(syncedPrefs);
523
- }
524
- }, [isModalOpen, preferences, toggleableCategories]);
525
- const open = DialogProps2?.open ?? isModalOpen ?? false;
526
- const handleSave = () => {
527
- setPreferences(tempPreferences);
523
+ const isHydrated = useConsentHydration();
524
+ const designTokens = useDesignTokens();
525
+ const open = debug ? true : isHydrated && !consented;
526
+ if (!open) return null;
527
+ const bannerStyle = {
528
+ p: designTokens?.spacing?.padding?.banner ?? 2,
529
+ maxWidth: 720,
530
+ mx: "auto",
531
+ backgroundColor: designTokens?.colors?.background,
532
+ color: designTokens?.colors?.text,
533
+ borderRadius: designTokens?.spacing?.borderRadius?.banner,
534
+ fontFamily: designTokens?.typography?.fontFamily
528
535
  };
529
- const handleCancel = () => {
530
- setTempPreferences(preferences);
531
- closePreferences();
536
+ const bannerContent = /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_Paper.default, { elevation: 3, sx: bannerStyle, ...PaperProps, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_Stack.default, { spacing: 1, children: [
537
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
538
+ import_Typography2.default,
539
+ {
540
+ variant: "body2",
541
+ sx: { fontSize: designTokens?.typography?.fontSize?.banner },
542
+ children: [
543
+ texts.bannerMessage,
544
+ " ",
545
+ policyLinkUrl && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
546
+ import_Link2.default,
547
+ {
548
+ href: policyLinkUrl,
549
+ underline: "hover",
550
+ target: "_blank",
551
+ rel: "noopener noreferrer",
552
+ sx: { color: designTokens?.colors?.primary },
553
+ children: texts.policyLink ?? "Saiba mais"
554
+ }
555
+ )
556
+ ]
557
+ }
558
+ ),
559
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
560
+ import_Stack.default,
561
+ {
562
+ direction: { xs: "column", sm: "row" },
563
+ spacing: 1,
564
+ justifyContent: "flex-end",
565
+ children: [
566
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
567
+ import_Button.default,
568
+ {
569
+ variant: "outlined",
570
+ onClick: rejectAll,
571
+ sx: { color: designTokens?.colors?.secondary },
572
+ children: texts.declineAll
573
+ }
574
+ ),
575
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
576
+ import_Button.default,
577
+ {
578
+ variant: "contained",
579
+ onClick: acceptAll,
580
+ sx: { backgroundColor: designTokens?.colors?.primary },
581
+ children: texts.acceptAll
582
+ }
583
+ ),
584
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
585
+ import_Button.default,
586
+ {
587
+ variant: "text",
588
+ onClick: openPreferences,
589
+ sx: { color: designTokens?.colors?.text },
590
+ children: texts.preferences
591
+ }
592
+ )
593
+ ]
594
+ }
595
+ ),
596
+ !hideBranding && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Branding, { variant: "banner" })
597
+ ] }) });
598
+ const positionStyle = {
599
+ position: "fixed",
600
+ zIndex: 1300,
601
+ ...designTokens?.layout?.position === "top" ? { top: 0 } : { bottom: 0 },
602
+ left: 0,
603
+ right: 0,
604
+ width: designTokens?.layout?.width?.desktop ?? "100%",
605
+ p: 2
532
606
  };
533
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
534
- import_Dialog.default,
607
+ if (blocking) {
608
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
609
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
610
+ import_Box.default,
611
+ {
612
+ sx: {
613
+ position: "fixed",
614
+ top: 0,
615
+ left: 0,
616
+ right: 0,
617
+ bottom: 0,
618
+ backgroundColor: designTokens?.layout?.backdrop ? "rgba(0, 0, 0, 0.5)" : "transparent",
619
+ zIndex: 1299
620
+ }
621
+ }
622
+ ),
623
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_Box.default, { sx: positionStyle, children: bannerContent })
624
+ ] });
625
+ }
626
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
627
+ import_Snackbar.default,
535
628
  {
536
- "aria-labelledby": "cookie-pref-title",
537
629
  open,
538
- onClose: handleCancel,
539
- ...DialogProps2,
540
- children: [
541
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_DialogTitle.default, { id: "cookie-pref-title", children: texts.modalTitle }),
542
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_DialogContent.default, { dividers: true, children: [
543
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_Typography2.default, { variant: "body2", sx: { mb: 2 }, children: texts.modalIntro }),
544
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_FormGroup.default, { children: [
545
- toggleableCategories.map((category) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
546
- import_FormControlLabel.default,
547
- {
548
- control: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
549
- import_Switch.default,
550
- {
551
- checked: tempPreferences[category.id] ?? false,
552
- onChange: (e) => setTempPreferences((prev) => ({
553
- ...prev,
554
- [category.id]: e.target.checked
555
- }))
556
- }
557
- ),
558
- label: `${category.name} - ${category.description}`
559
- },
560
- category.id
561
- )),
562
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
563
- import_FormControlLabel.default,
564
- {
565
- control: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_Switch.default, { checked: true, disabled: true }),
566
- label: texts.necessaryAlwaysOn
567
- }
568
- )
569
- ] })
570
- ] }),
571
- !hideBranding && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Branding, { variant: "modal" }),
572
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_DialogActions.default, { children: [
573
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_Button.default, { variant: "outlined", onClick: handleCancel, children: "Cancelar" }),
574
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_Button.default, { variant: "contained", onClick: handleSave, children: texts.save })
575
- ] })
576
- ]
630
+ anchorOrigin: {
631
+ vertical: designTokens?.layout?.position === "top" ? "top" : "bottom",
632
+ horizontal: "center"
633
+ },
634
+ ...SnackbarProps,
635
+ children: bannerContent
577
636
  }
578
637
  );
579
638
  }
580
- var import_Button, import_Dialog, import_DialogActions, import_DialogContent, import_DialogTitle, import_FormControlLabel, import_FormGroup, import_Switch, import_Typography2, import_react, import_jsx_runtime3;
581
- var init_PreferencesModal = __esm({
582
- "src/components/PreferencesModal.tsx"() {
639
+ var import_Button, import_Box, import_Paper, import_Snackbar, import_Stack, import_Typography2, import_Link2, import_jsx_runtime4;
640
+ var init_CookieBanner = __esm({
641
+ "src/components/CookieBanner.tsx"() {
583
642
  "use strict";
584
643
  import_Button = __toESM(require("@mui/material/Button"), 1);
585
- import_Dialog = __toESM(require("@mui/material/Dialog"), 1);
586
- import_DialogActions = __toESM(require("@mui/material/DialogActions"), 1);
587
- import_DialogContent = __toESM(require("@mui/material/DialogContent"), 1);
588
- import_DialogTitle = __toESM(require("@mui/material/DialogTitle"), 1);
589
- import_FormControlLabel = __toESM(require("@mui/material/FormControlLabel"), 1);
590
- import_FormGroup = __toESM(require("@mui/material/FormGroup"), 1);
591
- import_Switch = __toESM(require("@mui/material/Switch"), 1);
644
+ import_Box = __toESM(require("@mui/material/Box"), 1);
645
+ import_Paper = __toESM(require("@mui/material/Paper"), 1);
646
+ import_Snackbar = __toESM(require("@mui/material/Snackbar"), 1);
647
+ import_Stack = __toESM(require("@mui/material/Stack"), 1);
592
648
  import_Typography2 = __toESM(require("@mui/material/Typography"), 1);
593
- import_react = require("react");
594
- init_CategoriesContext();
649
+ import_Link2 = __toESM(require("@mui/material/Link"), 1);
650
+ init_useConsent();
651
+ init_DesignContext();
652
+ init_Branding();
653
+ import_jsx_runtime4 = require("react/jsx-runtime");
654
+ }
655
+ });
656
+
657
+ // src/components/FloatingPreferencesButton.tsx
658
+ function FloatingPreferencesButton({
659
+ position = "bottom-right",
660
+ offset = 24,
661
+ icon = /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_CookieOutlined.default, {}),
662
+ tooltip,
663
+ FabProps,
664
+ hideWhenConsented = false
665
+ }) {
666
+ const { openPreferences, consented } = useConsent();
667
+ const theme = (0, import_styles2.useTheme)();
668
+ if (hideWhenConsented && consented) {
669
+ return null;
670
+ }
671
+ const tooltipText = tooltip ?? "Gerenciar Prefer\xEAncias de Cookies";
672
+ const getPosition = () => {
673
+ const styles = {
674
+ position: "fixed",
675
+ zIndex: 1200
676
+ };
677
+ switch (position) {
678
+ case "bottom-left":
679
+ return { ...styles, bottom: offset, left: offset };
680
+ case "bottom-right":
681
+ return { ...styles, bottom: offset, right: offset };
682
+ case "top-left":
683
+ return { ...styles, top: offset, left: offset };
684
+ case "top-right":
685
+ return { ...styles, top: offset, right: offset };
686
+ default:
687
+ return { ...styles, bottom: offset, right: offset };
688
+ }
689
+ };
690
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_Tooltip.default, { title: tooltipText, placement: "top", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
691
+ import_Fab.default,
692
+ {
693
+ size: "medium",
694
+ color: "primary",
695
+ onClick: openPreferences,
696
+ sx: {
697
+ ...getPosition(),
698
+ backgroundColor: theme.palette.primary.main,
699
+ "&:hover": {
700
+ backgroundColor: theme.palette.primary.dark
701
+ }
702
+ },
703
+ "aria-label": tooltipText,
704
+ ...FabProps,
705
+ children: icon
706
+ }
707
+ ) });
708
+ }
709
+ var import_CookieOutlined, import_Fab, import_Tooltip, import_styles2, import_jsx_runtime5;
710
+ var init_FloatingPreferencesButton = __esm({
711
+ "src/components/FloatingPreferencesButton.tsx"() {
712
+ "use strict";
713
+ import_CookieOutlined = __toESM(require("@mui/icons-material/CookieOutlined"), 1);
714
+ import_Fab = __toESM(require("@mui/material/Fab"), 1);
715
+ import_Tooltip = __toESM(require("@mui/material/Tooltip"), 1);
716
+ import_styles2 = require("@mui/material/styles");
595
717
  init_useConsent();
596
- init_Branding();
597
- import_jsx_runtime3 = require("react/jsx-runtime");
718
+ import_jsx_runtime5 = require("react/jsx-runtime");
598
719
  }
599
720
  });
600
721
 
601
722
  // src/context/ConsentContext.tsx
602
- function createInitialPreferences(customCategories) {
603
- const prefs = { ...DEFAULT_PREFERENCES };
604
- if (customCategories) {
605
- customCategories.forEach((category) => {
606
- prefs[category.id] = category.essential === true;
607
- });
608
- }
609
- return prefs;
610
- }
611
- function createFullConsentState(consented, preferences, source, isModalOpen = false, existingState) {
723
+ function createFullConsentState(consented, preferences, source, projectConfig, isModalOpen = false, existingState) {
612
724
  const now = (/* @__PURE__ */ new Date()).toISOString();
613
725
  return {
614
726
  version: "1.0",
@@ -617,28 +729,33 @@ function createFullConsentState(consented, preferences, source, isModalOpen = fa
617
729
  consentDate: existingState?.consentDate || now,
618
730
  lastUpdate: now,
619
731
  source,
732
+ projectConfig,
620
733
  isModalOpen
621
734
  };
622
735
  }
623
736
  function reducer(state, action) {
624
737
  switch (action.type) {
625
738
  case "ACCEPT_ALL": {
626
- const prefs = createInitialPreferences(action.customCategories);
627
- Object.keys(prefs).forEach((key) => {
628
- prefs[key] = true;
629
- });
630
- return createFullConsentState(true, prefs, "banner", false, state);
739
+ const prefs = createProjectPreferences(action.config, true);
740
+ return createFullConsentState(
741
+ true,
742
+ prefs,
743
+ "banner",
744
+ action.config,
745
+ false,
746
+ state
747
+ );
631
748
  }
632
749
  case "REJECT_ALL": {
633
- const prefs = createInitialPreferences(action.customCategories);
634
- if (action.customCategories) {
635
- action.customCategories.forEach((category) => {
636
- if (category.essential) {
637
- prefs[category.id] = true;
638
- }
639
- });
640
- }
641
- return createFullConsentState(true, prefs, "banner", false, state);
750
+ const prefs = createProjectPreferences(action.config, false);
751
+ return createFullConsentState(
752
+ true,
753
+ prefs,
754
+ "banner",
755
+ action.config,
756
+ false,
757
+ state
758
+ );
642
759
  }
643
760
  case "SET_CATEGORY":
644
761
  return {
@@ -654,6 +771,7 @@ function reducer(state, action) {
654
771
  true,
655
772
  action.preferences,
656
773
  "modal",
774
+ action.config,
657
775
  false,
658
776
  state
659
777
  );
@@ -664,20 +782,30 @@ function reducer(state, action) {
664
782
  true,
665
783
  state.preferences,
666
784
  "modal",
785
+ action.config,
667
786
  false,
668
787
  state
669
788
  );
670
789
  case "RESET": {
671
790
  return createFullConsentState(
672
791
  false,
673
- createInitialPreferences(action.customCategories),
792
+ createProjectPreferences(action.config),
674
793
  "programmatic",
794
+ action.config,
675
795
  false
676
796
  );
677
797
  }
678
- case "HYDRATE":
679
- return { ...action.state, isModalOpen: false };
680
- // Nunca hidratar com modal aberto
798
+ case "HYDRATE": {
799
+ const validatedPreferences = validateProjectPreferences(
800
+ action.state.preferences,
801
+ action.config
802
+ );
803
+ return {
804
+ ...action.state,
805
+ preferences: validatedPreferences,
806
+ isModalOpen: false
807
+ };
808
+ }
681
809
  default:
682
810
  return state;
683
811
  }
@@ -685,96 +813,98 @@ function reducer(state, action) {
685
813
  function ConsentProvider({
686
814
  initialState,
687
815
  categories,
688
- // NOVO: configuração completa de categorias
816
+ // Nova prop para configuração de categorias
689
817
  texts: textsProp,
690
818
  theme,
691
- customCategories,
692
- // LEGACY: compatibilidade
819
+ designTokens,
693
820
  scriptIntegrations,
694
821
  // eslint-disable-line no-unused-vars
695
822
  PreferencesModalComponent,
696
823
  preferencesModalProps = {},
697
- disableAutomaticModal = false,
824
+ CookieBannerComponent,
825
+ cookieBannerProps = {},
826
+ FloatingPreferencesButtonComponent,
827
+ floatingPreferencesButtonProps = {},
828
+ disableFloatingPreferencesButton = false,
698
829
  hideBranding = false,
699
830
  onConsentGiven,
700
831
  onPreferencesSaved,
701
832
  cookie: cookieOpts,
702
833
  disableDeveloperGuidance,
703
- // NOVO: desabilita avisos de dev
704
834
  children
705
835
  }) {
706
- const texts = React3.useMemo(
836
+ const texts = React4.useMemo(
707
837
  () => ({ ...DEFAULT_TEXTS, ...textsProp ?? {} }),
708
838
  [textsProp]
709
839
  );
710
- const cookie = React3.useMemo(
840
+ const cookie = React4.useMemo(
711
841
  () => ({ ...DEFAULT_COOKIE_OPTS, ...cookieOpts ?? {} }),
712
842
  [cookieOpts]
713
843
  );
714
- const appliedTheme = React3.useMemo(
844
+ const appliedTheme = React4.useMemo(
715
845
  () => theme || defaultConsentTheme,
716
846
  [theme]
717
847
  );
718
- const finalCategoriesConfig = React3.useMemo(() => {
848
+ const finalCategoriesConfig = React4.useMemo(() => {
719
849
  if (categories) return categories;
720
- if (customCategories) {
721
- return {
722
- enabledCategories: ["analytics"],
723
- // padrão quando usando API antiga
724
- customCategories
725
- };
726
- }
727
- return void 0;
728
- }, [categories, customCategories]);
850
+ return DEFAULT_PROJECT_CATEGORIES;
851
+ }, [categories]);
729
852
  useDeveloperGuidance(finalCategoriesConfig, disableDeveloperGuidance);
730
- const boot = React3.useMemo(() => {
853
+ const boot = React4.useMemo(() => {
731
854
  if (initialState) return { ...initialState, isModalOpen: false };
732
855
  return createFullConsentState(
733
856
  false,
734
- createInitialPreferences(customCategories),
857
+ createProjectPreferences(finalCategoriesConfig),
735
858
  "banner",
859
+ finalCategoriesConfig,
736
860
  false
737
861
  );
738
- }, [initialState, customCategories]);
739
- const [state, dispatch] = React3.useReducer(reducer, boot);
740
- const [isHydrated, setIsHydrated] = React3.useState(false);
741
- React3.useEffect(() => {
862
+ }, [initialState, finalCategoriesConfig]);
863
+ const [state, dispatch] = React4.useReducer(reducer, boot);
864
+ const [isHydrated, setIsHydrated] = React4.useState(false);
865
+ React4.useEffect(() => {
742
866
  if (!initialState) {
743
867
  const saved = readConsentCookie(cookie.name);
744
868
  if (saved?.consented) {
745
- console.log("\u{1F680} Immediate hydration: Cookie found", saved);
746
- dispatch({ type: "HYDRATE", state: saved });
869
+ dispatch({
870
+ type: "HYDRATE",
871
+ state: saved,
872
+ config: finalCategoriesConfig
873
+ });
747
874
  }
748
875
  }
749
876
  setIsHydrated(true);
750
- }, [cookie.name, initialState]);
751
- React3.useEffect(() => {
752
- if (state.consented) writeConsentCookie(state, state.source, cookie);
753
- }, [state, cookie]);
754
- const prevConsented = React3.useRef(state.consented);
755
- React3.useEffect(() => {
877
+ }, [cookie.name, initialState, finalCategoriesConfig]);
878
+ React4.useEffect(() => {
879
+ if (state.consented)
880
+ writeConsentCookie(state, finalCategoriesConfig, cookie);
881
+ }, [state, cookie, finalCategoriesConfig]);
882
+ const prevConsented = React4.useRef(state.consented);
883
+ React4.useEffect(() => {
756
884
  if (!prevConsented.current && state.consented && onConsentGiven) {
757
885
  setTimeout(() => onConsentGiven(state), 150);
758
886
  }
759
887
  prevConsented.current = state.consented;
760
888
  }, [state, onConsentGiven]);
761
- const prevPrefs = React3.useRef(state.preferences);
762
- React3.useEffect(() => {
763
- if (state.consented && onPreferencesSaved && prevPrefs.current !== state.preferences) {
764
- setTimeout(() => onPreferencesSaved(state.preferences), 150);
765
- prevPrefs.current = state.preferences;
766
- }
767
- }, [state, onPreferencesSaved]);
768
- const api = React3.useMemo(() => {
769
- const acceptAll = () => dispatch({ type: "ACCEPT_ALL", customCategories });
770
- const rejectAll = () => dispatch({ type: "REJECT_ALL", customCategories });
889
+ const api = React4.useMemo(() => {
890
+ const acceptAll = () => dispatch({ type: "ACCEPT_ALL", config: finalCategoriesConfig });
891
+ const rejectAll = () => dispatch({ type: "REJECT_ALL", config: finalCategoriesConfig });
771
892
  const setPreference = (category, value) => dispatch({ type: "SET_CATEGORY", category, value });
772
- const setPreferences = (preferences) => dispatch({ type: "SET_PREFERENCES", preferences });
893
+ const setPreferences = (preferences) => {
894
+ dispatch({
895
+ type: "SET_PREFERENCES",
896
+ preferences,
897
+ config: finalCategoriesConfig
898
+ });
899
+ if (onPreferencesSaved) {
900
+ setTimeout(() => onPreferencesSaved(preferences), 150);
901
+ }
902
+ };
773
903
  const openPreferences = () => dispatch({ type: "OPEN_MODAL" });
774
- const closePreferences = () => dispatch({ type: "CLOSE_MODAL" });
904
+ const closePreferences = () => dispatch({ type: "CLOSE_MODAL", config: finalCategoriesConfig });
775
905
  const resetConsent = () => {
776
906
  removeConsentCookie(cookie);
777
- dispatch({ type: "RESET", customCategories });
907
+ dispatch({ type: "RESET", config: finalCategoriesConfig });
778
908
  };
779
909
  return {
780
910
  consented: !!state.consented,
@@ -788,58 +918,87 @@ function ConsentProvider({
788
918
  closePreferences,
789
919
  resetConsent
790
920
  };
791
- }, [state, cookie, customCategories]);
792
- 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)(
921
+ }, [state, cookie, finalCategoriesConfig, onPreferencesSaved]);
922
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_styles3.ThemeProvider, { theme: appliedTheme, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(StateCtx.Provider, { value: state, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ActionsCtx.Provider, { value: api, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(TextsCtx.Provider, { value: texts, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(HydrationCtx.Provider, { value: isHydrated, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(DesignProvider, { tokens: designTokens, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
793
923
  CategoriesProvider,
794
924
  {
795
925
  config: finalCategoriesConfig,
796
- categories: customCategories,
926
+ disableDeveloperGuidance,
797
927
  children: [
798
928
  children,
799
- !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 }) })
929
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(React4.Suspense, { fallback: null, children: PreferencesModalComponent ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
930
+ PreferencesModalComponent,
931
+ {
932
+ preferences: api.preferences,
933
+ setPreferences: api.setPreferences,
934
+ closePreferences: api.closePreferences,
935
+ isModalOpen: api.isModalOpen,
936
+ texts,
937
+ ...preferencesModalProps
938
+ }
939
+ ) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PreferencesModal, { hideBranding }) }),
940
+ !state.consented && isHydrated && (CookieBannerComponent ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
941
+ CookieBannerComponent,
942
+ {
943
+ consented: api.consented,
944
+ acceptAll: api.acceptAll,
945
+ rejectAll: api.rejectAll,
946
+ openPreferences: api.openPreferences,
947
+ texts,
948
+ ...cookieBannerProps
949
+ }
950
+ ) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CookieBanner, {})),
951
+ state.consented && !disableFloatingPreferencesButton && (FloatingPreferencesButtonComponent ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
952
+ FloatingPreferencesButtonComponent,
953
+ {
954
+ openPreferences: api.openPreferences,
955
+ consented: api.consented,
956
+ ...floatingPreferencesButtonProps
957
+ }
958
+ ) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(FloatingPreferencesButton, {}))
800
959
  ]
801
960
  }
802
- ) }) }) }) }) });
961
+ ) }) }) }) }) }) });
803
962
  }
804
963
  function useConsentStateInternal() {
805
- const ctx = React3.useContext(StateCtx);
964
+ const ctx = React4.useContext(StateCtx);
806
965
  if (!ctx)
807
966
  throw new Error("useConsentState must be used within ConsentProvider");
808
967
  return ctx;
809
968
  }
810
969
  function useConsentActionsInternal() {
811
- const ctx = React3.useContext(ActionsCtx);
970
+ const ctx = React4.useContext(ActionsCtx);
812
971
  if (!ctx)
813
972
  throw new Error("useConsentActions must be used within ConsentProvider");
814
973
  return ctx;
815
974
  }
816
975
  function useConsentTextsInternal() {
817
- const ctx = React3.useContext(TextsCtx);
976
+ const ctx = React4.useContext(TextsCtx);
818
977
  return ctx;
819
978
  }
820
979
  function useConsentHydrationInternal() {
821
- return React3.useContext(HydrationCtx);
980
+ return React4.useContext(HydrationCtx);
822
981
  }
823
- var React3, import_styles2, import_jsx_runtime4, PreferencesModal2, DEFAULT_PREFERENCES, DEFAULT_TEXTS, StateCtx, ActionsCtx, TextsCtx, HydrationCtx;
982
+ var React4, import_styles3, import_jsx_runtime6, PreferencesModal, DEFAULT_TEXTS, StateCtx, ActionsCtx, TextsCtx, HydrationCtx;
824
983
  var init_ConsentContext = __esm({
825
984
  "src/context/ConsentContext.tsx"() {
826
985
  "use strict";
827
- React3 = __toESM(require("react"), 1);
828
- import_styles2 = require("@mui/material/styles");
986
+ React4 = __toESM(require("react"), 1);
987
+ import_styles3 = require("@mui/material/styles");
829
988
  init_cookieUtils();
989
+ init_categoryUtils();
830
990
  init_theme();
831
991
  init_CategoriesContext();
992
+ init_DesignContext();
832
993
  init_developerGuidance();
833
- import_jsx_runtime4 = require("react/jsx-runtime");
834
- PreferencesModal2 = React3.lazy(
994
+ init_CookieBanner();
995
+ init_FloatingPreferencesButton();
996
+ import_jsx_runtime6 = require("react/jsx-runtime");
997
+ PreferencesModal = React4.lazy(
835
998
  () => Promise.resolve().then(() => (init_PreferencesModal(), PreferencesModal_exports)).then((m) => ({
836
999
  default: m.PreferencesModal
837
1000
  }))
838
1001
  );
839
- DEFAULT_PREFERENCES = {
840
- necessary: true
841
- // Sempre ativo (essencial)
842
- };
843
1002
  DEFAULT_TEXTS = {
844
1003
  // Textos básicos
845
1004
  bannerMessage: "Utilizamos cookies para melhorar sua experi\xEAncia.",
@@ -869,10 +1028,10 @@ var init_ConsentContext = __esm({
869
1028
  transferCountries: void 0
870
1029
  // Exibido se definido
871
1030
  };
872
- StateCtx = React3.createContext(null);
873
- ActionsCtx = React3.createContext(null);
874
- TextsCtx = React3.createContext(DEFAULT_TEXTS);
875
- HydrationCtx = React3.createContext(false);
1031
+ StateCtx = React4.createContext(null);
1032
+ ActionsCtx = React4.createContext(null);
1033
+ TextsCtx = React4.createContext(DEFAULT_TEXTS);
1034
+ HydrationCtx = React4.createContext(false);
876
1035
  }
877
1036
  });
878
1037
 
@@ -906,6 +1065,112 @@ var init_useConsent = __esm({
906
1065
  }
907
1066
  });
908
1067
 
1068
+ // src/components/PreferencesModal.tsx
1069
+ var PreferencesModal_exports = {};
1070
+ __export(PreferencesModal_exports, {
1071
+ PreferencesModal: () => PreferencesModal2
1072
+ });
1073
+ function PreferencesModal2({
1074
+ DialogProps: DialogProps2,
1075
+ hideBranding = false
1076
+ }) {
1077
+ const { preferences, setPreferences, closePreferences, isModalOpen } = useConsent();
1078
+ const texts = useConsentTexts();
1079
+ const { toggleableCategories } = useCategories();
1080
+ const [tempPreferences, setTempPreferences] = (0, import_react.useState)(
1081
+ () => {
1082
+ const initialPrefs = { necessary: true };
1083
+ toggleableCategories.forEach((category) => {
1084
+ initialPrefs[category.id] = preferences[category.id] ?? false;
1085
+ });
1086
+ return initialPrefs;
1087
+ }
1088
+ );
1089
+ (0, import_react.useEffect)(() => {
1090
+ if (isModalOpen) {
1091
+ const syncedPrefs = { necessary: true };
1092
+ toggleableCategories.forEach((category) => {
1093
+ syncedPrefs[category.id] = preferences[category.id] ?? false;
1094
+ });
1095
+ setTempPreferences(syncedPrefs);
1096
+ }
1097
+ }, [isModalOpen, preferences, toggleableCategories]);
1098
+ const open = DialogProps2?.open ?? isModalOpen ?? false;
1099
+ const handleSave = () => {
1100
+ setPreferences(tempPreferences);
1101
+ };
1102
+ const handleCancel = () => {
1103
+ setTempPreferences(preferences);
1104
+ closePreferences();
1105
+ };
1106
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1107
+ import_Dialog.default,
1108
+ {
1109
+ "aria-labelledby": "cookie-pref-title",
1110
+ open,
1111
+ onClose: handleCancel,
1112
+ ...DialogProps2,
1113
+ children: [
1114
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_DialogTitle.default, { id: "cookie-pref-title", children: texts.modalTitle }),
1115
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_DialogContent.default, { dividers: true, children: [
1116
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_Typography3.default, { variant: "body2", sx: { mb: 2 }, children: texts.modalIntro }),
1117
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_FormGroup.default, { children: [
1118
+ toggleableCategories.map((category) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1119
+ import_FormControlLabel.default,
1120
+ {
1121
+ control: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1122
+ import_Switch.default,
1123
+ {
1124
+ checked: tempPreferences[category.id] ?? false,
1125
+ onChange: (e) => setTempPreferences((prev) => ({
1126
+ ...prev,
1127
+ [category.id]: e.target.checked
1128
+ }))
1129
+ }
1130
+ ),
1131
+ label: `${category.name} - ${category.description}`
1132
+ },
1133
+ category.id
1134
+ )),
1135
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1136
+ import_FormControlLabel.default,
1137
+ {
1138
+ control: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_Switch.default, { checked: true, disabled: true }),
1139
+ label: texts.necessaryAlwaysOn
1140
+ }
1141
+ )
1142
+ ] })
1143
+ ] }),
1144
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_DialogActions.default, { children: [
1145
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_Button2.default, { variant: "outlined", onClick: handleCancel, children: "Cancelar" }),
1146
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_Button2.default, { variant: "contained", onClick: handleSave, children: texts.save })
1147
+ ] }),
1148
+ !hideBranding && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Branding, { variant: "modal" })
1149
+ ]
1150
+ }
1151
+ );
1152
+ }
1153
+ var import_Button2, import_Dialog, import_DialogActions, import_DialogContent, import_DialogTitle, import_FormControlLabel, import_FormGroup, import_Switch, import_Typography3, import_react, import_jsx_runtime7;
1154
+ var init_PreferencesModal = __esm({
1155
+ "src/components/PreferencesModal.tsx"() {
1156
+ "use strict";
1157
+ import_Button2 = __toESM(require("@mui/material/Button"), 1);
1158
+ import_Dialog = __toESM(require("@mui/material/Dialog"), 1);
1159
+ import_DialogActions = __toESM(require("@mui/material/DialogActions"), 1);
1160
+ import_DialogContent = __toESM(require("@mui/material/DialogContent"), 1);
1161
+ import_DialogTitle = __toESM(require("@mui/material/DialogTitle"), 1);
1162
+ import_FormControlLabel = __toESM(require("@mui/material/FormControlLabel"), 1);
1163
+ import_FormGroup = __toESM(require("@mui/material/FormGroup"), 1);
1164
+ import_Switch = __toESM(require("@mui/material/Switch"), 1);
1165
+ import_Typography3 = __toESM(require("@mui/material/Typography"), 1);
1166
+ import_react = require("react");
1167
+ init_CategoriesContext();
1168
+ init_useConsent();
1169
+ init_Branding();
1170
+ import_jsx_runtime7 = require("react/jsx-runtime");
1171
+ }
1172
+ });
1173
+
909
1174
  // src/index.ts
910
1175
  var index_exports = {};
911
1176
  __export(index_exports, {
@@ -913,10 +1178,8 @@ __export(index_exports, {
913
1178
  ConsentGate: () => ConsentGate,
914
1179
  ConsentProvider: () => ConsentProvider,
915
1180
  ConsentScriptLoader: () => ConsentScriptLoader,
916
- CookieBanner: () => CookieBanner,
917
1181
  DEFAULT_PROJECT_CATEGORIES: () => DEFAULT_PROJECT_CATEGORIES,
918
- FloatingPreferencesButton: () => FloatingPreferencesButton,
919
- PreferencesModal: () => PreferencesModal,
1182
+ PreferencesModal: () => PreferencesModal2,
920
1183
  analyzeDeveloperConfiguration: () => analyzeDeveloperConfiguration,
921
1184
  createGoogleAnalyticsIntegration: () => createGoogleAnalyticsIntegration,
922
1185
  createGoogleTagManagerIntegration: () => createGoogleTagManagerIntegration,
@@ -928,193 +1191,21 @@ __export(index_exports, {
928
1191
  useConsent: () => useConsent,
929
1192
  useConsentHydration: () => useConsentHydration,
930
1193
  useConsentScriptLoader: () => useConsentScriptLoader,
931
- useConsentTexts: () => useConsentTexts,
932
- useCustomCategories: () => useCustomCategories
1194
+ useConsentTexts: () => useConsentTexts
933
1195
  });
934
1196
  module.exports = __toCommonJS(index_exports);
935
-
936
- // src/components/CookieBanner.tsx
937
- var import_Button2 = __toESM(require("@mui/material/Button"), 1);
938
- var import_Box = __toESM(require("@mui/material/Box"), 1);
939
- var import_Paper = __toESM(require("@mui/material/Paper"), 1);
940
- var import_Snackbar = __toESM(require("@mui/material/Snackbar"), 1);
941
- var import_Stack = __toESM(require("@mui/material/Stack"), 1);
942
- var import_Typography3 = __toESM(require("@mui/material/Typography"), 1);
943
- var import_Link2 = __toESM(require("@mui/material/Link"), 1);
944
- init_useConsent();
945
- init_Branding();
946
- var import_jsx_runtime5 = require("react/jsx-runtime");
947
- function CookieBanner({
948
- policyLinkUrl,
949
- debug,
950
- blocking = true,
951
- // Por padrão, bloqueia até decisão
952
- hideBranding = false,
953
- SnackbarProps,
954
- PaperProps
955
- }) {
956
- const { consented, acceptAll, rejectAll, openPreferences } = useConsent();
957
- const texts = useConsentTexts();
958
- const isHydrated = useConsentHydration();
959
- const open = debug ? true : isHydrated && !consented;
960
- if (!open) return null;
961
- const bannerContent = /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
962
- import_Paper.default,
963
- {
964
- elevation: 3,
965
- sx: { p: 2, maxWidth: 720, mx: "auto" },
966
- ...PaperProps,
967
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_Stack.default, { spacing: 1, children: [
968
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_Typography3.default, { variant: "body2", children: [
969
- texts.bannerMessage,
970
- " ",
971
- policyLinkUrl && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
972
- import_Link2.default,
973
- {
974
- href: policyLinkUrl,
975
- underline: "hover",
976
- target: "_blank",
977
- rel: "noopener noreferrer",
978
- children: texts.policyLink ?? "Saiba mais"
979
- }
980
- )
981
- ] }),
982
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
983
- import_Stack.default,
984
- {
985
- direction: { xs: "column", sm: "row" },
986
- spacing: 1,
987
- justifyContent: "flex-end",
988
- children: [
989
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_Button2.default, { variant: "outlined", onClick: rejectAll, children: texts.declineAll }),
990
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_Button2.default, { variant: "contained", onClick: acceptAll, children: texts.acceptAll }),
991
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_Button2.default, { variant: "text", onClick: openPreferences, children: texts.preferences })
992
- ]
993
- }
994
- ),
995
- !hideBranding && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Branding, { variant: "banner" })
996
- ] })
997
- }
998
- );
999
- if (blocking) {
1000
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
1001
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1002
- import_Box.default,
1003
- {
1004
- sx: {
1005
- position: "fixed",
1006
- top: 0,
1007
- left: 0,
1008
- right: 0,
1009
- bottom: 0,
1010
- backgroundColor: "rgba(0, 0, 0, 0.5)",
1011
- zIndex: 1299
1012
- // Abaixo do banner mas acima do conteúdo
1013
- }
1014
- }
1015
- ),
1016
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1017
- import_Box.default,
1018
- {
1019
- sx: {
1020
- position: "fixed",
1021
- bottom: 0,
1022
- left: 0,
1023
- right: 0,
1024
- zIndex: 1300,
1025
- // Acima do overlay
1026
- p: 2
1027
- },
1028
- children: bannerContent
1029
- }
1030
- )
1031
- ] });
1032
- }
1033
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1034
- import_Snackbar.default,
1035
- {
1036
- open,
1037
- anchorOrigin: { vertical: "bottom", horizontal: "center" },
1038
- ...SnackbarProps,
1039
- children: bannerContent
1040
- }
1041
- );
1042
- }
1043
-
1044
- // src/index.ts
1045
1197
  init_PreferencesModal();
1046
-
1047
- // src/components/FloatingPreferencesButton.tsx
1048
- var import_CookieOutlined = __toESM(require("@mui/icons-material/CookieOutlined"), 1);
1049
- var import_Fab = __toESM(require("@mui/material/Fab"), 1);
1050
- var import_Tooltip = __toESM(require("@mui/material/Tooltip"), 1);
1051
- var import_styles3 = require("@mui/material/styles");
1052
- init_useConsent();
1053
- var import_jsx_runtime6 = require("react/jsx-runtime");
1054
- function FloatingPreferencesButton({
1055
- position = "bottom-right",
1056
- offset = 24,
1057
- icon = /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_CookieOutlined.default, {}),
1058
- tooltip,
1059
- FabProps,
1060
- hideWhenConsented = false
1061
- }) {
1062
- const { openPreferences, consented } = useConsent();
1063
- const theme = (0, import_styles3.useTheme)();
1064
- if (hideWhenConsented && consented) {
1065
- return null;
1066
- }
1067
- const tooltipText = tooltip ?? "Gerenciar Prefer\xEAncias de Cookies";
1068
- const getPosition = () => {
1069
- const styles = {
1070
- position: "fixed",
1071
- zIndex: 1200
1072
- };
1073
- switch (position) {
1074
- case "bottom-left":
1075
- return { ...styles, bottom: offset, left: offset };
1076
- case "bottom-right":
1077
- return { ...styles, bottom: offset, right: offset };
1078
- case "top-left":
1079
- return { ...styles, top: offset, left: offset };
1080
- case "top-right":
1081
- return { ...styles, top: offset, right: offset };
1082
- default:
1083
- return { ...styles, bottom: offset, right: offset };
1084
- }
1085
- };
1086
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_Tooltip.default, { title: tooltipText, placement: "top", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1087
- import_Fab.default,
1088
- {
1089
- size: "medium",
1090
- color: "primary",
1091
- onClick: openPreferences,
1092
- sx: {
1093
- ...getPosition(),
1094
- backgroundColor: theme.palette.primary.main,
1095
- "&:hover": {
1096
- backgroundColor: theme.palette.primary.dark
1097
- }
1098
- },
1099
- "aria-label": tooltipText,
1100
- ...FabProps,
1101
- children: icon
1102
- }
1103
- ) });
1104
- }
1105
-
1106
- // src/index.ts
1107
1198
  init_ConsentContext();
1108
1199
  init_useConsent();
1109
1200
  init_CategoriesContext();
1110
1201
 
1111
1202
  // src/utils/ConsentGate.tsx
1112
1203
  init_useConsent();
1113
- var import_jsx_runtime7 = require("react/jsx-runtime");
1204
+ var import_jsx_runtime8 = require("react/jsx-runtime");
1114
1205
  function ConsentGate(props) {
1115
1206
  const { preferences } = useConsent();
1116
1207
  if (!preferences[props.category]) return null;
1117
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_jsx_runtime7.Fragment, { children: props.children });
1208
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_jsx_runtime8.Fragment, { children: props.children });
1118
1209
  }
1119
1210
 
1120
1211
  // src/utils/scriptLoader.ts
@@ -1158,15 +1249,15 @@ function loadScript(id, src, category = null, attrs = {}) {
1158
1249
  init_theme();
1159
1250
 
1160
1251
  // src/utils/ConsentScriptLoader.tsx
1161
- var React4 = __toESM(require("react"), 1);
1252
+ var React5 = __toESM(require("react"), 1);
1162
1253
  init_useConsent();
1163
1254
  function ConsentScriptLoader({
1164
1255
  integrations,
1165
1256
  reloadOnChange = false
1166
1257
  }) {
1167
1258
  const { preferences, consented } = useConsent();
1168
- const loadedScripts = React4.useRef(/* @__PURE__ */ new Set());
1169
- React4.useEffect(() => {
1259
+ const loadedScripts = React5.useRef(/* @__PURE__ */ new Set());
1260
+ React5.useEffect(() => {
1170
1261
  if (!consented) return;
1171
1262
  integrations.forEach(async (integration) => {
1172
1263
  const shouldLoad = preferences[integration.category];
@@ -1184,9 +1275,6 @@ function ConsentScriptLoader({
1184
1275
  integration.init();
1185
1276
  }
1186
1277
  loadedScripts.current.add(integration.id);
1187
- console.log(
1188
- `\u2705 Script loaded: ${integration.id} (${integration.category})`
1189
- );
1190
1278
  } catch (error) {
1191
1279
  console.error(`\u274C Failed to load script: ${integration.id}`, error);
1192
1280
  }
@@ -1197,7 +1285,7 @@ function ConsentScriptLoader({
1197
1285
  }
1198
1286
  function useConsentScriptLoader() {
1199
1287
  const { preferences, consented } = useConsent();
1200
- return React4.useCallback(
1288
+ return React5.useCallback(
1201
1289
  async (integration) => {
1202
1290
  if (!consented) {
1203
1291
  console.warn(
@@ -1223,9 +1311,6 @@ function useConsentScriptLoader() {
1223
1311
  if (integration.init) {
1224
1312
  integration.init();
1225
1313
  }
1226
- console.log(
1227
- `\u2705 Script loaded: ${integration.id} (${integration.category})`
1228
- );
1229
1314
  return true;
1230
1315
  } catch (error) {
1231
1316
  console.error(`\u274C Failed to load script: ${integration.id}`, error);
@@ -1277,8 +1362,8 @@ function createGoogleTagManagerIntegration(config) {
1277
1362
  function createUserWayIntegration(config) {
1278
1363
  return {
1279
1364
  id: "userway",
1280
- category: "marketing",
1281
- // ou poderia ser uma categoria 'accessibility'
1365
+ category: "functional",
1366
+ // Categoria mais apropriada para acessibilidade
1282
1367
  src: `https://cdn.userway.org/widget.js`,
1283
1368
  init: () => {
1284
1369
  if (typeof window !== "undefined") {
@@ -1303,9 +1388,7 @@ init_developerGuidance();
1303
1388
  ConsentGate,
1304
1389
  ConsentProvider,
1305
1390
  ConsentScriptLoader,
1306
- CookieBanner,
1307
1391
  DEFAULT_PROJECT_CATEGORIES,
1308
- FloatingPreferencesButton,
1309
1392
  PreferencesModal,
1310
1393
  analyzeDeveloperConfiguration,
1311
1394
  createGoogleAnalyticsIntegration,
@@ -1318,6 +1401,5 @@ init_developerGuidance();
1318
1401
  useConsent,
1319
1402
  useConsentHydration,
1320
1403
  useConsentScriptLoader,
1321
- useConsentTexts,
1322
- useCustomCategories
1404
+ useConsentTexts
1323
1405
  });