@redacto.io/consent-sdk-react 0.0.1 → 0.0.3

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.mjs CHANGED
@@ -1,56 +1,39 @@
1
1
  // src/RedactoNoticeConsent/RedactoNoticeConsent.tsx
2
- import { useEffect as useEffect2, useMemo, useState as useState2 } from "react";
2
+ import { useEffect as useEffect2, useMemo, useState as useState2, useRef } from "react";
3
3
 
4
4
  // src/RedactoNoticeConsent/api/index.ts
5
5
  import { jwtDecode } from "jwt-decode";
6
- var BASE_URL = "https://api.redacto.tech";
7
- var BACKEND_URL = "http://localhost:3000";
6
+ var BASE_URL = "https://api.redacto.tech/consent";
8
7
  var fetchConsentContent = async ({
9
8
  noticeId,
10
9
  accessToken,
11
- refreshToken,
12
- language = "en"
10
+ baseUrl,
11
+ language = "en",
12
+ specific_uuid
13
13
  }) => {
14
14
  try {
15
15
  const decodedToken = jwtDecode(accessToken);
16
16
  const ORGANISATION_UUID = decodedToken == null ? void 0 : decodedToken.organisation_uuid;
17
17
  const WORKSPACE_UUID = decodedToken == null ? void 0 : decodedToken.workspace_uuid;
18
- const response = await fetch(
19
- `${BASE_URL}/consent/public/organisations/${ORGANISATION_UUID}/workspaces/${WORKSPACE_UUID}/notices/${noticeId}`,
20
- {
21
- method: "GET",
22
- headers: {
23
- Authorization: `Bearer ${accessToken}`,
24
- "Accept-Language": language,
25
- "Content-Type": "application/json"
26
- }
27
- }
18
+ const apiBaseUrl = baseUrl || BASE_URL;
19
+ const url = new URL(
20
+ `${apiBaseUrl}/public/organisations/${ORGANISATION_UUID}/workspaces/${WORKSPACE_UUID}/notices/${noticeId}`
28
21
  );
29
- if (response.status === 401) {
30
- try {
31
- const response2 = await fetch(
32
- `${BACKEND_URL}/api/consent/refresh-token`,
33
- {
34
- method: "POST",
35
- headers: {
36
- "Content-Type": "application/json"
37
- },
38
- body: JSON.stringify({
39
- refreshToken
40
- })
41
- }
42
- );
43
- if (!response2.ok) {
44
- throw new Error("Failed to get consent tokens");
45
- }
46
- const data2 = await response2.json();
47
- localStorage.setItem("accessToken", data2.token);
48
- localStorage.setItem("refreshToken", data2.refresh_token);
49
- localStorage.setItem("tokenExpiresAt", data2.expires_at);
50
- } catch (error) {
51
- console.error("Failed to setup consent:", error);
52
- throw error;
22
+ if (specific_uuid) {
23
+ url.searchParams.append("specific_uuid", specific_uuid);
24
+ }
25
+ const response = await fetch(url.toString(), {
26
+ method: "GET",
27
+ headers: {
28
+ Authorization: `Bearer ${accessToken}`,
29
+ "Accept-Language": language,
30
+ "Content-Type": "application/json"
53
31
  }
32
+ });
33
+ if (response.status === 401) {
34
+ const error = new Error("Unauthorized");
35
+ error.status = 401;
36
+ throw error;
54
37
  }
55
38
  if (response.status === 409) {
56
39
  const error = new Error("User has already provided consent");
@@ -71,9 +54,11 @@ var fetchConsentContent = async ({
71
54
  };
72
55
  var submitConsentEvent = async ({
73
56
  accessToken,
57
+ baseUrl,
74
58
  noticeUuid,
75
59
  purposes,
76
- declined
60
+ declined,
61
+ meta_data
77
62
  }) => {
78
63
  try {
79
64
  const primaryEmail = localStorage.getItem("userEmail");
@@ -90,7 +75,7 @@ var submitConsentEvent = async ({
90
75
  uuid: purpose.uuid,
91
76
  name: purpose.name,
92
77
  description: purpose.description,
93
- industries: purpose.industries,
78
+ industries: purpose.industries || "",
94
79
  selected: purpose.selected,
95
80
  data_elements: purpose.data_elements.map((element) => ({
96
81
  uuid: element.uuid,
@@ -100,10 +85,12 @@ var submitConsentEvent = async ({
100
85
  selected: element.required ? true : element.selected
101
86
  }))
102
87
  }))
103
- }
88
+ },
89
+ meta_data
104
90
  };
91
+ const apiBaseUrl = baseUrl || BASE_URL;
105
92
  const response = await fetch(
106
- `${BASE_URL}/consent/public/consent-events/organisations/${ORGANISATION_UUID}/workspaces/${WORKSPACE_UUID}/by-token`,
93
+ `${apiBaseUrl}/public/organisations/${ORGANISATION_UUID}/workspaces/${WORKSPACE_UUID}/by-token`,
107
94
  {
108
95
  method: "POST",
109
96
  headers: {
@@ -136,7 +123,10 @@ var styles = {
136
123
  justifyContent: "center",
137
124
  zIndex: 999,
138
125
  animation: "overlayFadeIn 0.2s cubic-bezier(0.16, 1, 0.3, 1)",
139
- pointerEvents: "all"
126
+ pointerEvents: "all",
127
+ margin: 0,
128
+ padding: 0,
129
+ boxSizing: "border-box"
140
130
  },
141
131
  modal: {
142
132
  position: "fixed",
@@ -151,7 +141,12 @@ var styles = {
151
141
  display: "flex",
152
142
  flexDirection: "column",
153
143
  maxHeight: "90vh",
154
- zIndex: 1e3
144
+ zIndex: 1e3,
145
+ margin: 0,
146
+ padding: 0,
147
+ boxSizing: "border-box",
148
+ textAlign: "left",
149
+ fontFamily: "inherit"
155
150
  },
156
151
  content: {
157
152
  margin: "22px",
@@ -159,7 +154,9 @@ var styles = {
159
154
  flexDirection: "column",
160
155
  flexGrow: 1,
161
156
  overflow: "hidden",
162
- minHeight: 0
157
+ minHeight: 0,
158
+ boxSizing: "border-box",
159
+ textAlign: "left"
163
160
  },
164
161
  topSection: {
165
162
  display: "flex",
@@ -168,17 +165,26 @@ var styles = {
168
165
  paddingBottom: "15px",
169
166
  borderBottom: "1px solid #e5e7eb",
170
167
  boxShadow: "0 1px 2px rgba(0, 0, 0, 0.03)",
171
- backgroundColor: "#ffffff"
168
+ backgroundColor: "#ffffff",
169
+ margin: 0,
170
+ boxSizing: "border-box",
171
+ textAlign: "left"
172
172
  },
173
173
  topLeft: {
174
174
  display: "flex",
175
175
  alignItems: "center",
176
- gap: "10px"
176
+ gap: "10px",
177
+ margin: 0,
178
+ padding: 0,
179
+ boxSizing: "border-box"
177
180
  },
178
181
  logo: {
179
182
  height: "32px",
180
183
  width: "auto",
181
- objectFit: "contain"
184
+ objectFit: "contain",
185
+ margin: 0,
186
+ padding: 0,
187
+ display: "block"
182
188
  },
183
189
  title: {
184
190
  fontSize: "18px",
@@ -186,7 +192,10 @@ var styles = {
186
192
  lineHeight: "150%",
187
193
  letterSpacing: "0.2px",
188
194
  verticalAlign: "middle",
189
- color: "#101828"
195
+ color: "#101828",
196
+ margin: 0,
197
+ padding: 0,
198
+ textAlign: "left"
190
199
  },
191
200
  topRight: {
192
201
  borderRadius: "8px",
@@ -202,6 +211,9 @@ var styles = {
202
211
  verticalAlign: "middle",
203
212
  color: "#344054",
204
213
  gap: "5px",
214
+ margin: 0,
215
+ boxSizing: "border-box",
216
+ textAlign: "left",
205
217
  cursor: "pointer",
206
218
  backgroundColor: "#ffffff"
207
219
  },
@@ -213,52 +225,78 @@ var styles = {
213
225
  flexGrow: 1,
214
226
  overflowY: "auto",
215
227
  minHeight: 0,
216
- paddingRight: "15px"
228
+ paddingRight: "15px",
229
+ boxSizing: "border-box",
230
+ textAlign: "left"
217
231
  },
218
232
  privacyText: {
219
233
  fontSize: "16px",
220
234
  fontWeight: 400,
221
235
  lineHeight: "150%",
222
236
  letterSpacing: "0.2px",
223
- color: "#344054"
237
+ color: "#344054",
238
+ margin: 0,
239
+ padding: 0,
240
+ textAlign: "left"
224
241
  },
225
242
  link: {
226
243
  color: "#4f87ff",
227
- textDecoration: "none"
244
+ textDecoration: "none",
245
+ margin: 0,
246
+ padding: 0,
247
+ boxSizing: "border-box"
228
248
  },
229
249
  subTitle: {
230
250
  fontWeight: 600,
231
251
  fontSize: "16px",
232
252
  lineHeight: "150%",
233
253
  letterSpacing: "0.2px",
234
- color: "#101828"
254
+ color: "#101828",
255
+ margin: 0,
256
+ padding: 0,
257
+ textAlign: "left"
235
258
  },
236
259
  optionsContainer: {
237
260
  display: "flex",
238
261
  flexDirection: "column",
239
- gap: "14px"
262
+ gap: "14px",
263
+ margin: 0,
264
+ padding: 0,
265
+ boxSizing: "border-box"
240
266
  },
241
267
  optionItem: {
242
268
  display: "flex",
243
269
  justifyContent: "space-between",
244
- alignItems: "center"
270
+ alignItems: "center",
271
+ margin: 0,
272
+ padding: 0,
273
+ boxSizing: "border-box"
245
274
  },
246
275
  optionLeft: {
247
276
  display: "flex",
248
277
  gap: "12px",
249
278
  alignItems: "center",
250
- cursor: "pointer"
279
+ cursor: "pointer",
280
+ margin: 0,
281
+ padding: 0,
282
+ boxSizing: "border-box"
251
283
  },
252
284
  optionTextContainer: {
253
285
  display: "flex",
254
- flexDirection: "column"
286
+ flexDirection: "column",
287
+ margin: 0,
288
+ padding: 0,
289
+ boxSizing: "border-box"
255
290
  },
256
291
  optionTitle: {
257
292
  fontWeight: 500,
258
293
  fontSize: "16px",
259
294
  lineHeight: "150%",
260
295
  letterSpacing: "0.2px",
261
- color: "#101828"
296
+ color: "#101828",
297
+ margin: 0,
298
+ padding: 0,
299
+ textAlign: "left"
262
300
  },
263
301
  optionDescription: {
264
302
  fontWeight: 400,
@@ -266,39 +304,69 @@ var styles = {
266
304
  lineHeight: "150%",
267
305
  letterSpacing: "0.2px",
268
306
  color: "#475467",
269
- verticalAlign: "middle"
307
+ verticalAlign: "middle",
308
+ margin: 0,
309
+ padding: 0,
310
+ textAlign: "left"
270
311
  },
271
312
  checkboxLarge: {
272
313
  height: "20px",
273
314
  width: "20px",
274
315
  padding: "4px",
275
316
  borderRadius: "5px",
276
- border: "2px solid #d0d5dd"
317
+ border: "2px solid #d0d5dd",
318
+ margin: 0,
319
+ boxSizing: "border-box",
320
+ appearance: "none",
321
+ WebkitAppearance: "none",
322
+ MozAppearance: "none",
323
+ cursor: "pointer",
324
+ position: "relative",
325
+ backgroundColor: "transparent"
277
326
  },
278
327
  dataElementsContainer: {
279
328
  marginLeft: "27px",
280
329
  display: "flex",
281
- flexDirection: "column"
330
+ flexDirection: "column",
331
+ margin: 0,
332
+ padding: 0,
333
+ boxSizing: "border-box",
334
+ paddingLeft: "22px"
282
335
  },
283
336
  dataElementItem: {
284
337
  display: "flex",
285
338
  alignItems: "center",
286
339
  gap: "10px",
287
- justifyContent: "space-between"
340
+ justifyContent: "space-between",
341
+ margin: 0,
342
+ padding: 0,
343
+ boxSizing: "border-box",
344
+ minHeight: "24px"
288
345
  },
289
346
  dataElementText: {
290
347
  fontWeight: 400,
291
348
  fontSize: "14px",
292
349
  lineHeight: "150%",
293
350
  letterSpacing: "0.2px",
294
- color: "#344054"
351
+ color: "#344054",
352
+ margin: 0,
353
+ padding: 0,
354
+ textAlign: "left"
295
355
  },
296
356
  checkboxSmall: {
297
357
  height: "16px",
298
358
  width: "16px",
299
359
  padding: "4px",
300
360
  borderRadius: "5px",
301
- border: "2px solid #d0d5dd"
361
+ border: "2px solid #d0d5dd",
362
+ margin: 0,
363
+ boxSizing: "border-box",
364
+ appearance: "none",
365
+ WebkitAppearance: "none",
366
+ MozAppearance: "none",
367
+ cursor: "pointer",
368
+ position: "relative",
369
+ backgroundColor: "transparent"
302
370
  },
303
371
  bottomSection: {
304
372
  display: "flex",
@@ -307,7 +375,9 @@ var styles = {
307
375
  paddingTop: "15px",
308
376
  borderTop: "1px solid #e5e7eb",
309
377
  boxShadow: "0 -1px 2px rgba(0, 0, 0, 0.03)",
310
- backgroundColor: "#ffffff"
378
+ backgroundColor: "#ffffff",
379
+ margin: 0,
380
+ boxSizing: "border-box"
311
381
  },
312
382
  button: {
313
383
  width: "100%",
@@ -317,7 +387,10 @@ var styles = {
317
387
  fontSize: "16px",
318
388
  lineHeight: "150%",
319
389
  letterSpacing: "0.2px",
320
- cursor: "pointer"
390
+ cursor: "pointer",
391
+ margin: 0,
392
+ boxSizing: "border-box",
393
+ textAlign: "center"
321
394
  },
322
395
  acceptButton: {
323
396
  backgroundColor: "#4f87ff",
@@ -330,7 +403,10 @@ var styles = {
330
403
  color: "#000000"
331
404
  },
332
405
  languageSelectorContainer: {
333
- position: "relative"
406
+ position: "relative",
407
+ margin: 0,
408
+ padding: 0,
409
+ boxSizing: "border-box"
334
410
  },
335
411
  languageDropdown: {
336
412
  position: "absolute",
@@ -342,7 +418,10 @@ var styles = {
342
418
  boxShadow: "0px 2px 4px rgba(0, 0, 0, 0.1)",
343
419
  zIndex: 10,
344
420
  width: "max-content",
345
- marginTop: "4px"
421
+ marginTop: "4px",
422
+ padding: 0,
423
+ boxSizing: "border-box",
424
+ textAlign: "left"
346
425
  },
347
426
  languageItem: {
348
427
  padding: "8px 12px",
@@ -350,7 +429,10 @@ var styles = {
350
429
  fontSize: "12px",
351
430
  color: "#344054",
352
431
  backgroundColor: "#ffffff",
353
- borderBottom: "1px solid #e5e7eb"
432
+ borderBottom: "1px solid #e5e7eb",
433
+ margin: 0,
434
+ boxSizing: "border-box",
435
+ textAlign: "left"
354
436
  },
355
437
  selectedLanguageItem: {
356
438
  backgroundColor: "#f3f4f6",
@@ -362,7 +444,9 @@ var styles = {
362
444
  alignItems: "center",
363
445
  justifyContent: "center",
364
446
  padding: "2rem",
365
- minHeight: "200px"
447
+ minHeight: "200px",
448
+ margin: 0,
449
+ boxSizing: "border-box"
366
450
  },
367
451
  loadingSpinner: {
368
452
  width: "40px",
@@ -371,55 +455,8 @@ var styles = {
371
455
  borderTop: "4px solid #3498db",
372
456
  borderRadius: "50%",
373
457
  animation: "spin 1s linear infinite",
374
- marginBottom: "1rem"
375
- },
376
- // Media query styles
377
- "@media (max-width: 768px)": {
378
- modal: {
379
- width: "90%"
380
- },
381
- content: {
382
- margin: "20px"
383
- },
384
- title: {
385
- fontSize: "16px"
386
- },
387
- subTitle: {
388
- fontSize: "14px"
389
- },
390
- privacyText: {
391
- fontSize: "14px"
392
- },
393
- optionTitle: {
394
- fontSize: "14px"
395
- },
396
- optionDescription: {
397
- fontSize: "11px"
398
- },
399
- dataElementText: {
400
- fontSize: "12px"
401
- },
402
- topRight: {
403
- fontSize: "11px",
404
- padding: "3px 6px",
405
- height: "auto",
406
- width: "auto"
407
- },
408
- languageItem: {
409
- fontSize: "11px",
410
- padding: "6px 10px"
411
- },
412
- bottomSection: {
413
- flexDirection: "column",
414
- gap: "12px"
415
- },
416
- button: {
417
- fontSize: "14px",
418
- padding: "10px 20px"
419
- },
420
- middleSection: {
421
- paddingRight: "10px"
422
- }
458
+ marginBottom: "1rem",
459
+ boxSizing: "border-box"
423
460
  }
424
461
  };
425
462
 
@@ -453,29 +490,136 @@ var useMediaQuery = (query) => {
453
490
  return matches;
454
491
  };
455
492
 
493
+ // src/RedactoNoticeConsent/injectStyles.ts
494
+ var stylesInjected = false;
495
+ var injectCheckboxStyles = () => {
496
+ if (stylesInjected || typeof document === "undefined") {
497
+ return;
498
+ }
499
+ const STYLE_ID = "redacto-consent-checkbox-styles";
500
+ if (document.getElementById(STYLE_ID)) {
501
+ stylesInjected = true;
502
+ return;
503
+ }
504
+ const style = document.createElement("style");
505
+ style.id = STYLE_ID;
506
+ style.textContent = `
507
+ /* Redacto Consent SDK Checkbox Styles */
508
+ .redacto-checkbox-large {
509
+ appearance: none !important;
510
+ -webkit-appearance: none !important;
511
+ -moz-appearance: none !important;
512
+ height: 20px !important;
513
+ width: 20px !important;
514
+ border: 2px solid #d0d5dd !important;
515
+ border-radius: 5px !important;
516
+ background-color: transparent !important;
517
+ cursor: pointer !important;
518
+ position: relative !important;
519
+ box-sizing: border-box !important;
520
+ margin: 0 !important;
521
+ padding: 4px !important;
522
+ }
523
+
524
+ .redacto-checkbox-small {
525
+ appearance: none !important;
526
+ -webkit-appearance: none !important;
527
+ -moz-appearance: none !important;
528
+ height: 16px !important;
529
+ width: 16px !important;
530
+ border: 2px solid #d0d5dd !important;
531
+ border-radius: 5px !important;
532
+ background-color: transparent !important;
533
+ cursor: pointer !important;
534
+ position: relative !important;
535
+ box-sizing: border-box !important;
536
+ margin: 0 !important;
537
+ padding: 4px !important;
538
+ }
539
+
540
+ .redacto-checkbox-large:checked {
541
+ background-color: #4f87ff !important;
542
+ border-color: #4f87ff !important;
543
+ }
544
+
545
+ .redacto-checkbox-small:checked {
546
+ background-color: #4f87ff !important;
547
+ border-color: #4f87ff !important;
548
+ }
549
+
550
+ .redacto-checkbox-large:checked::after {
551
+ content: '' !important;
552
+ position: absolute !important;
553
+ left: 50% !important;
554
+ top: 50% !important;
555
+ transform: translate(-50%, -50%) rotate(45deg) !important;
556
+ width: 4px !important;
557
+ height: 8px !important;
558
+ border: solid white !important;
559
+ border-width: 0 2px 2px 0 !important;
560
+ box-sizing: border-box !important;
561
+ }
562
+
563
+ .redacto-checkbox-small:checked::after {
564
+ content: '' !important;
565
+ position: absolute !important;
566
+ left: 50% !important;
567
+ top: 50% !important;
568
+ transform: translate(-50%, -50%) rotate(45deg) !important;
569
+ width: 3px !important;
570
+ height: 6px !important;
571
+ border: solid white !important;
572
+ border-width: 0 1.5px 1.5px 0 !important;
573
+ box-sizing: border-box !important;
574
+ }
575
+
576
+ .redacto-checkbox-large:focus {
577
+ outline: 2px solid #4f87ff !important;
578
+ outline-offset: 2px !important;
579
+ }
580
+
581
+ .redacto-checkbox-small:focus {
582
+ outline: 2px solid #4f87ff !important;
583
+ outline-offset: 2px !important;
584
+ }
585
+ `;
586
+ document.head.appendChild(style);
587
+ stylesInjected = true;
588
+ };
589
+
456
590
  // src/RedactoNoticeConsent/RedactoNoticeConsent.tsx
457
591
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
458
592
  var RedactoNoticeConsent = ({
459
593
  noticeId,
460
594
  accessToken,
461
595
  refreshToken,
596
+ baseUrl,
462
597
  language = "en",
463
- blockUI = false,
598
+ blockUI = true,
464
599
  onAccept,
465
600
  onDecline,
466
601
  onError,
467
- settings
602
+ settings,
603
+ applicationId
468
604
  }) => {
469
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t;
605
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s;
470
606
  const [content, setContent] = useState2(null);
471
607
  const [isLoading, setIsLoading] = useState2(true);
472
608
  const [isSubmitting, setIsSubmitting] = useState2(false);
609
+ const [isRefreshingToken, setIsRefreshingToken] = useState2(false);
473
610
  const [isLanguageDropdownOpen, setIsLanguageDropdownOpen] = useState2(false);
474
611
  const [selectedLanguage, setSelectedLanguage] = useState2(language);
475
612
  const [collapsedPurposes, setCollapsedPurposes] = useState2({});
476
613
  const [selectedPurposes, setSelectedPurposes] = useState2({});
477
614
  const [selectedDataElements, setSelectedDataElements] = useState2({});
478
615
  const [hasAlreadyConsented, setHasAlreadyConsented] = useState2(false);
616
+ const [errorMessage, setErrorMessage] = useState2(null);
617
+ const [fetchError, setFetchError] = useState2(null);
618
+ const modalRef = useRef(null);
619
+ const firstFocusableRef = useRef(null);
620
+ const lastFocusableRef = useRef(null);
621
+ const MAX_REFRESH_ATTEMPTS = 1;
622
+ const [refreshAttempts, setRefreshAttempts] = useState2(0);
479
623
  const isMobile = useMediaQuery("(max-width: 768px)");
480
624
  const responsiveStyles = useMemo(
481
625
  () => ({
@@ -523,6 +667,28 @@ var RedactoNoticeConsent = ({
523
667
  },
524
668
  middleSection: {
525
669
  paddingRight: isMobile ? "10px" : "15px"
670
+ },
671
+ errorDialog: {
672
+ padding: isMobile ? "12px" : "16px",
673
+ maxWidth: isMobile ? "100%" : "400px",
674
+ marginBottom: isMobile ? "16px" : "20px"
675
+ },
676
+ errorTitle: {
677
+ fontSize: isMobile ? "16px" : "18px",
678
+ margin: isMobile ? "0 0 8px 0" : "0 0 12px 0"
679
+ },
680
+ errorMessage: {
681
+ fontSize: isMobile ? "12px" : "14px",
682
+ margin: isMobile ? "0 0 12px 0" : "0 0 16px 0"
683
+ },
684
+ errorButton: {
685
+ padding: isMobile ? "6px 12px" : "8px 16px",
686
+ fontSize: isMobile ? "12px" : "14px"
687
+ },
688
+ closeButton: {
689
+ top: isMobile ? "4px" : "8px",
690
+ right: isMobile ? "4px" : "8px",
691
+ padding: isMobile ? "2px" : "4px"
526
692
  }
527
693
  }),
528
694
  [isMobile]
@@ -574,65 +740,83 @@ var RedactoNoticeConsent = ({
574
740
  }
575
741
  return defaultText;
576
742
  };
577
- useEffect2(() => {
578
- const fetchNotice = async () => {
579
- setIsLoading(true);
580
- try {
581
- const consentContentData = await fetchConsentContent({
582
- noticeId,
583
- accessToken,
584
- refreshToken,
585
- language
586
- });
587
- setContent(consentContentData.detail.active_config);
588
- if (consentContentData.detail.active_config.default_language) {
589
- setSelectedLanguage(
590
- consentContentData.detail.active_config.default_language
591
- );
592
- }
593
- const initialCollapsedState = consentContentData.detail.active_config.purposes.reduce(
594
- (acc, purpose) => ({
595
- ...acc,
596
- [purpose.uuid]: true
597
- }),
598
- {}
599
- );
600
- setCollapsedPurposes(initialCollapsedState);
601
- const initialPurposeState = consentContentData.detail.active_config.purposes.reduce(
602
- (acc, purpose) => {
603
- return {
604
- ...acc,
605
- [purpose.uuid]: false
606
- // Initialize all purposes as unchecked
607
- };
608
- },
609
- {}
610
- );
611
- setSelectedPurposes(initialPurposeState);
612
- const initialDataElementState = consentContentData.detail.active_config.purposes.reduce(
613
- (acc, purpose) => {
614
- purpose.data_elements.forEach((element) => {
615
- const combinedId = `${purpose.uuid}-${element.uuid}`;
616
- acc[combinedId] = false;
617
- });
618
- return acc;
619
- },
620
- {}
743
+ const fetchNotice = async () => {
744
+ setIsLoading(true);
745
+ setFetchError(null);
746
+ try {
747
+ const consentContentData = await fetchConsentContent({
748
+ noticeId,
749
+ accessToken,
750
+ refreshToken,
751
+ baseUrl,
752
+ language,
753
+ specific_uuid: applicationId
754
+ });
755
+ setContent(consentContentData.detail.active_config);
756
+ if (consentContentData.detail.active_config.default_language) {
757
+ setSelectedLanguage(
758
+ consentContentData.detail.active_config.default_language
621
759
  );
622
- setSelectedDataElements(initialDataElementState);
623
- } catch (err) {
624
- console.error(err);
625
- if (err.status === 409) {
626
- setHasAlreadyConsented(true);
627
- } else {
628
- onError == null ? void 0 : onError(err);
629
- }
630
- } finally {
631
- setIsLoading(false);
632
760
  }
633
- };
761
+ const initialCollapsedState = consentContentData.detail.active_config.purposes.reduce(
762
+ (acc, purpose) => ({
763
+ ...acc,
764
+ [purpose.uuid]: true
765
+ }),
766
+ {}
767
+ );
768
+ setCollapsedPurposes(initialCollapsedState);
769
+ const initialPurposeState = consentContentData.detail.active_config.purposes.reduce(
770
+ (acc, purpose) => {
771
+ return {
772
+ ...acc,
773
+ [purpose.uuid]: false
774
+ };
775
+ },
776
+ {}
777
+ );
778
+ setSelectedPurposes(initialPurposeState);
779
+ const initialDataElementState = consentContentData.detail.active_config.purposes.reduce(
780
+ (acc, purpose) => {
781
+ purpose.data_elements.forEach((element) => {
782
+ const combinedId = `${purpose.uuid}-${element.uuid}`;
783
+ acc[combinedId] = false;
784
+ });
785
+ return acc;
786
+ },
787
+ {}
788
+ );
789
+ setSelectedDataElements(initialDataElementState);
790
+ } catch (err) {
791
+ console.error(err);
792
+ const error = err;
793
+ setFetchError(error);
794
+ if (error.status === 401 && refreshAttempts < MAX_REFRESH_ATTEMPTS) {
795
+ setRefreshAttempts((c) => c + 1);
796
+ setIsRefreshingToken(true);
797
+ onError == null ? void 0 : onError(error);
798
+ } else if (error.status === 409) {
799
+ setHasAlreadyConsented(true);
800
+ } else {
801
+ onError == null ? void 0 : onError(error);
802
+ }
803
+ } finally {
804
+ setIsLoading(false);
805
+ setIsRefreshingToken(false);
806
+ }
807
+ };
808
+ useEffect2(() => {
809
+ injectCheckboxStyles();
634
810
  fetchNotice();
635
- }, [noticeId, accessToken, refreshToken, language, onError]);
811
+ }, [
812
+ noticeId,
813
+ accessToken,
814
+ refreshToken,
815
+ language,
816
+ onError,
817
+ applicationId,
818
+ isRefreshingToken
819
+ ]);
636
820
  const togglePurposeCollapse = (purposeUuid) => {
637
821
  setCollapsedPurposes((prev) => ({
638
822
  ...prev,
@@ -693,9 +877,11 @@ var RedactoNoticeConsent = ({
693
877
  const handleAccept = async () => {
694
878
  try {
695
879
  setIsSubmitting(true);
880
+ setErrorMessage(null);
696
881
  if (content) {
697
882
  await submitConsentEvent({
698
883
  accessToken,
884
+ baseUrl,
699
885
  noticeUuid: content.notice_uuid,
700
886
  purposes: content.purposes.map((purpose) => ({
701
887
  ...purpose,
@@ -705,12 +891,19 @@ var RedactoNoticeConsent = ({
705
891
  selected: element.required ? true : selectedDataElements[`${purpose.uuid}-${element.uuid}`] || false
706
892
  }))
707
893
  })),
708
- declined: false
894
+ declined: false,
895
+ meta_data: applicationId ? { specific_uuid: applicationId } : void 0
709
896
  });
710
897
  }
711
898
  onAccept == null ? void 0 : onAccept();
712
899
  } catch (error) {
713
900
  console.error("Error submitting consent:", error);
901
+ const err = error;
902
+ if (err.status === 500) {
903
+ setErrorMessage(
904
+ "An error occurred while submitting your consent. Please try again later."
905
+ );
906
+ }
714
907
  onError == null ? void 0 : onError(error);
715
908
  } finally {
716
909
  setIsSubmitting(false);
@@ -735,7 +928,7 @@ var RedactoNoticeConsent = ({
735
928
  };
736
929
  const acceptButtonStyle = {
737
930
  ...buttonStyle,
738
- backgroundColor: ((_b = (_a = settings == null ? void 0 : settings.button) == null ? void 0 : _a.accept) == null ? void 0 : _b.backgroundColor) || "#4f87ff",
931
+ backgroundColor: ((_b = (_a = settings == null ? void 0 : settings.button) == null ? void 0 : _a.accept) == null ? void 0 : _b.backgroundColor) || (content == null ? void 0 : content.primary_color) || "#4f87ff",
739
932
  color: ((_d = (_c = settings == null ? void 0 : settings.button) == null ? void 0 : _c.accept) == null ? void 0 : _d.textColor) || "#ffffff"
740
933
  };
741
934
  const declineButtonStyle = {
@@ -745,18 +938,18 @@ var RedactoNoticeConsent = ({
745
938
  borderColor: (settings == null ? void 0 : settings.borderColor) || "#d0d5dd"
746
939
  };
747
940
  const linkStyle = {
748
- color: ((_i = settings == null ? void 0 : settings.link) == null ? void 0 : _i.color) || "#4f87ff"
941
+ color: (settings == null ? void 0 : settings.link) || (content == null ? void 0 : content.secondary_color) || "#4f87ff"
749
942
  };
750
943
  const languageSelectorStyle = {
751
944
  borderRadius: (settings == null ? void 0 : settings.borderRadius) || "8px",
752
945
  borderColor: (settings == null ? void 0 : settings.borderColor) || "#d0d5dd",
753
- backgroundColor: ((_k = (_j = settings == null ? void 0 : settings.button) == null ? void 0 : _j.language) == null ? void 0 : _k.backgroundColor) || "#ffffff",
754
- color: ((_m = (_l = settings == null ? void 0 : settings.button) == null ? void 0 : _l.language) == null ? void 0 : _m.textColor) || "#344054"
946
+ backgroundColor: ((_j = (_i = settings == null ? void 0 : settings.button) == null ? void 0 : _i.language) == null ? void 0 : _j.backgroundColor) || "#ffffff",
947
+ color: ((_l = (_k = settings == null ? void 0 : settings.button) == null ? void 0 : _k.language) == null ? void 0 : _l.textColor) || "#344054"
755
948
  };
756
949
  const selectedLanguageItemStyle = {
757
950
  ...languageSelectorStyle,
758
- backgroundColor: ((_o = (_n = settings == null ? void 0 : settings.button) == null ? void 0 : _n.language) == null ? void 0 : _o.selectedBackgroundColor) || "#f3f4f6",
759
- color: ((_q = (_p = settings == null ? void 0 : settings.button) == null ? void 0 : _p.language) == null ? void 0 : _q.selectedTextColor) || "#344054",
951
+ backgroundColor: ((_n = (_m = settings == null ? void 0 : settings.button) == null ? void 0 : _m.language) == null ? void 0 : _n.selectedBackgroundColor) || "#f3f4f6",
952
+ color: ((_p = (_o = settings == null ? void 0 : settings.button) == null ? void 0 : _o.language) == null ? void 0 : _p.selectedTextColor) || "#344054",
760
953
  fontWeight: 600
761
954
  };
762
955
  const headingStyle = {
@@ -768,11 +961,61 @@ var RedactoNoticeConsent = ({
768
961
  const sectionStyle = {
769
962
  backgroundColor: (settings == null ? void 0 : settings.backgroundColor) || "#ffffff"
770
963
  };
964
+ const handleCloseError = () => {
965
+ setErrorMessage(null);
966
+ };
967
+ useEffect2(() => {
968
+ const handleKeyDown = (event) => {
969
+ if (!modalRef.current) return;
970
+ const focusableElements = modalRef.current.querySelectorAll(
971
+ 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
972
+ );
973
+ if (!focusableElements.length) return;
974
+ if (event.key === "Escape") {
975
+ handleDecline();
976
+ }
977
+ if (event.key === "Tab") {
978
+ const firstElement = focusableElements[0];
979
+ const lastElement = focusableElements[focusableElements.length - 1];
980
+ if (event.shiftKey) {
981
+ if (document.activeElement === firstElement) {
982
+ event.preventDefault();
983
+ lastElement.focus();
984
+ }
985
+ } else {
986
+ if (document.activeElement === lastElement) {
987
+ event.preventDefault();
988
+ firstElement.focus();
989
+ }
990
+ }
991
+ }
992
+ };
993
+ const modal = modalRef.current;
994
+ modal == null ? void 0 : modal.addEventListener("keydown", handleKeyDown);
995
+ if (modal && !isLoading) {
996
+ const focusableElements = modal.querySelectorAll(
997
+ 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
998
+ );
999
+ const firstElement = focusableElements[0];
1000
+ firstElement == null ? void 0 : firstElement.focus();
1001
+ }
1002
+ return () => {
1003
+ modal == null ? void 0 : modal.removeEventListener("keydown", handleKeyDown);
1004
+ };
1005
+ }, [isLoading, handleDecline]);
771
1006
  return /* @__PURE__ */ jsx(Fragment, { children: hasAlreadyConsented ? null : /* @__PURE__ */ jsxs(Fragment, { children: [
772
- blockUI && /* @__PURE__ */ jsx("div", { style: styles.overlay, "aria-hidden": "true" }),
1007
+ blockUI && /* @__PURE__ */ jsx(
1008
+ "div",
1009
+ {
1010
+ style: styles.overlay,
1011
+ "aria-hidden": "true",
1012
+ role: "presentation"
1013
+ }
1014
+ ),
773
1015
  /* @__PURE__ */ jsx(
774
1016
  "div",
775
1017
  {
1018
+ ref: modalRef,
776
1019
  style: {
777
1020
  ...styles.modal,
778
1021
  ...responsiveStyles.modal,
@@ -781,10 +1024,187 @@ var RedactoNoticeConsent = ({
781
1024
  role: "dialog",
782
1025
  "aria-modal": "true",
783
1026
  "aria-labelledby": "privacy-notice-title",
784
- children: isLoading ? /* @__PURE__ */ jsxs("div", { style: styles.loadingContainer, children: [
1027
+ "aria-describedby": "privacy-notice-description",
1028
+ tabIndex: -1,
1029
+ children: isLoading || isRefreshingToken ? /* @__PURE__ */ jsxs("div", { style: styles.loadingContainer, children: [
785
1030
  /* @__PURE__ */ jsx("div", { style: styles.loadingSpinner }),
786
- /* @__PURE__ */ jsx("p", { style: { ...styles.privacyText, ...textStyle }, children: "Loading..." })
787
- ] }) : /* @__PURE__ */ jsxs("div", { style: { ...styles.content, ...responsiveStyles.content }, children: [
1031
+ /* @__PURE__ */ jsx("p", { style: { ...styles.privacyText, ...textStyle }, children: isRefreshingToken ? "Refreshing session..." : "Loading..." })
1032
+ ] }) : fetchError ? /* @__PURE__ */ jsx(
1033
+ "div",
1034
+ {
1035
+ style: {
1036
+ ...styles.content,
1037
+ ...responsiveStyles.content,
1038
+ display: "flex",
1039
+ flexDirection: "column",
1040
+ alignItems: "center",
1041
+ justifyContent: "center",
1042
+ textAlign: "center",
1043
+ padding: "40px 20px"
1044
+ },
1045
+ children: /* @__PURE__ */ jsxs(
1046
+ "div",
1047
+ {
1048
+ style: {
1049
+ color: "#DC2626",
1050
+ padding: responsiveStyles.errorDialog.padding,
1051
+ borderRadius: "8px",
1052
+ marginBottom: responsiveStyles.errorDialog.marginBottom,
1053
+ width: "100%",
1054
+ maxWidth: responsiveStyles.errorDialog.maxWidth,
1055
+ position: "relative"
1056
+ },
1057
+ children: [
1058
+ /* @__PURE__ */ jsx(
1059
+ "button",
1060
+ {
1061
+ onClick: handleDecline,
1062
+ style: {
1063
+ position: "absolute",
1064
+ top: responsiveStyles.closeButton.top,
1065
+ right: responsiveStyles.closeButton.right,
1066
+ background: "none",
1067
+ border: "none",
1068
+ color: "#DC2626",
1069
+ cursor: "pointer",
1070
+ padding: responsiveStyles.closeButton.padding,
1071
+ display: "flex",
1072
+ alignItems: "center",
1073
+ justifyContent: "center"
1074
+ },
1075
+ "aria-label": "Close error message",
1076
+ children: /* @__PURE__ */ jsx(
1077
+ "svg",
1078
+ {
1079
+ width: isMobile ? "14" : "16",
1080
+ height: isMobile ? "14" : "16",
1081
+ viewBox: "0 0 16 16",
1082
+ fill: "none",
1083
+ xmlns: "http://www.w3.org/2000/svg",
1084
+ "aria-hidden": "true",
1085
+ children: /* @__PURE__ */ jsx(
1086
+ "path",
1087
+ {
1088
+ d: "M12 4L4 12M4 4L12 12",
1089
+ stroke: "currentColor",
1090
+ strokeWidth: "2",
1091
+ strokeLinecap: "round",
1092
+ strokeLinejoin: "round"
1093
+ }
1094
+ )
1095
+ }
1096
+ )
1097
+ }
1098
+ ),
1099
+ /* @__PURE__ */ jsx(
1100
+ "h3",
1101
+ {
1102
+ style: {
1103
+ margin: responsiveStyles.errorTitle.margin,
1104
+ fontSize: responsiveStyles.errorTitle.fontSize,
1105
+ fontWeight: "600"
1106
+ },
1107
+ children: "Error Loading Consent Notice"
1108
+ }
1109
+ ),
1110
+ /* @__PURE__ */ jsx(
1111
+ "p",
1112
+ {
1113
+ style: {
1114
+ margin: responsiveStyles.errorMessage.margin,
1115
+ fontSize: responsiveStyles.errorMessage.fontSize,
1116
+ lineHeight: "1.5"
1117
+ },
1118
+ children: fetchError.message || "Failed to load consent notice. Please try again."
1119
+ }
1120
+ ),
1121
+ /* @__PURE__ */ jsx(
1122
+ "button",
1123
+ {
1124
+ onClick: fetchNotice,
1125
+ style: {
1126
+ backgroundColor: "#DC2626",
1127
+ color: "#FFFFFF",
1128
+ border: "none",
1129
+ padding: responsiveStyles.errorButton.padding,
1130
+ borderRadius: "6px",
1131
+ cursor: "pointer",
1132
+ fontSize: responsiveStyles.errorButton.fontSize,
1133
+ fontWeight: "500",
1134
+ transition: "background-color 0.2s"
1135
+ },
1136
+ onMouseOver: (e) => e.currentTarget.style.backgroundColor = "#B91C1C",
1137
+ onMouseOut: (e) => e.currentTarget.style.backgroundColor = "#DC2626",
1138
+ children: "Refresh"
1139
+ }
1140
+ )
1141
+ ]
1142
+ }
1143
+ )
1144
+ }
1145
+ ) : /* @__PURE__ */ jsxs("div", { style: { ...styles.content, ...responsiveStyles.content }, children: [
1146
+ errorMessage && /* @__PURE__ */ jsxs(
1147
+ "div",
1148
+ {
1149
+ role: "alert",
1150
+ style: {
1151
+ backgroundColor: "#FEE2E2",
1152
+ color: "#DC2626",
1153
+ padding: "12px",
1154
+ borderRadius: "6px",
1155
+ marginBottom: "16px",
1156
+ fontSize: "14px",
1157
+ border: "1px solid #FCA5A5",
1158
+ position: "relative",
1159
+ display: "flex",
1160
+ alignItems: "center",
1161
+ justifyContent: "space-between"
1162
+ },
1163
+ children: [
1164
+ /* @__PURE__ */ jsx("span", { children: errorMessage }),
1165
+ /* @__PURE__ */ jsx(
1166
+ "button",
1167
+ {
1168
+ type: "button",
1169
+ onClick: handleCloseError,
1170
+ style: {
1171
+ background: "none",
1172
+ border: "none",
1173
+ color: "#DC2626",
1174
+ cursor: "pointer",
1175
+ padding: "4px",
1176
+ marginLeft: "8px",
1177
+ display: "flex",
1178
+ alignItems: "center",
1179
+ justifyContent: "center"
1180
+ },
1181
+ "aria-label": "Close error message",
1182
+ children: /* @__PURE__ */ jsx(
1183
+ "svg",
1184
+ {
1185
+ width: "16",
1186
+ height: "16",
1187
+ viewBox: "0 0 16 16",
1188
+ fill: "none",
1189
+ xmlns: "http://www.w3.org/2000/svg",
1190
+ "aria-hidden": "true",
1191
+ children: /* @__PURE__ */ jsx(
1192
+ "path",
1193
+ {
1194
+ d: "M12 4L4 12M4 4L12 12",
1195
+ stroke: "currentColor",
1196
+ strokeWidth: "2",
1197
+ strokeLinecap: "round",
1198
+ strokeLinejoin: "round"
1199
+ }
1200
+ )
1201
+ }
1202
+ )
1203
+ }
1204
+ )
1205
+ ]
1206
+ }
1207
+ ),
788
1208
  /* @__PURE__ */ jsxs("div", { style: { ...styles.topSection, ...sectionStyle }, children: [
789
1209
  /* @__PURE__ */ jsxs("div", { style: styles.topLeft, children: [
790
1210
  /* @__PURE__ */ jsx(
@@ -792,7 +1212,7 @@ var RedactoNoticeConsent = ({
792
1212
  {
793
1213
  style: styles.logo,
794
1214
  src: (content == null ? void 0 : content.logo_url) || redacto_logo_default,
795
- alt: "logo"
1215
+ alt: "Redacto Logo"
796
1216
  }
797
1217
  ),
798
1218
  /* @__PURE__ */ jsx(
@@ -812,6 +1232,7 @@ var RedactoNoticeConsent = ({
812
1232
  /* @__PURE__ */ jsxs(
813
1233
  "button",
814
1234
  {
1235
+ ref: firstFocusableRef,
815
1236
  style: {
816
1237
  ...styles.topRight,
817
1238
  ...responsiveStyles.topRight,
@@ -820,6 +1241,7 @@ var RedactoNoticeConsent = ({
820
1241
  onClick: toggleLanguageDropdown,
821
1242
  "aria-expanded": isLanguageDropdownOpen,
822
1243
  "aria-haspopup": "listbox",
1244
+ "aria-controls": "language-listbox",
823
1245
  children: [
824
1246
  selectedLanguage,
825
1247
  /* @__PURE__ */ jsx(
@@ -830,11 +1252,12 @@ var RedactoNoticeConsent = ({
830
1252
  height: "16",
831
1253
  viewBox: "0 0 16 16",
832
1254
  fill: "none",
833
- stroke: ((_s = (_r = settings == null ? void 0 : settings.button) == null ? void 0 : _r.language) == null ? void 0 : _s.textColor) || "currentColor",
1255
+ stroke: ((_r = (_q = settings == null ? void 0 : settings.button) == null ? void 0 : _q.language) == null ? void 0 : _r.textColor) || "currentColor",
834
1256
  strokeWidth: "2",
835
1257
  strokeLinecap: "round",
836
1258
  strokeLinejoin: "round",
837
1259
  style: { flexShrink: 0, marginLeft: "4px" },
1260
+ "aria-hidden": "true",
838
1261
  children: /* @__PURE__ */ jsx("path", { d: "M4 6l4 4 4-4" })
839
1262
  }
840
1263
  )
@@ -844,6 +1267,7 @@ var RedactoNoticeConsent = ({
844
1267
  isLanguageDropdownOpen && /* @__PURE__ */ jsx(
845
1268
  "ul",
846
1269
  {
1270
+ id: "language-listbox",
847
1271
  style: {
848
1272
  ...styles.languageDropdown,
849
1273
  ...languageSelectorStyle
@@ -874,6 +1298,7 @@ var RedactoNoticeConsent = ({
874
1298
  /* @__PURE__ */ jsxs(
875
1299
  "div",
876
1300
  {
1301
+ id: "privacy-notice-description",
877
1302
  style: {
878
1303
  ...styles.middleSection,
879
1304
  ...responsiveStyles.middleSection,
@@ -900,6 +1325,7 @@ var RedactoNoticeConsent = ({
900
1325
  href: (content == null ? void 0 : content.privacy_policy_url) || "#",
901
1326
  target: "_blank",
902
1327
  rel: "noopener noreferrer",
1328
+ "aria-label": "Privacy Policy (opens in new tab)",
903
1329
  children: [
904
1330
  "[",
905
1331
  getTranslatedText(
@@ -918,7 +1344,9 @@ var RedactoNoticeConsent = ({
918
1344
  {
919
1345
  style: { ...styles.link, ...linkStyle },
920
1346
  href: (content == null ? void 0 : content.sub_processors_url) || "#",
921
- target: "",
1347
+ target: "_blank",
1348
+ rel: "noopener noreferrer",
1349
+ "aria-label": "Vendors List (opens in new tab)",
922
1350
  children: [
923
1351
  "[",
924
1352
  getTranslatedText(
@@ -947,13 +1375,23 @@ var RedactoNoticeConsent = ({
947
1375
  )
948
1376
  }
949
1377
  ),
950
- /* @__PURE__ */ jsx("div", { style: styles.optionsContainer, children: (_t = content == null ? void 0 : content.purposes) == null ? void 0 : _t.map((purpose) => /* @__PURE__ */ jsxs("div", { children: [
1378
+ /* @__PURE__ */ jsx("div", { style: styles.optionsContainer, children: (_s = content == null ? void 0 : content.purposes) == null ? void 0 : _s.map((purpose) => /* @__PURE__ */ jsxs("div", { children: [
951
1379
  /* @__PURE__ */ jsxs("div", { style: styles.optionItem, children: [
952
1380
  /* @__PURE__ */ jsxs(
953
1381
  "div",
954
1382
  {
955
1383
  style: styles.optionLeft,
956
1384
  onClick: () => togglePurposeCollapse(purpose.uuid),
1385
+ role: "button",
1386
+ tabIndex: 0,
1387
+ "aria-expanded": !collapsedPurposes[purpose.uuid],
1388
+ "aria-controls": `purpose-${purpose.uuid}`,
1389
+ onKeyDown: (e) => {
1390
+ if (e.key === "Enter" || e.key === " ") {
1391
+ e.preventDefault();
1392
+ togglePurposeCollapse(purpose.uuid);
1393
+ }
1394
+ },
957
1395
  children: [
958
1396
  /* @__PURE__ */ jsx(
959
1397
  "div",
@@ -980,6 +1418,7 @@ var RedactoNoticeConsent = ({
980
1418
  transform: !collapsedPurposes[purpose.uuid] ? "rotate(90deg)" : "rotate(0deg)",
981
1419
  transition: "transform 0.3s ease"
982
1420
  },
1421
+ "aria-hidden": "true",
983
1422
  children: /* @__PURE__ */ jsx("path", { d: "M1 1L6 6L1 11" })
984
1423
  }
985
1424
  )
@@ -1023,61 +1462,79 @@ var RedactoNoticeConsent = ({
1023
1462
  /* @__PURE__ */ jsx(
1024
1463
  "input",
1025
1464
  {
1026
- style: styles.checkboxLarge,
1465
+ className: "redacto-checkbox-large",
1027
1466
  type: "checkbox",
1028
1467
  checked: selectedPurposes[purpose.uuid] || false,
1029
- onChange: () => handlePurposeCheckboxChange(purpose.uuid)
1468
+ onChange: () => handlePurposeCheckboxChange(purpose.uuid),
1469
+ "aria-label": `Select all data elements for ${getTranslatedText(
1470
+ `purposes.name`,
1471
+ purpose.name,
1472
+ purpose.uuid
1473
+ )}`
1030
1474
  }
1031
1475
  )
1032
1476
  ] }),
1033
- !collapsedPurposes[purpose.uuid] && purpose.data_elements && purpose.data_elements.length > 0 && /* @__PURE__ */ jsx("div", { style: styles.dataElementsContainer, children: purpose.data_elements.map((dataElement) => /* @__PURE__ */ jsxs(
1477
+ !collapsedPurposes[purpose.uuid] && purpose.data_elements && purpose.data_elements.length > 0 && /* @__PURE__ */ jsx(
1034
1478
  "div",
1035
1479
  {
1036
- style: styles.dataElementItem,
1037
- children: [
1038
- /* @__PURE__ */ jsxs(
1039
- "span",
1040
- {
1041
- style: {
1042
- ...styles.dataElementText,
1043
- ...responsiveStyles.dataElementText,
1044
- ...textStyle
1045
- },
1046
- children: [
1047
- getTranslatedText(
1048
- `data_elements.name`,
1049
- dataElement.name,
1050
- dataElement.uuid
1051
- ),
1052
- dataElement.required && /* @__PURE__ */ jsx(
1053
- "span",
1054
- {
1055
- style: {
1056
- color: "red",
1057
- marginLeft: "4px"
1058
- },
1059
- children: "*"
1060
- }
1061
- )
1062
- ]
1063
- }
1064
- ),
1065
- /* @__PURE__ */ jsx(
1066
- "input",
1067
- {
1068
- style: styles.checkboxSmall,
1069
- type: "checkbox",
1070
- checked: selectedDataElements[`${purpose.uuid}-${dataElement.uuid}`] || false,
1071
- onChange: () => handleDataElementCheckboxChange(
1072
- dataElement.uuid,
1073
- purpose.uuid
1480
+ id: `purpose-${purpose.uuid}`,
1481
+ style: styles.dataElementsContainer,
1482
+ children: purpose.data_elements.map((dataElement) => /* @__PURE__ */ jsxs(
1483
+ "div",
1484
+ {
1485
+ style: styles.dataElementItem,
1486
+ children: [
1487
+ /* @__PURE__ */ jsxs(
1488
+ "span",
1489
+ {
1490
+ style: {
1491
+ ...styles.dataElementText,
1492
+ ...responsiveStyles.dataElementText,
1493
+ ...textStyle
1494
+ },
1495
+ children: [
1496
+ getTranslatedText(
1497
+ `data_elements.name`,
1498
+ dataElement.name,
1499
+ dataElement.uuid
1500
+ ),
1501
+ dataElement.required && /* @__PURE__ */ jsx(
1502
+ "span",
1503
+ {
1504
+ style: {
1505
+ color: "red",
1506
+ marginLeft: "4px"
1507
+ },
1508
+ "aria-label": "required",
1509
+ children: "*"
1510
+ }
1511
+ )
1512
+ ]
1513
+ }
1514
+ ),
1515
+ /* @__PURE__ */ jsx(
1516
+ "input",
1517
+ {
1518
+ className: "redacto-checkbox-small",
1519
+ type: "checkbox",
1520
+ checked: selectedDataElements[`${purpose.uuid}-${dataElement.uuid}`] || false,
1521
+ onChange: () => handleDataElementCheckboxChange(
1522
+ dataElement.uuid,
1523
+ purpose.uuid
1524
+ ),
1525
+ "aria-label": `Select ${getTranslatedText(
1526
+ `data_elements.name`,
1527
+ dataElement.name,
1528
+ dataElement.uuid
1529
+ )}${dataElement.required ? " (required)" : ""}`
1530
+ }
1074
1531
  )
1075
- }
1076
- )
1077
- ]
1078
- },
1079
- dataElement.uuid
1080
- )) })
1532
+ ]
1533
+ },
1534
+ dataElement.uuid
1535
+ ))
1536
+ }
1537
+ )
1081
1538
  ] }, purpose.uuid)) })
1082
1539
  ]
1083
1540
  }
@@ -1094,6 +1551,7 @@ var RedactoNoticeConsent = ({
1094
1551
  /* @__PURE__ */ jsx(
1095
1552
  "button",
1096
1553
  {
1554
+ ref: lastFocusableRef,
1097
1555
  style: {
1098
1556
  ...styles.button,
1099
1557
  ...responsiveStyles.button,
@@ -1103,6 +1561,10 @@ var RedactoNoticeConsent = ({
1103
1561
  },
1104
1562
  onClick: handleAccept,
1105
1563
  disabled: acceptDisabled,
1564
+ "aria-label": getTranslatedText(
1565
+ "confirm_button_text",
1566
+ (content == null ? void 0 : content.confirm_button_text) || "Accept"
1567
+ ),
1106
1568
  children: isSubmitting ? "Processing..." : getTranslatedText(
1107
1569
  "confirm_button_text",
1108
1570
  (content == null ? void 0 : content.confirm_button_text) || "Accept"
@@ -1120,6 +1582,10 @@ var RedactoNoticeConsent = ({
1120
1582
  },
1121
1583
  onClick: handleDecline,
1122
1584
  disabled: isSubmitting,
1585
+ "aria-label": getTranslatedText(
1586
+ "decline_button_text",
1587
+ (content == null ? void 0 : content.decline_button_text) || "Decline"
1588
+ ),
1123
1589
  children: isSubmitting ? "Processing..." : getTranslatedText(
1124
1590
  "decline_button_text",
1125
1591
  (content == null ? void 0 : content.decline_button_text) || "Decline"