react-lgpd-consent 0.1.8 → 0.1.11
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 +50 -9
- package/dist/{PreferencesModal-4FDYT7VE.js → PreferencesModal-IHXZDNYT.js} +1 -1
- package/dist/{chunk-Y4XEAQXV.js → chunk-LRMSFSP2.js} +109 -28
- package/dist/index.cjs +203 -47
- package/dist/index.d.cts +30 -4
- package/dist/index.d.ts +30 -4
- package/dist/index.js +72 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,7 +2,39 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/react-lgpd-consent)
|
|
4
4
|
[](https://github.com/lucianoedipo/react-lgpd-consent/blob/main/LICENSE)
|
|
5
|
-
[
|
|
37
|
+
|
|
6
38
|
[](https://reactjs.org/)
|
|
7
39
|
[](https://mui.com/)
|
|
8
40
|
|
|
@@ -24,6 +56,7 @@ Solução moderna, acessível e personalizável para gerenciar consentimento de
|
|
|
24
56
|
- 🎨 **Sistema de Temas**: Temas customizáveis para integração visual perfeita
|
|
25
57
|
- ⚡ **Carregamento Condicional**: Scripts só executam após consentimento explícito
|
|
26
58
|
- 🔌 **Modal Automático**: Modal de preferências incluído automaticamente com lazy loading
|
|
59
|
+
- 🎛️ **Botão Flutuante**: Componente opcional para acesso fácil às preferências
|
|
27
60
|
|
|
28
61
|
## 🚀 Instalação
|
|
29
62
|
|
|
@@ -44,7 +77,11 @@ npm install @mui/material js-cookie
|
|
|
44
77
|
## � Exemplo Completo
|
|
45
78
|
|
|
46
79
|
```tsx
|
|
47
|
-
import {
|
|
80
|
+
import {
|
|
81
|
+
ConsentProvider,
|
|
82
|
+
CookieBanner,
|
|
83
|
+
FloatingPreferencesButton,
|
|
84
|
+
} from 'react-lgpd-consent'
|
|
48
85
|
|
|
49
86
|
function App() {
|
|
50
87
|
return (
|
|
@@ -53,8 +90,11 @@ function App() {
|
|
|
53
90
|
<h1>Meu Site</h1>
|
|
54
91
|
<p>Conteúdo do site...</p>
|
|
55
92
|
|
|
56
|
-
{/* Banner de cookies */}
|
|
93
|
+
{/* Banner de cookies - Modal incluído automaticamente! */}
|
|
57
94
|
<CookieBanner policyLinkUrl="/privacy-policy" blocking={true} />
|
|
95
|
+
|
|
96
|
+
{/* Botão flutuante opcional para acesso às preferências */}
|
|
97
|
+
<FloatingPreferencesButton position="bottom-right" />
|
|
58
98
|
</div>
|
|
59
99
|
</ConsentProvider>
|
|
60
100
|
)
|
|
@@ -343,12 +383,13 @@ Para controle total, desabilite o modal automático:
|
|
|
343
383
|
|
|
344
384
|
### Components
|
|
345
385
|
|
|
346
|
-
| Componente
|
|
347
|
-
|
|
|
348
|
-
| `ConsentProvider`
|
|
349
|
-
| `CookieBanner`
|
|
350
|
-
| `PreferencesModal`
|
|
351
|
-
| `
|
|
386
|
+
| Componente | Descrição | Props Principais |
|
|
387
|
+
| --------------------------- | ------------------------------------------------ | ---------------------------------------------------------------------------------------- |
|
|
388
|
+
| `ConsentProvider` | Provider principal do contexto | `initialState`, `texts`, `theme`, `hideBranding`, `PreferencesModalComponent`, callbacks |
|
|
389
|
+
| `CookieBanner` | Banner de consentimento | `policyLinkUrl`, `blocking`, `hideBranding`, `debug`, pass-through MUI props |
|
|
390
|
+
| `PreferencesModal` | Modal de preferências (incluído automaticamente) | `DialogProps`, `hideBranding` - **Opcional** |
|
|
391
|
+
| `FloatingPreferencesButton` | Botão flutuante para abrir preferências | `position`, `hideWhenConsented`, `tooltip`, `icon`, `FabProps` |
|
|
392
|
+
| `ConsentGate` | Renderização condicional por categoria | `category`, `children` |
|
|
352
393
|
|
|
353
394
|
### Hook `useConsent()`
|
|
354
395
|
|
|
@@ -7,8 +7,8 @@ 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
|
|
11
|
-
import {
|
|
10
|
+
import Typography2 from "@mui/material/Typography";
|
|
11
|
+
import { useEffect as useEffect2, useState as useState2 } from "react";
|
|
12
12
|
|
|
13
13
|
// src/context/ConsentContext.tsx
|
|
14
14
|
import * as React from "react";
|
|
@@ -20,7 +20,7 @@ var DEFAULT_COOKIE_OPTS = {
|
|
|
20
20
|
name: "cookieConsent",
|
|
21
21
|
maxAgeDays: 365,
|
|
22
22
|
sameSite: "Lax",
|
|
23
|
-
secure:
|
|
23
|
+
secure: typeof window !== "undefined" ? window.location.protocol === "https:" : false,
|
|
24
24
|
path: "/"
|
|
25
25
|
};
|
|
26
26
|
function readConsentCookie(name = DEFAULT_COOKIE_OPTS.name) {
|
|
@@ -123,7 +123,7 @@ var defaultConsentTheme = createTheme({
|
|
|
123
123
|
// src/context/ConsentContext.tsx
|
|
124
124
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
125
125
|
var PreferencesModal = React.lazy(
|
|
126
|
-
() => import("./PreferencesModal-
|
|
126
|
+
() => import("./PreferencesModal-IHXZDNYT.js").then((m) => ({
|
|
127
127
|
default: m.PreferencesModal
|
|
128
128
|
}))
|
|
129
129
|
);
|
|
@@ -191,6 +191,7 @@ function reducer(state, action) {
|
|
|
191
191
|
var StateCtx = React.createContext(null);
|
|
192
192
|
var ActionsCtx = React.createContext(null);
|
|
193
193
|
var TextsCtx = React.createContext(DEFAULT_TEXTS);
|
|
194
|
+
var HydrationCtx = React.createContext(false);
|
|
194
195
|
function ConsentProvider({
|
|
195
196
|
initialState,
|
|
196
197
|
texts: textsProp,
|
|
@@ -198,6 +199,7 @@ function ConsentProvider({
|
|
|
198
199
|
PreferencesModalComponent,
|
|
199
200
|
preferencesModalProps = {},
|
|
200
201
|
disableAutomaticModal = false,
|
|
202
|
+
hideBranding = false,
|
|
201
203
|
onConsentGiven,
|
|
202
204
|
onPreferencesSaved,
|
|
203
205
|
cookie: cookieOpts,
|
|
@@ -217,14 +219,24 @@ function ConsentProvider({
|
|
|
217
219
|
);
|
|
218
220
|
const boot = React.useMemo(() => {
|
|
219
221
|
if (initialState) return { ...initialState, isModalOpen: false };
|
|
220
|
-
|
|
221
|
-
return saved ?? {
|
|
222
|
+
return {
|
|
222
223
|
consented: false,
|
|
223
224
|
preferences: { ...DEFAULT_PREFERENCES },
|
|
224
225
|
isModalOpen: false
|
|
225
226
|
};
|
|
226
|
-
}, [initialState
|
|
227
|
+
}, [initialState]);
|
|
227
228
|
const [state, dispatch] = React.useReducer(reducer, boot);
|
|
229
|
+
const [isHydrated, setIsHydrated] = React.useState(false);
|
|
230
|
+
React.useEffect(() => {
|
|
231
|
+
if (typeof window !== "undefined" && !initialState) {
|
|
232
|
+
const saved = readConsentCookie(cookie.name);
|
|
233
|
+
if (saved?.consented) {
|
|
234
|
+
console.log("\u{1F680} Immediate hydration: Cookie found", saved);
|
|
235
|
+
dispatch({ type: "HYDRATE", state: saved });
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
setIsHydrated(true);
|
|
239
|
+
}, [cookie.name, initialState]);
|
|
228
240
|
React.useEffect(() => {
|
|
229
241
|
if (state.consented) writeConsentCookie(state, cookie);
|
|
230
242
|
}, [state, cookie]);
|
|
@@ -266,10 +278,10 @@ function ConsentProvider({
|
|
|
266
278
|
resetConsent
|
|
267
279
|
};
|
|
268
280
|
}, [state, cookie]);
|
|
269
|
-
return /* @__PURE__ */ jsx(ThemeProvider, { theme: appliedTheme, children: /* @__PURE__ */ jsx(StateCtx.Provider, { value: state, children: /* @__PURE__ */ jsx(ActionsCtx.Provider, { value: api, children: /* @__PURE__ */
|
|
281
|
+
return /* @__PURE__ */ jsx(ThemeProvider, { theme: appliedTheme, children: /* @__PURE__ */ jsx(StateCtx.Provider, { value: state, children: /* @__PURE__ */ jsx(ActionsCtx.Provider, { value: api, children: /* @__PURE__ */ jsx(TextsCtx.Provider, { value: texts, children: /* @__PURE__ */ jsxs(HydrationCtx.Provider, { value: isHydrated, children: [
|
|
270
282
|
children,
|
|
271
|
-
!disableAutomaticModal && /* @__PURE__ */ jsx(React.Suspense, { fallback: null, children: PreferencesModalComponent ? /* @__PURE__ */ jsx(PreferencesModalComponent, { ...preferencesModalProps }) : /* @__PURE__ */ jsx(PreferencesModal, {}) })
|
|
272
|
-
] }) }) }) });
|
|
283
|
+
!disableAutomaticModal && /* @__PURE__ */ jsx(React.Suspense, { fallback: null, children: PreferencesModalComponent ? /* @__PURE__ */ jsx(PreferencesModalComponent, { ...preferencesModalProps }) : /* @__PURE__ */ jsx(PreferencesModal, { hideBranding }) })
|
|
284
|
+
] }) }) }) }) });
|
|
273
285
|
}
|
|
274
286
|
function useConsentStateInternal() {
|
|
275
287
|
const ctx = React.useContext(StateCtx);
|
|
@@ -287,6 +299,9 @@ function useConsentTextsInternal() {
|
|
|
287
299
|
const ctx = React.useContext(TextsCtx);
|
|
288
300
|
return ctx;
|
|
289
301
|
}
|
|
302
|
+
function useConsentHydrationInternal() {
|
|
303
|
+
return React.useContext(HydrationCtx);
|
|
304
|
+
}
|
|
290
305
|
|
|
291
306
|
// src/hooks/useConsent.ts
|
|
292
307
|
function useConsent() {
|
|
@@ -308,15 +323,78 @@ function useConsent() {
|
|
|
308
323
|
function useConsentTexts() {
|
|
309
324
|
return useConsentTextsInternal();
|
|
310
325
|
}
|
|
326
|
+
function useConsentHydration() {
|
|
327
|
+
return useConsentHydrationInternal();
|
|
328
|
+
}
|
|
311
329
|
|
|
312
|
-
// src/components/
|
|
330
|
+
// src/components/Branding.tsx
|
|
331
|
+
import Link from "@mui/material/Link";
|
|
332
|
+
import Typography from "@mui/material/Typography";
|
|
313
333
|
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
334
|
+
var brandingStyles = {
|
|
335
|
+
banner: {
|
|
336
|
+
fontSize: "0.65rem",
|
|
337
|
+
textAlign: "center",
|
|
338
|
+
mt: 1,
|
|
339
|
+
opacity: 0.7,
|
|
340
|
+
fontStyle: "italic"
|
|
341
|
+
},
|
|
342
|
+
modal: {
|
|
343
|
+
fontSize: "0.65rem",
|
|
344
|
+
textAlign: "center",
|
|
345
|
+
px: 3,
|
|
346
|
+
pb: 1,
|
|
347
|
+
opacity: 0.7,
|
|
348
|
+
fontStyle: "italic"
|
|
349
|
+
}
|
|
350
|
+
};
|
|
351
|
+
var linkStyles = {
|
|
352
|
+
textDecoration: "none",
|
|
353
|
+
fontWeight: 500,
|
|
354
|
+
"&:hover": {
|
|
355
|
+
textDecoration: "underline"
|
|
356
|
+
}
|
|
357
|
+
};
|
|
358
|
+
function Branding({ variant, hidden = false }) {
|
|
359
|
+
if (hidden) return null;
|
|
360
|
+
return /* @__PURE__ */ jsxs2(
|
|
361
|
+
Typography,
|
|
362
|
+
{
|
|
363
|
+
variant: "caption",
|
|
364
|
+
sx: (theme) => ({
|
|
365
|
+
...brandingStyles[variant],
|
|
366
|
+
color: theme.palette.text.secondary
|
|
367
|
+
}),
|
|
368
|
+
children: [
|
|
369
|
+
"fornecido por",
|
|
370
|
+
" ",
|
|
371
|
+
/* @__PURE__ */ jsx2(
|
|
372
|
+
Link,
|
|
373
|
+
{
|
|
374
|
+
href: "https://ledipo.eti.br",
|
|
375
|
+
target: "_blank",
|
|
376
|
+
rel: "noopener noreferrer",
|
|
377
|
+
sx: (theme) => ({
|
|
378
|
+
...linkStyles,
|
|
379
|
+
color: theme.palette.primary.main
|
|
380
|
+
}),
|
|
381
|
+
children: "L\xC9dipO.eti.br"
|
|
382
|
+
}
|
|
383
|
+
)
|
|
384
|
+
]
|
|
385
|
+
}
|
|
386
|
+
);
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
// src/components/PreferencesModal.tsx
|
|
390
|
+
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
314
391
|
function PreferencesModal2({
|
|
315
|
-
DialogProps: DialogProps2
|
|
392
|
+
DialogProps: DialogProps2,
|
|
393
|
+
hideBranding = false
|
|
316
394
|
}) {
|
|
317
395
|
const { preferences, setPreferences, closePreferences, isModalOpen } = useConsent();
|
|
318
396
|
const texts = useConsentTexts();
|
|
319
|
-
const [tempPreferences, setTempPreferences] =
|
|
397
|
+
const [tempPreferences, setTempPreferences] = useState2(preferences);
|
|
320
398
|
useEffect2(() => {
|
|
321
399
|
if (isModalOpen) {
|
|
322
400
|
setTempPreferences(preferences);
|
|
@@ -330,7 +408,7 @@ function PreferencesModal2({
|
|
|
330
408
|
setTempPreferences(preferences);
|
|
331
409
|
closePreferences();
|
|
332
410
|
};
|
|
333
|
-
return /* @__PURE__ */
|
|
411
|
+
return /* @__PURE__ */ jsxs3(
|
|
334
412
|
Dialog,
|
|
335
413
|
{
|
|
336
414
|
"aria-labelledby": "cookie-pref-title",
|
|
@@ -338,14 +416,14 @@ function PreferencesModal2({
|
|
|
338
416
|
onClose: handleCancel,
|
|
339
417
|
...DialogProps2,
|
|
340
418
|
children: [
|
|
341
|
-
/* @__PURE__ */
|
|
342
|
-
/* @__PURE__ */
|
|
343
|
-
/* @__PURE__ */
|
|
344
|
-
/* @__PURE__ */
|
|
345
|
-
/* @__PURE__ */
|
|
419
|
+
/* @__PURE__ */ jsx3(DialogTitle, { id: "cookie-pref-title", children: texts.modalTitle }),
|
|
420
|
+
/* @__PURE__ */ jsxs3(DialogContent, { dividers: true, children: [
|
|
421
|
+
/* @__PURE__ */ jsx3(Typography2, { variant: "body2", sx: { mb: 2 }, children: texts.modalIntro }),
|
|
422
|
+
/* @__PURE__ */ jsxs3(FormGroup, { children: [
|
|
423
|
+
/* @__PURE__ */ jsx3(
|
|
346
424
|
FormControlLabel,
|
|
347
425
|
{
|
|
348
|
-
control: /* @__PURE__ */
|
|
426
|
+
control: /* @__PURE__ */ jsx3(
|
|
349
427
|
Switch,
|
|
350
428
|
{
|
|
351
429
|
checked: tempPreferences.analytics,
|
|
@@ -358,10 +436,10 @@ function PreferencesModal2({
|
|
|
358
436
|
label: "Cookies Anal\xEDticos (medem uso do site)"
|
|
359
437
|
}
|
|
360
438
|
),
|
|
361
|
-
/* @__PURE__ */
|
|
439
|
+
/* @__PURE__ */ jsx3(
|
|
362
440
|
FormControlLabel,
|
|
363
441
|
{
|
|
364
|
-
control: /* @__PURE__ */
|
|
442
|
+
control: /* @__PURE__ */ jsx3(
|
|
365
443
|
Switch,
|
|
366
444
|
{
|
|
367
445
|
checked: tempPreferences.marketing,
|
|
@@ -374,18 +452,19 @@ function PreferencesModal2({
|
|
|
374
452
|
label: "Cookies de Marketing/Publicidade"
|
|
375
453
|
}
|
|
376
454
|
),
|
|
377
|
-
/* @__PURE__ */
|
|
455
|
+
/* @__PURE__ */ jsx3(
|
|
378
456
|
FormControlLabel,
|
|
379
457
|
{
|
|
380
|
-
control: /* @__PURE__ */
|
|
458
|
+
control: /* @__PURE__ */ jsx3(Switch, { checked: true, disabled: true }),
|
|
381
459
|
label: texts.necessaryAlwaysOn
|
|
382
460
|
}
|
|
383
461
|
)
|
|
384
462
|
] })
|
|
385
463
|
] }),
|
|
386
|
-
/* @__PURE__ */
|
|
387
|
-
|
|
388
|
-
/* @__PURE__ */
|
|
464
|
+
!hideBranding && /* @__PURE__ */ jsx3(Branding, { variant: "modal" }),
|
|
465
|
+
/* @__PURE__ */ jsxs3(DialogActions, { children: [
|
|
466
|
+
/* @__PURE__ */ jsx3(Button, { variant: "outlined", onClick: handleCancel, children: "Cancelar" }),
|
|
467
|
+
/* @__PURE__ */ jsx3(Button, { variant: "contained", onClick: handleSave, children: texts.save })
|
|
389
468
|
] })
|
|
390
469
|
]
|
|
391
470
|
}
|
|
@@ -394,8 +473,10 @@ function PreferencesModal2({
|
|
|
394
473
|
|
|
395
474
|
export {
|
|
396
475
|
defaultConsentTheme,
|
|
476
|
+
Branding,
|
|
397
477
|
PreferencesModal2 as PreferencesModal,
|
|
398
478
|
ConsentProvider,
|
|
399
479
|
useConsent,
|
|
400
|
-
useConsentTexts
|
|
480
|
+
useConsentTexts,
|
|
481
|
+
useConsentHydration
|
|
401
482
|
};
|
package/dist/index.cjs
CHANGED
|
@@ -65,7 +65,7 @@ var init_cookieUtils = __esm({
|
|
|
65
65
|
name: "cookieConsent",
|
|
66
66
|
maxAgeDays: 365,
|
|
67
67
|
sameSite: "Lax",
|
|
68
|
-
secure:
|
|
68
|
+
secure: typeof window !== "undefined" ? window.location.protocol === "https:" : false,
|
|
69
69
|
path: "/"
|
|
70
70
|
};
|
|
71
71
|
}
|
|
@@ -148,13 +148,79 @@ var init_theme = __esm({
|
|
|
148
148
|
}
|
|
149
149
|
});
|
|
150
150
|
|
|
151
|
+
// src/components/Branding.tsx
|
|
152
|
+
function Branding({ variant, hidden = false }) {
|
|
153
|
+
if (hidden) return null;
|
|
154
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
155
|
+
import_Typography.default,
|
|
156
|
+
{
|
|
157
|
+
variant: "caption",
|
|
158
|
+
sx: (theme) => ({
|
|
159
|
+
...brandingStyles[variant],
|
|
160
|
+
color: theme.palette.text.secondary
|
|
161
|
+
}),
|
|
162
|
+
children: [
|
|
163
|
+
"fornecido por",
|
|
164
|
+
" ",
|
|
165
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
166
|
+
import_Link.default,
|
|
167
|
+
{
|
|
168
|
+
href: "https://ledipo.eti.br",
|
|
169
|
+
target: "_blank",
|
|
170
|
+
rel: "noopener noreferrer",
|
|
171
|
+
sx: (theme) => ({
|
|
172
|
+
...linkStyles,
|
|
173
|
+
color: theme.palette.primary.main
|
|
174
|
+
}),
|
|
175
|
+
children: "L\xC9dipO.eti.br"
|
|
176
|
+
}
|
|
177
|
+
)
|
|
178
|
+
]
|
|
179
|
+
}
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
var import_Link, import_Typography, import_jsx_runtime, brandingStyles, linkStyles;
|
|
183
|
+
var init_Branding = __esm({
|
|
184
|
+
"src/components/Branding.tsx"() {
|
|
185
|
+
"use strict";
|
|
186
|
+
import_Link = __toESM(require("@mui/material/Link"), 1);
|
|
187
|
+
import_Typography = __toESM(require("@mui/material/Typography"), 1);
|
|
188
|
+
import_jsx_runtime = require("react/jsx-runtime");
|
|
189
|
+
brandingStyles = {
|
|
190
|
+
banner: {
|
|
191
|
+
fontSize: "0.65rem",
|
|
192
|
+
textAlign: "center",
|
|
193
|
+
mt: 1,
|
|
194
|
+
opacity: 0.7,
|
|
195
|
+
fontStyle: "italic"
|
|
196
|
+
},
|
|
197
|
+
modal: {
|
|
198
|
+
fontSize: "0.65rem",
|
|
199
|
+
textAlign: "center",
|
|
200
|
+
px: 3,
|
|
201
|
+
pb: 1,
|
|
202
|
+
opacity: 0.7,
|
|
203
|
+
fontStyle: "italic"
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
linkStyles = {
|
|
207
|
+
textDecoration: "none",
|
|
208
|
+
fontWeight: 500,
|
|
209
|
+
"&:hover": {
|
|
210
|
+
textDecoration: "underline"
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
|
|
151
216
|
// src/components/PreferencesModal.tsx
|
|
152
217
|
var PreferencesModal_exports = {};
|
|
153
218
|
__export(PreferencesModal_exports, {
|
|
154
219
|
PreferencesModal: () => PreferencesModal
|
|
155
220
|
});
|
|
156
221
|
function PreferencesModal({
|
|
157
|
-
DialogProps: DialogProps2
|
|
222
|
+
DialogProps: DialogProps2,
|
|
223
|
+
hideBranding = false
|
|
158
224
|
}) {
|
|
159
225
|
const { preferences, setPreferences, closePreferences, isModalOpen } = useConsent();
|
|
160
226
|
const texts = useConsentTexts();
|
|
@@ -172,7 +238,7 @@ function PreferencesModal({
|
|
|
172
238
|
setTempPreferences(preferences);
|
|
173
239
|
closePreferences();
|
|
174
240
|
};
|
|
175
|
-
return /* @__PURE__ */ (0,
|
|
241
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
176
242
|
import_Dialog.default,
|
|
177
243
|
{
|
|
178
244
|
"aria-labelledby": "cookie-pref-title",
|
|
@@ -180,14 +246,14 @@ function PreferencesModal({
|
|
|
180
246
|
onClose: handleCancel,
|
|
181
247
|
...DialogProps2,
|
|
182
248
|
children: [
|
|
183
|
-
/* @__PURE__ */ (0,
|
|
184
|
-
/* @__PURE__ */ (0,
|
|
185
|
-
/* @__PURE__ */ (0,
|
|
186
|
-
/* @__PURE__ */ (0,
|
|
187
|
-
/* @__PURE__ */ (0,
|
|
249
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_DialogTitle.default, { id: "cookie-pref-title", children: texts.modalTitle }),
|
|
250
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_DialogContent.default, { dividers: true, children: [
|
|
251
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_Typography2.default, { variant: "body2", sx: { mb: 2 }, children: texts.modalIntro }),
|
|
252
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_FormGroup.default, { children: [
|
|
253
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
188
254
|
import_FormControlLabel.default,
|
|
189
255
|
{
|
|
190
|
-
control: /* @__PURE__ */ (0,
|
|
256
|
+
control: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
191
257
|
import_Switch.default,
|
|
192
258
|
{
|
|
193
259
|
checked: tempPreferences.analytics,
|
|
@@ -200,10 +266,10 @@ function PreferencesModal({
|
|
|
200
266
|
label: "Cookies Anal\xEDticos (medem uso do site)"
|
|
201
267
|
}
|
|
202
268
|
),
|
|
203
|
-
/* @__PURE__ */ (0,
|
|
269
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
204
270
|
import_FormControlLabel.default,
|
|
205
271
|
{
|
|
206
|
-
control: /* @__PURE__ */ (0,
|
|
272
|
+
control: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
207
273
|
import_Switch.default,
|
|
208
274
|
{
|
|
209
275
|
checked: tempPreferences.marketing,
|
|
@@ -216,24 +282,25 @@ function PreferencesModal({
|
|
|
216
282
|
label: "Cookies de Marketing/Publicidade"
|
|
217
283
|
}
|
|
218
284
|
),
|
|
219
|
-
/* @__PURE__ */ (0,
|
|
285
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
220
286
|
import_FormControlLabel.default,
|
|
221
287
|
{
|
|
222
|
-
control: /* @__PURE__ */ (0,
|
|
288
|
+
control: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_Switch.default, { checked: true, disabled: true }),
|
|
223
289
|
label: texts.necessaryAlwaysOn
|
|
224
290
|
}
|
|
225
291
|
)
|
|
226
292
|
] })
|
|
227
293
|
] }),
|
|
228
|
-
/* @__PURE__ */ (0,
|
|
229
|
-
|
|
230
|
-
/* @__PURE__ */ (0,
|
|
294
|
+
!hideBranding && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Branding, { variant: "modal" }),
|
|
295
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_DialogActions.default, { children: [
|
|
296
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_Button.default, { variant: "outlined", onClick: handleCancel, children: "Cancelar" }),
|
|
297
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_Button.default, { variant: "contained", onClick: handleSave, children: texts.save })
|
|
231
298
|
] })
|
|
232
299
|
]
|
|
233
300
|
}
|
|
234
301
|
);
|
|
235
302
|
}
|
|
236
|
-
var import_Button, import_Dialog, import_DialogActions, import_DialogContent, import_DialogTitle, import_FormControlLabel, import_FormGroup, import_Switch,
|
|
303
|
+
var import_Button, import_Dialog, import_DialogActions, import_DialogContent, import_DialogTitle, import_FormControlLabel, import_FormGroup, import_Switch, import_Typography2, import_react, import_jsx_runtime2;
|
|
237
304
|
var init_PreferencesModal = __esm({
|
|
238
305
|
"src/components/PreferencesModal.tsx"() {
|
|
239
306
|
"use strict";
|
|
@@ -245,10 +312,11 @@ var init_PreferencesModal = __esm({
|
|
|
245
312
|
import_FormControlLabel = __toESM(require("@mui/material/FormControlLabel"), 1);
|
|
246
313
|
import_FormGroup = __toESM(require("@mui/material/FormGroup"), 1);
|
|
247
314
|
import_Switch = __toESM(require("@mui/material/Switch"), 1);
|
|
248
|
-
|
|
315
|
+
import_Typography2 = __toESM(require("@mui/material/Typography"), 1);
|
|
249
316
|
import_react = require("react");
|
|
250
317
|
init_useConsent();
|
|
251
|
-
|
|
318
|
+
init_Branding();
|
|
319
|
+
import_jsx_runtime2 = require("react/jsx-runtime");
|
|
252
320
|
}
|
|
253
321
|
});
|
|
254
322
|
|
|
@@ -306,6 +374,7 @@ function ConsentProvider({
|
|
|
306
374
|
PreferencesModalComponent,
|
|
307
375
|
preferencesModalProps = {},
|
|
308
376
|
disableAutomaticModal = false,
|
|
377
|
+
hideBranding = false,
|
|
309
378
|
onConsentGiven,
|
|
310
379
|
onPreferencesSaved,
|
|
311
380
|
cookie: cookieOpts,
|
|
@@ -325,14 +394,24 @@ function ConsentProvider({
|
|
|
325
394
|
);
|
|
326
395
|
const boot = React.useMemo(() => {
|
|
327
396
|
if (initialState) return { ...initialState, isModalOpen: false };
|
|
328
|
-
|
|
329
|
-
return saved ?? {
|
|
397
|
+
return {
|
|
330
398
|
consented: false,
|
|
331
399
|
preferences: { ...DEFAULT_PREFERENCES },
|
|
332
400
|
isModalOpen: false
|
|
333
401
|
};
|
|
334
|
-
}, [initialState
|
|
402
|
+
}, [initialState]);
|
|
335
403
|
const [state, dispatch] = React.useReducer(reducer, boot);
|
|
404
|
+
const [isHydrated, setIsHydrated] = React.useState(false);
|
|
405
|
+
React.useEffect(() => {
|
|
406
|
+
if (typeof window !== "undefined" && !initialState) {
|
|
407
|
+
const saved = readConsentCookie(cookie.name);
|
|
408
|
+
if (saved?.consented) {
|
|
409
|
+
console.log("\u{1F680} Immediate hydration: Cookie found", saved);
|
|
410
|
+
dispatch({ type: "HYDRATE", state: saved });
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
setIsHydrated(true);
|
|
414
|
+
}, [cookie.name, initialState]);
|
|
336
415
|
React.useEffect(() => {
|
|
337
416
|
if (state.consented) writeConsentCookie(state, cookie);
|
|
338
417
|
}, [state, cookie]);
|
|
@@ -374,10 +453,10 @@ function ConsentProvider({
|
|
|
374
453
|
resetConsent
|
|
375
454
|
};
|
|
376
455
|
}, [state, cookie]);
|
|
377
|
-
return /* @__PURE__ */ (0,
|
|
456
|
+
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: [
|
|
378
457
|
children,
|
|
379
|
-
!disableAutomaticModal && /* @__PURE__ */ (0,
|
|
380
|
-
] }) }) }) });
|
|
458
|
+
!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 }) })
|
|
459
|
+
] }) }) }) }) });
|
|
381
460
|
}
|
|
382
461
|
function useConsentStateInternal() {
|
|
383
462
|
const ctx = React.useContext(StateCtx);
|
|
@@ -395,7 +474,10 @@ function useConsentTextsInternal() {
|
|
|
395
474
|
const ctx = React.useContext(TextsCtx);
|
|
396
475
|
return ctx;
|
|
397
476
|
}
|
|
398
|
-
|
|
477
|
+
function useConsentHydrationInternal() {
|
|
478
|
+
return React.useContext(HydrationCtx);
|
|
479
|
+
}
|
|
480
|
+
var React, import_styles2, import_jsx_runtime3, PreferencesModal2, DEFAULT_PREFERENCES, DEFAULT_TEXTS, StateCtx, ActionsCtx, TextsCtx, HydrationCtx;
|
|
399
481
|
var init_ConsentContext = __esm({
|
|
400
482
|
"src/context/ConsentContext.tsx"() {
|
|
401
483
|
"use strict";
|
|
@@ -403,7 +485,7 @@ var init_ConsentContext = __esm({
|
|
|
403
485
|
import_styles2 = require("@mui/material/styles");
|
|
404
486
|
init_cookieUtils();
|
|
405
487
|
init_theme();
|
|
406
|
-
|
|
488
|
+
import_jsx_runtime3 = require("react/jsx-runtime");
|
|
407
489
|
PreferencesModal2 = React.lazy(
|
|
408
490
|
() => Promise.resolve().then(() => (init_PreferencesModal(), PreferencesModal_exports)).then((m) => ({
|
|
409
491
|
default: m.PreferencesModal
|
|
@@ -427,6 +509,7 @@ var init_ConsentContext = __esm({
|
|
|
427
509
|
StateCtx = React.createContext(null);
|
|
428
510
|
ActionsCtx = React.createContext(null);
|
|
429
511
|
TextsCtx = React.createContext(DEFAULT_TEXTS);
|
|
512
|
+
HydrationCtx = React.createContext(false);
|
|
430
513
|
}
|
|
431
514
|
});
|
|
432
515
|
|
|
@@ -450,6 +533,9 @@ function useConsent() {
|
|
|
450
533
|
function useConsentTexts() {
|
|
451
534
|
return useConsentTextsInternal();
|
|
452
535
|
}
|
|
536
|
+
function useConsentHydration() {
|
|
537
|
+
return useConsentHydrationInternal();
|
|
538
|
+
}
|
|
453
539
|
var init_useConsent = __esm({
|
|
454
540
|
"src/hooks/useConsent.ts"() {
|
|
455
541
|
"use strict";
|
|
@@ -463,10 +549,12 @@ __export(index_exports, {
|
|
|
463
549
|
ConsentGate: () => ConsentGate,
|
|
464
550
|
ConsentProvider: () => ConsentProvider,
|
|
465
551
|
CookieBanner: () => CookieBanner,
|
|
552
|
+
FloatingPreferencesButton: () => FloatingPreferencesButton,
|
|
466
553
|
PreferencesModal: () => PreferencesModal,
|
|
467
554
|
defaultConsentTheme: () => defaultConsentTheme,
|
|
468
555
|
loadScript: () => loadScript,
|
|
469
556
|
useConsent: () => useConsent,
|
|
557
|
+
useConsentHydration: () => useConsentHydration,
|
|
470
558
|
useConsentTexts: () => useConsentTexts
|
|
471
559
|
});
|
|
472
560
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -474,37 +562,40 @@ module.exports = __toCommonJS(index_exports);
|
|
|
474
562
|
// src/components/CookieBanner.tsx
|
|
475
563
|
var import_Button2 = __toESM(require("@mui/material/Button"), 1);
|
|
476
564
|
var import_Box = __toESM(require("@mui/material/Box"), 1);
|
|
477
|
-
var import_Link = __toESM(require("@mui/material/Link"), 1);
|
|
478
565
|
var import_Paper = __toESM(require("@mui/material/Paper"), 1);
|
|
479
566
|
var import_Snackbar = __toESM(require("@mui/material/Snackbar"), 1);
|
|
480
567
|
var import_Stack = __toESM(require("@mui/material/Stack"), 1);
|
|
481
|
-
var
|
|
568
|
+
var import_Typography3 = __toESM(require("@mui/material/Typography"), 1);
|
|
569
|
+
var import_Link2 = __toESM(require("@mui/material/Link"), 1);
|
|
482
570
|
init_useConsent();
|
|
483
|
-
|
|
571
|
+
init_Branding();
|
|
572
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
484
573
|
function CookieBanner({
|
|
485
574
|
policyLinkUrl,
|
|
486
575
|
debug,
|
|
487
576
|
blocking = true,
|
|
488
577
|
// Por padrão, bloqueia até decisão
|
|
578
|
+
hideBranding = false,
|
|
489
579
|
SnackbarProps,
|
|
490
580
|
PaperProps
|
|
491
581
|
}) {
|
|
492
582
|
const { consented, acceptAll, rejectAll, openPreferences } = useConsent();
|
|
493
583
|
const texts = useConsentTexts();
|
|
494
|
-
const
|
|
584
|
+
const isHydrated = useConsentHydration();
|
|
585
|
+
const open = debug ? true : isHydrated && !consented;
|
|
495
586
|
if (!open) return null;
|
|
496
|
-
const bannerContent = /* @__PURE__ */ (0,
|
|
587
|
+
const bannerContent = /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
497
588
|
import_Paper.default,
|
|
498
589
|
{
|
|
499
590
|
elevation: 3,
|
|
500
591
|
sx: { p: 2, maxWidth: 720, mx: "auto" },
|
|
501
592
|
...PaperProps,
|
|
502
|
-
children: /* @__PURE__ */ (0,
|
|
503
|
-
/* @__PURE__ */ (0,
|
|
593
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_Stack.default, { spacing: 1, children: [
|
|
594
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_Typography3.default, { variant: "body2", children: [
|
|
504
595
|
texts.bannerMessage,
|
|
505
596
|
" ",
|
|
506
|
-
policyLinkUrl && /* @__PURE__ */ (0,
|
|
507
|
-
|
|
597
|
+
policyLinkUrl && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
598
|
+
import_Link2.default,
|
|
508
599
|
{
|
|
509
600
|
href: policyLinkUrl,
|
|
510
601
|
underline: "hover",
|
|
@@ -514,25 +605,26 @@ function CookieBanner({
|
|
|
514
605
|
}
|
|
515
606
|
)
|
|
516
607
|
] }),
|
|
517
|
-
/* @__PURE__ */ (0,
|
|
608
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
518
609
|
import_Stack.default,
|
|
519
610
|
{
|
|
520
611
|
direction: { xs: "column", sm: "row" },
|
|
521
612
|
spacing: 1,
|
|
522
613
|
justifyContent: "flex-end",
|
|
523
614
|
children: [
|
|
524
|
-
/* @__PURE__ */ (0,
|
|
525
|
-
/* @__PURE__ */ (0,
|
|
526
|
-
/* @__PURE__ */ (0,
|
|
615
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_Button2.default, { variant: "outlined", onClick: rejectAll, children: texts.declineAll }),
|
|
616
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_Button2.default, { variant: "contained", onClick: acceptAll, children: texts.acceptAll }),
|
|
617
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_Button2.default, { variant: "text", onClick: openPreferences, children: texts.preferences })
|
|
527
618
|
]
|
|
528
619
|
}
|
|
529
|
-
)
|
|
620
|
+
),
|
|
621
|
+
!hideBranding && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Branding, { variant: "banner" })
|
|
530
622
|
] })
|
|
531
623
|
}
|
|
532
624
|
);
|
|
533
625
|
if (blocking) {
|
|
534
|
-
return /* @__PURE__ */ (0,
|
|
535
|
-
/* @__PURE__ */ (0,
|
|
626
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
627
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
536
628
|
import_Box.default,
|
|
537
629
|
{
|
|
538
630
|
sx: {
|
|
@@ -547,7 +639,7 @@ function CookieBanner({
|
|
|
547
639
|
}
|
|
548
640
|
}
|
|
549
641
|
),
|
|
550
|
-
/* @__PURE__ */ (0,
|
|
642
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
551
643
|
import_Box.default,
|
|
552
644
|
{
|
|
553
645
|
sx: {
|
|
@@ -564,7 +656,7 @@ function CookieBanner({
|
|
|
564
656
|
)
|
|
565
657
|
] });
|
|
566
658
|
}
|
|
567
|
-
return /* @__PURE__ */ (0,
|
|
659
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
568
660
|
import_Snackbar.default,
|
|
569
661
|
{
|
|
570
662
|
open,
|
|
@@ -577,16 +669,78 @@ function CookieBanner({
|
|
|
577
669
|
|
|
578
670
|
// src/index.ts
|
|
579
671
|
init_PreferencesModal();
|
|
672
|
+
|
|
673
|
+
// src/components/FloatingPreferencesButton.tsx
|
|
674
|
+
var import_Fab = __toESM(require("@mui/material/Fab"), 1);
|
|
675
|
+
var import_Tooltip = __toESM(require("@mui/material/Tooltip"), 1);
|
|
676
|
+
var import_Settings = __toESM(require("@mui/icons-material/Settings"), 1);
|
|
677
|
+
var import_styles3 = require("@mui/material/styles");
|
|
678
|
+
init_useConsent();
|
|
679
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
680
|
+
function FloatingPreferencesButton({
|
|
681
|
+
position = "bottom-right",
|
|
682
|
+
offset = 24,
|
|
683
|
+
icon = /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_Settings.default, {}),
|
|
684
|
+
tooltip,
|
|
685
|
+
FabProps,
|
|
686
|
+
hideWhenConsented = false
|
|
687
|
+
}) {
|
|
688
|
+
const { openPreferences, consented } = useConsent();
|
|
689
|
+
const theme = (0, import_styles3.useTheme)();
|
|
690
|
+
if (hideWhenConsented && consented) {
|
|
691
|
+
return null;
|
|
692
|
+
}
|
|
693
|
+
const tooltipText = tooltip ?? "Gerenciar Prefer\xEAncias de Cookies";
|
|
694
|
+
const getPosition = () => {
|
|
695
|
+
const styles = {
|
|
696
|
+
position: "fixed",
|
|
697
|
+
zIndex: 1200
|
|
698
|
+
// Abaixo do modal mas acima do conteúdo
|
|
699
|
+
};
|
|
700
|
+
switch (position) {
|
|
701
|
+
case "bottom-left":
|
|
702
|
+
return { ...styles, bottom: offset, left: offset };
|
|
703
|
+
case "bottom-right":
|
|
704
|
+
return { ...styles, bottom: offset, right: offset };
|
|
705
|
+
case "top-left":
|
|
706
|
+
return { ...styles, top: offset, left: offset };
|
|
707
|
+
case "top-right":
|
|
708
|
+
return { ...styles, top: offset, right: offset };
|
|
709
|
+
default:
|
|
710
|
+
return { ...styles, bottom: offset, right: offset };
|
|
711
|
+
}
|
|
712
|
+
};
|
|
713
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_Tooltip.default, { title: tooltipText, placement: "top", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
714
|
+
import_Fab.default,
|
|
715
|
+
{
|
|
716
|
+
size: "medium",
|
|
717
|
+
color: "primary",
|
|
718
|
+
onClick: openPreferences,
|
|
719
|
+
sx: {
|
|
720
|
+
...getPosition(),
|
|
721
|
+
backgroundColor: theme.palette.primary.main,
|
|
722
|
+
"&:hover": {
|
|
723
|
+
backgroundColor: theme.palette.primary.dark
|
|
724
|
+
}
|
|
725
|
+
},
|
|
726
|
+
"aria-label": tooltipText,
|
|
727
|
+
...FabProps,
|
|
728
|
+
children: icon
|
|
729
|
+
}
|
|
730
|
+
) });
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
// src/index.ts
|
|
580
734
|
init_ConsentContext();
|
|
581
735
|
init_useConsent();
|
|
582
736
|
|
|
583
737
|
// src/utils/ConsentGate.tsx
|
|
584
738
|
init_useConsent();
|
|
585
|
-
var
|
|
739
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
586
740
|
function ConsentGate(props) {
|
|
587
741
|
const { preferences } = useConsent();
|
|
588
742
|
if (!preferences[props.category]) return null;
|
|
589
|
-
return /* @__PURE__ */ (0,
|
|
743
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_jsx_runtime6.Fragment, { children: props.children });
|
|
590
744
|
}
|
|
591
745
|
|
|
592
746
|
// src/utils/scriptLoader.ts
|
|
@@ -633,9 +787,11 @@ init_theme();
|
|
|
633
787
|
ConsentGate,
|
|
634
788
|
ConsentProvider,
|
|
635
789
|
CookieBanner,
|
|
790
|
+
FloatingPreferencesButton,
|
|
636
791
|
PreferencesModal,
|
|
637
792
|
defaultConsentTheme,
|
|
638
793
|
loadScript,
|
|
639
794
|
useConsent,
|
|
795
|
+
useConsentHydration,
|
|
640
796
|
useConsentTexts
|
|
641
797
|
});
|
package/dist/index.d.cts
CHANGED
|
@@ -2,6 +2,7 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
|
2
2
|
import { PaperProps } from '@mui/material/Paper';
|
|
3
3
|
import { SnackbarProps } from '@mui/material/Snackbar';
|
|
4
4
|
import { DialogProps } from '@mui/material/Dialog';
|
|
5
|
+
import { FabProps } from '@mui/material/Fab';
|
|
5
6
|
import * as React$1 from 'react';
|
|
6
7
|
import * as _mui_material_styles from '@mui/material/styles';
|
|
7
8
|
|
|
@@ -9,16 +10,34 @@ interface CookieBannerProps {
|
|
|
9
10
|
policyLinkUrl?: string;
|
|
10
11
|
debug?: boolean;
|
|
11
12
|
blocking?: boolean;
|
|
13
|
+
hideBranding?: boolean;
|
|
12
14
|
SnackbarProps?: Partial<SnackbarProps>;
|
|
13
15
|
PaperProps?: Partial<PaperProps>;
|
|
14
16
|
}
|
|
15
17
|
declare function CookieBanner({ policyLinkUrl, debug, blocking, // Por padrão, bloqueia até decisão
|
|
16
|
-
SnackbarProps, PaperProps, }: Readonly<CookieBannerProps>): react_jsx_runtime.JSX.Element | null;
|
|
18
|
+
hideBranding, SnackbarProps, PaperProps, }: Readonly<CookieBannerProps>): react_jsx_runtime.JSX.Element | null;
|
|
17
19
|
|
|
18
20
|
interface PreferencesModalProps {
|
|
19
21
|
DialogProps?: Partial<DialogProps>;
|
|
22
|
+
hideBranding?: boolean;
|
|
20
23
|
}
|
|
21
|
-
declare function PreferencesModal({ DialogProps, }: Readonly<PreferencesModalProps>): react_jsx_runtime.JSX.Element;
|
|
24
|
+
declare function PreferencesModal({ DialogProps, hideBranding, }: Readonly<PreferencesModalProps>): react_jsx_runtime.JSX.Element;
|
|
25
|
+
|
|
26
|
+
interface FloatingPreferencesButtonProps {
|
|
27
|
+
/** Posição do botão flutuante. Padrão: 'bottom-right' */
|
|
28
|
+
position?: 'bottom-left' | 'bottom-right' | 'top-left' | 'top-right';
|
|
29
|
+
/** Offset da borda em pixels. Padrão: 24 */
|
|
30
|
+
offset?: number;
|
|
31
|
+
/** Ícone customizado. Padrão: SettingsIcon */
|
|
32
|
+
icon?: React.ReactNode;
|
|
33
|
+
/** Tooltip customizado */
|
|
34
|
+
tooltip?: string;
|
|
35
|
+
/** Props do Fab do MUI */
|
|
36
|
+
FabProps?: Partial<FabProps>;
|
|
37
|
+
/** Se deve esconder quando consentimento já foi dado. Padrão: false */
|
|
38
|
+
hideWhenConsented?: boolean;
|
|
39
|
+
}
|
|
40
|
+
declare function FloatingPreferencesButton({ position, offset, icon, tooltip, FabProps, hideWhenConsented, }: Readonly<FloatingPreferencesButtonProps>): react_jsx_runtime.JSX.Element | null;
|
|
22
41
|
|
|
23
42
|
/**
|
|
24
43
|
* Categoria de consentimento para cookies.
|
|
@@ -86,6 +105,8 @@ interface ConsentProviderProps {
|
|
|
86
105
|
preferencesModalProps?: Record<string, any>;
|
|
87
106
|
/** Desabilita o modal automático (para usar componente totalmente customizado). */
|
|
88
107
|
disableAutomaticModal?: boolean;
|
|
108
|
+
/** Esconde branding "fornecido por LÉdipO.eti.br". */
|
|
109
|
+
hideBranding?: boolean;
|
|
89
110
|
/** Callback chamado quando o consentimento é dado. */
|
|
90
111
|
onConsentGiven?: (state: ConsentState) => void;
|
|
91
112
|
/** Callback chamado ao salvar preferências. */
|
|
@@ -121,7 +142,7 @@ interface ConsentContextValue {
|
|
|
121
142
|
resetConsent: () => void;
|
|
122
143
|
}
|
|
123
144
|
|
|
124
|
-
declare function ConsentProvider({ initialState, texts: textsProp, theme, PreferencesModalComponent, preferencesModalProps, disableAutomaticModal, onConsentGiven, onPreferencesSaved, cookie: cookieOpts, children, }: Readonly<ConsentProviderProps>): react_jsx_runtime.JSX.Element;
|
|
145
|
+
declare function ConsentProvider({ initialState, texts: textsProp, theme, PreferencesModalComponent, preferencesModalProps, disableAutomaticModal, hideBranding, onConsentGiven, onPreferencesSaved, cookie: cookieOpts, children, }: Readonly<ConsentProviderProps>): react_jsx_runtime.JSX.Element;
|
|
125
146
|
|
|
126
147
|
declare function useConsent(): ConsentContextValue;
|
|
127
148
|
/**
|
|
@@ -129,6 +150,11 @@ declare function useConsent(): ConsentContextValue;
|
|
|
129
150
|
* Útil para componentes personalizados que precisam dos textos configurados.
|
|
130
151
|
*/
|
|
131
152
|
declare function useConsentTexts(): ConsentTexts;
|
|
153
|
+
/**
|
|
154
|
+
* Hook para verificar se a hidratação do cookie foi concluída.
|
|
155
|
+
* Útil para evitar flash do banner antes de verificar cookies existentes.
|
|
156
|
+
*/
|
|
157
|
+
declare function useConsentHydration(): boolean;
|
|
132
158
|
|
|
133
159
|
declare function ConsentGate(props: Readonly<{
|
|
134
160
|
category: Category;
|
|
@@ -147,4 +173,4 @@ declare function loadScript(id: string, src: string, category?: 'analytics' | 'm
|
|
|
147
173
|
*/
|
|
148
174
|
declare const defaultConsentTheme: _mui_material_styles.Theme;
|
|
149
175
|
|
|
150
|
-
export { type Category, type ConsentCookieOptions, ConsentGate, type ConsentPreferences, ConsentProvider, type ConsentState, type ConsentTexts, CookieBanner, PreferencesModal, defaultConsentTheme, loadScript, useConsent, useConsentTexts };
|
|
176
|
+
export { type Category, type ConsentCookieOptions, ConsentGate, type ConsentPreferences, ConsentProvider, type ConsentState, type ConsentTexts, CookieBanner, FloatingPreferencesButton, PreferencesModal, defaultConsentTheme, loadScript, useConsent, useConsentHydration, useConsentTexts };
|
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
|
2
2
|
import { PaperProps } from '@mui/material/Paper';
|
|
3
3
|
import { SnackbarProps } from '@mui/material/Snackbar';
|
|
4
4
|
import { DialogProps } from '@mui/material/Dialog';
|
|
5
|
+
import { FabProps } from '@mui/material/Fab';
|
|
5
6
|
import * as React$1 from 'react';
|
|
6
7
|
import * as _mui_material_styles from '@mui/material/styles';
|
|
7
8
|
|
|
@@ -9,16 +10,34 @@ interface CookieBannerProps {
|
|
|
9
10
|
policyLinkUrl?: string;
|
|
10
11
|
debug?: boolean;
|
|
11
12
|
blocking?: boolean;
|
|
13
|
+
hideBranding?: boolean;
|
|
12
14
|
SnackbarProps?: Partial<SnackbarProps>;
|
|
13
15
|
PaperProps?: Partial<PaperProps>;
|
|
14
16
|
}
|
|
15
17
|
declare function CookieBanner({ policyLinkUrl, debug, blocking, // Por padrão, bloqueia até decisão
|
|
16
|
-
SnackbarProps, PaperProps, }: Readonly<CookieBannerProps>): react_jsx_runtime.JSX.Element | null;
|
|
18
|
+
hideBranding, SnackbarProps, PaperProps, }: Readonly<CookieBannerProps>): react_jsx_runtime.JSX.Element | null;
|
|
17
19
|
|
|
18
20
|
interface PreferencesModalProps {
|
|
19
21
|
DialogProps?: Partial<DialogProps>;
|
|
22
|
+
hideBranding?: boolean;
|
|
20
23
|
}
|
|
21
|
-
declare function PreferencesModal({ DialogProps, }: Readonly<PreferencesModalProps>): react_jsx_runtime.JSX.Element;
|
|
24
|
+
declare function PreferencesModal({ DialogProps, hideBranding, }: Readonly<PreferencesModalProps>): react_jsx_runtime.JSX.Element;
|
|
25
|
+
|
|
26
|
+
interface FloatingPreferencesButtonProps {
|
|
27
|
+
/** Posição do botão flutuante. Padrão: 'bottom-right' */
|
|
28
|
+
position?: 'bottom-left' | 'bottom-right' | 'top-left' | 'top-right';
|
|
29
|
+
/** Offset da borda em pixels. Padrão: 24 */
|
|
30
|
+
offset?: number;
|
|
31
|
+
/** Ícone customizado. Padrão: SettingsIcon */
|
|
32
|
+
icon?: React.ReactNode;
|
|
33
|
+
/** Tooltip customizado */
|
|
34
|
+
tooltip?: string;
|
|
35
|
+
/** Props do Fab do MUI */
|
|
36
|
+
FabProps?: Partial<FabProps>;
|
|
37
|
+
/** Se deve esconder quando consentimento já foi dado. Padrão: false */
|
|
38
|
+
hideWhenConsented?: boolean;
|
|
39
|
+
}
|
|
40
|
+
declare function FloatingPreferencesButton({ position, offset, icon, tooltip, FabProps, hideWhenConsented, }: Readonly<FloatingPreferencesButtonProps>): react_jsx_runtime.JSX.Element | null;
|
|
22
41
|
|
|
23
42
|
/**
|
|
24
43
|
* Categoria de consentimento para cookies.
|
|
@@ -86,6 +105,8 @@ interface ConsentProviderProps {
|
|
|
86
105
|
preferencesModalProps?: Record<string, any>;
|
|
87
106
|
/** Desabilita o modal automático (para usar componente totalmente customizado). */
|
|
88
107
|
disableAutomaticModal?: boolean;
|
|
108
|
+
/** Esconde branding "fornecido por LÉdipO.eti.br". */
|
|
109
|
+
hideBranding?: boolean;
|
|
89
110
|
/** Callback chamado quando o consentimento é dado. */
|
|
90
111
|
onConsentGiven?: (state: ConsentState) => void;
|
|
91
112
|
/** Callback chamado ao salvar preferências. */
|
|
@@ -121,7 +142,7 @@ interface ConsentContextValue {
|
|
|
121
142
|
resetConsent: () => void;
|
|
122
143
|
}
|
|
123
144
|
|
|
124
|
-
declare function ConsentProvider({ initialState, texts: textsProp, theme, PreferencesModalComponent, preferencesModalProps, disableAutomaticModal, onConsentGiven, onPreferencesSaved, cookie: cookieOpts, children, }: Readonly<ConsentProviderProps>): react_jsx_runtime.JSX.Element;
|
|
145
|
+
declare function ConsentProvider({ initialState, texts: textsProp, theme, PreferencesModalComponent, preferencesModalProps, disableAutomaticModal, hideBranding, onConsentGiven, onPreferencesSaved, cookie: cookieOpts, children, }: Readonly<ConsentProviderProps>): react_jsx_runtime.JSX.Element;
|
|
125
146
|
|
|
126
147
|
declare function useConsent(): ConsentContextValue;
|
|
127
148
|
/**
|
|
@@ -129,6 +150,11 @@ declare function useConsent(): ConsentContextValue;
|
|
|
129
150
|
* Útil para componentes personalizados que precisam dos textos configurados.
|
|
130
151
|
*/
|
|
131
152
|
declare function useConsentTexts(): ConsentTexts;
|
|
153
|
+
/**
|
|
154
|
+
* Hook para verificar se a hidratação do cookie foi concluída.
|
|
155
|
+
* Útil para evitar flash do banner antes de verificar cookies existentes.
|
|
156
|
+
*/
|
|
157
|
+
declare function useConsentHydration(): boolean;
|
|
132
158
|
|
|
133
159
|
declare function ConsentGate(props: Readonly<{
|
|
134
160
|
category: Category;
|
|
@@ -147,4 +173,4 @@ declare function loadScript(id: string, src: string, category?: 'analytics' | 'm
|
|
|
147
173
|
*/
|
|
148
174
|
declare const defaultConsentTheme: _mui_material_styles.Theme;
|
|
149
175
|
|
|
150
|
-
export { type Category, type ConsentCookieOptions, ConsentGate, type ConsentPreferences, ConsentProvider, type ConsentState, type ConsentTexts, CookieBanner, PreferencesModal, defaultConsentTheme, loadScript, useConsent, useConsentTexts };
|
|
176
|
+
export { type Category, type ConsentCookieOptions, ConsentGate, type ConsentPreferences, ConsentProvider, type ConsentState, type ConsentTexts, CookieBanner, FloatingPreferencesButton, PreferencesModal, defaultConsentTheme, loadScript, useConsent, useConsentHydration, useConsentTexts };
|
package/dist/index.js
CHANGED
|
@@ -1,31 +1,35 @@
|
|
|
1
1
|
import {
|
|
2
|
+
Branding,
|
|
2
3
|
ConsentProvider,
|
|
3
4
|
PreferencesModal,
|
|
4
5
|
defaultConsentTheme,
|
|
5
6
|
useConsent,
|
|
7
|
+
useConsentHydration,
|
|
6
8
|
useConsentTexts
|
|
7
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-LRMSFSP2.js";
|
|
8
10
|
|
|
9
11
|
// src/components/CookieBanner.tsx
|
|
10
12
|
import Button from "@mui/material/Button";
|
|
11
13
|
import Box from "@mui/material/Box";
|
|
12
|
-
import Link from "@mui/material/Link";
|
|
13
14
|
import Paper from "@mui/material/Paper";
|
|
14
15
|
import Snackbar from "@mui/material/Snackbar";
|
|
15
16
|
import Stack from "@mui/material/Stack";
|
|
16
17
|
import Typography from "@mui/material/Typography";
|
|
18
|
+
import Link from "@mui/material/Link";
|
|
17
19
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
18
20
|
function CookieBanner({
|
|
19
21
|
policyLinkUrl,
|
|
20
22
|
debug,
|
|
21
23
|
blocking = true,
|
|
22
24
|
// Por padrão, bloqueia até decisão
|
|
25
|
+
hideBranding = false,
|
|
23
26
|
SnackbarProps,
|
|
24
27
|
PaperProps
|
|
25
28
|
}) {
|
|
26
29
|
const { consented, acceptAll, rejectAll, openPreferences } = useConsent();
|
|
27
30
|
const texts = useConsentTexts();
|
|
28
|
-
const
|
|
31
|
+
const isHydrated = useConsentHydration();
|
|
32
|
+
const open = debug ? true : isHydrated && !consented;
|
|
29
33
|
if (!open) return null;
|
|
30
34
|
const bannerContent = /* @__PURE__ */ jsx(
|
|
31
35
|
Paper,
|
|
@@ -60,7 +64,8 @@ function CookieBanner({
|
|
|
60
64
|
/* @__PURE__ */ jsx(Button, { variant: "text", onClick: openPreferences, children: texts.preferences })
|
|
61
65
|
]
|
|
62
66
|
}
|
|
63
|
-
)
|
|
67
|
+
),
|
|
68
|
+
!hideBranding && /* @__PURE__ */ jsx(Branding, { variant: "banner" })
|
|
64
69
|
] })
|
|
65
70
|
}
|
|
66
71
|
);
|
|
@@ -109,12 +114,71 @@ function CookieBanner({
|
|
|
109
114
|
);
|
|
110
115
|
}
|
|
111
116
|
|
|
117
|
+
// src/components/FloatingPreferencesButton.tsx
|
|
118
|
+
import Fab from "@mui/material/Fab";
|
|
119
|
+
import Tooltip from "@mui/material/Tooltip";
|
|
120
|
+
import SettingsIcon from "@mui/icons-material/Settings";
|
|
121
|
+
import { useTheme } from "@mui/material/styles";
|
|
122
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
123
|
+
function FloatingPreferencesButton({
|
|
124
|
+
position = "bottom-right",
|
|
125
|
+
offset = 24,
|
|
126
|
+
icon = /* @__PURE__ */ jsx2(SettingsIcon, {}),
|
|
127
|
+
tooltip,
|
|
128
|
+
FabProps,
|
|
129
|
+
hideWhenConsented = false
|
|
130
|
+
}) {
|
|
131
|
+
const { openPreferences, consented } = useConsent();
|
|
132
|
+
const theme = useTheme();
|
|
133
|
+
if (hideWhenConsented && consented) {
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
const tooltipText = tooltip ?? "Gerenciar Prefer\xEAncias de Cookies";
|
|
137
|
+
const getPosition = () => {
|
|
138
|
+
const styles = {
|
|
139
|
+
position: "fixed",
|
|
140
|
+
zIndex: 1200
|
|
141
|
+
// Abaixo do modal mas acima do conteúdo
|
|
142
|
+
};
|
|
143
|
+
switch (position) {
|
|
144
|
+
case "bottom-left":
|
|
145
|
+
return { ...styles, bottom: offset, left: offset };
|
|
146
|
+
case "bottom-right":
|
|
147
|
+
return { ...styles, bottom: offset, right: offset };
|
|
148
|
+
case "top-left":
|
|
149
|
+
return { ...styles, top: offset, left: offset };
|
|
150
|
+
case "top-right":
|
|
151
|
+
return { ...styles, top: offset, right: offset };
|
|
152
|
+
default:
|
|
153
|
+
return { ...styles, bottom: offset, right: offset };
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
return /* @__PURE__ */ jsx2(Tooltip, { title: tooltipText, placement: "top", children: /* @__PURE__ */ jsx2(
|
|
157
|
+
Fab,
|
|
158
|
+
{
|
|
159
|
+
size: "medium",
|
|
160
|
+
color: "primary",
|
|
161
|
+
onClick: openPreferences,
|
|
162
|
+
sx: {
|
|
163
|
+
...getPosition(),
|
|
164
|
+
backgroundColor: theme.palette.primary.main,
|
|
165
|
+
"&:hover": {
|
|
166
|
+
backgroundColor: theme.palette.primary.dark
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
"aria-label": tooltipText,
|
|
170
|
+
...FabProps,
|
|
171
|
+
children: icon
|
|
172
|
+
}
|
|
173
|
+
) });
|
|
174
|
+
}
|
|
175
|
+
|
|
112
176
|
// src/utils/ConsentGate.tsx
|
|
113
|
-
import { Fragment as Fragment2, jsx as
|
|
177
|
+
import { Fragment as Fragment2, jsx as jsx3 } from "react/jsx-runtime";
|
|
114
178
|
function ConsentGate(props) {
|
|
115
179
|
const { preferences } = useConsent();
|
|
116
180
|
if (!preferences[props.category]) return null;
|
|
117
|
-
return /* @__PURE__ */
|
|
181
|
+
return /* @__PURE__ */ jsx3(Fragment2, { children: props.children });
|
|
118
182
|
}
|
|
119
183
|
|
|
120
184
|
// src/utils/scriptLoader.ts
|
|
@@ -157,9 +221,11 @@ export {
|
|
|
157
221
|
ConsentGate,
|
|
158
222
|
ConsentProvider,
|
|
159
223
|
CookieBanner,
|
|
224
|
+
FloatingPreferencesButton,
|
|
160
225
|
PreferencesModal,
|
|
161
226
|
defaultConsentTheme,
|
|
162
227
|
loadScript,
|
|
163
228
|
useConsent,
|
|
229
|
+
useConsentHydration,
|
|
164
230
|
useConsentTexts
|
|
165
231
|
};
|
package/package.json
CHANGED