@redacto.io/consent-sdk-react 9.5.0-beta.0 → 10.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/.turbo/turbo-build.log +22 -25
  2. package/CHANGELOG.md +16 -2
  3. package/dist/index.d.mts +13 -4
  4. package/dist/index.d.ts +13 -4
  5. package/dist/index.js +116 -11
  6. package/dist/index.mjs +116 -11
  7. package/dist/privacy-center.d.mts +76 -19
  8. package/dist/privacy-center.d.ts +76 -19
  9. package/dist/privacy-center.js +2022 -1378
  10. package/dist/privacy-center.mjs +1946 -1297
  11. package/package.json +1 -1
  12. package/src/RedactoNoticeConsent/RedactoNoticeConsent.test.tsx +5 -0
  13. package/src/RedactoNoticeConsent/RedactoNoticeConsent.tsx +29 -3
  14. package/src/RedactoNoticeConsent/api/index.ts +130 -1
  15. package/src/RedactoNoticeConsent/api/types.ts +33 -0
  16. package/src/RedactoNoticeConsent/types.ts +1 -0
  17. package/src/RedactoNoticeConsentInline/RedactoNoticeConsentInline.tsx +3 -0
  18. package/src/RedactoNoticeConsentInline/api/index.ts +4 -1
  19. package/src/RedactoNoticeConsentInline/api/types.ts +1 -0
  20. package/src/RedactoNoticeConsentInline/types.ts +1 -0
  21. package/src/RedactoPrivacyCenter/PrivacyCenterLayout.tsx +8 -5
  22. package/src/RedactoPrivacyCenter/RedactoPrivacyCenter.tsx +3 -1
  23. package/src/RedactoPrivacyCenter/api/actions.ts +15 -2
  24. package/src/RedactoPrivacyCenter/api/client.ts +146 -20
  25. package/src/RedactoPrivacyCenter/components/AppShell/UserMenu.tsx +64 -35
  26. package/src/RedactoPrivacyCenter/components/ConsentManager.tsx +12 -1
  27. package/src/RedactoPrivacyCenter/components/Form.tsx +63 -7
  28. package/src/RedactoPrivacyCenter/components/SelectUser.tsx +83 -0
  29. package/src/RedactoPrivacyCenter/components/SelectUserGate.tsx +193 -0
  30. package/src/RedactoPrivacyCenter/components/constant.ts +11 -0
  31. package/src/RedactoPrivacyCenter/components/groupHelpers.ts +64 -1
  32. package/src/RedactoPrivacyCenter/context/BaseUrlContext.tsx +8 -2
  33. package/src/RedactoPrivacyCenter/context/ProfileSwitchContext.tsx +15 -0
  34. package/src/RedactoPrivacyCenter/context/types.ts +1 -0
  35. package/src/RedactoPrivacyCenter/lib/api.ts +8 -0
  36. package/src/RedactoPrivacyCenter/lib/constants.ts +9 -0
  37. package/src/RedactoPrivacyCenter/lib/types.ts +63 -1
  38. package/src/RedactoPrivacyCenter/locales/as/translation.json +7 -1
  39. package/src/RedactoPrivacyCenter/locales/bho/translation.json +7 -1
  40. package/src/RedactoPrivacyCenter/locales/bn/translation.json +7 -1
  41. package/src/RedactoPrivacyCenter/locales/brx/translation.json +7 -1
  42. package/src/RedactoPrivacyCenter/locales/doi/translation.json +7 -1
  43. package/src/RedactoPrivacyCenter/locales/en/translation.json +7 -1
  44. package/src/RedactoPrivacyCenter/locales/gom/translation.json +7 -1
  45. package/src/RedactoPrivacyCenter/locales/gu/translation.json +7 -1
  46. package/src/RedactoPrivacyCenter/locales/hi/translation.json +7 -1
  47. package/src/RedactoPrivacyCenter/locales/kn/translation.json +7 -1
  48. package/src/RedactoPrivacyCenter/locales/ks/translation.json +7 -1
  49. package/src/RedactoPrivacyCenter/locales/mai/translation.json +7 -1
  50. package/src/RedactoPrivacyCenter/locales/ml/translation.json +7 -1
  51. package/src/RedactoPrivacyCenter/locales/mni-Mtei/translation.json +7 -1
  52. package/src/RedactoPrivacyCenter/locales/mr/translation.json +7 -1
  53. package/src/RedactoPrivacyCenter/locales/ne/translation.json +7 -1
  54. package/src/RedactoPrivacyCenter/locales/or/translation.json +7 -1
  55. package/src/RedactoPrivacyCenter/locales/pa/translation.json +7 -1
  56. package/src/RedactoPrivacyCenter/locales/sa/translation.json +7 -1
  57. package/src/RedactoPrivacyCenter/locales/sat/translation.json +7 -1
  58. package/src/RedactoPrivacyCenter/locales/sd/translation.json +7 -1
  59. package/src/RedactoPrivacyCenter/locales/ta/translation.json +7 -1
  60. package/src/RedactoPrivacyCenter/locales/te/translation.json +7 -1
  61. package/src/RedactoPrivacyCenter/locales/ur/translation.json +7 -1
  62. package/src/RedactoPrivacyCenter/styles/injectStyles.ts +105 -0
  63. package/tests/Form.test.tsx +58 -7
  64. package/tests/consentClient.test.ts +171 -0
  65. package/tests/manageConsentServer.test.ts +38 -0
  66. package/tests/mocks.ts +1 -0
