@redacto.io/consent-sdk-react 10.2.0 → 10.2.1-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1343,6 +1343,24 @@ var purposeCoversProduct = (purpose, productUuid) => {
1343
1343
  return scope.includes(productUuid);
1344
1344
  };
1345
1345
  var isMultiProduct = (products) => Boolean(products && products.length > 1);
1346
+ var serverMarksMandatoryProducts = (products) => Boolean(
1347
+ products && products.length > 0 && products.every((product) => product.mandatory !== void 0)
1348
+ );
1349
+ var gatedProductUuids = (products) => new Set(
1350
+ (products != null ? products : []).filter((product) => product.mandatory === true).map((product) => product.uuid)
1351
+ );
1352
+ var rowProductUuid = (row, products) => {
1353
+ var _a;
1354
+ return (_a = row.productUuid) != null ? _a : (products == null ? void 0 : products.length) === 1 ? products[0].uuid : void 0;
1355
+ };
1356
+ var rowsUnderGate = (rows, products) => {
1357
+ const gated = gatedProductUuids(products);
1358
+ if (gated.size === 0) return [];
1359
+ return rows.filter((row) => {
1360
+ const productUuid = rowProductUuid(row, products);
1361
+ return productUuid !== void 0 && gated.has(productUuid);
1362
+ });
1363
+ };
1346
1364
  var groupPurposesByProduct = (products, purposes, order) => {
1347
1365
  if (!products || products.length === 0) return [];
1348
1366
  return products.map((product) => {
@@ -1442,6 +1460,7 @@ var buildPreselection = (purposes, mode) => {
1442
1460
  return { selectedPurposes, selectedDataElements };
1443
1461
  };
1444
1462
  var hasRequiredDataElement = (purpose) => purpose.data_elements.some((element) => element.required);
1463
+ var isBlockingRequiredElement = (element) => element.required && element.enabled;
1445
1464
 
1446
1465
  // src/RedactoNoticeConsent/layout.ts
1447
1466
  var resolveLogoPosition = (raw) => raw === "center" || raw === "right" ? raw : DEFAULT_LOGO_POSITION;
@@ -2075,6 +2094,16 @@ var CHEVRON_WRAPPER_STYLE = {
2075
2094
  justifyContent: "center",
2076
2095
  marginLeft: "5px"
2077
2096
  };
2097
+ var reviewIndicatorStyle = (size) => ({
2098
+ display: "flex",
2099
+ alignItems: "center",
2100
+ justifyContent: "center",
2101
+ width: `${size}px`,
2102
+ height: `${size}px`,
2103
+ borderRadius: "50%",
2104
+ flexShrink: 0,
2105
+ boxSizing: "border-box"
2106
+ });
2078
2107
  var CollapseChevron = ({ open, color }) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: CHEVRON_WRAPPER_STYLE, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2079
2108
  "svg",
2080
2109
  {
@@ -2097,6 +2126,7 @@ var CollapseChevron = ({ open, color }) => /* @__PURE__ */ (0, import_jsx_runtim
2097
2126
  ) });
2098
2127
  var ProductSectionHeader = ({
2099
2128
  product,
2129
+ isRequired,
2100
2130
  purposeCount,
2101
2131
  allSelected,
2102
2132
  someSelected,
@@ -2137,7 +2167,7 @@ var ProductSectionHeader = ({
2137
2167
  children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(CollapseChevron, { open: !collapsed, color: headingColor })
2138
2168
  }
2139
2169
  ),
2140
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: styles4.optionTextContainer, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2170
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: styles4.optionTextContainer, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
2141
2171
  "h2",
2142
2172
  {
2143
2173
  id: `product-name-${product.uuid}`,
@@ -2146,7 +2176,10 @@ var ProductSectionHeader = ({
2146
2176
  ...responsiveStyles.optionTitle,
2147
2177
  color: headingColor
2148
2178
  },
2149
- children: name
2179
+ children: [
2180
+ name,
2181
+ isRequired && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(RequiredMarker, {})
2182
+ ]
2150
2183
  }
2151
2184
  ) })
2152
2185
  ] }),
