react-lgpd-consent 0.2.5 → 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.
@@ -1,5 +1,5 @@
1
1
  // src/components/PreferencesModal.tsx
2
- import Button from "@mui/material/Button";
2
+ import Button2 from "@mui/material/Button";
3
3
  import Dialog from "@mui/material/Dialog";
4
4
  import DialogActions from "@mui/material/DialogActions";
5
5
  import DialogContent from "@mui/material/DialogContent";
@@ -7,7 +7,7 @@ import DialogTitle from "@mui/material/DialogTitle";
7
7
  import FormControlLabel from "@mui/material/FormControlLabel";
8
8
  import FormGroup from "@mui/material/FormGroup";
9
9
  import Switch from "@mui/material/Switch";
10
- import Typography2 from "@mui/material/Typography";
10
+ import Typography3 from "@mui/material/Typography";
11
11
  import { useEffect as useEffect4, useState as useState2 } from "react";
12
12
 
13
13
  // src/context/CategoriesContext.tsx
@@ -16,9 +16,8 @@ import * as React2 from "react";
16
16
  // src/utils/developerGuidance.ts
17
17
  import * as React from "react";
18
18
  var DEFAULT_PROJECT_CATEGORIES = {
19
- enabledCategories: ["analytics"],
19
+ enabledCategories: ["analytics"]
20
20
  // Só analytics além de necessary
21
- customCategories: []
22
21
  };
23
22
  function analyzeDeveloperConfiguration(config) {
24
23
  const guidance = {
@@ -77,17 +76,6 @@ function analyzeDeveloperConfiguration(config) {
77
76
  });
78
77
  }
79
78
  });
80
- const customCategories = finalConfig.customCategories || [];
81
- customCategories.forEach((category) => {
82
- guidance.activeCategoriesInfo.push({
83
- id: category.id,
84
- name: category.name,
85
- description: category.description,
86
- essential: category.essential === true,
87
- uiRequired: category.essential !== true
88
- // Apenas não-essenciais precisam toggle
89
- });
90
- });
91
79
  const totalToggleable = guidance.activeCategoriesInfo.filter(
92
80
  (c) => c.uiRequired
93
81
  ).length;
@@ -102,18 +90,10 @@ function analyzeDeveloperConfiguration(config) {
102
90
  'prejudicar experi\xEAncia do usu\xE1rio. Considere agrupar categorias similares.`
103
91
  );
104
92
  }
105
- const poorDescriptions = customCategories.filter(
106
- (c) => !c.description || c.description.length < 10
107
- );
108
- if (poorDescriptions.length > 0) {
109
- guidance.warnings.push(
110
- `Categorias customizadas com descri\xE7\xF5es inadequadas: ${poorDescriptions.map((c) => c.id).join(", ")}. Descri\xE7\xF5es claras s\xE3o obrigat\xF3rias para compliance LGPD.`
111
- );
112
- }
113
93
  return guidance;
114
94
  }
115
95
  function logDeveloperGuidance(guidance, disableGuidanceProp) {
116
- if (disableGuidanceProp === true) {
96
+ if (disableGuidanceProp) {
117
97
  return;
118
98
  }
119
99
  const isProduction = (
@@ -137,7 +117,8 @@ function logDeveloperGuidance(guidance, disableGuidanceProp) {
137
117
  console.groupEnd();
138
118
  }
139
119
  if (guidance.usingDefaults) {
140
- console.info(
120
+ console.warn(
121
+ // Changed from console.info to console.warn
141
122
  `${PREFIX} \u{1F4CB} Usando configura\xE7\xE3o padr\xE3o. Para personalizar, use a prop "categories" no ConsentProvider.`
142
123
  );
143
124
  }
@@ -162,6 +143,9 @@ function useDeveloperGuidance(config, disableGuidanceProp) {
162
143
  [config]
163
144
  );
164
145
  React.useEffect(() => {
146
+ if (disableGuidanceProp === true) {
147
+ return;
148
+ }
165
149
  logDeveloperGuidance(guidance, disableGuidanceProp);
166
150
  }, [guidance, stringifiedConfig, disableGuidanceProp]);
167
151
  return guidance;
@@ -172,27 +156,15 @@ import { jsx } from "react/jsx-runtime";
172
156
  var CategoriesContext = React2.createContext(
173
157
  null
174
158
  );
175
- var CategoriesCtx = React2.createContext([]);
176
159
  function CategoriesProvider({
177
160
  children,
178
- categories,
179
- // LEGACY: prop antiga (apenas customCategories)
180
- config
161
+ config,
181
162
  // NOVO: configuração completa
163
+ disableDeveloperGuidance
182
164
  }) {
183
165
  const contextValue = React2.useMemo(() => {
184
- let finalConfig;
185
- if (categories && !config) {
186
- finalConfig = {
187
- enabledCategories: DEFAULT_PROJECT_CATEGORIES.enabledCategories,
188
- customCategories: categories
189
- };
190
- } else {
191
- finalConfig = config || DEFAULT_PROJECT_CATEGORIES;
192
- }
193
- const guidance = analyzeDeveloperConfiguration(
194
- config || (categories ? { customCategories: categories } : void 0)
195
- );
166
+ const finalConfig = config || DEFAULT_PROJECT_CATEGORIES;
167
+ const guidance = analyzeDeveloperConfiguration(config);
196
168
  const toggleableCategories = guidance.activeCategoriesInfo.filter(
197
169
  (cat) => cat.uiRequired
198
170
  );
@@ -200,14 +172,13 @@ function CategoriesProvider({
200
172
  config: finalConfig,
201
173
  guidance,
202
174
  toggleableCategories,
203
- allCategories: guidance.activeCategoriesInfo,
204
- legacyCategories: categories || []
175
+ allCategories: guidance.activeCategoriesInfo
205
176
  };
206
- }, [config, categories]);
177
+ }, [config]);
207
178
  React2.useEffect(() => {
208
- logDeveloperGuidance(contextValue.guidance);
209
- }, [contextValue.guidance]);
210
- return /* @__PURE__ */ jsx(CategoriesContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(CategoriesCtx.Provider, { value: contextValue.legacyCategories, children }) });
179
+ logDeveloperGuidance(contextValue.guidance, disableDeveloperGuidance);
180
+ }, [contextValue.guidance, disableDeveloperGuidance]);
181
+ return /* @__PURE__ */ jsx(CategoriesContext.Provider, { value: contextValue, children });
211
182
  }
