react-lgpd-consent 0.1.13 → 0.2.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
@@ -145,10 +145,81 @@ var init_theme = __esm({
145
145
  }
146
146
  });
147
147
 
148
+ // src/context/CategoriesContext.tsx
149
+ function CategoriesProvider({
150
+ categories,
151
+ children
152
+ }) {
153
+ const value = React.useMemo(() => categories || [], [categories]);
154
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CategoriesCtx.Provider, { value, children });
155
+ }
156
+ function useCustomCategories() {
157
+ return React.useContext(CategoriesCtx);
158
+ }
159
+ function useAllCategories() {
160
+ const customCategories = useCustomCategories();
161
+ return React.useMemo(() => {
162
+ const defaultCategories = [
163
+ {
164
+ id: "necessary",
165
+ name: "Cookies Necess\xE1rios",
166
+ description: "Essenciais para o funcionamento b\xE1sico do site. Incluem cookies de sess\xE3o, autentica\xE7\xE3o e seguran\xE7a.",
167
+ essential: true,
168
+ cookies: ["PHPSESSID", "JSESSIONID", "cookieConsent", "csrf_token"]
169
+ },
170
+ {
171
+ id: "analytics",
172
+ name: "Analytics e Estat\xEDsticas",
173
+ description: "Permitem medir audi\xEAncia e desempenho, gerando estat\xEDsticas an\xF4nimas de uso.",
174
+ essential: false,
175
+ cookies: ["_ga", "_ga_*", "_gid", "_gat", "gtag"]
176
+ },
177
+ {
178
+ id: "functional",
179
+ name: "Cookies Funcionais",
180
+ description: "Melhoram a experi\xEAncia do usu\xE1rio, lembrando prefer\xEAncias e configura\xE7\xF5es.",
181
+ essential: false,
182
+ cookies: ["language", "theme", "timezone", "preferences"]
183
+ },
184
+ {
185
+ id: "marketing",
186
+ name: "Marketing e Publicidade",
187
+ description: "Utilizados para publicidade direcionada e medi\xE7\xE3o de campanhas publicit\xE1rias.",
188
+ essential: false,
189
+ cookies: ["_fbp", "fr", "tr", "ads_*", "doubleclick"]
190
+ },
191
+ {
192
+ id: "social",
193
+ name: "Redes Sociais",
194
+ description: "Permitem compartilhamento e integra\xE7\xE3o com redes sociais como Facebook, YouTube, etc.",
195
+ essential: false,
196
+ cookies: ["__Secure-*", "sb", "datr", "c_user", "social_*"]
197
+ },
198
+ {
199
+ id: "personalization",
200
+ name: "Personaliza\xE7\xE3o",
201
+ description: "Adaptam o conte\xFAdo e interface \xE0s prefer\xEAncias individuais do usu\xE1rio.",
202
+ essential: false,
203
+ cookies: ["personalization_*", "content_*", "layout_*"]
204
+ }
205
+ ];
206
+ return [...defaultCategories, ...customCategories];
207
+ }, [customCategories]);
208
+ }
209
+ var React, import_jsx_runtime, CategoriesCtx;
210
+ var init_CategoriesContext = __esm({
211
+ "src/context/CategoriesContext.tsx"() {
212
+ "use strict";
213
+ React = __toESM(require("react"), 1);
214
+ import_jsx_runtime = require("react/jsx-runtime");
215
+ CategoriesCtx = React.createContext([]);
216
+ }
217
+ });
218
+
148
219
  // src/components/Branding.tsx