@@ -1,25 +1,22 @@
1
-
2
- > @redacto.io/consent-sdk-react@9.4.0-beta.0 build /Users/sadanmianredacto/Developer/redacto/consent-sdk/packages/consent-sdk-react
3
- > tsup
4
-
5
- CLI Building entry: {"index":"src/index.ts","privacy-center":"src/privacy-center.ts"}
6
- CLI Using tsconfig: tsconfig.json
7
- CLI tsup v8.5.1
8
- CLI Using tsup config: /Users/sadanmianredacto/Developer/redacto/consent-sdk/packages/consent-sdk-react/tsup.config.ts
9
- CLI Target: es2019
10
- CLI Cleaning output folder
11
- ESM Build start
12
- CJS Build start
13
- CJS dist/index.js 517.55 KB
14
- CJS dist/privacy-center.js 2.18 MB
15
- CJS ⚡️ Build success in 60ms
16
- ESM dist/chunk-6A665OPR.mjs 841.00 B
17
- ESM dist/index.mjs 503.10 KB
18
- ESM dist/privacy-center.mjs 2.15 MB
19
- ESM ⚡️ Build success in 66ms
20
- DTS Build start
21
- DTS ⚡️ Build success in 2580ms
22
- DTS dist/index.d.mts 8.03 KB
23
- DTS dist/privacy-center.d.mts 30.69 KB
24
- DTS dist/index.d.ts 8.03 KB
25
- DTS dist/privacy-center.d.ts 30.69 KB
1
+ $ tsup
2
+ CLI Building entry: {"index":"src/index.ts","privacy-center":"src/privacy-center.ts"}
3
+ CLI Using tsconfig: tsconfig.json
4
+ CLI tsup v8.5.1
5
+ CLI Using tsup config: /Users/sadanmianredacto/Developer/redacto/consent-sdk/packages/consent-sdk-react/tsup.config.ts
6
+ CLI Target: es2019
7
+ CLI Cleaning output folder
8
+ ESM Build start
9
+ CJS Build start
10
+ CJS dist/index.js 520.79 KB
11
+ CJS dist/privacy-center.js 2.24 MB
12
+ CJS ⚡️ Build success in 124ms
13
+ ESM dist/index.mjs 506.34 KB
14
+ ESM dist/chunk-6A665OPR.mjs 841.00 B
15
+ ESM dist/privacy-center.mjs 2.20 MB
16
+ ESM ⚡️ Build success in 124ms
17
+ DTS Build start
18
+ DTS ⚡️ Build success in 2664ms
19
+ DTS dist/index.d.mts 8.27 KB
20
+ DTS dist/privacy-center.d.mts 33.25 KB
21
+ DTS dist/index.d.ts 8.27 KB
22
+ DTS dist/privacy-center.d.ts 33.25 KB
package/CHANGELOG.md CHANGED
@@ -1,10 +1,24 @@
1
1
  # @redacto.io/consent-sdk-react
2
2
 
3
- ## 9.5.0-beta.0
3
+ ## 10.0.0-beta.1
4
+
5
+ ### Major Changes
6
+
7
+ - feat(privacy-center): shared-contact profile picker (OTP + embeddable SDK)
4
8
 
5
9
  ### Minor Changes
6
10
 
7
- - fix(privacy-center): resolve mobile/org_user_id as contact for mobile-only logins
11
+ - 61d18e8: fix(privacy-center): resolve mobile/org_user_id as contact for mobile-only logins
12
+
13
+ ### Patch Changes
14
+
15
+ - 8145b3d: Privacy Center: when `ledgerBaseUrl` is not provided, consent reads/writes (user-consents, group purposes, manage-consent, receipts list, receipt PDF) fall back to the legacy Python `/dsar/privacy-center` endpoints and payloads instead of 404ing against `${baseUrl}/public/...`, and the DSAR form's ledger picker overlay is skipped. Fixes the Privacy Center showing "No Data" for integrations without a deployed Go ledger.
16
+
17
+ ## 10.0.0-beta.0
18
+
19
+ ### Major Changes
20
+
21
+ - route consent writes & Privacy Center reads through the Go ledger (ledgerBaseUrl)
8
22
 
9
23
  ## 9.4.0
10
24
 
package/dist/index.d.mts CHANGED
@@ -1,4 +1,3 @@
1
- import * as react_jsx_runtime from 'react/jsx-runtime';
2
1
  import * as react from 'react';
3
2
  import react__default from 'react';
4
3
 
