@sudeep7353/grantly-react-consent 0.1.4 → 0.1.6
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 +636 -643
- package/dist/index.cjs +3 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +92 -90
- package/dist/index.esm.js +3 -3
- package/dist/index.esm.js.map +1 -1
- package/dist/package.json +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,643 +1,636 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
return (
|
|
108
|
-
<ConsentWidget
|
|
109
|
-
clientId="your-client-id"
|
|
110
|
-
xUserId="user-123"
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
|
140
|
-
| `
|
|
141
|
-
| `
|
|
142
|
-
| `
|
|
143
|
-
| `
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
```
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
clientId
|
|
202
|
-
|
|
203
|
-
//
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
```
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
--consent-widget-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
```
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
--consent-widget-
|
|
261
|
-
--consent-widget-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
| `
|
|
320
|
-
| `
|
|
321
|
-
| `
|
|
322
|
-
| `
|
|
323
|
-
| `
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
--
|
|
368
|
-
--
|
|
369
|
-
--
|
|
370
|
-
--
|
|
371
|
-
--
|
|
372
|
-
--
|
|
373
|
-
--
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
```
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
--
|
|
382
|
-
--
|
|
383
|
-
--
|
|
384
|
-
--
|
|
385
|
-
--
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
--
|
|
393
|
-
--
|
|
394
|
-
--
|
|
395
|
-
--
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
--
|
|
405
|
-
--
|
|
406
|
-
--
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
```
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
```
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
.consent
|
|
637
|
-
--consent-widget-container-bg: transparent;
|
|
638
|
-
--consent-widget-container-padding: 1rem;
|
|
639
|
-
--consent-widget-container-border-radius: 4px;
|
|
640
|
-
--consent-widget-button-border-radius: 4px;
|
|
641
|
-
--consent-widget-spacing-md: 0.5rem;
|
|
642
|
-
}
|
|
643
|
-
```
|
|
1
|
+
# @gfox/grantly-react-consent
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@gfox/grantly-react-consent)
|
|
4
|
+
[](https://www.npmjs.com/package/@gfox/grantly-react-consent)
|
|
5
|
+
[](https://www.npmjs.com/package/@gfox/grantly-react-consent)
|
|
6
|
+
|
|
7
|
+
A React component library that simplifies user consent management, offering components for both consent collection and revocation. Built with TypeScript support and fully customizable styling.
|
|
8
|
+
|
|
9
|
+
## Table of Contents
|
|
10
|
+
|
|
11
|
+
- [Installation](#installation)
|
|
12
|
+
- [Quick Start](#quick-start)
|
|
13
|
+
- [Requirements](#requirements)
|
|
14
|
+
- [TypeScript Support](#typescript-support)
|
|
15
|
+
- [ConsentWidget](#consentwidget)
|
|
16
|
+
- [Props](#consentwidget-props)
|
|
17
|
+
- [Display Modes](#display-modes)
|
|
18
|
+
- [Ref Methods](#ref-methods)
|
|
19
|
+
- [Status Callbacks](#status-callbacks)
|
|
20
|
+
- [Styling](#consentwidget-styling)
|
|
21
|
+
- [WithdrawConsentWidget](#withdrawconsentwidget)
|
|
22
|
+
- [Props](#withdrawconsentwidget-props)
|
|
23
|
+
- [Display Modes](#withdrawconsentwidget-display-modes)
|
|
24
|
+
- [Status Callbacks](#withdrawconsentwidget-status-callbacks)
|
|
25
|
+
- [Styling](#withdrawconsentwidget-styling)
|
|
26
|
+
- [Examples](#examples)
|
|
27
|
+
- [Troubleshooting](#troubleshooting)
|
|
28
|
+
- [License](#license)
|
|
29
|
+
|
|
30
|
+
## Installation
|
|
31
|
+
|
|
32
|
+
Install the package using your preferred package manager:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npm install @gfox/grantly-react-consent
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
yarn add @gfox/grantly-react-consent
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
pnpm add @gfox/grantly-react-consent
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Quick Start
|
|
47
|
+
|
|
48
|
+
Get started with the Consent Widget in just a few steps:
|
|
49
|
+
|
|
50
|
+
1. **Install the package** (see installation above)
|
|
51
|
+
2. **Import the component** in your React application
|
|
52
|
+
3. **Configure the required props**
|
|
53
|
+
|
|
54
|
+
### Basic Example
|
|
55
|
+
|
|
56
|
+
```jsx
|
|
57
|
+
import React from 'react';
|
|
58
|
+
import { ConsentWidget } from '@gfox/grantly-react-consent';
|
|
59
|
+
|
|
60
|
+
function App() {
|
|
61
|
+
const handleStatusChange = (data) => {
|
|
62
|
+
console.log('Consent status changed:', data.status, data);
|
|
63
|
+
|
|
64
|
+
if (data.status === 'accepted') {
|
|
65
|
+
console.log('User accepted purposes:', data.acceptedPurposes);
|
|
66
|
+
} else if (data.status === 'already-consented') {
|
|
67
|
+
console.log('User already consented');
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
return (
|
|
72
|
+
<div className="App">
|
|
73
|
+
<ConsentWidget
|
|
74
|
+
clientId="your-client-id"
|
|
75
|
+
xUserId="user-123"
|
|
76
|
+
onStatusChange={handleStatusChange}
|
|
77
|
+
/>
|
|
78
|
+
</div>
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export default App;
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Requirements
|
|
86
|
+
|
|
87
|
+
- **React** >= 17.0.0
|
|
88
|
+
- **React-DOM** >= 17.0.0
|
|
89
|
+
|
|
90
|
+
These are peer dependencies and must be installed in your project.
|
|
91
|
+
|
|
92
|
+
## TypeScript Support
|
|
93
|
+
|
|
94
|
+
This package includes full TypeScript definitions. No additional `@types` package is required.
|
|
95
|
+
|
|
96
|
+
```tsx
|
|
97
|
+
import { ConsentWidget, WithdrawConsentWidget, ConsentStatusDetail, WithdrawConsentStatusDetail } from '@gfox/grantly-react-consent';
|
|
98
|
+
|
|
99
|
+
function App() {
|
|
100
|
+
const handleStatusChange = (data: ConsentStatusDetail) => {
|
|
101
|
+
// TypeScript will provide full type checking and autocomplete
|
|
102
|
+
if (data.status === 'accepted') {
|
|
103
|
+
console.log(data.acceptedPurposes); // TypeScript knows this exists
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
return (
|
|
108
|
+
<ConsentWidget
|
|
109
|
+
clientId="your-client-id"
|
|
110
|
+
xUserId="user-123"
|
|
111
|
+
onStatusChange={handleStatusChange}
|
|
112
|
+
/>
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## ConsentWidget
|
|
118
|
+
|
|
119
|
+
A React component for managing user consent and data agreements with multiple display modes and customizable styling.
|
|
120
|
+
|
|
121
|
+
### Description
|
|
122
|
+
|
|
123
|
+
The Consent Widget is a flexible React component that handles user consent management for data processing purposes. It supports three display modes: popup (default), inline, and plain, making it suitable for various integration scenarios. The widget automatically fetches consent agreements from an API and provides an intuitive interface for users to select their consent preferences.
|
|
124
|
+
|
|
125
|
+
**Key Features:**
|
|
126
|
+
- Automatic scroll locking in popup mode
|
|
127
|
+
- Consent modification mode with smart button enabling
|
|
128
|
+
- Programmatic consent submission via ref
|
|
129
|
+
- Comprehensive status callbacks
|
|
130
|
+
- Multi-language support via `acceptLanguage` prop
|
|
131
|
+
- Markdown support for agreement text
|
|
132
|
+
- XSS protection via DOMPurify
|
|
133
|
+
|
|
134
|
+
### ConsentWidget Props
|
|
135
|
+
|
|
136
|
+
| Prop | Type | Required | Default | Description |
|
|
137
|
+
|------|------|----------|---------|-------------|
|
|
138
|
+
| `clientId` | `string` | Required | - | Client identifier for the consent request |
|
|
139
|
+
| `xUserId` | `string` | Required | - | User identifier |
|
|
140
|
+
| `acceptLanguage` | `string` | Optional | `"en"` | Language code for content localization (e.g., "en", "en-US", "hi") |
|
|
141
|
+
| `displayMode` | `string` | Optional | `""` | Display mode flags (see Display Modes below) |
|
|
142
|
+
| `modifyConsent` | `boolean` | Optional | `false` | Enable consent modification mode. When enabled, the submit button is only enabled when consent has been modified |
|
|
143
|
+
| `onStatusChange` | `function` | Optional | - | Callback for consent status updates (see Status Callbacks below) |
|
|
144
|
+
|
|
145
|
+
### Display Modes
|
|
146
|
+
|
|
147
|
+
The `displayMode` prop accepts space-separated flags:
|
|
148
|
+
|
|
149
|
+
| Flag | Description |
|
|
150
|
+
|------|-------------|
|
|
151
|
+
| **Default (popup)** | Modal overlay with full consent interface. Automatically locks background scroll when open |
|
|
152
|
+
| `plain` | Inline display without modal styling. No scroll locking |
|
|
153
|
+
| `inline` | Compact inline display (hides title, agreement text, and action buttons) |
|
|
154
|
+
| `no-agreement-title` | Hide the agreement title |
|
|
155
|
+
| `no-agreement-text` | Hide the agreement description text |
|
|
156
|
+
| `no-change-summary` | Hide purpose change summaries (shown by default in all modes except `inline`) |
|
|
157
|
+
|
|
158
|
+
**Note:** In default (popup) mode, the widget automatically locks background scrolling when the modal is open and restores it when closed. This ensures a clean user experience where users can only interact with the consent modal when it's open.
|
|
159
|
+
|
|
160
|
+
**Examples:**
|
|
161
|
+
```jsx
|
|
162
|
+
// Modal popup (default)
|
|
163
|
+
<ConsentWidget displayMode="" />
|
|
164
|
+
|
|
165
|
+
// Plain inline mode
|
|
166
|
+
<ConsentWidget displayMode="plain" />
|
|
167
|
+
|
|
168
|
+
// Compact inline with hidden title
|
|
169
|
+
<ConsentWidget displayMode="inline no-agreement-title" />
|
|
170
|
+
|
|
171
|
+
// Plain mode with hidden change summary
|
|
172
|
+
<ConsentWidget displayMode="plain no-change-summary" />
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Ref Methods
|
|
176
|
+
|
|
177
|
+
The component supports ref forwarding and exposes the following method:
|
|
178
|
+
|
|
179
|
+
| Method | Description |
|
|
180
|
+
|--------|-------------|
|
|
181
|
+
| `submitConsent()` | Programmatically submit the consent. Returns a Promise that resolves with the consent result |
|
|
182
|
+
|
|
183
|
+
**Example:**
|
|
184
|
+
```jsx
|
|
185
|
+
import { useRef } from 'react';
|
|
186
|
+
import { ConsentWidget } from '@gfox/grantly-react-consent';
|
|
187
|
+
|
|
188
|
+
const consentRef = useRef();
|
|
189
|
+
|
|
190
|
+
const handleSubmit = async () => {
|
|
191
|
+
try {
|
|
192
|
+
const result = await consentRef.current.submitConsent();
|
|
193
|
+
console.log('Consent submitted:', result);
|
|
194
|
+
} catch (error) {
|
|
195
|
+
console.error('Failed to submit:', error);
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
<ConsentWidget
|
|
200
|
+
ref={consentRef}
|
|
201
|
+
clientId="your-client-id"
|
|
202
|
+
xUserId="user-123"
|
|
203
|
+
// ... other props
|
|
204
|
+
/>
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### Status Callbacks
|
|
208
|
+
|
|
209
|
+
The `onStatusChange` callback receives status updates with the following structure:
|
|
210
|
+
|
|
211
|
+
```tsx
|
|
212
|
+
onStatusChange({
|
|
213
|
+
status: 'in-progress' | 'already-consented' | 'accepted' | 'declined' | 'error',
|
|
214
|
+
clientId: string,
|
|
215
|
+
userId: string,
|
|
216
|
+
// Conditional fields based on status:
|
|
217
|
+
acceptedPurposes?: string[], // present when status is 'accepted' or 'declined'
|
|
218
|
+
agreementVersionId?: string, // present when status is 'accepted' or 'declined'
|
|
219
|
+
error?: string // ONLY present when status is 'error' (contains error message)
|
|
220
|
+
})
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
| Status | Description | Additional Fields |
|
|
224
|
+
|--------|-------------|-------------------|
|
|
225
|
+
| `"in-progress"` | Widget is fetching consent agreement data | None |
|
|
226
|
+
| `"already-consented"` | User has already consented (204 response). Widget won't open in popup mode | None |
|
|
227
|
+
| `"accepted"` | User has successfully submitted consent | `acceptedPurposes`, `agreementVersionId` |
|
|
228
|
+
| `"declined"` | User closed the modal without submitting consent | `acceptedPurposes: []`, `agreementVersionId` |
|
|
229
|
+
| `"error"` | An error occurred during fetch or submission | `error` (contains error message string) |
|
|
230
|
+
|
|
231
|
+
### ConsentWidget Styling
|
|
232
|
+
|
|
233
|
+
The widget exposes CSS custom properties for complete customization:
|
|
234
|
+
|
|
235
|
+
#### Base Properties
|
|
236
|
+
```css
|
|
237
|
+
--consent-widget-width: 100%;
|
|
238
|
+
--consent-widget-font-family: inherit;
|
|
239
|
+
--consent-widget-font-size: inherit;
|
|
240
|
+
--consent-widget-text-color: #f9fafb;
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
#### Modal Properties
|
|
244
|
+
```css
|
|
245
|
+
--consent-widget-modal-bg: rgba(0, 0, 0, 0.8);
|
|
246
|
+
--consent-widget-modal-content-bg: #1f2937;
|
|
247
|
+
--consent-widget-modal-z-index: 9999;
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
#### Container Properties
|
|
251
|
+
```css
|
|
252
|
+
--consent-widget-container-bg: #1f2937;
|
|
253
|
+
--consent-widget-container-padding: 2rem;
|
|
254
|
+
--consent-widget-container-border-radius: 16px;
|
|
255
|
+
--consent-widget-container-max-width: 800px;
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
#### Button Properties
|
|
259
|
+
```css
|
|
260
|
+
--consent-widget-primary-bg: #8b5cf6;
|
|
261
|
+
--consent-widget-secondary-bg: transparent;
|
|
262
|
+
--consent-widget-button-padding: 0.75rem 1.5rem;
|
|
263
|
+
--consent-widget-button-border-radius: 6px;
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
#### Spacing Properties
|
|
267
|
+
```css
|
|
268
|
+
--consent-widget-spacing-xs: 0.25rem;
|
|
269
|
+
--consent-widget-spacing-sm: 0.5rem;
|
|
270
|
+
--consent-widget-spacing-md: 1rem;
|
|
271
|
+
--consent-widget-spacing-lg: 1.5rem;
|
|
272
|
+
--consent-widget-spacing-xl: 2rem;
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
Override these variables in your CSS to customize the widget appearance:
|
|
276
|
+
|
|
277
|
+
```css
|
|
278
|
+
.consent-widget {
|
|
279
|
+
--consent-widget-primary-bg: #007bff;
|
|
280
|
+
--consent-widget-container-border-radius: 8px;
|
|
281
|
+
--consent-widget-text-color: #333;
|
|
282
|
+
}
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
## WithdrawConsentWidget
|
|
286
|
+
|
|
287
|
+
A React component that allows users to view and withdraw their existing consents. The widget displays consent information in a clean, customizable interface with support for both modal and inline display modes.
|
|
288
|
+
|
|
289
|
+
**Key Features:**
|
|
290
|
+
- Automatic modal opening when consents are loaded (default mode)
|
|
291
|
+
- ESC key support to close modal
|
|
292
|
+
- Automatic scroll locking in modal mode
|
|
293
|
+
- Status callback deduplication to prevent duplicate events
|
|
294
|
+
- Auto-detection of display mode from consent data
|
|
295
|
+
- Multi-language support via `acceptLanguage` prop
|
|
296
|
+
- Markdown support for agreement text
|
|
297
|
+
- XSS protection via DOMPurify
|
|
298
|
+
|
|
299
|
+
**Note:** The widget returns `null` (doesn't render) when loading or when there are no consents. Use the `onStatusChange` callback to handle these states.
|
|
300
|
+
|
|
301
|
+
### WithdrawConsentWidget Props
|
|
302
|
+
|
|
303
|
+
| Prop | Type | Required | Default | Description |
|
|
304
|
+
|------|------|----------|---------|-------------|
|
|
305
|
+
| `clientId` | `string` | Required | - | Client identifier for the application |
|
|
306
|
+
| `userId` | `string` | Required | - | User identifier |
|
|
307
|
+
| `displayMode` | `string` | Optional | `""` | Display mode flags (see Display Modes) |
|
|
308
|
+
| `acceptLanguage` | `string` | Optional | `"en"` | Language code for content localization (e.g., "en", "en-US", "hi") |
|
|
309
|
+
| `onStatusChange` | `function` | Optional | - | Callback for widget status changes (see Status Callbacks below) |
|
|
310
|
+
| `onModifyConsent` | `function` | Optional | - | Callback when user clicks modify consent. Receives the consent object as parameter |
|
|
311
|
+
|
|
312
|
+
### WithdrawConsentWidget Display Modes
|
|
313
|
+
|
|
314
|
+
The `displayMode` prop accepts space-separated flags:
|
|
315
|
+
|
|
316
|
+
| Flag | Description |
|
|
317
|
+
|------|-------------|
|
|
318
|
+
| **Default (modal)** | Modal overlay with full interface. Automatically opens when consents are loaded. Locks background scroll and supports ESC key to close |
|
|
319
|
+
| `plain` | Inline display without modal. No scroll locking |
|
|
320
|
+
| `no-agreement-title` | Hide agreement titles |
|
|
321
|
+
| `no-agreement-text` | Hide agreement descriptions |
|
|
322
|
+
| `no-consent-timestamps` | Hide consent timestamps (consented_at, expires_at, withdrawn_at) |
|
|
323
|
+
| `no-modify-button` | Hide modify consent buttons |
|
|
324
|
+
|
|
325
|
+
**Note:**
|
|
326
|
+
- In default (modal) mode, the widget automatically opens the modal when consents are successfully loaded
|
|
327
|
+
- The modal locks background scrolling when open and restores it when closed
|
|
328
|
+
- Press ESC key to close the modal in default mode
|
|
329
|
+
- The widget automatically determines the display mode from the first consent's `display_mode` if not explicitly provided via props
|
|
330
|
+
|
|
331
|
+
**Examples:**
|
|
332
|
+
```jsx
|
|
333
|
+
// Modal mode (default)
|
|
334
|
+
<WithdrawConsentWidget displayMode="" />
|
|
335
|
+
|
|
336
|
+
// Plain inline mode
|
|
337
|
+
<WithdrawConsentWidget displayMode="plain" />
|
|
338
|
+
|
|
339
|
+
// Plain mode with hidden titles and timestamps
|
|
340
|
+
<WithdrawConsentWidget displayMode="plain no-agreement-title no-consent-timestamps" />
|
|
341
|
+
|
|
342
|
+
// Modal mode without modify buttons
|
|
343
|
+
<WithdrawConsentWidget displayMode="no-modify-button" />
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
### WithdrawConsentWidget Styling
|
|
347
|
+
|
|
348
|
+
The widget exposes CSS variables for complete customization. All variables are prefixed with `--wcw-`:
|
|
349
|
+
|
|
350
|
+
#### Layout & Spacing
|
|
351
|
+
```css
|
|
352
|
+
--wcw-max-width: 800px;
|
|
353
|
+
--wcw-padding: 20px;
|
|
354
|
+
--wcw-margin: 0 auto;
|
|
355
|
+
--wcw-border-radius: 8px;
|
|
356
|
+
--wcw-spacing-xs: 4px;
|
|
357
|
+
--wcw-spacing-sm: 8px;
|
|
358
|
+
--wcw-spacing-md: 12px;
|
|
359
|
+
--wcw-spacing-lg: 16px;
|
|
360
|
+
--wcw-spacing-xl: 20px;
|
|
361
|
+
--wcw-spacing-2xl: 24px;
|
|
362
|
+
--wcw-spacing-3xl: 40px;
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
#### Colors
|
|
366
|
+
```css
|
|
367
|
+
--wcw-bg-primary: #ffffff;
|
|
368
|
+
--wcw-bg-secondary: #f9fafb;
|
|
369
|
+
--wcw-text-primary: #1f2937;
|
|
370
|
+
--wcw-text-secondary: #4b5563;
|
|
371
|
+
--wcw-primary: #8b5cf6;
|
|
372
|
+
--wcw-danger: #8b5cf6;
|
|
373
|
+
--wcw-success: #059669;
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
#### Typography
|
|
377
|
+
```css
|
|
378
|
+
--wcw-font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
|
|
379
|
+
--wcw-font-size-base: 14px;
|
|
380
|
+
--wcw-font-size-small: 12px;
|
|
381
|
+
--wcw-font-size-large: 18px;
|
|
382
|
+
--wcw-font-size-xl: 24px;
|
|
383
|
+
--wcw-font-weight-normal: 400;
|
|
384
|
+
--wcw-font-weight-medium: 500;
|
|
385
|
+
--wcw-font-weight-semibold: 600;
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
#### Shadows & Transitions
|
|
389
|
+
```css
|
|
390
|
+
--wcw-shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
391
|
+
--wcw-shadow-md: 0 4px 12px rgba(0, 0, 0, 0.1);
|
|
392
|
+
--wcw-shadow-lg: 0 8px 25px rgba(0, 0, 0, 0.15);
|
|
393
|
+
--wcw-transition-fast: 0.15s ease;
|
|
394
|
+
--wcw-transition-normal: 0.2s ease;
|
|
395
|
+
--wcw-transition-slow: 0.3s ease;
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
#### Plain Mode Variables
|
|
399
|
+
```css
|
|
400
|
+
--wcw-plain-bg: transparent;
|
|
401
|
+
--wcw-plain-shadow: none;
|
|
402
|
+
--wcw-plain-border: none;
|
|
403
|
+
--wcw-plain-padding: 0;
|
|
404
|
+
--wcw-plain-margin: 0;
|
|
405
|
+
--wcw-plain-max-width: none;
|
|
406
|
+
--wcw-plain-min-height: auto;
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
### WithdrawConsentWidget Status Callbacks
|
|
410
|
+
|
|
411
|
+
The `onStatusChange` callback receives status updates with the following structure:
|
|
412
|
+
|
|
413
|
+
```tsx
|
|
414
|
+
onStatusChange({
|
|
415
|
+
status: 'in-progress' | 'consents-loaded' | 'no-consents' | 'withdrawing' | 'withdrawn' | 'error',
|
|
416
|
+
clientId: string,
|
|
417
|
+
// Additional fields based on status:
|
|
418
|
+
consents?: Consent[], // present when status is 'consents-loaded' or 'withdrawn'
|
|
419
|
+
totalCount?: number, // present when status is 'consents-loaded' or 'no-consents'
|
|
420
|
+
withdrawnConsent?: Consent, // present when status is 'withdrawing' or 'withdrawn'
|
|
421
|
+
error?: string // present when status is 'error'
|
|
422
|
+
})
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
| Status | Description |
|
|
426
|
+
|--------|-------------|
|
|
427
|
+
| `"in-progress"` | Widget is fetching consents from the API |
|
|
428
|
+
| `"consents-loaded"` | Consents successfully loaded. Includes `consents` array and `totalCount` |
|
|
429
|
+
| `"no-consents"` | User has no active consents. Includes `totalCount: 0` |
|
|
430
|
+
| `"withdrawing"` | Consent withdrawal in progress. Includes `withdrawnConsent` |
|
|
431
|
+
| `"withdrawn"` | Consent successfully withdrawn. Includes updated `consents` array and `withdrawnConsent` |
|
|
432
|
+
| `"error"` | Error occurred during operation. Includes `error` message |
|
|
433
|
+
|
|
434
|
+
**Note:** The callback uses deduplication to avoid firing duplicate status updates for the same state.
|
|
435
|
+
|
|
436
|
+
**Example:**
|
|
437
|
+
```jsx
|
|
438
|
+
<WithdrawConsentWidget
|
|
439
|
+
onStatusChange={(data) => {
|
|
440
|
+
switch (data.status) {
|
|
441
|
+
case 'consents-loaded':
|
|
442
|
+
console.log('Loaded consents:', data.consents);
|
|
443
|
+
console.log('Total count:', data.totalCount);
|
|
444
|
+
break;
|
|
445
|
+
case 'withdrawn':
|
|
446
|
+
console.log('Consent withdrawn:', data.withdrawnConsent);
|
|
447
|
+
console.log('Remaining consents:', data.consents);
|
|
448
|
+
break;
|
|
449
|
+
case 'no-consents':
|
|
450
|
+
console.log('User has no active consents');
|
|
451
|
+
break;
|
|
452
|
+
case 'error':
|
|
453
|
+
console.error('Error:', data.error);
|
|
454
|
+
break;
|
|
455
|
+
}
|
|
456
|
+
}}
|
|
457
|
+
/>
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
## Examples
|
|
461
|
+
|
|
462
|
+
### Advanced ConsentWidget Usage
|
|
463
|
+
|
|
464
|
+
#### Inline Mode with Custom Styling
|
|
465
|
+
|
|
466
|
+
```jsx
|
|
467
|
+
import React from 'react';
|
|
468
|
+
import { ConsentWidget } from '@gfox/grantly-react-consent';
|
|
469
|
+
import './ConsentWidget.css';
|
|
470
|
+
|
|
471
|
+
function InlineConsent() {
|
|
472
|
+
return (
|
|
473
|
+
<div className="consent-section">
|
|
474
|
+
<h2>Data Processing Consent</h2>
|
|
475
|
+
<ConsentWidget
|
|
476
|
+
clientId="your-client-id"
|
|
477
|
+
xUserId="user-123"
|
|
478
|
+
displayMode="inline no-agreement-title"
|
|
479
|
+
acceptLanguage="en"
|
|
480
|
+
onStatusChange={(data) => {
|
|
481
|
+
if (data.status === 'accepted') {
|
|
482
|
+
console.log('User has given consent');
|
|
483
|
+
}
|
|
484
|
+
}}
|
|
485
|
+
/>
|
|
486
|
+
</div>
|
|
487
|
+
);
|
|
488
|
+
}
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
#### Plain Mode for Embedded Use
|
|
492
|
+
|
|
493
|
+
```jsx
|
|
494
|
+
import React from 'react';
|
|
495
|
+
import { ConsentWidget } from '@gfox/grantly-react-consent';
|
|
496
|
+
|
|
497
|
+
function EmbeddedConsent() {
|
|
498
|
+
return (
|
|
499
|
+
<div className="embedded-consent">
|
|
500
|
+
<ConsentWidget
|
|
501
|
+
clientId="your-client-id"
|
|
502
|
+
xUserId="user-123"
|
|
503
|
+
displayMode="plain no-change-summary"
|
|
504
|
+
modifyConsent={true}
|
|
505
|
+
onStatusChange={(data) => {
|
|
506
|
+
// Handle consent modifications
|
|
507
|
+
if (data.status === 'accepted') {
|
|
508
|
+
console.log('Consent modified:', data.acceptedPurposes);
|
|
509
|
+
}
|
|
510
|
+
}}
|
|
511
|
+
/>
|
|
512
|
+
</div>
|
|
513
|
+
);
|
|
514
|
+
}
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
**Note:** When `modifyConsent={true}`, the submit button is only enabled when the user has actually changed their consent selection from the initial state. This prevents unnecessary API calls when no changes are made.
|
|
518
|
+
|
|
519
|
+
### Advanced WithdrawConsentWidget Usage
|
|
520
|
+
|
|
521
|
+
#### Modal Mode with Custom Callbacks
|
|
522
|
+
|
|
523
|
+
```jsx
|
|
524
|
+
import React, { useState } from 'react';
|
|
525
|
+
import { WithdrawConsentWidget } from '@gfox/grantly-react-consent';
|
|
526
|
+
|
|
527
|
+
function ConsentManagement() {
|
|
528
|
+
const [consentData, setConsentData] = useState(null);
|
|
529
|
+
|
|
530
|
+
const handleStatusChange = (data) => {
|
|
531
|
+
switch (data.status) {
|
|
532
|
+
case 'consents-loaded':
|
|
533
|
+
setConsentData(data.consents);
|
|
534
|
+
break;
|
|
535
|
+
case 'withdrawn':
|
|
536
|
+
alert('Consent successfully withdrawn');
|
|
537
|
+
setConsentData(data.consents); // Update with remaining consents
|
|
538
|
+
break;
|
|
539
|
+
case 'error':
|
|
540
|
+
console.error('Error:', data.error);
|
|
541
|
+
break;
|
|
542
|
+
}
|
|
543
|
+
};
|
|
544
|
+
|
|
545
|
+
const handleModifyConsent = (consent) => {
|
|
546
|
+
// Redirect to consent modification page
|
|
547
|
+
window.location.href = `/modify-consent/${consent.id}`;
|
|
548
|
+
};
|
|
549
|
+
|
|
550
|
+
return (
|
|
551
|
+
<div>
|
|
552
|
+
<h1>Manage Your Consents</h1>
|
|
553
|
+
<WithdrawConsentWidget
|
|
554
|
+
clientId="your-client-id"
|
|
555
|
+
userId="user-123"
|
|
556
|
+
onStatusChange={handleStatusChange}
|
|
557
|
+
onModifyConsent={handleModifyConsent}
|
|
558
|
+
/>
|
|
559
|
+
</div>
|
|
560
|
+
);
|
|
561
|
+
}
|
|
562
|
+
```
|
|
563
|
+
|
|
564
|
+
#### Plain Mode for Settings Page
|
|
565
|
+
|
|
566
|
+
```jsx
|
|
567
|
+
import React from 'react';
|
|
568
|
+
import { WithdrawConsentWidget } from '@gfox/grantly-react-consent';
|
|
569
|
+
|
|
570
|
+
function SettingsPage() {
|
|
571
|
+
return (
|
|
572
|
+
<div className="settings-page">
|
|
573
|
+
<h2>Privacy Settings</h2>
|
|
574
|
+
<div className="consent-management">
|
|
575
|
+
<WithdrawConsentWidget
|
|
576
|
+
clientId="your-client-id"
|
|
577
|
+
userId="user-123"
|
|
578
|
+
displayMode="plain no-modify-button"
|
|
579
|
+
acceptLanguage="en"
|
|
580
|
+
onStatusChange={(data) => {
|
|
581
|
+
if (data.status === 'no-consents') {
|
|
582
|
+
console.log('User has no active consents');
|
|
583
|
+
}
|
|
584
|
+
}}
|
|
585
|
+
/>
|
|
586
|
+
</div>
|
|
587
|
+
</div>
|
|
588
|
+
);
|
|
589
|
+
}
|
|
590
|
+
```
|
|
591
|
+
|
|
592
|
+
### Custom Styling Examples
|
|
593
|
+
|
|
594
|
+
#### Dark Theme
|
|
595
|
+
|
|
596
|
+
```css
|
|
597
|
+
.consent-widget {
|
|
598
|
+
--consent-widget-container-bg: #1a1a1a;
|
|
599
|
+
--consent-widget-text-color: #ffffff;
|
|
600
|
+
--consent-widget-primary-bg: #6366f1;
|
|
601
|
+
--consent-widget-modal-bg: rgba(0, 0, 0, 0.9);
|
|
602
|
+
--consent-widget-modal-content-bg: #2d2d2d;
|
|
603
|
+
}
|
|
604
|
+
```
|
|
605
|
+
|
|
606
|
+
#### Brand Colors
|
|
607
|
+
|
|
608
|
+
```css
|
|
609
|
+
.consent-widget {
|
|
610
|
+
--consent-widget-primary-bg: #007bff;
|
|
611
|
+
--consent-widget-secondary-bg: #6c757d;
|
|
612
|
+
--consent-widget-container-border-radius: 12px;
|
|
613
|
+
--consent-widget-button-padding: 1rem 2rem;
|
|
614
|
+
}
|
|
615
|
+
```
|
|
616
|
+
|
|
617
|
+
#### Minimal Design
|
|
618
|
+
|
|
619
|
+
```css
|
|
620
|
+
.consent-widget {
|
|
621
|
+
--consent-widget-container-bg: transparent;
|
|
622
|
+
--consent-widget-container-padding: 1rem;
|
|
623
|
+
--consent-widget-container-border-radius: 4px;
|
|
624
|
+
--consent-widget-button-border-radius: 4px;
|
|
625
|
+
--consent-widget-spacing-md: 0.5rem;
|
|
626
|
+
}
|
|
627
|
+
```
|
|
628
|
+
|
|
629
|
+
|
|
630
|
+
## License
|
|
631
|
+
|
|
632
|
+
This project is licensed under the Apache License 2.0.
|
|
633
|
+
|
|
634
|
+
## Links
|
|
635
|
+
|
|
636
|
+
- [NPM Package](https://www.npmjs.com/package/@gfox/grantly-react-consent)
|