149
220
  function Branding({ variant, hidden = false }) {
150
221
  if (hidden) return null;
151
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
222
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
152
223
  import_Typography.default,
153
224
  {
154
225
  variant: "caption",
@@ -159,7 +230,7 @@ function Branding({ variant, hidden = false }) {
159
230
  children: [
160
231
  "fornecido por",
161
232
  " ",
162
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
233
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
163
234
  import_Link.default,
164
235
  {
165
236
  href: "https://www.ledipo.eti.br",
@@ -176,13 +247,13 @@ function Branding({ variant, hidden = false }) {
176
247
  }
177
248
  );
178
249
  }
179
- var import_Link, import_Typography, import_jsx_runtime, brandingStyles, linkStyles;
250
+ var import_Link, import_Typography, import_jsx_runtime2, brandingStyles, linkStyles;
180
251
  var init_Branding = __esm({
181
252
  "src/components/Branding.tsx"() {
182
253
  "use strict";
183
254
  import_Link = __toESM(require("@mui/material/Link"), 1);
184
255
  import_Typography = __toESM(require("@mui/material/Typography"), 1);
185
- import_jsx_runtime = require("react/jsx-runtime");
256
+ import_jsx_runtime2 = require("react/jsx-runtime");
186
257
  brandingStyles = {
187
258
  banner: {
188
259
  fontSize: "0.65rem",
@@ -235,7 +306,7 @@ function PreferencesModal({
235
306
  setTempPreferences(preferences);
236
307
  closePreferences();
237
308
  };
238
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
309
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
239
310
  import_Dialog.default,
240
311
  {
241
312
  "aria-labelledby": "cookie-pref-title",
@@ -243,14 +314,14 @@ function PreferencesModal({
243
314
  onClose: handleCancel,
244
315
  ...DialogProps2,
245
316
  children: [
246
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_DialogTitle.default, { id: "cookie-pref-title", children: texts.modalTitle }),
247
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_DialogContent.default, { dividers: true, children: [
248
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_Typography2.default, { variant: "body2", sx: { mb: 2 }, children: texts.modalIntro }),
249
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_FormGroup.default, { children: [
250
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
317
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_DialogTitle.default, { id: "cookie-pref-title", children: texts.modalTitle }),
318
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_DialogContent.default, { dividers: true, children: [
319
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_Typography2.default, { variant: "body2", sx: { mb: 2 }, children: texts.modalIntro }),
320
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_FormGroup.default, { children: [
321
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
251
322
  import_FormControlLabel.default,
252
323
  {
253
- control: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
324
+ control: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
254
325
  import_Switch.default,
255
326
  {
256
327
  checked: tempPreferences.analytics,
@@ -263,10 +334,10 @@ function PreferencesModal({
263
334
  label: "Cookies Anal\xEDticos (medem uso do site)"
264
335
  }
265
336
  ),
266
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
337
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
267
338
  import_FormControlLabel.default,
268
339
  {
269
- control: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
340
+ control: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
270
341
  import_Switch.default,
271
342
  {
272
343
  checked: tempPreferences.marketing,
@@ -279,25 +350,25 @@ function PreferencesModal({
279
350
  label: "Cookies de Marketing/Publicidade"
280
351
  }
281
352
  ),
282
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
353
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
283
354
  import_FormControlLabel.default,
284
355
  {
285
- control: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_Switch.default, { checked: true, disabled: true }),
356
+ control: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_Switch.default, { checked: true, disabled: true }),
286
357
  label: texts.necessaryAlwaysOn
287
358
  }
288
359
  )
289
360
  ] })
290
361
  ] }),
291
- !hideBranding && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Branding, { variant: "modal" }),
292
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_DialogActions.default, { children: [
293
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_Button.default, { variant: "outlined", onClick: handleCancel, children: "Cancelar" }),
294
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_Button.default, { variant: "contained", onClick: handleSave, children: texts.save })
362
+ !hideBranding && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Branding, { variant: "modal" }),
363
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_DialogActions.default, { children: [
364
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_Button.default, { variant: "outlined", onClick: handleCancel, children: "Cancelar" }),
365
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_Button.default, { variant: "contained", onClick: handleSave, children: texts.save })
295
366
  ] })
296
367
  ]
297
368
  }
298
369
  );
299
370
  }
300
- var import_Button, import_Dialog, import_DialogActions, import_DialogContent, import_DialogTitle, import_FormControlLabel, import_FormGroup, import_Switch, import_Typography2, import_react, import_jsx_runtime2;
371
+ var import_Button, import_Dialog, import_DialogActions, import_DialogContent, import_DialogTitle, import_FormControlLabel, import_FormGroup, import_Switch, import_Typography2, import_react, import_jsx_runtime3;
301
372
  var init_PreferencesModal = __esm({
302
373
  "src/components/PreferencesModal.tsx"() {
303
374
  "use strict";
@@ -313,25 +384,48 @@ var init_PreferencesModal = __esm({
313
384
  import_react = require("react");
314
385
  init_useConsent();
315
386
  init_Branding();
316
- import_jsx_runtime2 = require("react/jsx-runtime");
387
+ import_jsx_runtime3 = require("react/jsx-runtime");
317
388
  }
318
389
  });
319
390
 
320
391
  // src/context/ConsentContext.tsx
392
+ function createInitialPreferences(customCategories) {
393
+ const prefs = { ...DEFAULT_PREFERENCES };
394
+ if (customCategories) {
395
+ customCategories.forEach((category) => {
396
+ prefs[category.id] = category.essential === true;
397
+ });
398
+ }
399
+ return prefs;
400
+ }
321
401
  function reducer(state, action) {
322
402
  switch (action.type) {
323
- case "ACCEPT_ALL":
403
+ case "ACCEPT_ALL": {
404
+ const prefs = createInitialPreferences(action.customCategories);
405
+ Object.keys(prefs).forEach((key) => {
406
+ prefs[key] = true;
407
+ });
324
408
  return {
325
409
  consented: true,
326
- preferences: { analytics: true, marketing: true },
410
+ preferences: prefs,
327
411
  isModalOpen: false
328
412
  };
329
- case "REJECT_ALL":
413
+ }
414
+ case "REJECT_ALL": {
415
+ const prefs = createInitialPreferences(action.customCategories);
416
+ if (action.customCategories) {
417
+ action.customCategories.forEach((category) => {
418
+ if (category.essential) {
419
+ prefs[category.id] = true;
420
+ }
421
+ });
422
+ }
330
423
  return {
331
424
  consented: true,
332
- preferences: { analytics: false, marketing: false },
425
+ preferences: prefs,
333
426
  isModalOpen: false
334
427
  };
428
+ }
335
429
  case "SET_CATEGORY":
336
430
  return {
337
431
  ...state,
@@ -352,12 +446,13 @@ function reducer(state, action) {
352
446
  case "CLOSE_MODAL":
353
447
  return { ...state, isModalOpen: false, consented: true };
354
448
  // houve interação
355
- case "RESET":
449
+ case "RESET": {
356
450
  return {
357
451
  consented: false,
358
- preferences: { ...DEFAULT_PREFERENCES },
452
+ preferences: createInitialPreferences(action.customCategories),
359
453
  isModalOpen: false
360
454
  };
455
+ }
361
456
  case "HYDRATE":
362
457
  return { ...action.state };
363
458
  default:
@@ -368,6 +463,8 @@ function ConsentProvider({
368
463
  initialState,
369
464
  texts: textsProp,
370
465
  theme,
466
+ customCategories,
467
+ scriptIntegrations,
371
468
  PreferencesModalComponent,
372
469
  preferencesModalProps = {},
373
470
  disableAutomaticModal = false,
@@ -377,29 +474,29 @@ function ConsentProvider({
377
474
  cookie: cookieOpts,
378
475
  children
379
476
  }) {
380
- const texts = React.useMemo(
477
+ const texts = React2.useMemo(
381
478
  () => ({ ...DEFAULT_TEXTS, ...textsProp ?? {} }),
382
479
  [textsProp]
383
480
  );
384
- const cookie = React.useMemo(
481
+ const cookie = React2.useMemo(
385
482
  () => ({ ...DEFAULT_COOKIE_OPTS, ...cookieOpts ?? {} }),
386
483
  [cookieOpts]
387
484
  );
388
- const appliedTheme = React.useMemo(
485
+ const appliedTheme = React2.useMemo(
389
486
  () => theme || defaultConsentTheme,
390
487
  [theme]
391
488
  );
392
- const boot = React.useMemo(() => {
489
+ const boot = React2.useMemo(() => {
393
490
  if (initialState) return { ...initialState, isModalOpen: false };
394
491
  return {
395
492
  consented: false,
396
- preferences: { ...DEFAULT_PREFERENCES },
493
+ preferences: createInitialPreferences(customCategories),
397
494
  isModalOpen: false
398
495
  };
399
- }, [initialState]);
400
- const [state, dispatch] = React.useReducer(reducer, boot);
401
- const [isHydrated, setIsHydrated] = React.useState(false);
402
- React.useEffect(() => {
496
+ }, [initialState, customCategories]);
497
+ const [state, dispatch] = React2.useReducer(reducer, boot);
498
+ const [isHydrated, setIsHydrated] = React2.useState(false);
499
+ React2.useEffect(() => {
403
500
  if (!initialState) {
404
501
  const saved = readConsentCookie(cookie.name);
405
502
  if (saved?.consented) {
@@ -409,33 +506,33 @@ function ConsentProvider({
409
506
  }
410
507
  setIsHydrated(true);
411
508
  }, [cookie.name, initialState]);
412
- React.useEffect(() => {
509
+ React2.useEffect(() => {
413
510
  if (state.consented) writeConsentCookie(state, cookie);
414
511
  }, [state, cookie]);
415
- const prevConsented = React.useRef(state.consented);
416
- React.useEffect(() => {
512
+ const prevConsented = React2.useRef(state.consented);
513
+ React2.useEffect(() => {
417
514
  if (!prevConsented.current && state.consented && onConsentGiven) {
418
515
  setTimeout(() => onConsentGiven(state), 150);
419
516
  }
420
517
  prevConsented.current = state.consented;
421
518
  }, [state, onConsentGiven]);
422
- const prevPrefs = React.useRef(state.preferences);
423
- React.useEffect(() => {
519
+ const prevPrefs = React2.useRef(state.preferences);
520
+ React2.useEffect(() => {
424
521
  if (state.consented && onPreferencesSaved && prevPrefs.current !== state.preferences) {
425
522
  setTimeout(() => onPreferencesSaved(state.preferences), 150);
426
523
  prevPrefs.current = state.preferences;
427
524
  }
428
525
  }, [state, onPreferencesSaved]);
429
- const api = React.useMemo(() => {
430
- const acceptAll = () => dispatch({ type: "ACCEPT_ALL" });
431
- const rejectAll = () => dispatch({ type: "REJECT_ALL" });
526
+ const api = React2.useMemo(() => {
527
+ const acceptAll = () => dispatch({ type: "ACCEPT_ALL", customCategories });
528
+ const rejectAll = () => dispatch({ type: "REJECT_ALL", customCategories });
432
529
  const setPreference = (category, value) => dispatch({ type: "SET_CATEGORY", category, value });
433
530
  const setPreferences = (preferences) => dispatch({ type: "SET_PREFERENCES", preferences });
434
531
  const openPreferences = () => dispatch({ type: "OPEN_MODAL" });
435
532
  const closePreferences = () => dispatch({ type: "CLOSE_MODAL" });
436
533
  const resetConsent = () => {
437
534
  removeConsentCookie(cookie);
438
- dispatch({ type: "RESET" });
535
+ dispatch({ type: "RESET", customCategories });
439
536
  };
440
537
  return {
441
538
  consented: !!state.consented,
@@ -449,50 +546,57 @@ function ConsentProvider({
449
546
  closePreferences,
450
547
  resetConsent
451
548
  };
452
- }, [state, cookie]);
453
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_styles2.ThemeProvider, { theme: appliedTheme, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(StateCtx.Provider, { value: state, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ActionsCtx.Provider, { value: api, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(TextsCtx.Provider, { value: texts, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(HydrationCtx.Provider, { value: isHydrated, children: [
549
+ }, [state, cookie, customCategories]);
550
+ 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)(CategoriesProvider, { categories: customCategories, children: [
454
551
  children,
455
- !disableAutomaticModal && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(React.Suspense, { fallback: null, children: PreferencesModalComponent ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(PreferencesModalComponent, { ...preferencesModalProps }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(PreferencesModal2, { hideBranding }) })
456
- ] }) }) }) }) });
552
+ !disableAutomaticModal && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(React2.Suspense, { fallback: null, children: PreferencesModalComponent ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PreferencesModalComponent, { ...preferencesModalProps }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PreferencesModal2, { hideBranding }) })
553
+ ] }) }) }) }) }) });
457
554
  }
458
555
  function useConsentStateInternal() {
459
- const ctx = React.useContext(StateCtx);
556
+ const ctx = React2.useContext(StateCtx);
460
557
  if (!ctx)
461
558
  throw new Error("useConsentState must be used within ConsentProvider");
462
559
  return ctx;
463
560
  }
464
561
  function useConsentActionsInternal() {
465
- const ctx = React.useContext(ActionsCtx);
562
+ const ctx = React2.useContext(ActionsCtx);
466
563
  if (!ctx)
467
564
  throw new Error("useConsentActions must be used within ConsentProvider");
468
565
  return ctx;
469
566
  }
470
567
  function useConsentTextsInternal() {
471
- const ctx = React.useContext(TextsCtx);
568
+ const ctx = React2.useContext(TextsCtx);
472
569
  return ctx;
473
570
  }
474
571
  function useConsentHydrationInternal() {
475
- return React.useContext(HydrationCtx);
572
+ return React2.useContext(HydrationCtx);
476
573
  }
477
- var React, import_styles2, import_jsx_runtime3, PreferencesModal2, DEFAULT_PREFERENCES, DEFAULT_TEXTS, StateCtx, ActionsCtx, TextsCtx, HydrationCtx;
574
+ var React2, import_styles2, import_jsx_runtime4, PreferencesModal2, DEFAULT_PREFERENCES, DEFAULT_TEXTS, StateCtx, ActionsCtx, TextsCtx, HydrationCtx;
478
575
  var init_ConsentContext = __esm({
479
576
  "src/context/ConsentContext.tsx"() {
480
577
  "use strict";
481
- React = __toESM(require("react"), 1);
578
+ React2 = __toESM(require("react"), 1);
482
579
  import_styles2 = require("@mui/material/styles");
483
580
  init_cookieUtils();
484
581
  init_theme();
485
- import_jsx_runtime3 = require("react/jsx-runtime");
486
- PreferencesModal2 = React.lazy(
582
+ init_CategoriesContext();
583
+ import_jsx_runtime4 = require("react/jsx-runtime");
584
+ PreferencesModal2 = React2.lazy(
487
585
  () => Promise.resolve().then(() => (init_PreferencesModal(), PreferencesModal_exports)).then((m) => ({
488
586
  default: m.PreferencesModal
489
587
  }))
490
588
  );
491
589
  DEFAULT_PREFERENCES = {
590
+ necessary: true,
591
+ // Sempre ativo (essencial)
492
592
  analytics: false,
493
- marketing: false
593
+ functional: false,
594
+ marketing: false,
595
+ social: false,
596
+ personalization: false
494
597
  };
495
598
  DEFAULT_TEXTS = {
599
+ // Textos básicos
496
600
  bannerMessage: "Utilizamos cookies para melhorar sua experi\xEAncia.",
497
601
  acceptAll: "Aceitar todos",
498
602
  declineAll: "Recusar",
@@ -501,12 +605,29 @@ var init_ConsentContext = __esm({
501
605
  modalTitle: "Prefer\xEAncias de Cookies",
502
606
  modalIntro: "Ajuste as categorias de cookies. Cookies necess\xE1rios s\xE3o sempre utilizados para funcionalidades b\xE1sicas.",
503
607
  save: "Salvar prefer\xEAncias",
504
- necessaryAlwaysOn: "Cookies necess\xE1rios (sempre ativos)"
608
+ necessaryAlwaysOn: "Cookies necess\xE1rios (sempre ativos)",
609
+ // Textos ANPD expandidos (opcionais)
610
+ controllerInfo: void 0,
611
+ // Exibido se definido
612
+ dataTypes: void 0,
613
+ // Exibido se definido
614
+ thirdPartySharing: void 0,
615
+ // Exibido se definido
616
+ userRights: void 0,
617
+ // Exibido se definido
618
+ contactInfo: void 0,
619
+ // Exibido se definido
620
+ retentionPeriod: void 0,
621
+ // Exibido se definido
622
+ lawfulBasis: void 0,
623
+ // Exibido se definido
624
+ transferCountries: void 0
625
+ // Exibido se definido
505
626
  };
506
- StateCtx = React.createContext(null);
507
- ActionsCtx = React.createContext(null);
508
- TextsCtx = React.createContext(DEFAULT_TEXTS);
509
- HydrationCtx = React.createContext(false);
627
+ StateCtx = React2.createContext(null);
628
+ ActionsCtx = React2.createContext(null);
629
+ TextsCtx = React2.createContext(DEFAULT_TEXTS);
630
+ HydrationCtx = React2.createContext(false);
510
631
  }
511
632
  });
512
633
 
@@ -543,16 +664,24 @@ var init_useConsent = __esm({
543
664
  // src/index.ts
544
665
  var index_exports = {};
545
666
  __export(index_exports, {
667
+ COMMON_INTEGRATIONS: () => COMMON_INTEGRATIONS,
546
668
  ConsentGate: () => ConsentGate,
547
669
  ConsentProvider: () => ConsentProvider,
670
+ ConsentScriptLoader: () => ConsentScriptLoader,
548
671
  CookieBanner: () => CookieBanner,
549
672
  FloatingPreferencesButton: () => FloatingPreferencesButton,
550
673
  PreferencesModal: () => PreferencesModal,
674
+ createGoogleAnalyticsIntegration: () => createGoogleAnalyticsIntegration,
675
+ createGoogleTagManagerIntegration: () => createGoogleTagManagerIntegration,
676
+ createUserWayIntegration: () => createUserWayIntegration,
551
677
  defaultConsentTheme: () => defaultConsentTheme,
552
678
  loadScript: () => loadScript,
679
+ useAllCategories: () => useAllCategories,
553
680
  useConsent: () => useConsent,
554
681
  useConsentHydration: () => useConsentHydration,
555
- useConsentTexts: () => useConsentTexts
682
+ useConsentScriptLoader: () => useConsentScriptLoader,
683
+ useConsentTexts: () => useConsentTexts,
684
+ useCustomCategories: () => useCustomCategories
556
685
  });
557
686
  module.exports = __toCommonJS(index_exports);
558
687
 
@@ -566,7 +695,7 @@ var import_Typography3 = __toESM(require("@mui/material/Typography"), 1);
566
695
  var import_Link2 = __toESM(require("@mui/material/Link"), 1);
567
696
  init_useConsent();
568
697
  init_Branding();
569
- var import_jsx_runtime4 = require("react/jsx-runtime");
698
+ var import_jsx_runtime5 = require("react/jsx-runtime");
570
699
  function CookieBanner({
571
700
  policyLinkUrl,
572
701
  debug,
@@ -581,17 +710,17 @@ function CookieBanner({
581
710
  const isHydrated = useConsentHydration();
582
711
  const open = debug ? true : isHydrated && !consented;
583
712
  if (!open) return null;
584
- const bannerContent = /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
713
+ const bannerContent = /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
585
714
  import_Paper.default,
586
715
  {
587
716
  elevation: 3,
588
717
  sx: { p: 2, maxWidth: 720, mx: "auto" },
589
718
  ...PaperProps,
590
- children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_Stack.default, { spacing: 1, children: [
591
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_Typography3.default, { variant: "body2", children: [
719
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_Stack.default, { spacing: 1, children: [
720
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_Typography3.default, { variant: "body2", children: [
592
721
  texts.bannerMessage,
593
722
  " ",
594
- policyLinkUrl && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
723
+ policyLinkUrl && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
595
724
  import_Link2.default,
596
725
  {
597
726
  href: policyLinkUrl,
@@ -602,26 +731,26 @@ function CookieBanner({
602
731
  }
603
732
  )
604
733
  ] }),
605
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
734
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
606
735
  import_Stack.default,
607
736
  {
608
737
  direction: { xs: "column", sm: "row" },
609
738
  spacing: 1,
610
739
  justifyContent: "flex-end",
611
740
  children: [
612
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_Button2.default, { variant: "outlined", onClick: rejectAll, children: texts.declineAll }),
613
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_Button2.default, { variant: "contained", onClick: acceptAll, children: texts.acceptAll }),
614
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_Button2.default, { variant: "text", onClick: openPreferences, children: texts.preferences })
741
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_Button2.default, { variant: "outlined", onClick: rejectAll, children: texts.declineAll }),
742
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_Button2.default, { variant: "contained", onClick: acceptAll, children: texts.acceptAll }),
743
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_Button2.default, { variant: "text", onClick: openPreferences, children: texts.preferences })
615
744
  ]
616
745
  }
617
746
  ),
618
- !hideBranding && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Branding, { variant: "banner" })
747
+ !hideBranding && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Branding, { variant: "banner" })
619
748
  ] })
620
749
  }
621
750
  );
622
751
  if (blocking) {
623
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
624
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
752
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
753
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
625
754
  import_Box.default,
626
755
  {
627
756
  sx: {
@@ -636,7 +765,7 @@ function CookieBanner({
636
765
  }
637
766
  }
638
767
  ),
639
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
768
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
640
769
  import_Box.default,
641
770
  {
642
771
  sx: {
@@ -653,7 +782,7 @@ function CookieBanner({
653
782
  )
654
783
  ] });
655
784
  }
656
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
785
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
657
786
  import_Snackbar.default,
658
787
  {
659
788
  open,
@@ -673,11 +802,11 @@ var import_Fab = __toESM(require("@mui/material/Fab"), 1);
673
802
  var import_Tooltip = __toESM(require("@mui/material/Tooltip"), 1);
674
803
  var import_styles3 = require("@mui/material/styles");
675
804
  init_useConsent();
676
- var import_jsx_runtime5 = require("react/jsx-runtime");
805
+ var import_jsx_runtime6 = require("react/jsx-runtime");
677
806
  function FloatingPreferencesButton({
678
807
  position = "bottom-right",
679
808
  offset = 24,
680
- icon = /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_CookieOutlined.default, {}),
809
+ icon = /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_CookieOutlined.default, {}),
681
810
  tooltip,
682
811
  FabProps,
683
812
  hideWhenConsented = false
@@ -706,7 +835,7 @@ function FloatingPreferencesButton({
706
835
  return { ...styles, bottom: offset, right: offset };
707
836
  }
708
837
  };
709
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_Tooltip.default, { title: tooltipText, placement: "top", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
838
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_Tooltip.default, { title: tooltipText, placement: "top", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
710
839
  import_Fab.default,
711
840
  {
712
841
  size: "medium",
@@ -729,14 +858,15 @@ function FloatingPreferencesButton({
729
858
  // src/index.ts
730
859
  init_ConsentContext();
731
860
  init_useConsent();
861
+ init_CategoriesContext();
732
862
 
733
863
  // src/utils/ConsentGate.tsx
734
864
  init_useConsent();
735
- var import_jsx_runtime6 = require("react/jsx-runtime");
865
+ var import_jsx_runtime7 = require("react/jsx-runtime");
736
866
  function ConsentGate(props) {
737
867
  const { preferences } = useConsent();
738
868
  if (!preferences[props.category]) return null;
739
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_jsx_runtime6.Fragment, { children: props.children });
869
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_jsx_runtime7.Fragment, { children: props.children });
740
870
  }
741
871
 
742
872
  // src/utils/scriptLoader.ts
@@ -778,16 +908,162 @@ function loadScript(id, src, category = null, attrs = {}) {
778
908
 
779
909
  // src/index.ts
780
910
  init_theme();
911
+
912
+ // src/utils/ConsentScriptLoader.tsx
913
+ var React3 = __toESM(require("react"), 1);
914
+ init_useConsent();
915
+ function ConsentScriptLoader({
916
+ integrations,
917
+ reloadOnChange = false
918
+ }) {
919
+ const { preferences, consented } = useConsent();
920
+ const loadedScripts = React3.useRef(/* @__PURE__ */ new Set());
921
+ React3.useEffect(() => {
922
+ if (!consented) return;
923
+ integrations.forEach(async (integration) => {
924
+ const shouldLoad = preferences[integration.category];
925
+ const alreadyLoaded = loadedScripts.current.has(integration.id);
926
+ if (shouldLoad && (!alreadyLoaded || reloadOnChange)) {
927
+ try {
928
+ await loadScript(
929
+ integration.id,
930
+ integration.src,
931
+ integration.category,
932
+ // Categoria dinâmica
933
+ integration.attrs
934
+ );
935
+ if (integration.init) {
936
+ integration.init();
937
+ }
938
+ loadedScripts.current.add(integration.id);
939
+ console.log(
940
+ `\u2705 Script loaded: ${integration.id} (${integration.category})`
941
+ );
942
+ } catch (error) {
943
+ console.error(`\u274C Failed to load script: ${integration.id}`, error);
944
+ }
945
+ }
946
+ });
947
+ }, [preferences, consented, integrations, reloadOnChange]);
948
+ return null;
949
+ }
950
+ function useConsentScriptLoader() {
951
+ const { preferences, consented } = useConsent();
952
+ return React3.useCallback(
953
+ async (integration) => {
954
+ if (!consented) {
955
+ console.warn(
956
+ `\u26A0\uFE0F Cannot load script ${integration.id}: No consent given`
957
+ );
958
+ return false;
959
+ }
960
+ const shouldLoad = preferences[integration.category];
961
+ if (!shouldLoad) {
962
+ console.warn(
963
+ `\u26A0\uFE0F Cannot load script ${integration.id}: Category '${integration.category}' not consented`
964
+ );
965
+ return false;
966
+ }
967
+ try {
968
+ await loadScript(
969
+ integration.id,
970
+ integration.src,
971
+ integration.category,
972
+ // Categoria dinâmica
973
+ integration.attrs
974
+ );
975
+ if (integration.init) {
976
+ integration.init();
977
+ }
978
+ console.log(
979
+ `\u2705 Script loaded: ${integration.id} (${integration.category})`
980
+ );
981
+ return true;
982
+ } catch (error) {
983
+ console.error(`\u274C Failed to load script: ${integration.id}`, error);
984
+ return false;
985
+ }
986
+ },
987
+ [preferences, consented]
988
+ );
989
+ }
990
+
991
+ // src/utils/scriptIntegrations.ts
992
+ function createGoogleAnalyticsIntegration(config) {
993
+ return {
994
+ id: "google-analytics",
995
+ category: "analytics",
996
+ src: `https://www.googletagmanager.com/gtag/js?id=${config.measurementId}`,
997
+ init: () => {
998
+ if (typeof window !== "undefined") {
999
+ let gtag2 = function(...args) {
1000
+ window.dataLayer.push(arguments);
1001
+ };
1002
+ var gtag = gtag2;
1003
+ window.dataLayer = window.dataLayer || [];
1004
+ window.gtag = gtag2;
1005
+ gtag2("js", /* @__PURE__ */ new Date());
1006
+ gtag2("config", config.measurementId, config.config || {});
1007
+ }
1008
+ },
1009
+ attrs: { async: "true" }
1010
+ };
1011
+ }
1012
+ function createGoogleTagManagerIntegration(config) {
1013
+ return {
1014
+ id: "google-tag-manager",
1015
+ category: "analytics",
1016
+ src: `https://www.googletagmanager.com/gtm.js?id=${config.containerId}`,
1017
+ init: () => {
1018
+ if (typeof window !== "undefined") {
1019
+ const dataLayerName = config.dataLayerName || "dataLayer";
1020
+ window[dataLayerName] = window[dataLayerName] || [];
1021
+ window[dataLayerName].push({
1022
+ "gtm.start": (/* @__PURE__ */ new Date()).getTime(),
1023
+ event: "gtm.js"
1024
+ });
1025
+ }
1026
+ }
1027
+ };
1028
+ }
1029
+ function createUserWayIntegration(config) {
1030
+ return {
1031
+ id: "userway",
1032
+ category: "marketing",
1033
+ // ou poderia ser uma categoria 'accessibility'
1034
+ src: `https://cdn.userway.org/widget.js`,
1035
+ init: () => {
1036
+ if (typeof window !== "undefined") {
1037
+ window.UserWayWidgetApp = window.UserWayWidgetApp || {};
1038
+ window.UserWayWidgetApp.accountId = config.accountId;
1039
+ }
1040
+ },
1041
+ attrs: { "data-account": config.accountId }
1042
+ };
1043
+ }
1044
+ var COMMON_INTEGRATIONS = {
1045
+ googleAnalytics: createGoogleAnalyticsIntegration,
1046
+ googleTagManager: createGoogleTagManagerIntegration,
1047
+ userway: createUserWayIntegration
1048
+ };
781
1049
  // Annotate the CommonJS export names for ESM import in node:
782
1050
  0 && (module.exports = {
1051
+ COMMON_INTEGRATIONS,
783
1052
  ConsentGate,
784
1053
  ConsentProvider,
1054
+ ConsentScriptLoader,
785
1055
  CookieBanner,
786
1056
  FloatingPreferencesButton,
787
1057
  PreferencesModal,
1058
+ createGoogleAnalyticsIntegration,
1059
+ createGoogleTagManagerIntegration,
1060
+ createUserWayIntegration,
788
1061
  defaultConsentTheme,
789
1062
  loadScript,
1063
+ useAllCategories,
790
1064
  useConsent,
791
1065
  useConsentHydration,
792
- useConsentTexts
1066
+ useConsentScriptLoader,
1067
+ useConsentTexts,
1068
+ useCustomCategories
793
1069
  });