@@ -47,6 +46,7 @@ type Props$1 = Readonly<{
47
46
  accessToken: string;
48
47
  refreshToken: string;
49
48
  baseUrl?: string;
49
+ ledgerBaseUrl?: string;
50
50
  settings?: Partial<Settings$1>;
51
51
  language?: string;
52
52
  blockUI?: boolean;
@@ -61,6 +61,14 @@ type Props$1 = Readonly<{
61
61
  reviewModeButtonText?: string;
62
62
  }>;
63
63
 
64
+ /**
65
+ * Redacto Notice Consent Component
66
+ *
67
+ * A comprehensive consent management component that handles both initial consent
68
+ * collection and reconsent flows with visual distinction between already-consented
69
+ * and needs-consent purposes.
70
+ */
71
+
64
72
  /**
65
73
  * RedactoNoticeConsent
66
74
  *
@@ -68,7 +76,7 @@ type Props$1 = Readonly<{
68
76
  * to view and manage their consent preferences. Supports both initial consent
69
77
  * collection and reconsent flows.
70
78
  */
71
- declare const RedactoNoticeConsent: ({ noticeId, accessToken, refreshToken, baseUrl, language, blockUI, onAccept, onDecline, onError, settings, applicationId, validateAgainst, digilockerMode, digilockerCallbackUrl, includeFullyConsentedData, reviewModeButtonText, }: Props$1) => react_jsx_runtime.JSX.Element;
79
+ declare const RedactoNoticeConsent: ({ noticeId, accessToken, refreshToken, baseUrl, ledgerBaseUrl, language, blockUI, onAccept, onDecline, onError, settings, applicationId, validateAgainst, digilockerMode, digilockerCallbackUrl, includeFullyConsentedData, reviewModeButtonText, }: Props$1) => react__default.JSX.Element;
72
80
 
73
81
  type Settings = {
74
82
  button: {
@@ -102,6 +110,7 @@ type Props = Readonly<{
102
110
  accessToken?: string;
103
111
  refreshToken?: string;
104
112
  baseUrl?: string;
113
+ ledgerBaseUrl?: string;
105
114
  settings?: Partial<Settings>;
106
115
  language?: string;
107
116
  onAccept?: () => void;
@@ -112,7 +121,7 @@ type Props = Readonly<{
112
121
  }>;
113
122
 
114
123
  declare const RedactoConsentInline: react.MemoExoticComponent<{
115
- ({ org_uuid, workspace_uuid, notice_uuid, accessToken, baseUrl, language, onAccept, onError, onValidationChange, settings, applicationId, }: Props): react_jsx_runtime.JSX.Element | null;
124
+ ({ org_uuid, workspace_uuid, notice_uuid, accessToken, baseUrl, ledgerBaseUrl, language, onAccept, onError, onValidationChange, settings, applicationId, }: Props): react.JSX.Element | null;
116
125
  displayName: string;
117
126
  }>;
118
127
 
@@ -150,7 +159,7 @@ type RedactoNoticeAssistedProps = {
150
159
  * submit, `onComplete` fires immediately with no confirmation screen (mirroring
151
160
  * RedactoNoticeConsent's `onAccept`). Steps: `notice` → `verify` (with `otpSent`).
152
161
  */
153
- declare const RedactoNoticeAssisted: ({ organisationUuid, workspaceUuid, noticeUuid, baseUrl, onDecline, onComplete, }: RedactoNoticeAssistedProps) => react_jsx_runtime.JSX.Element;
162
+ declare const RedactoNoticeAssisted: ({ organisationUuid, workspaceUuid, noticeUuid, baseUrl, onDecline, onComplete, }: RedactoNoticeAssistedProps) => react.JSX.Element;
154
163
 
155
164
  /**
156
165
  * DigiLockerCallback Component
package/dist/index.d.ts CHANGED
@@ -1,4 +1,3 @@
1
- import * as react_jsx_runtime from 'react/jsx-runtime';
2
1
  import * as react from 'react';
3
2
  import react__default from 'react';
4
3
 
@@ -47,6 +46,7 @@ type Props$1 = Readonly<{
47
46
  accessToken: string;
48
47
  refreshToken: string;
49
48
  baseUrl?: string;
49
+ ledgerBaseUrl?: string;
50
50
  settings?: Partial<Settings$1>;
51
51
  language?: string;
52
52
  blockUI?: boolean;
@@ -61,6 +61,14 @@ type Props$1 = Readonly<{
61
61
  reviewModeButtonText?: string;
62
62
  }>;
63
63
 
64
+ /**
65
+ * Redacto Notice Consent Component
66
+ *
67
+ * A comprehensive consent management component that handles both initial consent
68
+ * collection and reconsent flows with visual distinction between already-consented
69
+ * and needs-consent purposes.
70
+ */
71
+
64
72
  /**
65
73
  * RedactoNoticeConsent
66
74
  *
@@ -68,7 +76,7 @@ type Props$1 = Readonly<{
68
76
  * to view and manage their consent preferences. Supports both initial consent
69
77
  * collection and reconsent flows.
70
78
  */
71
- declare const RedactoNoticeConsent: ({ noticeId, accessToken, refreshToken, baseUrl, language, blockUI, onAccept, onDecline, onError, settings, applicationId, validateAgainst, digilockerMode, digilockerCallbackUrl, includeFullyConsentedData, reviewModeButtonText, }: Props$1) => react_jsx_runtime.JSX.Element;
79
+ declare const RedactoNoticeConsent: ({ noticeId, accessToken, refreshToken, baseUrl, ledgerBaseUrl, language, blockUI, onAccept, onDecline, onError, settings, applicationId, validateAgainst, digilockerMode, digilockerCallbackUrl, includeFullyConsentedData, reviewModeButtonText, }: Props$1) => react__default.JSX.Element;
72
80
 
73
81
  type Settings = {
74
82
  button: {
@@ -102,6 +110,7 @@ type Props = Readonly<{
102
110
  accessToken?: string;
103
111
  refreshToken?: string;
104
112
  baseUrl?: string;
113
+ ledgerBaseUrl?: string;
105
114
  settings?: Partial<Settings>;
106
115
  language?: string;
107
116
  onAccept?: () => void;
@@ -112,7 +121,7 @@ type Props = Readonly<{
112
121
  }>;
113
122
 
114
123
  declare const RedactoConsentInline: react.MemoExoticComponent<{
115
- ({ org_uuid, workspace_uuid, notice_uuid, accessToken, baseUrl, language, onAccept, onError, onValidationChange, settings, applicationId, }: Props): react_jsx_runtime.JSX.Element | null;
124
+ ({ org_uuid, workspace_uuid, notice_uuid, accessToken, baseUrl, ledgerBaseUrl, language, onAccept, onError, onValidationChange, settings, applicationId, }: Props): react.JSX.Element | null;
116
125
  displayName: string;
117
126
  }>;
118
127
 
@@ -150,7 +159,7 @@ type RedactoNoticeAssistedProps = {
150
159
  * submit, `onComplete` fires immediately with no confirmation screen (mirroring
151
160
  * RedactoNoticeConsent's `onAccept`). Steps: `notice` → `verify` (with `otpSent`).
152
161
  */
153
- declare const RedactoNoticeAssisted: ({ organisationUuid, workspaceUuid, noticeUuid, baseUrl, onDecline, onComplete, }: RedactoNoticeAssistedProps) => react_jsx_runtime.JSX.Element;
162
+ declare const RedactoNoticeAssisted: ({ organisationUuid, workspaceUuid, noticeUuid, baseUrl, onDecline, onComplete, }: RedactoNoticeAssistedProps) => react.JSX.Element;
154
163
 
155
164
  /**
156
165
  * DigiLockerCallback Component
package/dist/index.js CHANGED
@@ -182,6 +182,7 @@ var fetchConsentContent = async ({
182
182
  var submitConsentEvent = async ({
183
183
  accessToken,
184
184
  baseUrl,
185
+ ledgerBaseUrl,
185
186
  noticeUuid,
186
187
  purposes,
187
188
  declined,
@@ -202,7 +203,7 @@ var submitConsentEvent = async ({
202
203
  if (!ORGANISATION_UUID || !WORKSPACE_UUID) {
203
204
  throw new Error("Invalid token: missing organization or workspace UUID");
204
205
  }
205
- const apiBaseUrl = baseUrl || BASE_URL;
206
+ const apiBaseUrl = ledgerBaseUrl || baseUrl || BASE_URL;
206
207
  const validatedPurposes = purposes.map((purpose) => {
207
208
  if (!purpose.uuid) {
208
209
  throw new Error(`Invalid purpose data: missing uuid`);
@@ -248,6 +249,88 @@ var submitConsentEvent = async ({
248
249
  }
249
250
  apiCache.clear();
250
251
  };
252
+ var fetchNoticeConsentStatus = async ({
253
+ accessToken,
254
+ ledgerBaseUrl,
255
+ noticeUuid,
256
+ signal
257
+ }) => {
258
+ if (!accessToken || !ledgerBaseUrl || !noticeUuid) {
259
+ return null;
260
+ }
261
+ const decodedToken = decodeTokenSafely(accessToken);
262
+ if (!decodedToken) {
263
+ return null;
264
+ }
265
+ const { organisation_uuid: ORGANISATION_UUID, workspace_uuid: WORKSPACE_UUID } = decodedToken;
266
+ if (!ORGANISATION_UUID || !WORKSPACE_UUID) {
267
+ return null;
268
+ }
269
+ try {
270
+ const response = await fetch(
271
+ `${ledgerBaseUrl}/public/organisations/${ORGANISATION_UUID}/workspaces/${WORKSPACE_UUID}/notices/${noticeUuid}/check-consent`,
272
+ {
273
+ method: "POST",
274
+ headers: {
275
+ Authorization: `Bearer ${accessToken}`,
276
+ "Content-Type": "application/json"
277
+ },
278
+ body: "{}",
279
+ signal
280
+ }
281
+ );
282
+ if (!response.ok) {
283
+ return null;
284
+ }
285
+ const data = await response.json();
286
+ const body = data && typeof data === "object" && "detail" in data && data.detail ? data.detail : data;
287
+ if (!body || !Array.isArray(body.purposes)) {
288
+ return null;
289
+ }
290
+ return body;
291
+ } catch {
292
+ return null;
293
+ }
294
+ };
295
+ var buildLedgerConsentOverlay = (status, configPurposes) => {
296
+ var _a, _b;
297
+ const byUuid = new Map(status.purposes.map((p) => [p.uuid, p]));
298
+ const hasHistory = status.purposes.some(
299
+ (p) => (p.status || "INACTIVE") !== "INACTIVE"
300
+ );
301
+ if (!hasHistory) {
302
+ return null;
303
+ }
304
+ const purpose_selections = {};
305
+ for (const cp of configPurposes) {
306
+ const lp = byUuid.get(cp.uuid);
307
+ const purposeStatus = (lp == null ? void 0 : lp.status) || "INACTIVE";
308
+ const selectedByUuid = new Map(
309
+ ((lp == null ? void 0 : lp.data_elements) || []).map((de) => [de.uuid, de.selected])
310
+ );
311
+ const data_elements = {};
312
+ for (const de of cp.data_elements) {
313
+ data_elements[de.uuid] = {
314
+ selected: (_a = selectedByUuid.get(de.uuid)) != null ? _a : false,
315
+ enabled: de.enabled,
316
+ required: de.required
317
+ };
318
+ }
319
+ purpose_selections[cp.uuid] = {
320
+ selected: (_b = lp == null ? void 0 : lp.selected) != null ? _b : false,
321
+ status: purposeStatus,
322
+ needs_reconsent: purposeStatus !== "ACTIVE",
323
+ data_elements
324
+ };
325
+ }
326
+ const reconsent_required = configPurposes.some(
327
+ (cp) => {
328
+ var _a2;
329
+ return (((_a2 = purpose_selections[cp.uuid]) == null ? void 0 : _a2.status) || "INACTIVE") !== "ACTIVE";
330
+ }
331
+ );
332
+ return { reconsent_required, purpose_selections };
333
+ };
251
334
  var fetchTTSAudioUrls = async ({
252
335
  accessToken,
253
336
  baseUrl,
@@ -2294,6 +2377,7 @@ var RedactoNoticeConsent = ({
2294
2377
  accessToken,
2295
2378
  refreshToken,
2296
2379
  baseUrl,
2380
+ ledgerBaseUrl,
2297
2381
  language = "en",
2298
2382
  blockUI = true,
2299
2383
  onAccept,
@@ -2648,7 +2732,7 @@ var RedactoNoticeConsent = ({
2648
2732
  return content.dpo_info[key] || defaultText;
2649
2733
  };
2650
2734
  const fetchNotice = async () => {
2651
- var _a2;
2735
+ var _a2, _b2, _c2;
2652
2736
  if (isRequestInProgressRef.current) {
2653
2737
  return;
2654
2738
  }
@@ -2689,8 +2773,24 @@ var RedactoNoticeConsent = ({
2689
2773
  {}
2690
2774
  );
2691
2775
  setCollapsedPurposes(initialCollapsedState);
2692
- const isReconsentRequired = consentContentData.detail.reconsent_required;
2693
- const purposeSelections = consentContentData.detail.purpose_selections;
2776
+ let isReconsentRequired = consentContentData.detail.reconsent_required;
2777
+ let purposeSelections = consentContentData.detail.purpose_selections;
2778
+ if (ledgerBaseUrl && !applicationId) {
2779
+ const ledgerStatus = await fetchNoticeConsentStatus({
2780
+ accessToken,
2781
+ ledgerBaseUrl,
2782
+ noticeUuid: noticeId,
2783
+ signal: (_b2 = abortControllerRef.current) == null ? void 0 : _b2.signal
2784
+ });
2785
+ if (ledgerStatus) {
2786
+ const overlay = buildLedgerConsentOverlay(
2787
+ ledgerStatus,
2788
+ activeConfig.purposes
2789
+ );
2790
+ isReconsentRequired = (_c2 = overlay == null ? void 0 : overlay.reconsent_required) != null ? _c2 : false;
2791
+ purposeSelections = overlay == null ? void 0 : overlay.purpose_selections;
2792
+ }
2793
+ }
2694
2794
  const newCategorizedPurposes = isReconsentRequired ? {
2695
2795
  alreadyConsented: activeConfig.purposes.filter(
2696
2796
  (purpose) => {
@@ -2721,9 +2821,9 @@ var RedactoNoticeConsent = ({
2721
2821
  const initialDataElementState = activeConfig.purposes.reduce(
2722
2822
  (acc, purpose) => {
2723
2823
  purpose.data_elements.forEach((element) => {
2724
- var _a3, _b2;
2824
+ var _a3, _b3;
2725
2825
  const combinedId = `${purpose.uuid}-${element.uuid}`;
2726
- if ((_b2 = (_a3 = purposeSelections == null ? void 0 : purposeSelections[purpose.uuid]) == null ? void 0 : _a3.data_elements) == null ? void 0 : _b2[element.uuid]) {
2826
+ if ((_b3 = (_a3 = purposeSelections == null ? void 0 : purposeSelections[purpose.uuid]) == null ? void 0 : _a3.data_elements) == null ? void 0 : _b3[element.uuid]) {
2727
2827
  acc[combinedId] = purposeSelections[purpose.uuid].data_elements[element.uuid].selected;
2728
2828
  } else {
2729
2829
  acc[combinedId] = false;
@@ -2739,9 +2839,9 @@ var RedactoNoticeConsent = ({
2739
2839
  const initialSelections = {};
2740
2840
  newCategorizedPurposes.alreadyConsented.forEach((purpose) => {
2741
2841
  purpose.data_elements.forEach((element) => {
2742
- var _a3, _b2;
2842
+ var _a3, _b3;
2743
2843
  const combinedId = `${purpose.uuid}-${element.uuid}`;
2744
- if ((_b2 = (_a3 = purposeSelections == null ? void 0 : purposeSelections[purpose.uuid]) == null ? void 0 : _a3.data_elements) == null ? void 0 : _b2[element.uuid]) {
2844
+ if ((_b3 = (_a3 = purposeSelections == null ? void 0 : purposeSelections[purpose.uuid]) == null ? void 0 : _a3.data_elements) == null ? void 0 : _b3[element.uuid]) {
2745
2845
  initialSelections[combinedId] = purposeSelections[purpose.uuid].data_elements[element.uuid].selected;
2746
2846
  } else {
2747
2847
  initialSelections[combinedId] = false;
@@ -2762,9 +2862,9 @@ var RedactoNoticeConsent = ({
2762
2862
  activeConfig.purposes.forEach(
2763
2863
  (purpose) => {
2764
2864
  purpose.data_elements.forEach((element) => {
2765
- var _a3, _b2;
2865
+ var _a3, _b3;
2766
2866
  const combinedId = `${purpose.uuid}-${element.uuid}`;
2767
- if ((_b2 = (_a3 = purposeSelections[purpose.uuid]) == null ? void 0 : _a3.data_elements) == null ? void 0 : _b2[element.uuid]) {
2867
+ if ((_b3 = (_a3 = purposeSelections[purpose.uuid]) == null ? void 0 : _a3.data_elements) == null ? void 0 : _b3[element.uuid]) {
2768
2868
  initialSelections[combinedId] = purposeSelections[purpose.uuid].data_elements[element.uuid].selected;
2769
2869
  } else {
2770
2870
  initialSelections[combinedId] = false;
@@ -2896,6 +2996,7 @@ var RedactoNoticeConsent = ({
2896
2996
  await submitConsentEvent({
2897
2997
  accessToken,
2898
2998
  baseUrl,
2999
+ ledgerBaseUrl,
2899
3000
  noticeUuid: content.notice_uuid,
2900
3001
  purposes: content.purposes.map((purpose) => {
2901
3002
  const isAlreadyConsented = (categorizedPurposes == null ? void 0 : categorizedPurposes.alreadyConsented.some(
@@ -4677,12 +4778,13 @@ var submitConsentEvent2 = async ({
4677
4778
  workspace_uuid,
4678
4779
  accessToken,
4679
4780
  baseUrl,
4781
+ ledgerBaseUrl,
4680
4782
  noticeUuid,
4681
4783
  purposes,
4682
4784
  declined,
4683
4785
  meta_data
4684
4786
  }) => {
4685
- const apiBaseUrl = baseUrl || BASE_URL2;
4787
+ const apiBaseUrl = ledgerBaseUrl || baseUrl || BASE_URL2;
4686
4788
  const payload = {
4687
4789
  notice_uuid: noticeUuid,
4688
4790
  purposes: purposes.map((purpose) => {
@@ -5133,6 +5235,7 @@ var RedactoConsentInlineComponent = ({
5133
5235
  notice_uuid,
5134
5236
  accessToken,
5135
5237
  baseUrl,
5238
+ ledgerBaseUrl,
5136
5239
  language = "en",
5137
5240
  onAccept,
5138
5241
  onError,
@@ -5367,6 +5470,7 @@ var RedactoConsentInlineComponent = ({
5367
5470
  workspace_uuid,
5368
5471
  accessToken: tokenToUse,
5369
5472
  baseUrl,
5473
+ ledgerBaseUrl,
5370
5474
  noticeUuid: content.notice_uuid,
5371
5475
  purposes: content.purposes.map((purpose) => {
5372
5476
  const hasSelectedRequiredElement = purpose.data_elements.some(
@@ -5405,6 +5509,7 @@ var RedactoConsentInlineComponent = ({
5405
5509
  org_uuid,
5406
5510
  workspace_uuid,
5407
5511
  baseUrl,
5512
+ ledgerBaseUrl,
5408
5513
  selectedDataElements,
5409
5514
  selectedPurposes,
5410
5515
  applicationId,
package/dist/index.mjs CHANGED
@@ -156,6 +156,7 @@ var fetchConsentContent = async ({
156
156
  var submitConsentEvent = async ({
157
157
  accessToken,
158
158
  baseUrl,
159
+ ledgerBaseUrl,
159
160
  noticeUuid,
160
161
  purposes,
161
162
  declined,
@@ -176,7 +177,7 @@ var submitConsentEvent = async ({
176
177
  if (!ORGANISATION_UUID || !WORKSPACE_UUID) {
177
178
  throw new Error("Invalid token: missing organization or workspace UUID");
178
179
  }
179
- const apiBaseUrl = baseUrl || BASE_URL;
180
+ const apiBaseUrl = ledgerBaseUrl || baseUrl || BASE_URL;
180
181
  const validatedPurposes = purposes.map((purpose) => {
181
182
  if (!purpose.uuid) {
182
183
  throw new Error(`Invalid purpose data: missing uuid`);
@@ -222,6 +223,88 @@ var submitConsentEvent = async ({
222
223
  }
223
224
  apiCache.clear();
224
225
  };
226
+ var fetchNoticeConsentStatus = async ({
227
+ accessToken,
228
+ ledgerBaseUrl,
229
+ noticeUuid,
230
+ signal
231
+ }) => {
232
+ if (!accessToken || !ledgerBaseUrl || !noticeUuid) {
233
+ return null;
234
+ }
235
+ const decodedToken = decodeTokenSafely(accessToken);
236
+ if (!decodedToken) {
237
+ return null;
238
+ }
239
+ const { organisation_uuid: ORGANISATION_UUID, workspace_uuid: WORKSPACE_UUID } = decodedToken;
240
+ if (!ORGANISATION_UUID || !WORKSPACE_UUID) {
241
+ return null;
242
+ }
243
+ try {
244
+ const response = await fetch(
245
+ `${ledgerBaseUrl}/public/organisations/${ORGANISATION_UUID}/workspaces/${WORKSPACE_UUID}/notices/${noticeUuid}/check-consent`,
246
+ {
247
+ method: "POST",
248
+ headers: {
249
+ Authorization: `Bearer ${accessToken}`,
250
+ "Content-Type": "application/json"
251
+ },
252
+ body: "{}",
253
+ signal
254
+ }
255
+ );
256
+ if (!response.ok) {
257
+ return null;
258
+ }
259
+ const data = await response.json();
260
+ const body = data && typeof data === "object" && "detail" in data && data.detail ? data.detail : data;
261
+ if (!body || !Array.isArray(body.purposes)) {
262
+ return null;
263
+ }
264
+ return body;
265
+ } catch {
266
+ return null;
267
+ }
268
+ };
269
+ var buildLedgerConsentOverlay = (status, configPurposes) => {
270
+ var _a, _b;
271
+ const byUuid = new Map(status.purposes.map((p) => [p.uuid, p]));
272
+ const hasHistory = status.purposes.some(
273
+ (p) => (p.status || "INACTIVE") !== "INACTIVE"
274
+ );
275
+ if (!hasHistory) {
276
+ return null;
277
+ }
278
+ const purpose_selections = {};
279
+ for (const cp of configPurposes) {
280
+ const lp = byUuid.get(cp.uuid);
281
+ const purposeStatus = (lp == null ? void 0 : lp.status) || "INACTIVE";
282
+ const selectedByUuid = new Map(
283
+ ((lp == null ? void 0 : lp.data_elements) || []).map((de) => [de.uuid, de.selected])
284
+ );
285
+ const data_elements = {};
286
+ for (const de of cp.data_elements) {
287
+ data_elements[de.uuid] = {
288
+ selected: (_a = selectedByUuid.get(de.uuid)) != null ? _a : false,
289
+ enabled: de.enabled,
290
+ required: de.required
291
+ };
292
+ }
293
+ purpose_selections[cp.uuid] = {
294
+ selected: (_b = lp == null ? void 0 : lp.selected) != null ? _b : false,
295
+ status: purposeStatus,
296
+ needs_reconsent: purposeStatus !== "ACTIVE",
297
+ data_elements
298
+ };
299
+ }
300
+ const reconsent_required = configPurposes.some(
301
+ (cp) => {
302
+ var _a2;
303
+ return (((_a2 = purpose_selections[cp.uuid]) == null ? void 0 : _a2.status) || "INACTIVE") !== "ACTIVE";
304
+ }
305
+ );
306
+ return { reconsent_required, purpose_selections };
307
+ };
225
308
  var fetchTTSAudioUrls = async ({
226
309
  accessToken,
227
310
  baseUrl,
@@ -2241,6 +2324,7 @@ var RedactoNoticeConsent = ({
2241
2324
  accessToken,
2242
2325
  refreshToken,
2243
2326
  baseUrl,
2327
+ ledgerBaseUrl,
2244
2328
  language = "en",
2245
2329
  blockUI = true,
2246
2330
  onAccept,
@@ -2595,7 +2679,7 @@ var RedactoNoticeConsent = ({
2595
2679
  return content.dpo_info[key] || defaultText;
2596
2680
  };
2597
2681
  const fetchNotice = async () => {
2598
- var _a2;
2682
+ var _a2, _b2, _c2;
2599
2683
  if (isRequestInProgressRef.current) {
2600
2684
  return;
2601
2685
  }
@@ -2636,8 +2720,24 @@ var RedactoNoticeConsent = ({
2636
2720
  {}
2637
2721
  );
2638
2722
  setCollapsedPurposes(initialCollapsedState);
2639
- const isReconsentRequired = consentContentData.detail.reconsent_required;
2640
- const purposeSelections = consentContentData.detail.purpose_selections;
2723
+ let isReconsentRequired = consentContentData.detail.reconsent_required;
2724
+ let purposeSelections = consentContentData.detail.purpose_selections;
2725
+ if (ledgerBaseUrl && !applicationId) {
2726
+ const ledgerStatus = await fetchNoticeConsentStatus({
2727
+ accessToken,
2728
+ ledgerBaseUrl,
2729
+ noticeUuid: noticeId,
2730
+ signal: (_b2 = abortControllerRef.current) == null ? void 0 : _b2.signal
2731
+ });
2732
+ if (ledgerStatus) {
2733
+ const overlay = buildLedgerConsentOverlay(
2734
+ ledgerStatus,
2735
+ activeConfig.purposes
2736
+ );
2737
+ isReconsentRequired = (_c2 = overlay == null ? void 0 : overlay.reconsent_required) != null ? _c2 : false;
2738
+ purposeSelections = overlay == null ? void 0 : overlay.purpose_selections;
2739
+ }
2740
+ }
2641
2741
  const newCategorizedPurposes = isReconsentRequired ? {
2642
2742
  alreadyConsented: activeConfig.purposes.filter(
2643
2743
  (purpose) => {
@@ -2668,9 +2768,9 @@ var RedactoNoticeConsent = ({
2668
2768
  const initialDataElementState = activeConfig.purposes.reduce(
2669
2769
  (acc, purpose) => {
2670
2770
  purpose.data_elements.forEach((element) => {
2671
- var _a3, _b2;
2771
+ var _a3, _b3;
2672
2772
  const combinedId = `${purpose.uuid}-${element.uuid}`;
2673
- if ((_b2 = (_a3 = purposeSelections == null ? void 0 : purposeSelections[purpose.uuid]) == null ? void 0 : _a3.data_elements) == null ? void 0 : _b2[element.uuid]) {
2773
+ if ((_b3 = (_a3 = purposeSelections == null ? void 0 : purposeSelections[purpose.uuid]) == null ? void 0 : _a3.data_elements) == null ? void 0 : _b3[element.uuid]) {
2674
2774
  acc[combinedId] = purposeSelections[purpose.uuid].data_elements[element.uuid].selected;
2675
2775
  } else {
2676
2776
  acc[combinedId] = false;
@@ -2686,9 +2786,9 @@ var RedactoNoticeConsent = ({
2686
2786
  const initialSelections = {};
2687
2787
  newCategorizedPurposes.alreadyConsented.forEach((purpose) => {
2688
2788
  purpose.data_elements.forEach((element) => {
2689
- var _a3, _b2;
2789
+ var _a3, _b3;
2690
2790
  const combinedId = `${purpose.uuid}-${element.uuid}`;
2691
- if ((_b2 = (_a3 = purposeSelections == null ? void 0 : purposeSelections[purpose.uuid]) == null ? void 0 : _a3.data_elements) == null ? void 0 : _b2[element.uuid]) {
2791
+ if ((_b3 = (_a3 = purposeSelections == null ? void 0 : purposeSelections[purpose.uuid]) == null ? void 0 : _a3.data_elements) == null ? void 0 : _b3[element.uuid]) {
2692
2792
  initialSelections[combinedId] = purposeSelections[purpose.uuid].data_elements[element.uuid].selected;
2693
2793
  } else {
2694
2794
  initialSelections[combinedId] = false;
@@ -2709,9 +2809,9 @@ var RedactoNoticeConsent = ({
2709
2809
  activeConfig.purposes.forEach(
2710
2810
  (purpose) => {
2711
2811
  purpose.data_elements.forEach((element) => {
2712
- var _a3, _b2;
2812
+ var _a3, _b3;
2713
2813
  const combinedId = `${purpose.uuid}-${element.uuid}`;
2714
- if ((_b2 = (_a3 = purposeSelections[purpose.uuid]) == null ? void 0 : _a3.data_elements) == null ? void 0 : _b2[element.uuid]) {
2814
+ if ((_b3 = (_a3 = purposeSelections[purpose.uuid]) == null ? void 0 : _a3.data_elements) == null ? void 0 : _b3[element.uuid]) {
2715
2815
  initialSelections[combinedId] = purposeSelections[purpose.uuid].data_elements[element.uuid].selected;
2716
2816
  } else {
2717
2817
  initialSelections[combinedId] = false;
@@ -2843,6 +2943,7 @@ var RedactoNoticeConsent = ({
2843
2943
  await submitConsentEvent({
2844
2944
  accessToken,
2845
2945
  baseUrl,
2946
+ ledgerBaseUrl,
2846
2947
  noticeUuid: content.notice_uuid,
2847
2948
  purposes: content.purposes.map((purpose) => {
2848
2949
  const isAlreadyConsented = (categorizedPurposes == null ? void 0 : categorizedPurposes.alreadyConsented.some(
@@ -4624,12 +4725,13 @@ var submitConsentEvent2 = async ({
4624
4725
  workspace_uuid,
4625
4726
  accessToken,
4626
4727
  baseUrl,
4728
+ ledgerBaseUrl,
4627
4729
  noticeUuid,
4628
4730
  purposes,
4629
4731
  declined,
4630
4732
  meta_data
4631
4733
  }) => {
4632
- const apiBaseUrl = baseUrl || BASE_URL2;
4734
+ const apiBaseUrl = ledgerBaseUrl || baseUrl || BASE_URL2;
4633
4735
  const payload = {
4634
4736
  notice_uuid: noticeUuid,
4635
4737
  purposes: purposes.map((purpose) => {
@@ -5080,6 +5182,7 @@ var RedactoConsentInlineComponent = ({
5080
5182
  notice_uuid,
5081
5183
  accessToken,
5082
5184
  baseUrl,
5185
+ ledgerBaseUrl,
5083
5186
  language = "en",
5084
5187
  onAccept,
5085
5188
  onError,
@@ -5314,6 +5417,7 @@ var RedactoConsentInlineComponent = ({
5314
5417
  workspace_uuid,
5315
5418
  accessToken: tokenToUse,
5316
5419
  baseUrl,
5420
+ ledgerBaseUrl,
5317
5421
  noticeUuid: content.notice_uuid,
5318
5422
  purposes: content.purposes.map((purpose) => {
5319
5423
  const hasSelectedRequiredElement = purpose.data_elements.some(
@@ -5352,6 +5456,7 @@ var RedactoConsentInlineComponent = ({
5352
5456
  org_uuid,
5353
5457
  workspace_uuid,
5354
5458
  baseUrl,
5459
+ ledgerBaseUrl,
5355
5460
  selectedDataElements,
5356
5461
  selectedPurposes,
5357
5462
  applicationId,