@react-lgpd-consent/mui 0.6.3 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -28,6 +28,12 @@ pnpm add @react-lgpd-consent/mui @mui/material @mui/icons-material
28
28
  - `@mui/icons-material@^7.0.0 || ^6.0.0 || ^5.15.0` (opcional)
29
29
  - `react@^18.2.0 || ^19.0.0`, `react-dom@^18.2.0 || ^19.0.0`
30
30
 
31
+ ### Entradas de importação (evite ambiguidades)
32
+
33
+ - `@react-lgpd-consent/mui/ui`: **apenas UI** (ConsentProvider MUI + componentes). Ideal para bundles menores e sem re-export do core.
34
+ - `@react-lgpd-consent/mui`: compatibilidade total (re-exporta o core); use `headless` ou `ConsentProviderHeadless` daqui se precisar da lógica.
35
+ - `@react-lgpd-consent/core`: headless puro, recomendado para hooks/utils na sua própria UI.
36
+
31
37
  ## 🚀 Uso Básico
32
38
 
33
39
  ```tsx
@@ -70,6 +76,40 @@ function App() {
70
76
  }
71
77
  ```
72
78
 
79
+ ## 🆕 Novidades v0.7.0
80
+
81
+ ### Callbacks de Lifecycle
82
+
83
+ Monitore eventos para auditoria:
84
+
85
+ ```tsx
86
+ import { ConsentProvider } from '@react-lgpd-consent/mui'
87
+
88
+ <ConsentProvider
89
+ onConsentInit={(state) => console.log('Inicializado:', state)}
90
+ onConsentChange={(current, prev) => console.log('Mudou:', current)}
91
+ onAuditLog={(entry) => {
92
+ fetch('/api/audit', { method: 'POST', body: JSON.stringify(entry) })
93
+ }}
94
+ >
95
+ ```
96
+
97
+ ### Presets ANPD
98
+
99
+ ```tsx
100
+ import { createAnpdCategories } from '@react-lgpd-consent/mui'
101
+
102
+ const categories = createAnpdCategories({
103
+ include: ['analytics', 'marketing']
104
+ })
105
+
106
+ <ConsentProvider categories={categories}>
107
+ ```
108
+
109
+ 📖 **Documentação completa:** [API.md](../react-lgpd-consent/API.md) | [TROUBLESHOOTING.md](../../TROUBLESHOOTING.md)
110
+
111
+ ---
112
+
73
113
  ### Uso Headless (Avançado)
74
114
 
75
115
  Se você quiser controle total sobre a UI:
@@ -135,4 +175,3 @@ function CustomUI() {
135
175
  ## 📄 Licença
136
176
 
137
177
  MIT © [Luciano Édipo](https://github.com/lucianoedipo)
138
-
package/dist/index.cjs CHANGED
@@ -42,6 +42,7 @@ function _interopNamespace(e) {
42
42
  return Object.freeze(n);
43
43
  }
44
44
 
45
+ var core__namespace = /*#__PURE__*/_interopNamespace(core);
45
46
  var Link__default = /*#__PURE__*/_interopDefault(Link);
46
47
  var Typography__default = /*#__PURE__*/_interopDefault(Typography);
47
48
  var React3__namespace = /*#__PURE__*/_interopNamespace(React3);
@@ -211,15 +212,16 @@ function CookieBanner({
211
212
  ] }),
212
213
  !hideBranding && /* @__PURE__ */ jsxRuntime.jsx(Branding, { variant: "banner" })
213
214
  ] }) });
214
- const positionStyle = {
215
+ const resolveBannerZIndex = (theme) => designTokens?.layout?.zIndex?.banner ?? theme?.zIndex?.snackbar ?? 1400;
216
+ const positionStyle = (theme) => ({
215
217
  position: "fixed",
216
- zIndex: 1300,
218
+ zIndex: resolveBannerZIndex(theme),
217
219
  ...designTokens?.layout?.position === "top" ? { top: 0 } : { bottom: 0 },
218
220
  left: 0,
219
221
  right: 0,
220
222
  width: designTokens?.layout?.width?.desktop ?? "100%",
221
223
  p: 2
222
- };
224
+ });
223
225
  const backdropToken = designTokens?.layout?.backdrop;