212
183
  function useCategories() {
213
184
  const context = React2.useContext(CategoriesContext);
@@ -229,12 +200,9 @@ function useCategoryStatus(categoryId) {
229
200
  description: category?.description
230
201
  };
231
202
  }
232
- function useCustomCategories() {
233
- return React2.useContext(CategoriesCtx);
234
- }
235
203
 
236
204
  // src/context/ConsentContext.tsx
237
- import * as React3 from "react";
205
+ import * as React4 from "react";
238
206
  import { ThemeProvider } from "@mui/material/styles";
239
207
 
240
208
  // src/utils/cookieUtils.ts
@@ -286,7 +254,7 @@ function migrateLegacyCookie(legacyData) {
286
254
  return null;
287
255
  }
288
256
  }
289
- function writeConsentCookie(state, source = "banner", opts) {
257
+ function writeConsentCookie(state, config, opts, source = "banner") {
290
258
  if (typeof document === "undefined") return;
291
259
  const now = (/* @__PURE__ */ new Date()).toISOString();
292
260
  const o = { ...DEFAULT_COOKIE_OPTS, ...opts };
@@ -297,7 +265,8 @@ function writeConsentCookie(state, source = "banner", opts) {
297
265
  consentDate: state.consentDate || now,
298
266
  // Preservar data original ou usar atual
299
267
  lastUpdate: now,
300
- source
268
+ source,
269
+ projectConfig: config
301
270
  // isModalOpen NÃO é persistido (campo de UI apenas)
302
271
  };
303
272
  Cookies.set(o.name, JSON.stringify(cookieData), {
@@ -313,6 +282,34 @@ function removeConsentCookie(opts) {
313
282
  Cookies.remove(o.name, { path: o.path });
314
283
  }
315
284
 
285
+ // src/utils/categoryUtils.ts
286
+ function createProjectPreferences(config, defaultValue = false) {
287
+ const preferences = {
288
+ necessary: true
289
+ // Sempre presente e true (essencial)
290
+ };
291
+ const enabledCategories = config?.enabledCategories || [];
292
+ enabledCategories.forEach((category) => {
293
+ if (category !== "necessary") {
294
+ preferences[category] = defaultValue;
295
+ }
296
+ });
297
+ return preferences;
298
+ }
299
+ function validateProjectPreferences(preferences, config) {
300
+ const validPreferences = {
301
+ necessary: true
302
+ // Sempre válida
303
+ };
304
+ const enabledCategories = config?.enabledCategories || [];
305
+ enabledCategories.forEach((category) => {
306
+ if (category !== "necessary" && preferences[category] !== void 0) {
307
+ validPreferences[category] = preferences[category];
308
+ }
309
+ });
310
+ return validPreferences;
311
+ }
312
+
316
313
  // src/utils/theme.ts
317
314
  import { createTheme } from "@mui/material/styles";
318
315
  var defaultConsentTheme = createTheme({
@@ -381,27 +378,285 @@ var defaultConsentTheme = createTheme({
381
378
  }
382
379
  });
383
380
 
381
+ // src/context/DesignContext.tsx
382
+ import * as React3 from "react";
383
+ import { jsx as jsx2 } from "react/jsx-runtime";
384
+ var DesignContext = React3.createContext(void 0);
385
+ function DesignProvider({
386
+ tokens,
387
+ children
388
+ }) {
389
+ return /* @__PURE__ */ jsx2(DesignContext.Provider, { value: tokens, children });
390
+ }
391
+ function useDesignTokens() {
392
+ return React3.useContext(DesignContext);
393
+ }
394
+
395
+ // src/components/CookieBanner.tsx
396
+ import Button from "@mui/material/Button";
397
+ import Box from "@mui/material/Box";
398
+ import Paper from "@mui/material/Paper";
399
+ import Snackbar from "@mui/material/Snackbar";
400
+ import Stack from "@mui/material/Stack";
401
+ import Typography2 from "@mui/material/Typography";
402
+ import Link2 from "@mui/material/Link";
403
+
404
+ // src/components/Branding.tsx
405
+ import Link from "@mui/material/Link";
406
+ import Typography from "@mui/material/Typography";
407
+ import { jsx as jsx3, jsxs } from "react/jsx-runtime";
408
+ var brandingStyles = {
409
+ banner: {
410
+ fontSize: "0.65rem",
411
+ textAlign: "right",
412
+ mt: 1,
413
+ opacity: 0.7,
414
+ fontStyle: "italic",
415
+ width: "100%"
416
+ },
417
+ modal: {
418
+ fontSize: "0.65rem",
419
+ textAlign: "right",
420
+ px: 3,
421
+ pb: 1,
422
+ opacity: 0.7,
423
+ fontStyle: "italic",
424
+ width: "100%"
425
+ }
426
+ };
427
+ var linkStyles = {
428
+ textDecoration: "none",
429
+ fontWeight: 500,
430
+ "&:hover": {
431
+ textDecoration: "underline"
432
+ }
433
+ };
434
+ function Branding({ variant, hidden = false }) {
435
+ if (hidden) return null;
436
+ return /* @__PURE__ */ jsxs(
437
+ Typography,
438
+ {
439
+ variant: "caption",
440
+ sx: (theme) => ({
441
+ ...brandingStyles[variant],
442
+ color: theme.palette.text.secondary
443
+ }),
444
+ children: [
445
+ "fornecido por",
446
+ " ",
447
+ /* @__PURE__ */ jsx3(
448
+ Link,
449
+ {
450
+ href: "https://www.ledipo.eti.br",
451
+ target: "_blank",
452
+ rel: "noopener noreferrer",
453
+ sx: (theme) => ({
454
+ ...linkStyles,
455
+ color: theme.palette.primary.main
456
+ }),
457
+ children: "L\xC9dipO.eti.br"
458
+ }
459
+ )
460
+ ]
461
+ }
462
+ );
463
+ }
464
+
465
+ // src/components/CookieBanner.tsx
466
+ import { Fragment, jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
467
+ function CookieBanner({
468
+ policyLinkUrl,
469
+ debug,
470
+ blocking = true,
471
+ hideBranding = false,
472
+ SnackbarProps,
473
+ PaperProps
474
+ }) {
475
+ const { consented, acceptAll, rejectAll, openPreferences } = useConsent();
476
+ const texts = useConsentTexts();
477
+ const isHydrated = useConsentHydration();
478
+ const designTokens = useDesignTokens();
479
+ const open = debug ? true : isHydrated && !consented;
480
+ if (!open) return null;
481
+ const bannerStyle = {
482
+ p: designTokens?.spacing?.padding?.banner ?? 2,
483
+ maxWidth: 720,
484
+ mx: "auto",
485
+ backgroundColor: designTokens?.colors?.background,
486
+ color: designTokens?.colors?.text,
487
+ borderRadius: designTokens?.spacing?.borderRadius?.banner,
488
+ fontFamily: designTokens?.typography?.fontFamily
489
+ };
490
+ const bannerContent = /* @__PURE__ */ jsx4(Paper, { elevation: 3, sx: bannerStyle, ...PaperProps, children: /* @__PURE__ */ jsxs2(Stack, { spacing: 1, children: [
491
+ /* @__PURE__ */ jsxs2(
492
+ Typography2,
493
+ {
494
+ variant: "body2",
495
+ sx: { fontSize: designTokens?.typography?.fontSize?.banner },
496
+ children: [
497
+ texts.bannerMessage,
498
+ " ",
499
+ policyLinkUrl && /* @__PURE__ */ jsx4(
500
+ Link2,
501
+ {
502
+ href: policyLinkUrl,
503
+ underline: "hover",
504
+ target: "_blank",
505
+ rel: "noopener noreferrer",
506
+ sx: { color: designTokens?.colors?.primary },
507
+ children: texts.policyLink ?? "Saiba mais"
508
+ }
509
+ )
510
+ ]
511
+ }
512
+ ),
513
+ /* @__PURE__ */ jsxs2(
514
+ Stack,
515
+ {
516
+ direction: { xs: "column", sm: "row" },
517
+ spacing: 1,
518
+ justifyContent: "flex-end",
519
+ children: [
520
+ /* @__PURE__ */ jsx4(
521
+ Button,
522
+ {
523
+ variant: "outlined",
524
+ onClick: rejectAll,
525
+ sx: { color: designTokens?.colors?.secondary },
526
+ children: texts.declineAll
527
+ }
528
+ ),
529
+ /* @__PURE__ */ jsx4(
530
+ Button,
531
+ {
532
+ variant: "contained",
533
+ onClick: acceptAll,
534
+ sx: { backgroundColor: designTokens?.colors?.primary },
535
+ children: texts.acceptAll
536
+ }
537
+ ),
538
+ /* @__PURE__ */ jsx4(
539
+ Button,
540
+ {
541
+ variant: "text",
542
+ onClick: openPreferences,
543
+ sx: { color: designTokens?.colors?.text },
544
+ children: texts.preferences
545
+ }
546
+ )
547
+ ]
548
+ }
549
+ ),
550
+ !hideBranding && /* @__PURE__ */ jsx4(Branding, { variant: "banner" })
551
+ ] }) });
552
+ const positionStyle = {
553
+ position: "fixed",
554
+ zIndex: 1300,
555
+ ...designTokens?.layout?.position === "top" ? { top: 0 } : { bottom: 0 },
556
+ left: 0,
557
+ right: 0,
558
+ width: designTokens?.layout?.width?.desktop ?? "100%",
559
+ p: 2
560
+ };
561
+ if (blocking) {
562
+ return /* @__PURE__ */ jsxs2(Fragment, { children: [
563
+ /* @__PURE__ */ jsx4(
564
+ Box,
565
+ {
566
+ sx: {
567
+ position: "fixed",
568
+ top: 0,
569
+ left: 0,
570
+ right: 0,
571
+ bottom: 0,
572
+ backgroundColor: designTokens?.layout?.backdrop ? "rgba(0, 0, 0, 0.5)" : "transparent",
573
+ zIndex: 1299
574
+ }
575
+ }
576
+ ),
577
+ /* @__PURE__ */ jsx4(Box, { sx: positionStyle, children: bannerContent })
578
+ ] });
579
+ }
580
+ return /* @__PURE__ */ jsx4(
581
+ Snackbar,
582
+ {
583
+ open,
584
+ anchorOrigin: {
585
+ vertical: designTokens?.layout?.position === "top" ? "top" : "bottom",
586
+ horizontal: "center"
587
+ },
588
+ ...SnackbarProps,
589
+ children: bannerContent
590
+ }
591
+ );
592
+ }
593
+
594
+ // src/components/FloatingPreferencesButton.tsx
595
+ import CookieOutlined from "@mui/icons-material/CookieOutlined";
596
+ import Fab from "@mui/material/Fab";
597
+ import Tooltip from "@mui/material/Tooltip";
598
+ import { useTheme } from "@mui/material/styles";
599
+ import { jsx as jsx5 } from "react/jsx-runtime";
600
+ function FloatingPreferencesButton({
601
+ position = "bottom-right",
602
+ offset = 24,
603
+ icon = /* @__PURE__ */ jsx5(CookieOutlined, {}),
604
+ tooltip,
605
+ FabProps,
606
+ hideWhenConsented = false
607
+ }) {
608
+ const { openPreferences, consented } = useConsent();
609
+ const theme = useTheme();
610
+ if (hideWhenConsented && consented) {
611
+ return null;
612
+ }
613
+ const tooltipText = tooltip ?? "Gerenciar Prefer\xEAncias de Cookies";
614
+ const getPosition = () => {
615
+ const styles = {
616
+ position: "fixed",
617
+ zIndex: 1200
618
+ };
619
+ switch (position) {
620
+ case "bottom-left":
621
+ return { ...styles, bottom: offset, left: offset };
622
+ case "bottom-right":
623
+ return { ...styles, bottom: offset, right: offset };
624
+ case "top-left":
625
+ return { ...styles, top: offset, left: offset };
626
+ case "top-right":
627
+ return { ...styles, top: offset, right: offset };
628
+ default:
629
+ return { ...styles, bottom: offset, right: offset };
630
+ }
631
+ };
632
+ return /* @__PURE__ */ jsx5(Tooltip, { title: tooltipText, placement: "top", children: /* @__PURE__ */ jsx5(
633
+ Fab,
634
+ {
635
+ size: "medium",
636
+ color: "primary",
637
+ onClick: openPreferences,
638
+ sx: {
639
+ ...getPosition(),
640
+ backgroundColor: theme.palette.primary.main,
641
+ "&:hover": {
642
+ backgroundColor: theme.palette.primary.dark
643
+ }
644
+ },
645
+ "aria-label": tooltipText,
646
+ ...FabProps,
647
+ children: icon
648
+ }
649
+ ) });
650
+ }
651
+
384
652
  // src/context/ConsentContext.tsx
385
- import { jsx as jsx2, jsxs } from "react/jsx-runtime";
386
- var PreferencesModal = React3.lazy(
387
- () => import("./PreferencesModal-B6N62JYB.js").then((m) => ({
653
+ import { jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
654
+ var PreferencesModal = React4.lazy(
655
+ () => import("./PreferencesModal-XCTM6WJN.js").then((m) => ({
388
656
  default: m.PreferencesModal
389
657
  }))
390
658
  );
391
- var DEFAULT_PREFERENCES = {
392
- necessary: true
393
- // Sempre ativo (essencial)
394
- };
395
- function createInitialPreferences(customCategories) {
396
- const prefs = { ...DEFAULT_PREFERENCES };
397
- if (customCategories) {
398
- customCategories.forEach((category) => {
399
- prefs[category.id] = category.essential === true;
400
- });
401
- }
402
- return prefs;
403
- }
404
- function createFullConsentState(consented, preferences, source, isModalOpen = false, existingState) {
659
+ function createFullConsentState(consented, preferences, source, projectConfig, isModalOpen = false, existingState) {
405
660
  const now = (/* @__PURE__ */ new Date()).toISOString();
406
661
  return {
407
662
  version: "1.0",
@@ -410,6 +665,7 @@ function createFullConsentState(consented, preferences, source, isModalOpen = fa
410
665
  consentDate: existingState?.consentDate || now,
411
666
  lastUpdate: now,
412
667
  source,
668
+ projectConfig,
413
669
  isModalOpen
414
670
  };
415
671
  }
@@ -445,22 +701,26 @@ var DEFAULT_TEXTS = {
445
701
  function reducer(state, action) {
446
702
  switch (action.type) {
447
703
  case "ACCEPT_ALL": {
448
- const prefs = createInitialPreferences(action.customCategories);
449
- Object.keys(prefs).forEach((key) => {
450
- prefs[key] = true;
451
- });
452
- return createFullConsentState(true, prefs, "banner", false, state);
704
+ const prefs = createProjectPreferences(action.config, true);
705
+ return createFullConsentState(
706
+ true,
707
+ prefs,
708
+ "banner",
709
+ action.config,
710
+ false,
711
+ state
712
+ );
453
713
  }
454
714
  case "REJECT_ALL": {
455
- const prefs = createInitialPreferences(action.customCategories);
456
- if (action.customCategories) {
457
- action.customCategories.forEach((category) => {
458
- if (category.essential) {
459
- prefs[category.id] = true;
460
- }
461
- });
462
- }
463
- return createFullConsentState(true, prefs, "banner", false, state);
715
+ const prefs = createProjectPreferences(action.config, false);
716
+ return createFullConsentState(
717
+ true,
718
+ prefs,
719
+ "banner",
720
+ action.config,
721
+ false,
722
+ state
723
+ );
464
724
  }
465
725
  case "SET_CATEGORY":
466
726
  return {
@@ -476,6 +736,7 @@ function reducer(state, action) {
476
736
  true,
477
737
  action.preferences,
478
738
  "modal",
739
+ action.config,
479
740
  false,
480
741
  state
481
742
  );
@@ -486,121 +747,133 @@ function reducer(state, action) {
486
747
  true,
487
748
  state.preferences,
488
749
  "modal",
750
+ action.config,
489
751
  false,
490
752
  state
491
753
  );
492
754
  case "RESET": {
493
755
  return createFullConsentState(
494
756
  false,
495
- createInitialPreferences(action.customCategories),
757
+ createProjectPreferences(action.config),
496
758
  "programmatic",
759
+ action.config,
497
760
  false
498
761
  );
499
762
  }
500
- case "HYDRATE":
501
- return { ...action.state, isModalOpen: false };
502
- // Nunca hidratar com modal aberto
763
+ case "HYDRATE": {
764
+ const validatedPreferences = validateProjectPreferences(
765
+ action.state.preferences,
766
+ action.config
767
+ );
768
+ return {
769
+ ...action.state,
770
+ preferences: validatedPreferences,
771
+ isModalOpen: false
772
+ };
773
+ }
503
774
  default:
504
775
  return state;
505
776
  }
506
777
  }
507
- var StateCtx = React3.createContext(null);
508
- var ActionsCtx = React3.createContext(null);
509
- var TextsCtx = React3.createContext(DEFAULT_TEXTS);
510
- var HydrationCtx = React3.createContext(false);
778
+ var StateCtx = React4.createContext(null);
779
+ var ActionsCtx = React4.createContext(null);
780
+ var TextsCtx = React4.createContext(DEFAULT_TEXTS);
781
+ var HydrationCtx = React4.createContext(false);
511
782
  function ConsentProvider({
512
783
  initialState,
513
784
  categories,
514
- // NOVO: configuração completa de categorias
785
+ // Nova prop para configuração de categorias
515
786
  texts: textsProp,
516
787
  theme,
517
- customCategories,
518
- // LEGACY: compatibilidade
788
+ designTokens,
519
789
  scriptIntegrations,
520
790
  // eslint-disable-line no-unused-vars
521
791
  PreferencesModalComponent,
522
792
  preferencesModalProps = {},
523
- disableAutomaticModal = false,
793
+ CookieBannerComponent,
794
+ cookieBannerProps = {},
795
+ FloatingPreferencesButtonComponent,
796
+ floatingPreferencesButtonProps = {},
797
+ disableFloatingPreferencesButton = false,
524
798
  hideBranding = false,
525
799
  onConsentGiven,
526
800
  onPreferencesSaved,
527
801
  cookie: cookieOpts,
528
802
  disableDeveloperGuidance,
529
- // NOVO: desabilita avisos de dev
530
803
  children
531
804
  }) {
532
- const texts = React3.useMemo(
805
+ const texts = React4.useMemo(
533
806
  () => ({ ...DEFAULT_TEXTS, ...textsProp ?? {} }),
534
807
  [textsProp]
535
808
  );
536
- const cookie = React3.useMemo(
809
+ const cookie = React4.useMemo(
537
810
  () => ({ ...DEFAULT_COOKIE_OPTS, ...cookieOpts ?? {} }),
538
811
  [cookieOpts]
539
812
  );
540
- const appliedTheme = React3.useMemo(
813
+ const appliedTheme = React4.useMemo(
541
814
  () => theme || defaultConsentTheme,
542
815
  [theme]
543
816
  );
544
- const finalCategoriesConfig = React3.useMemo(() => {
817
+ const finalCategoriesConfig = React4.useMemo(() => {
545
818
  if (categories) return categories;
546
- if (customCategories) {
547
- return {
548
- enabledCategories: ["analytics"],
549
- // padrão quando usando API antiga
550
- customCategories
551
- };
552
- }
553
- return void 0;
554
- }, [categories, customCategories]);
819
+ return DEFAULT_PROJECT_CATEGORIES;
820
+ }, [categories]);
555
821
  useDeveloperGuidance(finalCategoriesConfig, disableDeveloperGuidance);
556
- const boot = React3.useMemo(() => {
822
+ const boot = React4.useMemo(() => {
557
823
  if (initialState) return { ...initialState, isModalOpen: false };
558
824
  return createFullConsentState(
559
825
  false,
560
- createInitialPreferences(customCategories),
826
+ createProjectPreferences(finalCategoriesConfig),
561
827
  "banner",
828
+ finalCategoriesConfig,
562
829
  false
563
830
  );
564
- }, [initialState, customCategories]);
565
- const [state, dispatch] = React3.useReducer(reducer, boot);
566
- const [isHydrated, setIsHydrated] = React3.useState(false);
567
- React3.useEffect(() => {
831
+ }, [initialState, finalCategoriesConfig]);
832
+ const [state, dispatch] = React4.useReducer(reducer, boot);
833
+ const [isHydrated, setIsHydrated] = React4.useState(false);
834
+ React4.useEffect(() => {
568
835
  if (!initialState) {
569
836
  const saved = readConsentCookie(cookie.name);
570
837
  if (saved?.consented) {
571
- console.log("\u{1F680} Immediate hydration: Cookie found", saved);
572
- dispatch({ type: "HYDRATE", state: saved });
838
+ dispatch({
839
+ type: "HYDRATE",
840
+ state: saved,
841
+ config: finalCategoriesConfig
842
+ });
573
843
  }
574
844
  }
575
845
  setIsHydrated(true);
576
- }, [cookie.name, initialState]);
577
- React3.useEffect(() => {
578
- if (state.consented) writeConsentCookie(state, state.source, cookie);
579
- }, [state, cookie]);
580
- const prevConsented = React3.useRef(state.consented);
581
- React3.useEffect(() => {
846
+ }, [cookie.name, initialState, finalCategoriesConfig]);
847
+ React4.useEffect(() => {
848
+ if (state.consented)
849
+ writeConsentCookie(state, finalCategoriesConfig, cookie);
850
+ }, [state, cookie, finalCategoriesConfig]);
851
+ const prevConsented = React4.useRef(state.consented);
852
+ React4.useEffect(() => {
582
853
  if (!prevConsented.current && state.consented && onConsentGiven) {
583
854
  setTimeout(() => onConsentGiven(state), 150);
584
855
  }
585
856
  prevConsented.current = state.consented;
586
857
  }, [state, onConsentGiven]);
587
- const prevPrefs = React3.useRef(state.preferences);
588
- React3.useEffect(() => {
589
- if (state.consented && onPreferencesSaved && prevPrefs.current !== state.preferences) {
590
- setTimeout(() => onPreferencesSaved(state.preferences), 150);
591
- prevPrefs.current = state.preferences;
592
- }
593
- }, [state, onPreferencesSaved]);
594
- const api = React3.useMemo(() => {
595
- const acceptAll = () => dispatch({ type: "ACCEPT_ALL", customCategories });
596
- const rejectAll = () => dispatch({ type: "REJECT_ALL", customCategories });
858
+ const api = React4.useMemo(() => {
859
+ const acceptAll = () => dispatch({ type: "ACCEPT_ALL", config: finalCategoriesConfig });
860
+ const rejectAll = () => dispatch({ type: "REJECT_ALL", config: finalCategoriesConfig });
597
861
  const setPreference = (category, value) => dispatch({ type: "SET_CATEGORY", category, value });
598
- const setPreferences = (preferences) => dispatch({ type: "SET_PREFERENCES", preferences });
862
+ const setPreferences = (preferences) => {
863
+ dispatch({
864
+ type: "SET_PREFERENCES",
865
+ preferences,
866
+ config: finalCategoriesConfig
867
+ });
868
+ if (onPreferencesSaved) {
869
+ setTimeout(() => onPreferencesSaved(preferences), 150);
870
+ }
871
+ };
599
872
  const openPreferences = () => dispatch({ type: "OPEN_MODAL" });
600
- const closePreferences = () => dispatch({ type: "CLOSE_MODAL" });
873
+ const closePreferences = () => dispatch({ type: "CLOSE_MODAL", config: finalCategoriesConfig });
601
874
  const resetConsent = () => {
602
875
  removeConsentCookie(cookie);
603
- dispatch({ type: "RESET", customCategories });
876
+ dispatch({ type: "RESET", config: finalCategoriesConfig });
604
877
  };
605
878
  return {
606
879
  consented: !!state.consented,
@@ -614,37 +887,66 @@ function ConsentProvider({
614
887
  closePreferences,
615
888
  resetConsent
616
889
  };
617
- }, [state, cookie, customCategories]);
618
- return /* @__PURE__ */ jsx2(ThemeProvider, { theme: appliedTheme, children: /* @__PURE__ */ jsx2(StateCtx.Provider, { value: state, children: /* @__PURE__ */ jsx2(ActionsCtx.Provider, { value: api, children: /* @__PURE__ */ jsx2(TextsCtx.Provider, { value: texts, children: /* @__PURE__ */ jsx2(HydrationCtx.Provider, { value: isHydrated, children: /* @__PURE__ */ jsxs(
890
+ }, [state, cookie, finalCategoriesConfig, onPreferencesSaved]);
891
+ return /* @__PURE__ */ jsx6(ThemeProvider, { theme: appliedTheme, children: /* @__PURE__ */ jsx6(StateCtx.Provider, { value: state, children: /* @__PURE__ */ jsx6(ActionsCtx.Provider, { value: api, children: /* @__PURE__ */ jsx6(TextsCtx.Provider, { value: texts, children: /* @__PURE__ */ jsx6(HydrationCtx.Provider, { value: isHydrated, children: /* @__PURE__ */ jsx6(DesignProvider, { tokens: designTokens, children: /* @__PURE__ */ jsxs3(
619
892
  CategoriesProvider,
620
893
  {
621
894
  config: finalCategoriesConfig,
622
- categories: customCategories,
895
+ disableDeveloperGuidance,
623
896
  children: [
624
897
  children,
625
- !disableAutomaticModal && /* @__PURE__ */ jsx2(React3.Suspense, { fallback: null, children: PreferencesModalComponent ? /* @__PURE__ */ jsx2(PreferencesModalComponent, { ...preferencesModalProps }) : /* @__PURE__ */ jsx2(PreferencesModal, { hideBranding }) })
898
+ /* @__PURE__ */ jsx6(React4.Suspense, { fallback: null, children: PreferencesModalComponent ? /* @__PURE__ */ jsx6(
899
+ PreferencesModalComponent,
900
+ {
901
+ preferences: api.preferences,
902
+ setPreferences: api.setPreferences,
903
+ closePreferences: api.closePreferences,
904
+ isModalOpen: api.isModalOpen,
905
+ texts,
906
+ ...preferencesModalProps
907
+ }
908
+ ) : /* @__PURE__ */ jsx6(PreferencesModal, { hideBranding }) }),
909
+ !state.consented && isHydrated && (CookieBannerComponent ? /* @__PURE__ */ jsx6(
910
+ CookieBannerComponent,
911
+ {
912
+ consented: api.consented,
913
+ acceptAll: api.acceptAll,
914
+ rejectAll: api.rejectAll,
915
+ openPreferences: api.openPreferences,
916
+ texts,
917
+ ...cookieBannerProps
918
+ }
919
+ ) : /* @__PURE__ */ jsx6(CookieBanner, {})),
920
+ state.consented && !disableFloatingPreferencesButton && (FloatingPreferencesButtonComponent ? /* @__PURE__ */ jsx6(
921
+ FloatingPreferencesButtonComponent,
922
+ {
923
+ openPreferences: api.openPreferences,
924
+ consented: api.consented,
925
+ ...floatingPreferencesButtonProps
926
+ }
927
+ ) : /* @__PURE__ */ jsx6(FloatingPreferencesButton, {}))
626
928
  ]
627
929
  }
628
- ) }) }) }) }) });
930
+ ) }) }) }) }) }) });
629
931
  }
630
932
  function useConsentStateInternal() {
631
- const ctx = React3.useContext(StateCtx);
933
+ const ctx = React4.useContext(StateCtx);
632
934
  if (!ctx)
633
935
  throw new Error("useConsentState must be used within ConsentProvider");
634
936
  return ctx;
635
937
  }
636
938
  function useConsentActionsInternal() {
637
- const ctx = React3.useContext(ActionsCtx);
939
+ const ctx = React4.useContext(ActionsCtx);
638
940
  if (!ctx)
639
941
  throw new Error("useConsentActions must be used within ConsentProvider");
640
942
  return ctx;
641
943
  }
642
944
  function useConsentTextsInternal() {
643
- const ctx = React3.useContext(TextsCtx);
945
+ const ctx = React4.useContext(TextsCtx);
644
946
  return ctx;
645
947
  }
646
948
  function useConsentHydrationInternal() {
647
- return React3.useContext(HydrationCtx);
949
+ return React4.useContext(HydrationCtx);
648
950
  }
649
951
 
650
952
  // src/hooks/useConsent.ts
@@ -671,67 +973,8 @@ function useConsentHydration() {
671
973
  return useConsentHydrationInternal();
672
974
  }
673
975
 
674
- // src/components/Branding.tsx
675
- import Link from "@mui/material/Link";
676
- import Typography from "@mui/material/Typography";
677
- import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
678
- var brandingStyles = {
679
- banner: {
680
- fontSize: "0.65rem",
681
- textAlign: "center",
682
- mt: 1,
683
- opacity: 0.7,
684
- fontStyle: "italic"
685
- },
686
- modal: {
687
- fontSize: "0.65rem",
688
- textAlign: "center",
689
- px: 3,
690
- pb: 1,
691
- opacity: 0.7,
692
- fontStyle: "italic"
693
- }
694
- };
695
- var linkStyles = {
696
- textDecoration: "none",
697
- fontWeight: 500,
698
- "&:hover": {
699
- textDecoration: "underline"
700
- }
701
- };
702
- function Branding({ variant, hidden = false }) {
703
- if (hidden) return null;
704
- return /* @__PURE__ */ jsxs2(
705
- Typography,
706
- {
707
- variant: "caption",
708
- sx: (theme) => ({
709
- ...brandingStyles[variant],
710
- color: theme.palette.text.secondary
711
- }),
712
- children: [
713
- "fornecido por",
714
- " ",
715
- /* @__PURE__ */ jsx3(
716
- Link,
717
- {
718
- href: "https://www.ledipo.eti.br",
719
- target: "_blank",
720
- rel: "noopener noreferrer",
721
- sx: (theme) => ({
722
- ...linkStyles,
723
- color: theme.palette.primary.main
724
- }),
725
- children: "L\xC9dipO.eti.br"
726
- }
727
- )
728
- ]
729
- }
730
- );
731
- }
732
-
733
976
  // src/components/PreferencesModal.tsx
734
- import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
977
+ import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
735
978
  function PreferencesModal2({
736
979
  DialogProps: DialogProps2,
737
980
  hideBranding = false
@@ -765,7 +1008,7 @@ function PreferencesModal2({
765
1008
  setTempPreferences(preferences);
766
1009
  closePreferences();
767
1010
  };
768
- return /* @__PURE__ */ jsxs3(
1011
+ return /* @__PURE__ */ jsxs4(
769
1012
  Dialog,
770
1013
  {
771
1014
  "aria-labelledby": "cookie-pref-title",
@@ -773,14 +1016,14 @@ function PreferencesModal2({
773
1016
  onClose: handleCancel,
774
1017
  ...DialogProps2,
775
1018
  children: [
776
- /* @__PURE__ */ jsx4(DialogTitle, { id: "cookie-pref-title", children: texts.modalTitle }),
777
- /* @__PURE__ */ jsxs3(DialogContent, { dividers: true, children: [
778
- /* @__PURE__ */ jsx4(Typography2, { variant: "body2", sx: { mb: 2 }, children: texts.modalIntro }),
779
- /* @__PURE__ */ jsxs3(FormGroup, { children: [
780
- toggleableCategories.map((category) => /* @__PURE__ */ jsx4(
1019
+ /* @__PURE__ */ jsx7(DialogTitle, { id: "cookie-pref-title", children: texts.modalTitle }),
1020
+ /* @__PURE__ */ jsxs4(DialogContent, { dividers: true, children: [
1021
+ /* @__PURE__ */ jsx7(Typography3, { variant: "body2", sx: { mb: 2 }, children: texts.modalIntro }),
1022
+ /* @__PURE__ */ jsxs4(FormGroup, { children: [
1023
+ toggleableCategories.map((category) => /* @__PURE__ */ jsx7(
781
1024
  FormControlLabel,
782
1025
  {
783
- control: /* @__PURE__ */ jsx4(
1026
+ control: /* @__PURE__ */ jsx7(
784
1027
  Switch,
785
1028
  {
786
1029
  checked: tempPreferences[category.id] ?? false,
@@ -794,36 +1037,34 @@ function PreferencesModal2({
794
1037
  },
795
1038
  category.id
796
1039
  )),
797
- /* @__PURE__ */ jsx4(
1040
+ /* @__PURE__ */ jsx7(
798
1041
  FormControlLabel,
799
1042
  {
800
- control: /* @__PURE__ */ jsx4(Switch, { checked: true, disabled: true }),
1043
+ control: /* @__PURE__ */ jsx7(Switch, { checked: true, disabled: true }),
801
1044
  label: texts.necessaryAlwaysOn
802
1045
  }
803
1046
  )
804
1047
  ] })
805
1048
  ] }),
806
- !hideBranding && /* @__PURE__ */ jsx4(Branding, { variant: "modal" }),
807
- /* @__PURE__ */ jsxs3(DialogActions, { children: [
808
- /* @__PURE__ */ jsx4(Button, { variant: "outlined", onClick: handleCancel, children: "Cancelar" }),
809
- /* @__PURE__ */ jsx4(Button, { variant: "contained", onClick: handleSave, children: texts.save })
810
- ] })
1049
+ /* @__PURE__ */ jsxs4(DialogActions, { children: [
1050
+ /* @__PURE__ */ jsx7(Button2, { variant: "outlined", onClick: handleCancel, children: "Cancelar" }),
1051
+ /* @__PURE__ */ jsx7(Button2, { variant: "contained", onClick: handleSave, children: texts.save })
1052
+ ] }),
1053
+ !hideBranding && /* @__PURE__ */ jsx7(Branding, { variant: "modal" })
811
1054
  ]
812
1055
  }
813
1056
  );
814
1057
  }
815
1058
 
816
1059
  export {
817
- defaultConsentTheme,
818
1060
  DEFAULT_PROJECT_CATEGORIES,
819
1061
  analyzeDeveloperConfiguration,
820
1062
  useCategories,
821
1063
  useCategoryStatus,
822
- useCustomCategories,
823
- Branding,
824
- PreferencesModal2 as PreferencesModal,
1064
+ defaultConsentTheme,
825
1065
  ConsentProvider,
826
1066
  useConsent,
827
1067
  useConsentTexts,
828
- useConsentHydration
1068
+ useConsentHydration,
1069
+ PreferencesModal2 as PreferencesModal
829
1070
  };