@@ -2166,6 +2199,7 @@ var ProductSectionHeader = ({
2166
2199
  var PurposeItem = ({
2167
2200
  purpose,
2168
2201
  productUuid,
2202
+ productIsRequired,
2169
2203
  selectedPurposes,
2170
2204
  collapsedPurposes,
2171
2205
  selectedDataElements,
@@ -2235,7 +2269,7 @@ var PurposeItem = ({
2235
2269
  },
2236
2270
  children: [
2237
2271
  getTranslatedText(`purposes.name`, purpose.name, purpose.uuid),
2238
- hasRequiredDataElement(purpose) && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(RequiredMarker, {})
2272
+ productIsRequired !== false && hasRequiredDataElement(purpose) && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(RequiredMarker, {})
2239
2273
  ]
2240
2274
  },
2241
2275
  `purpose-name-${purpose.uuid}-${selectedLanguage}`
@@ -2279,12 +2313,7 @@ var PurposeItem = ({
2279
2313
  "div",
2280
2314
  {
2281
2315
  style: {
2282
- display: "flex",
2283
- alignItems: "center",
2284
- justifyContent: "center",
2285
- width: "20px",
2286
- height: "20px",
2287
- borderRadius: "50%",
2316
+ ...reviewIndicatorStyle(20),
2288
2317
  backgroundColor: "#10B981",
2289
2318
  marginLeft: "12px"
2290
2319
  },
@@ -2373,12 +2402,7 @@ var PurposeItem = ({
2373
2402
  "div",
2374
2403
  {
2375
2404
  style: {
2376
- display: "flex",
2377
- alignItems: "center",
2378
- justifyContent: "center",
2379
- width: "16px",
2380
- height: "16px",
2381
- borderRadius: "50%",
2405
+ ...reviewIndicatorStyle(16),
2382
2406
  backgroundColor: "#10B981"
2383
2407
  },
2384
2408
  "aria-label": `Consented to ${getTranslatedText(
@@ -2414,12 +2438,7 @@ var PurposeItem = ({
2414
2438
  "div",
2415
2439
  {
2416
2440
  style: {
2417
- display: "flex",
2418
- alignItems: "center",
2419
- justifyContent: "center",
2420
- width: "16px",
2421
- height: "16px",
2422
- borderRadius: "50%",
2441
+ ...reviewIndicatorStyle(16),
2423
2442
  border: "2px solid #d0d5dd",
2424
2443
  backgroundColor: "transparent"
2425
2444
  },
@@ -3349,7 +3368,8 @@ var RedactoNoticeConsent = ({
3349
3368
  digilockerCallbackUrl = "/digilocker-callback",
3350
3369
  // Default callback path
3351
3370
  includeFullyConsentedData = false,
3352
- reviewModeButtonText = "Continue"
3371
+ reviewModeButtonText = "Continue",
3372
+ defaultOpenProducts
3353
3373
  }) => {
3354
3374
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y;
3355
3375
  const sandboxParams = (0, import_react3.useMemo)(
@@ -3421,6 +3441,8 @@ var RedactoNoticeConsent = ({
3421
3441
  const [collapsedProducts, setCollapsedProducts] = (0, import_react3.useState)({});
3422
3442
  const [collapsedPurposes, setCollapsedPurposes] = (0, import_react3.useState)({});
3423
3443
  const [hasAlreadyConsented, setHasAlreadyConsented] = (0, import_react3.useState)(false);
3444
+ const [consentedProducts, setConsentedProducts] = (0, import_react3.useState)({});
3445
+ const [consentedPurposes, setConsentedPurposes] = (0, import_react3.useState)({});
3424
3446
  const [isFullyConsentedReviewMode, setIsFullyConsentedReviewMode] = (0, import_react3.useState)(false);
3425
3447
  const [isLanguageDropdownOpen, setIsLanguageDropdownOpen] = (0, import_react3.useState)(false);
3426
3448
  const [selectedLanguage, setSelectedLanguage] = (0, import_react3.useState)(language);
@@ -3604,42 +3626,67 @@ var RedactoNoticeConsent = ({
3604
3626
  },
3605
3627
  [content]
3606
3628
  );
3607
- const areAllRequiredElementsChecked = (0, import_react3.useMemo)(() => {
3608
- var _a2;
3609
- if (!content) return false;
3610
- if (purposeRows.length === 0) return true;
3611
- const isSatisfied = ({
3612
- purpose,
3613
- productUuid
3614
- }) => {
3615
- const key = productPurposeKey(productUuid, purpose.uuid);
3616
- const requiredElements = purpose.data_elements.filter(
3617
- (element) => element.required && element.enabled
3618
- );
3619
- return requiredElements.every(
3620
- (element) => selectedDataElements[`${key}-${element.uuid}`]
3621
- );
3622
- };
3623
- const rowsByProduct = /* @__PURE__ */ new Map();
3624
- for (const row of purposeRows) {
3625
- const groupKey = (_a2 = row.productUuid) != null ? _a2 : "";
3626
- const group = rowsByProduct.get(groupKey);
3627
- if (group) {
3628
- group.push(row);
3629
- } else {
3630
- rowsByProduct.set(groupKey, [row]);
3629
+ const productMandatoryIsAuthoritative = (0, import_react3.useMemo)(
3630
+ () => serverMarksMandatoryProducts(content == null ? void 0 : content.products),
3631
+ [content]
3632
+ );
3633
+ const gatedProducts = (0, import_react3.useMemo)(
3634
+ () => gatedProductUuids(content == null ? void 0 : content.products),
3635
+ [content]
3636
+ );
3637
+ const productIsRequiredFor = (0, import_react3.useCallback)(
3638
+ (productUuid) => {
3639
+ var _a2;
3640
+ if (!productMandatoryIsAuthoritative) return void 0;
3641
+ const resolved = productUuid != null ? productUuid : ((_a2 = content == null ? void 0 : content.products) == null ? void 0 : _a2.length) === 1 ? content.products[0].uuid : void 0;
3642
+ return resolved !== void 0 && gatedProducts.has(resolved);
3643
+ },
3644
+ [productMandatoryIsAuthoritative, gatedProducts, content]
3645
+ );
3646
+ const confirmSatisfiedWith = (0, import_react3.useCallback)(
3647
+ (selection) => {
3648
+ var _a2;
3649
+ if (!content) return false;
3650
+ if (purposeRows.length === 0) return true;
3651
+ const isSatisfied = ({
3652
+ purpose,
3653
+ productUuid
3654
+ }) => {
3655
+ const key = productPurposeKey(productUuid, purpose.uuid);
3656
+ const requiredElements = purpose.data_elements.filter(
3657
+ isBlockingRequiredElement
3658
+ );
3659
+ return requiredElements.every(
3660
+ (element) => selection[`${key}-${element.uuid}`]
3661
+ );
3662
+ };
3663
+ if (serverMarksMandatoryProducts(content.products)) {
3664
+ return rowsUnderGate(purposeRows, content.products).every(isSatisfied);
3631
3665
  }
3632
- }
3633
- const groups = [...rowsByProduct.values()];
3634
- const everyProductHasMandatory = groups.every(
3635
- (rows) => rows.some(
3636
- ({ purpose }) => purpose.data_elements.some(
3637
- (element) => element.required && element.enabled
3666
+ const rowsByProduct = /* @__PURE__ */ new Map();
3667
+ for (const row of purposeRows) {
3668
+ const groupKey = (_a2 = row.productUuid) != null ? _a2 : "";
3669
+ const group = rowsByProduct.get(groupKey);
3670
+ if (group) {
3671
+ group.push(row);
3672
+ } else {
3673
+ rowsByProduct.set(groupKey, [row]);
3674
+ }
3675
+ }
3676
+ const groups = [...rowsByProduct.values()];
3677
+ const everyProductHasMandatory = groups.every(
3678
+ (rows) => rows.some(
3679
+ ({ purpose }) => purpose.data_elements.some(isBlockingRequiredElement)
3638
3680
  )
3639
- )
3640
- );
3641
- return everyProductHasMandatory ? groups.some((rows) => rows.every(isSatisfied)) : purposeRows.every(isSatisfied);
3642
- }, [content, purposeRows, selectedDataElements]);
3681
+ );
3682
+ return everyProductHasMandatory ? groups.some((rows) => rows.every(isSatisfied)) : purposeRows.every(isSatisfied);
3683
+ },
3684
+ [content, purposeRows]
3685
+ );
3686
+ const areAllRequiredElementsChecked = (0, import_react3.useMemo)(
3687
+ () => confirmSatisfiedWith(selectedDataElements),
3688
+ [confirmSatisfiedWith, selectedDataElements]
3689
+ );
3643
3690
  const acceptDisabled = isSubmitting || !areAllRequiredElementsChecked;
3644
3691
  (0, import_react3.useEffect)(() => {
3645
3692
  var _a2, _b2;
@@ -3652,6 +3699,7 @@ var RedactoNoticeConsent = ({
3652
3699
  setInitialDataElementSelections({});
3653
3700
  setCollapsedPurposes({});
3654
3701
  setCollapsedProducts({});
3702
+ setConsentedProducts({});
3655
3703
  setHasAlreadyConsented(false);
3656
3704
  setErrorMessage(null);
3657
3705
  setFetchError(null);
@@ -3835,15 +3883,18 @@ var RedactoNoticeConsent = ({
3835
3883
  {}
3836
3884
  );
3837
3885
  setCollapsedPurposes(initialCollapsedState);
3886
+ const openByDefault = new Set(defaultOpenProducts != null ? defaultOpenProducts : []);
3887
+ const groups = groupPurposesByProduct(
3888
+ activeConfig.products,
3889
+ activeConfig.purposes,
3890
+ activeConfig.product_purpose_order
3891
+ );
3892
+ const soleSection = groups.length === 1;
3838
3893
  setCollapsedProducts(
3839
- groupPurposesByProduct(
3840
- activeConfig.products,
3841
- activeConfig.purposes,
3842
- activeConfig.product_purpose_order
3843
- ).reduce(
3844
- (acc, group, index) => ({
3894
+ groups.reduce(
3895
+ (acc, group) => ({
3845
3896
  ...acc,
3846
- [group.product.uuid]: index > 0
3897
+ [group.product.uuid]: !soleSection && !openByDefault.has(group.product.uuid)
3847
3898
  }),
3848
3899
  {}
3849
3900
  )
@@ -3870,9 +3921,10 @@ var RedactoNoticeConsent = ({
3870
3921
  activeConfig.purposes,
3871
3922
  activeConfig.product_purpose_order
3872
3923
  );
3924
+ const productPurposeSelections = consentContentData.detail.product_purpose_selections;
3873
3925
  const recordedFor = (purposeUuid, productUuid) => {
3874
- var _a3, _b2;
3875
- const perProduct = productUuid ? (_b2 = (_a3 = activeConfig.product_purpose_selections) == null ? void 0 : _a3[productUuid]) == null ? void 0 : _b2[purposeUuid] : void 0;
3926
+ var _a3;
3927
+ const perProduct = productUuid ? (_a3 = productPurposeSelections == null ? void 0 : productPurposeSelections[productUuid]) == null ? void 0 : _a3[purposeUuid] : void 0;
3876
3928
  return perProduct != null ? perProduct : purposeSelections == null ? void 0 : purposeSelections[purposeUuid];
3877
3929
  };
3878
3930
  const initialPurposeState = seedRows.reduce(
@@ -3912,55 +3964,63 @@ var RedactoNoticeConsent = ({
3912
3964
  {}
3913
3965
  );
3914
3966
  setSelectedDataElements(initialDataElementState);
3967
+ const rowIsRecorded = ({
3968
+ purpose,
3969
+ productUuid
3970
+ }) => {
3971
+ var _a3;
3972
+ return ((_a3 = recordedFor(purpose.uuid, productUuid)) == null ? void 0 : _a3.selected) === true;
3973
+ };
3974
+ const recordedElementSelections = () => {
3975
+ const selections = {};
3976
+ seedRows.filter(rowIsRecorded).forEach(({ purpose, productUuid }) => {
3977
+ const rowKey = productPurposeKey(productUuid, purpose.uuid);
3978
+ purpose.data_elements.forEach((element) => {
3979
+ var _a3, _b2, _c2, _d2;
3980
+ selections[`${rowKey}-${element.uuid}`] = (_d2 = (_c2 = (_b2 = (_a3 = recordedFor(purpose.uuid, productUuid)) == null ? void 0 : _a3.data_elements) == null ? void 0 : _b2[element.uuid]) == null ? void 0 : _c2.selected) != null ? _d2 : false;
3981
+ });
3982
+ });
3983
+ return selections;
3984
+ };
3985
+ if (purposeSelections || productPurposeSelections) {
3986
+ const settled = {};
3987
+ const settledRows = {};
3988
+ seedRows.forEach((row) => {
3989
+ var _a3;
3990
+ const recorded = rowIsRecorded(row);
3991
+ if (!row.productUuid) {
3992
+ return;
3993
+ }
3994
+ settledRows[productPurposeKey(row.productUuid, row.purpose.uuid)] = recorded;
3995
+ settled[row.productUuid] = ((_a3 = settled[row.productUuid]) != null ? _a3 : true) && recorded;
3996
+ });
3997
+ setConsentedProducts(settled);
3998
+ setConsentedPurposes(settledRows);
3999
+ }
3915
4000
  if (isReconsentRequired && newCategorizedPurposes) {
3916
4001
  setIsFullyConsentedReviewMode(false);
3917
4002
  const initialSelections = {};
3918
4003
  const alreadyConsentedUuids = new Set(
3919
4004
  newCategorizedPurposes.alreadyConsented.map((p) => p.uuid)
3920
4005
  );
3921
- seedRows.filter(({ purpose }) => alreadyConsentedUuids.has(purpose.uuid)).forEach(({ purpose, productUuid }) => {
4006
+ seedRows.filter(
4007
+ (row) => alreadyConsentedUuids.has(row.purpose.uuid) || rowIsRecorded(row)
4008
+ ).forEach(({ purpose, productUuid }) => {
3922
4009
  const rowKey = productPurposeKey(productUuid, purpose.uuid);
3923
4010
  purpose.data_elements.forEach((element) => {
3924
- var _a3, _b2;
4011
+ var _a3, _b2, _c2, _d2;
3925
4012
  const combinedId = `${rowKey}-${element.uuid}`;
3926
- if ((_b2 = (_a3 = purposeSelections == null ? void 0 : purposeSelections[purpose.uuid]) == null ? void 0 : _a3.data_elements) == null ? void 0 : _b2[element.uuid]) {
3927
- initialSelections[combinedId] = purposeSelections[purpose.uuid].data_elements[element.uuid].selected;
3928
- } else {
3929
- initialSelections[combinedId] = false;
3930
- }
4013
+ initialSelections[combinedId] = (_d2 = (_c2 = (_b2 = (_a3 = recordedFor(purpose.uuid, productUuid)) == null ? void 0 : _a3.data_elements) == null ? void 0 : _b2[element.uuid]) == null ? void 0 : _c2.selected) != null ? _d2 : false;
3931
4014
  });
3932
4015
  });
3933
4016
  setInitialDataElementSelections(initialSelections);
3934
- } else if (includeFullyConsentedData && purposeSelections) {
3935
- const allPurposesSelected = seedRows.length > 0 && seedRows.every(
3936
- ({ purpose, productUuid }) => {
3937
- var _a3;
3938
- return ((_a3 = recordedFor(purpose.uuid, productUuid)) == null ? void 0 : _a3.selected) === true;
3939
- }
3940
- );
4017
+ } else if (includeFullyConsentedData && (purposeSelections || productPurposeSelections)) {
4018
+ const allPurposesSelected = seedRows.length > 0 && seedRows.every(rowIsRecorded);
3941
4019
  setIsFullyConsentedReviewMode(allPurposesSelected);
3942
- if (allPurposesSelected) {
3943
- const initialSelections = {};
3944
- seedRows.forEach(({ purpose, productUuid }) => {
3945
- const rowKey = productPurposeKey(productUuid, purpose.uuid);
3946
- purpose.data_elements.forEach((element) => {
3947
- var _a3, _b2;
3948
- const combinedId = `${rowKey}-${element.uuid}`;
3949
- if ((_b2 = (_a3 = purposeSelections[purpose.uuid]) == null ? void 0 : _a3.data_elements) == null ? void 0 : _b2[element.uuid]) {
3950
- initialSelections[combinedId] = purposeSelections[purpose.uuid].data_elements[element.uuid].selected;
3951
- } else {
3952
- initialSelections[combinedId] = false;
3953
- }
3954
- });
3955
- });
3956
- setInitialDataElementSelections(initialSelections);
3957
- } else {
3958
- setIsFullyConsentedReviewMode(false);
3959
- setInitialDataElementSelections({});
3960
- }
4020
+ setInitialDataElementSelections(recordedElementSelections());
3961
4021
  } else {
3962
4022
  setIsFullyConsentedReviewMode(false);
3963
- setInitialDataElementSelections({});
4023
+ setInitialDataElementSelections(recordedElementSelections());
3964
4024
  }
3965
4025
  if (consentContentData.detail.is_minor) {
3966
4026
  setIsMinorFlow(true);
@@ -4042,6 +4102,26 @@ var RedactoNoticeConsent = ({
4042
4102
  [productUuid]: !prev[productUuid]
4043
4103
  }));
4044
4104
  };
4105
+ const toggleSection = (sectionPurposes, keyProductUuid) => {
4106
+ const nextState = !sectionPurposes.every(
4107
+ (purpose) => selectedPurposes[productPurposeKey(keyProductUuid, purpose.uuid)]
4108
+ );
4109
+ setSelectedPurposes((prev) => {
4110
+ const updated = { ...prev };
4111
+ sectionPurposes.forEach((purpose) => {
4112
+ updated[productPurposeKey(keyProductUuid, purpose.uuid)] = nextState;
4113
+ });
4114
+ return updated;
4115
+ });
4116
+ const elementOverrides = {};
4117
+ sectionPurposes.forEach((purpose) => {
4118
+ const key = productPurposeKey(keyProductUuid, purpose.uuid);
4119
+ purpose.data_elements.forEach((element) => {
4120
+ elementOverrides[`${key}-${element.uuid}`] = nextState;
4121
+ });
4122
+ });
4123
+ setSelectedDataElements((prev) => ({ ...prev, ...elementOverrides }));
4124
+ };
4045
4125
  const handleProductCheckboxChange = (productUuid) => {
4046
4126
  if (!content) {
4047
4127
  return;
@@ -4052,29 +4132,46 @@ var RedactoNoticeConsent = ({
4052
4132
  if (!group) {
4053
4133
  return;
4054
4134
  }
4055
- const nextState = !group.purposes.every(
4056
- (purpose) => selectedPurposes[productPurposeKey(productUuid, purpose.uuid)]
4135
+ const editable = group.purposes.filter(
4136
+ (purpose) => !consentedPurposes[productPurposeKey(productUuid, purpose.uuid)]
4057
4137
  );
4058
- setSelectedPurposes((prev) => {
4059
- const updated = { ...prev };
4060
- group.purposes.forEach((purpose) => {
4061
- updated[productPurposeKey(productUuid, purpose.uuid)] = nextState;
4062
- });
4063
- return updated;
4064
- });
4065
- setSelectedDataElements((prev) => {
4066
- const updated = { ...prev };
4067
- group.purposes.forEach((purpose) => {
4068
- const key = productPurposeKey(productUuid, purpose.uuid);
4069
- purpose.data_elements.forEach((element) => {
4070
- updated[`${key}-${element.uuid}`] = nextState;
4071
- });
4072
- });
4073
- return updated;
4074
- });
4075
- if (!nextState) {
4076
- setCollapsedProducts((prev) => ({ ...prev, [productUuid]: false }));
4138
+ if (editable.length === 0) {
4139
+ return;
4077
4140
  }
4141
+ toggleSection(editable, productUuid);
4142
+ };
4143
+ const soleProductSection = (rows) => {
4144
+ var _a2, _b2;
4145
+ const products = content == null ? void 0 : content.products;
4146
+ if (!products || products.length !== 1) {
4147
+ return rows;
4148
+ }
4149
+ const product = products[0];
4150
+ const purposes = (_a2 = content == null ? void 0 : content.purposes) != null ? _a2 : [];
4151
+ const selectedCount = purposes.filter(
4152
+ (purpose) => selectedPurposes[productPurposeKey(void 0, purpose.uuid)]
4153
+ ).length;
4154
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { children: [
4155
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
4156
+ ProductSectionHeader,
4157
+ {
4158
+ product,
4159
+ isRequired: productIsRequiredFor(product.uuid),
4160
+ purposeCount: purposes.length,
4161
+ allSelected: purposes.length > 0 && selectedCount === purposes.length,
4162
+ someSelected: selectedCount > 0,
4163
+ collapsed: collapsedProducts[product.uuid] || false,
4164
+ locked: (_b2 = consentedProducts[product.uuid]) != null ? _b2 : isFullyConsentedReviewMode,
4165
+ settings,
4166
+ styles,
4167
+ responsiveStyles,
4168
+ onToggleCollapse: () => toggleProductCollapse(product.uuid),
4169
+ onToggleSelect: () => toggleSection(purposes, void 0),
4170
+ getTranslatedText
4171
+ }
4172
+ ),
4173
+ !collapsedProducts[product.uuid] && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: styles.sectionBody, children: rows })
4174
+ ] });
4078
4175
  };
4079
4176
  const handleDataElementCheckboxChange = (elementUuid, purposeUuid, productUuid) => {
4080
4177
  if (!content) return;
@@ -5660,49 +5757,60 @@ var RedactoNoticeConsent = ({
5660
5757
  },
5661
5758
  `purpose-section-heading-${selectedLanguage}`
5662
5759
  ),
5663
- categorizedPurposes && !isMultiProduct(content == null ? void 0 : content.products) ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: styles.optionsContainer, children: [
5664
- categorizedPurposes.alreadyConsented.map((purpose) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
5665
- PurposeItem,
5666
- {
5667
- purpose,
5668
- selectedPurposes,
5669
- collapsedPurposes,
5670
- selectedDataElements,
5671
- settings,
5672
- styles,
5673
- responsiveStyles,
5674
- onPurposeToggle: handlePurposeCheckboxChange,
5675
- onPurposeCollapse: togglePurposeCollapse,
5676
- onDataElementToggle: handleDataElementCheckboxChange,
5677
- getTranslatedText,
5678
- isAlreadyConsented: true,
5679
- selectedLanguage,
5680
- initialDataElementSelections
5681
- },
5682
- `${purpose.uuid}-${selectedLanguage}`
5683
- )),
5684
- categorizedPurposes.needsConsent.map((purpose) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
5685
- PurposeItem,
5686
- {
5687
- purpose,
5688
- selectedPurposes,
5689
- collapsedPurposes,
5690
- selectedDataElements,
5691
- settings,
5692
- styles,
5693
- responsiveStyles,
5694
- onPurposeToggle: handlePurposeCheckboxChange,
5695
- onPurposeCollapse: togglePurposeCollapse,
5696
- onDataElementToggle: handleDataElementCheckboxChange,
5697
- getTranslatedText,
5698
- isAlreadyConsented: false,
5699
- selectedLanguage
5700
- },
5701
- `${purpose.uuid}-${selectedLanguage}`
5702
- ))
5703
- ] }) : (
5760
+ categorizedPurposes && !isMultiProduct(content == null ? void 0 : content.products) ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: styles.optionsContainer, children: soleProductSection(
5761
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
5762
+ categorizedPurposes.alreadyConsented.map(
5763
+ (purpose) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
5764
+ PurposeItem,
5765
+ {
5766
+ purpose,
5767
+ productIsRequired: productIsRequiredFor(
5768
+ void 0
5769
+ ),
5770
+ selectedPurposes,
5771
+ collapsedPurposes,
5772
+ selectedDataElements,
5773
+ settings,
5774
+ styles,
5775
+ responsiveStyles,
5776
+ onPurposeToggle: handlePurposeCheckboxChange,
5777
+ onPurposeCollapse: togglePurposeCollapse,
5778
+ onDataElementToggle: handleDataElementCheckboxChange,
5779
+ getTranslatedText,
5780
+ isAlreadyConsented: true,
5781
+ selectedLanguage,
5782
+ initialDataElementSelections
5783
+ },
5784
+ `${purpose.uuid}-${selectedLanguage}`
5785
+ )
5786
+ ),
5787
+ categorizedPurposes.needsConsent.map((purpose) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
5788
+ PurposeItem,
5789
+ {
5790
+ purpose,
5791
+ productIsRequired: productIsRequiredFor(
5792
+ void 0
5793
+ ),
5794
+ selectedPurposes,
5795
+ collapsedPurposes,
5796
+ selectedDataElements,
5797
+ settings,
5798
+ styles,
5799
+ responsiveStyles,
5800
+ onPurposeToggle: handlePurposeCheckboxChange,
5801
+ onPurposeCollapse: togglePurposeCollapse,
5802
+ onDataElementToggle: handleDataElementCheckboxChange,
5803
+ getTranslatedText,
5804
+ isAlreadyConsented: false,
5805
+ selectedLanguage
5806
+ },
5807
+ `${purpose.uuid}-${selectedLanguage}`
5808
+ ))
5809
+ ] })
5810
+ ) }) : (
5704
5811
  /* Regular consent UI */
5705
5812
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: styles.optionsContainer, children: isMultiProduct(content == null ? void 0 : content.products) ? productGroups.map((group) => {
5813
+ var _a2;
5706
5814
  const selectedInGroup = group.purposes.filter(
5707
5815
  (purpose) => selectedPurposes[productPurposeKey(
5708
5816
  group.product.uuid,
@@ -5714,11 +5822,14 @@ var RedactoNoticeConsent = ({
5714
5822
  ProductSectionHeader,
5715
5823
  {
5716
5824
  product: group.product,
5825
+ isRequired: productIsRequiredFor(
5826
+ group.product.uuid
5827
+ ),
5717
5828
  purposeCount: group.purposes.length,
5718
5829
  allSelected: selectedInGroup === group.purposes.length,
5719
5830
  someSelected: selectedInGroup > 0,
5720
5831
  collapsed: collapsedProducts[group.product.uuid] || false,
5721
- locked: isFullyConsentedReviewMode,
5832
+ locked: (_a2 = consentedProducts[group.product.uuid]) != null ? _a2 : false,
5722
5833
  settings,
5723
5834
  styles,
5724
5835
  responsiveStyles,
@@ -5733,50 +5844,64 @@ var RedactoNoticeConsent = ({
5733
5844
  id: `product-${group.product.uuid}`,
5734
5845
  style: styles.sectionBody,
5735
5846
  hidden: collapsedProducts[group.product.uuid] || false,
5736
- children: group.purposes.map((purpose) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
5737
- PurposeItem,
5738
- {
5739
- purpose,
5740
- productUuid: group.product.uuid,
5741
- selectedPurposes,
5742
- collapsedPurposes,
5743
- selectedDataElements,
5744
- settings,
5745
- styles,
5746
- responsiveStyles,
5747
- onPurposeToggle: handlePurposeCheckboxChange,
5748
- onPurposeCollapse: togglePurposeCollapse,
5749
- onDataElementToggle: handleDataElementCheckboxChange,
5750
- getTranslatedText,
5751
- isAlreadyConsented: isFullyConsentedReviewMode,
5752
- selectedLanguage,
5753
- initialDataElementSelections
5754
- },
5755
- `${group.product.uuid}-${purpose.uuid}-${selectedLanguage}`
5756
- ))
5847
+ children: group.purposes.map((purpose) => {
5848
+ var _a3;
5849
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
5850
+ PurposeItem,
5851
+ {
5852
+ purpose,
5853
+ productUuid: group.product.uuid,
5854
+ productIsRequired: productIsRequiredFor(
5855
+ group.product.uuid
5856
+ ),
5857
+ selectedPurposes,
5858
+ collapsedPurposes,
5859
+ selectedDataElements,
5860
+ settings,
5861
+ styles,
5862
+ responsiveStyles,
5863
+ onPurposeToggle: handlePurposeCheckboxChange,
5864
+ onPurposeCollapse: togglePurposeCollapse,
5865
+ onDataElementToggle: handleDataElementCheckboxChange,
5866
+ getTranslatedText,
5867
+ isAlreadyConsented: (_a3 = consentedPurposes[productPurposeKey(
5868
+ group.product.uuid,
5869
+ purpose.uuid
5870
+ )]) != null ? _a3 : false,
5871
+ selectedLanguage,
5872
+ initialDataElementSelections
5873
+ },
5874
+ `${group.product.uuid}-${purpose.uuid}-${selectedLanguage}`
5875
+ );
5876
+ })
5757
5877
  }
5758
5878
  )
5759
5879
  ] }, group.product.uuid);
5760
- }) : (_y = content == null ? void 0 : content.purposes) == null ? void 0 : _y.map((purpose) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
5761
- PurposeItem,
5762
- {
5763
- purpose,
5764
- selectedPurposes,
5765
- collapsedPurposes,
5766
- selectedDataElements,
5767
- settings,
5768
- styles,
5769
- responsiveStyles,
5770
- onPurposeToggle: handlePurposeCheckboxChange,
5771
- onPurposeCollapse: togglePurposeCollapse,
5772
- onDataElementToggle: handleDataElementCheckboxChange,
5773
- getTranslatedText,
5774
- isAlreadyConsented: isFullyConsentedReviewMode,
5775
- selectedLanguage,
5776
- initialDataElementSelections
5777
- },
5778
- `${purpose.uuid}-${selectedLanguage}`
5779
- )) })
5880
+ }) : soleProductSection(
5881
+ (_y = content == null ? void 0 : content.purposes) == null ? void 0 : _y.map((purpose) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
5882
+ PurposeItem,
5883
+ {
5884
+ purpose,
5885
+ productIsRequired: productIsRequiredFor(
5886
+ void 0
5887
+ ),
5888
+ selectedPurposes,
5889
+ collapsedPurposes,
5890
+ selectedDataElements,
5891
+ settings,
5892
+ styles,
5893
+ responsiveStyles,
5894
+ onPurposeToggle: handlePurposeCheckboxChange,
5895
+ onPurposeCollapse: togglePurposeCollapse,
5896
+ onDataElementToggle: handleDataElementCheckboxChange,
5897
+ getTranslatedText,
5898
+ isAlreadyConsented: isFullyConsentedReviewMode,
5899
+ selectedLanguage,
5900
+ initialDataElementSelections
5901
+ },
5902
+ `${purpose.uuid}-${selectedLanguage}`
5903
+ ))
5904
+ ) })
5780
5905
  ),
5781
5906
  ((content == null ? void 0 : content.privacy_center_url) || (content == null ? void 0 : content.dpo_info)) && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
5782
5907
  "div",