224
226
  const resolveBackdropColor = (theme) => {
225
227
  if (backdropToken === false) return "transparent";
@@ -235,8 +237,8 @@ function CookieBanner({
235
237
  };
236
238
  const isSafeRoute = (() => {
237
239
  try {
238
- if (typeof window === "undefined") return false;
239
- const current = new URL(window.location.href);
240
+ if (globalThis?.window === void 0) return false;
241
+ const current = new URL(globalThis.window.location.href);
240
242
  const safeUrls = [policyLinkUrl, termsLinkUrl].filter(Boolean);
241
243
  return safeUrls.some((u) => {
242
244
  try {
@@ -263,12 +265,12 @@ function CookieBanner({
263
265
  right: 0,
264
266
  bottom: 0,
265
267
  backgroundColor: resolveBackdropColor(theme),
266
- zIndex: 1299
268
+ zIndex: designTokens?.layout?.zIndex?.backdrop ?? (resolveBannerZIndex(theme) ? resolveBannerZIndex(theme) - 1 : 1299)
267
269
  }),
268
270
  "data-testid": "lgpd-cookie-banner-overlay"
269
271
  }
270
272
  ),
271
- /* @__PURE__ */ jsxRuntime.jsx(Box2__default.default, { sx: positionStyle, children: bannerContent })
273
+ /* @__PURE__ */ jsxRuntime.jsx(Box2__default.default, { sx: positionStyle, "data-testid": "lgpd-cookie-banner-wrapper", children: bannerContent })
272
274
  ] });
273
275
  }
274
276
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -401,7 +403,8 @@ function PreferencesModal({
401
403
  });
402
404
  }
403
405
  }, [isModalOpen, getInitialPreferences]);
404
- const open = DialogProps2?.open ?? isModalOpen ?? false;
406
+ const { open: dialogOpenProp, ...dialogRest } = DialogProps2 ?? {};
407
+ const open = dialogOpenProp ?? isModalOpen ?? false;
405
408
  const handleSave = () => {
406
409
  setPreferences(tempPreferences);
407
410
  };
@@ -418,7 +421,32 @@ function PreferencesModal({
418
421
  backgroundColor: designTokens?.colors?.background ?? theme.palette.background.paper,
419
422
  color: designTokens?.colors?.text ?? theme.palette.text.primary
420
423
  });
421
- return /* @__PURE__ */ jsxRuntime.jsxs(Dialog__default.default, { "aria-labelledby": "cookie-pref-title", open, onClose: handleCancel, ...DialogProps2, children: [
424
+ const resolveModalZIndex = React3__namespace.useCallback(
425
+ (theme) => designTokens?.layout?.zIndex?.modal ?? (theme?.zIndex?.modal ?? 1300) + 10,
426
+ [designTokens?.layout?.zIndex?.modal]
427
+ );
428
+ const modalZIndexToken = designTokens?.layout?.zIndex?.modal;
429
+ const rootSx = [
430
+ DialogProps2?.slotProps?.root && DialogProps2.slotProps.root.sx,
431
+ (theme) => ({ zIndex: resolveModalZIndex(theme) })
432
+ ].filter(Boolean);
433
+ const rootSlotProps = {
434
+ ...dialogRest?.slotProps?.root,
435
+ sx: rootSx,
436
+ ...modalZIndexToken ? { style: { zIndex: modalZIndexToken } } : {},
437
+ "data-testid": dialogRest?.slotProps?.root?.["data-testid"] ?? "lgpd-preferences-modal-root"
438
+ };
439
+ const mergedDialogProps = {
440
+ open,
441
+ fullWidth: true,
442
+ maxWidth: "sm",
443
+ ...dialogRest,
444
+ slotProps: {
445
+ ...dialogRest?.slotProps,
446
+ root: rootSlotProps
447
+ }
448
+ };
449
+ return /* @__PURE__ */ jsxRuntime.jsxs(Dialog__default.default, { "aria-labelledby": "cookie-pref-title", onClose: handleCancel, ...mergedDialogProps, children: [
422
450
  /* @__PURE__ */ jsxRuntime.jsx(DialogTitle__default.default, { id: "cookie-pref-title", sx: modalTitleSx, children: texts.modalTitle }),
423
451
  /* @__PURE__ */ jsxRuntime.jsxs(DialogContent__default.default, { dividers: true, sx: modalContentSx, children: [
424
452
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -452,7 +480,7 @@ function PreferencesModal({
452
480
  });
453
481
  const merged = [
454
482
  ...enrichedDescriptors,
455
- ...namesFromGuidance.filter((n) => !enrichedDescriptors.find((d) => d.name === n)).map((n) => ({ name: n, purpose: "-", duration: "-", provider: "-" }))
483
+ ...namesFromGuidance.filter((n) => !enrichedDescriptors.some((d) => d.name === n)).map((n) => ({ name: n, purpose: "-", duration: "-", provider: "-" }))
456
484
  ];
457
485
  let mergedFinal = merged;
458
486
  try {
@@ -587,6 +615,7 @@ Object.defineProperty(exports, "ConsentProviderHeadless", {
587
615
  enumerable: true,
588
616
  get: function () { return core.ConsentProvider; }
589
617
  });
618
+ exports.headless = core__namespace;
590
619
  exports.Branding = Branding;
591
620
  exports.ConsentProvider = ConsentProvider;
592
621
  exports.CookieBanner = CookieBanner;
package/dist/index.d.cts CHANGED
@@ -1,5 +1,7 @@
1
1
  import { ConsentProviderProps as ConsentProviderProps$1, ConsentPreferences } from '@react-lgpd-consent/core';
2
2
  export * from '@react-lgpd-consent/core';
3
+ import * as core from '@react-lgpd-consent/core';
4
+ export { core as headless };
3
5
  export { ConsentProvider as ConsentProviderHeadless } from '@react-lgpd-consent/core';
4
6
  import * as React from 'react';
5
7
  import * as react_jsx_runtime from 'react/jsx-runtime';
@@ -468,7 +470,7 @@ interface ConsentProviderProps extends ConsentProviderProps$1 {
468
470
  * @see {@link FloatingPreferencesButton} Para o botão flutuante usado por padrão
469
471
  * @see {@link https://mui.com/material-ui/customization/theming/ | MUI Theming Guide} Para customização de tema
470
472
  */
471
- declare function ConsentProvider({ disableDefaultModal, disableDefaultBanner, disableDefaultFloatingButton, PreferencesModalComponent, CookieBannerComponent, FloatingPreferencesButtonComponent, theme, hideBranding, cookieBannerProps, preferencesModalProps, floatingPreferencesButtonProps, children, ...coreProps }: ConsentProviderProps): react_jsx_runtime.JSX.Element;
473
+ declare function ConsentProvider({ disableDefaultModal, disableDefaultBanner, disableDefaultFloatingButton, PreferencesModalComponent, CookieBannerComponent, FloatingPreferencesButtonComponent, theme, hideBranding, cookieBannerProps, preferencesModalProps, floatingPreferencesButtonProps, children, ...coreProps }: Readonly<ConsentProviderProps>): react_jsx_runtime.JSX.Element;
472
474
  declare namespace ConsentProvider {
473
475
  var displayName: string;
474
476
  }
package/dist/index.d.ts CHANGED
@@ -1,5 +1,7 @@
1
1
  import { ConsentProviderProps as ConsentProviderProps$1, ConsentPreferences } from '@react-lgpd-consent/core';
2
2
  export * from '@react-lgpd-consent/core';
3
+ import * as core from '@react-lgpd-consent/core';
4
+ export { core as headless };
3
5
  export { ConsentProvider as ConsentProviderHeadless } from '@react-lgpd-consent/core';
4
6
  import * as React from 'react';
5
7
  import * as react_jsx_runtime from 'react/jsx-runtime';
@@ -468,7 +470,7 @@ interface ConsentProviderProps extends ConsentProviderProps$1 {
468
470
  * @see {@link FloatingPreferencesButton} Para o botão flutuante usado por padrão
469
471
  * @see {@link https://mui.com/material-ui/customization/theming/ | MUI Theming Guide} Para customização de tema
470
472
  */
471
- declare function ConsentProvider({ disableDefaultModal, disableDefaultBanner, disableDefaultFloatingButton, PreferencesModalComponent, CookieBannerComponent, FloatingPreferencesButtonComponent, theme, hideBranding, cookieBannerProps, preferencesModalProps, floatingPreferencesButtonProps, children, ...coreProps }: ConsentProviderProps): react_jsx_runtime.JSX.Element;
473
+ declare function ConsentProvider({ disableDefaultModal, disableDefaultBanner, disableDefaultFloatingButton, PreferencesModalComponent, CookieBannerComponent, FloatingPreferencesButtonComponent, theme, hideBranding, cookieBannerProps, preferencesModalProps, floatingPreferencesButtonProps, children, ...coreProps }: Readonly<ConsentProviderProps>): react_jsx_runtime.JSX.Element;
472
474
  declare namespace ConsentProvider {
473
475
  var displayName: string;
474
476
  }
package/dist/index.js CHANGED
@@ -1,5 +1,7 @@
1
1
  import { useConsentTexts, useDesignTokens, useConsent, logger, useConsentHydration, useCategories, getCookiesInfoForCategory, ConsentProvider as ConsentProvider$1 } from '@react-lgpd-consent/core';
2
2
  export * from '@react-lgpd-consent/core';
3
+ import * as core from '@react-lgpd-consent/core';
4
+ export { core as headless };
3
5
  export { ConsentProvider as ConsentProviderHeadless } from '@react-lgpd-consent/core';
4
6
  import Link from '@mui/material/Link';
5
7
  import Typography from '@mui/material/Typography';
@@ -172,15 +174,16 @@ function CookieBanner({
172
174
  ] }),
173
175
  !hideBranding && /* @__PURE__ */ jsx(Branding, { variant: "banner" })
174
176
  ] }) });
175
- const positionStyle = {
177
+ const resolveBannerZIndex = (theme) => designTokens?.layout?.zIndex?.banner ?? theme?.zIndex?.snackbar ?? 1400;
178
+ const positionStyle = (theme) => ({
176
179
  position: "fixed",
177
- zIndex: 1300,
180
+ zIndex: resolveBannerZIndex(theme),
178
181
  ...designTokens?.layout?.position === "top" ? { top: 0 } : { bottom: 0 },
179
182
  left: 0,
180
183
  right: 0,
181
184
  width: designTokens?.layout?.width?.desktop ?? "100%",
182
185
  p: 2
183
- };
186
+ });
184
187
  const backdropToken = designTokens?.layout?.backdrop;
185
188
  const resolveBackdropColor = (theme) => {
186
189
  if (backdropToken === false) return "transparent";
@@ -196,8 +199,8 @@ function CookieBanner({
196
199
  };
197
200
  const isSafeRoute = (() => {
198
201
  try {
199
- if (typeof window === "undefined") return false;
200
- const current = new URL(window.location.href);
202
+ if (globalThis?.window === void 0) return false;
203
+ const current = new URL(globalThis.window.location.href);
201
204
  const safeUrls = [policyLinkUrl, termsLinkUrl].filter(Boolean);
202
205
  return safeUrls.some((u) => {
203
206
  try {
@@ -224,12 +227,12 @@ function CookieBanner({
224
227
  right: 0,
225
228
  bottom: 0,
226
229
  backgroundColor: resolveBackdropColor(theme),
227
- zIndex: 1299
230
+ zIndex: designTokens?.layout?.zIndex?.backdrop ?? (resolveBannerZIndex(theme) ? resolveBannerZIndex(theme) - 1 : 1299)
228
231
  }),
229
232
  "data-testid": "lgpd-cookie-banner-overlay"
230
233
  }
231
234
  ),
232
- /* @__PURE__ */ jsx(Box2, { sx: positionStyle, children: bannerContent })
235
+ /* @__PURE__ */ jsx(Box2, { sx: positionStyle, "data-testid": "lgpd-cookie-banner-wrapper", children: bannerContent })
233
236
  ] });
234
237
  }
235
238
  return /* @__PURE__ */ jsx(
@@ -362,7 +365,8 @@ function PreferencesModal({
362
365
  });
363
366
  }
364
367
  }, [isModalOpen, getInitialPreferences]);
365
- const open = DialogProps2?.open ?? isModalOpen ?? false;
368
+ const { open: dialogOpenProp, ...dialogRest } = DialogProps2 ?? {};
369
+ const open = dialogOpenProp ?? isModalOpen ?? false;
366
370
  const handleSave = () => {
367
371
  setPreferences(tempPreferences);
368
372
  };
@@ -379,7 +383,32 @@ function PreferencesModal({
379
383
  backgroundColor: designTokens?.colors?.background ?? theme.palette.background.paper,
380
384
  color: designTokens?.colors?.text ?? theme.palette.text.primary
381
385
  });
382
- return /* @__PURE__ */ jsxs(Dialog, { "aria-labelledby": "cookie-pref-title", open, onClose: handleCancel, ...DialogProps2, children: [
386
+ const resolveModalZIndex = React3.useCallback(
387
+ (theme) => designTokens?.layout?.zIndex?.modal ?? (theme?.zIndex?.modal ?? 1300) + 10,
388
+ [designTokens?.layout?.zIndex?.modal]
389
+ );
390
+ const modalZIndexToken = designTokens?.layout?.zIndex?.modal;
391
+ const rootSx = [
392
+ DialogProps2?.slotProps?.root && DialogProps2.slotProps.root.sx,
393
+ (theme) => ({ zIndex: resolveModalZIndex(theme) })
394
+ ].filter(Boolean);
395
+ const rootSlotProps = {
396
+ ...dialogRest?.slotProps?.root,
397
+ sx: rootSx,
398
+ ...modalZIndexToken ? { style: { zIndex: modalZIndexToken } } : {},
399
+ "data-testid": dialogRest?.slotProps?.root?.["data-testid"] ?? "lgpd-preferences-modal-root"
400
+ };
401
+ const mergedDialogProps = {
402
+ open,
403
+ fullWidth: true,
404
+ maxWidth: "sm",
405
+ ...dialogRest,
406
+ slotProps: {
407
+ ...dialogRest?.slotProps,
408
+ root: rootSlotProps
409
+ }
410
+ };
411
+ return /* @__PURE__ */ jsxs(Dialog, { "aria-labelledby": "cookie-pref-title", onClose: handleCancel, ...mergedDialogProps, children: [
383
412
  /* @__PURE__ */ jsx(DialogTitle, { id: "cookie-pref-title", sx: modalTitleSx, children: texts.modalTitle }),
384
413
  /* @__PURE__ */ jsxs(DialogContent, { dividers: true, sx: modalContentSx, children: [
385
414
  /* @__PURE__ */ jsx(
@@ -413,7 +442,7 @@ function PreferencesModal({
413
442
  });
414
443
  const merged = [
415
444
  ...enrichedDescriptors,
416
- ...namesFromGuidance.filter((n) => !enrichedDescriptors.find((d) => d.name === n)).map((n) => ({ name: n, purpose: "-", duration: "-", provider: "-" }))
445
+ ...namesFromGuidance.filter((n) => !enrichedDescriptors.some((d) => d.name === n)).map((n) => ({ name: n, purpose: "-", duration: "-", provider: "-" }))
417
446
  ];
418
447
  let mergedFinal = merged;
419
448
  try {