@redacto.io/consent-sdk-react-native 5.0.0-beta.9 → 5.0.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.
@@ -10694,7 +10694,7 @@ function createConsentClient(baseUrl, ledgerBaseUrl) {
10694
10694
  * Submit a document for a document request (privacy center)
10695
10695
  */
10696
10696
  async submitDocumentForRequest(baseRequest, caseUuid, requestEventUuid, documentUuid, body, authToken, options) {
10697
- const url = `${baseUrl}/organisations/${baseRequest.organisationUuid}/workspaces/${baseRequest.workspaceUuid}/dsar/privacy-center/cases/${caseUuid}/document-requests/${requestEventUuid}/submit`;
10697
+ const url = `${baseUrl}/organisations/${baseRequest.organisationUuid}/workspaces/${baseRequest.workspaceUuid}/dsar/privacy-center/cases/${caseUuid}/document-requests/${requestEventUuid}/submit${sandboxIdentitySuffix()}`;
10698
10698
  return privacyCenterApiFetch(url, {
10699
10699
  ...options,
10700
10700
  method: "POST",
@@ -11974,7 +11974,11 @@ var resolveContactFromJwt = (decoded) => {
11974
11974
  }
11975
11975
  const userData = decoded.user_data || {};
11976
11976
  const candidate = decoded.contact || decoded.primary_email || userData.primary_email || userData.primary_mobile || userData.org_user_id;
11977
- return typeof candidate === "string" && candidate.trim() !== "" ? candidate : null;
11977
+ if (typeof candidate !== "string") {
11978
+ return null;
11979
+ }
11980
+ const contact = candidate.trim();
11981
+ return contact === "" ? null : contact;
11978
11982
  };
11979
11983
  var isJwtExpired = (token, bufferSeconds = 30) => {
11980
11984
  if (!token || typeof token !== "string") return true;
@@ -12116,6 +12120,23 @@ var formatDateTime = (timestamp) => {
12116
12120
  hours = hours % 12 || 12;
12117
12121
  return `${month} ${day}, ${year} at ${hours}:${minutes} ${ampm}`;
12118
12122
  };
12123
+ var extractCaseRef = (response) => {
12124
+ if (!response || typeof response !== "object") {
12125
+ return null;
12126
+ }
12127
+ const wrapper = response;
12128
+ const candidates = [wrapper.detail, response];
12129
+ for (const candidate of candidates) {
12130
+ if (!candidate || typeof candidate !== "object") {
12131
+ continue;
12132
+ }
12133
+ const { case_id: caseId, uuid } = candidate;
12134
+ if (caseId || uuid) {
12135
+ return { case_id: caseId != null ? caseId : "", uuid: uuid != null ? uuid : "" };
12136
+ }
12137
+ }
12138
+ return null;
12139
+ };
12119
12140
  var generateUuid = () => {
12120
12141
  return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
12121
12142
  const r = Math.random() * 16 | 0;
@@ -12135,9 +12156,10 @@ function extractJwtAuthData(token) {
12135
12156
  if (!decoded) {
12136
12157
  return { email: null, organizationId: null, workspaceId: null, organizationName: null };
12137
12158
  }
12138
- const contact = resolveContactFromJwt(decoded) || getStoredValue("email");
12159
+ const contact = resolveContactFromJwt(decoded);
12139
12160
  return {
12140
- email: typeof contact === "string" && contact.trim() !== "" ? contact : null,
12161
+ // `resolveContactFromJwt` already returns a trimmed, non-empty string or null.
12162
+ email: contact,
12141
12163
  organizationId: decoded.organisation_uuid || null,
12142
12164
  workspaceId: decoded.workspace_uuid || null,
12143
12165
  organizationName: decoded.organisation_name || null
@@ -12146,7 +12168,11 @@ function extractJwtAuthData(token) {
12146
12168
  function syncJwtDataToStore(token) {
12147
12169
  const authData = extractJwtAuthData(token);
12148
12170
  setStoredValue("access_token", token);
12149
- if (authData.email) setStoredValue("email", authData.email);
12171
+ if (authData.email) {
12172
+ setStoredValue("email", authData.email);
12173
+ } else {
12174
+ removeStoredValue("email");
12175
+ }
12150
12176
  if (authData.organizationId) setStoredValue("pc_org_id", authData.organizationId);
12151
12177
  if (authData.workspaceId) setStoredValue("pc_workspace_id", authData.workspaceId);
12152
12178
  return authData;
@@ -14756,6 +14782,11 @@ var useTimePeriodOptions = () => {
14756
14782
  );
14757
14783
  };
14758
14784
  var MAX_DISPLAYED_PURPOSE_NAMES_IN_ERASURE_MODAL = 3;
14785
+ var PRODUCT_SCOPED_REQUEST_TYPES = [
14786
+ "ACCESS" /* ACCESS */,
14787
+ "erasure" /* ERASURE */,
14788
+ "CORRECTION" /* CORRECTION */
14789
+ ];
14759
14790
  var SEARCH_DEBOUNCE_DELAY = 500;
14760
14791
  var FORM_PICKER_GROUP_LIMIT = 100;
14761
14792
  var LEGACY_PRODUCT_GROUP_UUID = "__legacy_flat_purposes__";
@@ -16529,27 +16560,38 @@ var uploadFileWithS2S = async ({
16529
16560
  authToken,
16530
16561
  baseUrl
16531
16562
  }) => {
16563
+ var _a3;
16532
16564
  try {
16533
- if (!authToken) {
16534
- throw new Error("Auth token is required for document upload");
16535
- }
16536
16565
  if (!baseUrl) {
16537
16566
  throw new Error("Base URL is required for document upload");
16538
16567
  }
16539
- const decodedToken = decodeJwtToken(authToken);
16540
- if (!decodedToken) {
16541
- throw new Error("Invalid access token");
16542
- }
16543
- const { organisation_uuid, workspace_uuid } = decodedToken;
16544
- if (!organisation_uuid || !workspace_uuid) {
16545
- throw new Error("Invalid token: missing organization or workspace UUID");
16568
+ const sandbox = getSandboxConfig();
16569
+ let organisation_uuid;
16570
+ let workspace_uuid;
16571
+ let authHeaders;
16572
+ if (sandbox) {
16573
+ organisation_uuid = sandbox.organisationUuid;
16574
+ workspace_uuid = sandbox.workspaceUuid;
16575
+ authHeaders = (_a3 = sandboxAuthHeaders()) != null ? _a3 : {};
16576
+ } else {
16577
+ if (!authToken) {
16578
+ throw new Error("Auth token is required for document upload");
16579
+ }
16580
+ const decodedToken = decodeJwtToken(authToken);
16581
+ if (!decodedToken) {
16582
+ throw new Error("Invalid access token");
16583
+ }
16584
+ if (!decodedToken.organisation_uuid || !decodedToken.workspace_uuid) {
16585
+ throw new Error("Invalid token: missing organization or workspace UUID");
16586
+ }
16587
+ organisation_uuid = decodedToken.organisation_uuid;
16588
+ workspace_uuid = decodedToken.workspace_uuid;
16589
+ authHeaders = { Authorization: `Bearer ${authToken}` };
16546
16590
  }
16547
16591
  const url = `${baseUrl}/organisations/${organisation_uuid}/workspaces/${workspace_uuid}/dsar/privacy-center/upload-document`;
16548
16592
  const response = await fetch(url, {
16549
16593
  method: "POST",
16550
- headers: {
16551
- "Authorization": `Bearer ${authToken}`
16552
- },
16594
+ headers: authHeaders,
16553
16595
  body: formData
16554
16596
  });
16555
16597
  if (!response.ok) {
@@ -16576,6 +16618,25 @@ var uploadFileWithS2S = async ({
16576
16618
  }
16577
16619
  };
16578
16620
 
16621
+ // src/RedactoPrivacyCenter/lib/requestType.ts
16622
+ var isRequestType = (requestType, expected) => typeof requestType === "string" && requestType.toLowerCase() === expected.toLowerCase();
16623
+ var isProductScopedRequestType = (requestType) => PRODUCT_SCOPED_REQUEST_TYPES.some((type) => isRequestType(requestType, type));
16624
+
16625
+ // src/RedactoPrivacyCenter/lib/erasureConsent.ts
16626
+ var isErasureRequestType = (requestType) => isRequestType(requestType, "erasure" /* ERASURE */);
16627
+ var resolveErasurePurposeNames = (purposeNames, fallback) => {
16628
+ if (purposeNames.length === 0 || purposeNames.length > MAX_DISPLAYED_PURPOSE_NAMES_IN_ERASURE_MODAL) {
16629
+ return fallback;
16630
+ }
16631
+ return purposeNames.join(", ");
16632
+ };
16633
+ var erasureConsentPayload = (requestType, revokeConsentOnFulfilment) => {
16634
+ if (!isErasureRequestType(requestType)) {
16635
+ return {};
16636
+ }
16637
+ return { revoke_consent_on_fulfilment: revokeConsentOnFulfilment };
16638
+ };
16639
+
16579
16640
  // src/RedactoPrivacyCenter/lib/filePicker.ts
16580
16641
  var import_react_native42 = require("react-native");
16581
16642
  async function pickFile() {
@@ -16812,12 +16873,6 @@ var buildGroupDataElements = (group) => {
16812
16873
  // src/RedactoPrivacyCenter/components/Form.tsx
16813
16874
  var import_jsx_runtime43 = require("react/jsx-runtime");
16814
16875
  var TOTAL_STEPS = 3;
16815
- var PRODUCT_SCOPED_REQUEST_TYPES = /* @__PURE__ */ new Set([
16816
- "ACCESS" /* ACCESS */,
16817
- "erasure" /* ERASURE */,
16818
- "CORRECTION" /* CORRECTION */
16819
- ]);
16820
- var isProductScopedRequestType = (rt) => PRODUCT_SCOPED_REQUEST_TYPES.has(rt);
16821
16876
  function Form({ onCreateRequest }) {
16822
16877
  const { t } = (0, import_react_i18next16.useTranslation)();
16823
16878
  const { accessToken, refreshToken, email, organizationId, workspaceId, updateTokens, onError } = useAuth();
@@ -16961,7 +17016,7 @@ function Form({ onCreateRequest }) {
16961
17016
  setSelectedProductKey(null);
16962
17017
  }
16963
17018
  setNominationData({ nominee_email: "", nominee_mobile: "" });
16964
- if (requestType === "grievance" /* GRIEVANCE */ && grievanceOptions.length > 0) {
17019
+ if (isRequestType(requestType, "grievance" /* GRIEVANCE */) && grievanceOptions.length > 0) {
16965
17020
  const resetGrievances = grievanceOptions.reduce(
16966
17021
  (acc, option) => {
16967
17022
  acc[option.value] = false;
@@ -16990,12 +17045,10 @@ function Form({ onCreateRequest }) {
16990
17045
  () => groupPurposes.filter((p) => selectedPurposes.has(p.uuid)).map((p) => p.name).filter(Boolean),
16991
17046
  [groupPurposes, selectedPurposes]
16992
17047
  );
16993
- const selectedErasurePurposeNames = (0, import_react29.useMemo)(() => {
16994
- if (selectedErasurePurposeList.length === 0 || selectedErasurePurposeList.length > MAX_DISPLAYED_PURPOSE_NAMES_IN_ERASURE_MODAL) {
16995
- return t("revokeConsentModalYourPurposes");
16996
- }
16997
- return selectedErasurePurposeList.join(", ");
16998
- }, [selectedErasurePurposeList, t]);
17048
+ const selectedErasurePurposeNames = (0, import_react29.useMemo)(
17049
+ () => resolveErasurePurposeNames(selectedErasurePurposeList, t("revokeConsentModalYourPurposes")),
17050
+ [selectedErasurePurposeList, t]
17051
+ );
16999
17052
  const togglePurpose = (0, import_react29.useCallback)(
17000
17053
  (purpose) => {
17001
17054
  const uuid = purpose.uuid;
@@ -17102,7 +17155,7 @@ function Form({ onCreateRequest }) {
17102
17155
  if (isProductScopedRequestType(requestType)) {
17103
17156
  if (allGroups.length === 0) return false;
17104
17157
  if (!selectedGroup) return false;
17105
- if (requestType === "CORRECTION" /* CORRECTION */) {
17158
+ if (isRequestType(requestType, "CORRECTION" /* CORRECTION */)) {
17106
17159
  if (selectedCorrectionFields.size === 0) return false;
17107
17160
  return Array.from(selectedCorrectionFields).every((fieldUuid) => {
17108
17161
  var _a3, _b;
@@ -17110,15 +17163,15 @@ function Form({ onCreateRequest }) {
17110
17163
  return Boolean(((_a3 = v == null ? void 0 : v.current) == null ? void 0 : _a3.trim()) && ((_b = v == null ? void 0 : v.updated) == null ? void 0 : _b.trim()));
17111
17164
  });
17112
17165
  }
17113
- if (requestType === "ACCESS" /* ACCESS */ || requestType === "erasure" /* ERASURE */) {
17166
+ if (isRequestType(requestType, "ACCESS" /* ACCESS */) || isErasureRequestType(requestType)) {
17114
17167
  return selectedPurposes.size > 0;
17115
17168
  }
17116
17169
  return false;
17117
17170
  }
17118
- if (requestType === "grievance" /* GRIEVANCE */) {
17171
+ if (isRequestType(requestType, "grievance" /* GRIEVANCE */)) {
17119
17172
  return Object.values(selectedGrievances).some(Boolean);
17120
17173
  }
17121
- if (requestType === "nomination" /* NOMINATION */) {
17174
+ if (isRequestType(requestType, "nomination" /* NOMINATION */)) {
17122
17175
  return Boolean(nominationData.nominee_email);
17123
17176
  }
17124
17177
  return false;
@@ -17132,7 +17185,10 @@ function Form({ onCreateRequest }) {
17132
17185
  selectedGrievances,
17133
17186
  nominationData
17134
17187
  ]);
17135
- const isFormValid = (0, import_react29.useMemo)(() => detailsValid && confirmChecked, [detailsValid, confirmChecked]);
17188
+ const isFormValid = (0, import_react29.useMemo)(
17189
+ () => Boolean(contact.trim()) && detailsValid && confirmChecked,
17190
+ [contact, detailsValid, confirmChecked]
17191
+ );
17136
17192
  const handleUpload = (0, import_react29.useCallback)(async () => {
17137
17193
  if (!organizationId || !workspaceId) return;
17138
17194
  const caseUuid = formDataResponse == null ? void 0 : formDataResponse.uuid;
@@ -17184,9 +17240,18 @@ function Form({ onCreateRequest }) {
17184
17240
  const removeUploadedDoc = (0, import_react29.useCallback)((uuid) => {
17185
17241
  setUploadedDocs((prev) => prev.filter((d) => d.uuid !== uuid));
17186
17242
  }, []);
17243
+ const alertSubmitFailed = (0, import_react29.useCallback)(
17244
+ (message) => {
17245
+ import_react_native44.Alert.alert(t("submit"), message || t("unableToSubmit") || "Unable to submit request. Please try again.");
17246
+ },
17247
+ [t]
17248
+ );
17187
17249
  const handleSubmit = (0, import_react29.useCallback)(async (revoke = false) => {
17188
- var _a3, _b, _c, _d;
17189
- if (!organizationId || !workspaceId || !contact || !requestType || !formDataResponse) return;
17250
+ var _a3;
17251
+ if (!organizationId || !workspaceId || !contact || !requestType || !formDataResponse) {
17252
+ alertSubmitFailed();
17253
+ return;
17254
+ }
17190
17255
  setRevokeConsentOnFulfilment(revoke);
17191
17256
  setIsSubmitting(true);
17192
17257
  try {
@@ -17213,27 +17278,27 @@ function Form({ onCreateRequest }) {
17213
17278
  purposes: updatePurposes,
17214
17279
  correction_data: correctionData,
17215
17280
  grievance_types: grievanceTypes,
17216
- ...requestType === "nomination" /* NOMINATION */ ? { nomination_data: nominationData } : {}
17281
+ ...isRequestType(requestType, "nomination" /* NOMINATION */) ? { nomination_data: nominationData } : {}
17217
17282
  },
17218
- time_period: requestType === "ACCESS" /* ACCESS */ ? parseInt(timePeriod || "30", 10) : 0,
17283
+ time_period: isRequestType(requestType, "ACCESS" /* ACCESS */) ? parseInt(timePeriod || "30", 10) : 0,
17219
17284
  requestor_note: additionalNote || "",
17220
- ...requestType === "erasure" /* ERASURE */ ? { revoke_consent_on_fulfilment: revoke } : {},
17285
+ ...erasureConsentPayload(requestType, revoke),
17221
17286
  ...anchorGroup ? { product_uuid: anchorGroup.product_uuid } : {},
17222
17287
  ...(anchorGroup == null ? void 0 : anchorGroup.nominator) ? { data_principal_uuid: anchorGroup.nominator.uuid } : {}
17223
17288
  };
17224
17289
  const response = await createCaseRequest(organizationId, workspaceId, request, false, false, authContext, consentClient);
17225
- const responseAny = response;
17226
- const newCaseId = (_c = (_b = responseAny == null ? void 0 : responseAny.case_id) != null ? _b : (_a3 = responseAny == null ? void 0 : responseAny.detail) == null ? void 0 : _a3.case_id) != null ? _c : null;
17290
+ const caseRef = extractCaseRef(response);
17291
+ const newCaseId = (caseRef == null ? void 0 : caseRef.case_id) || (caseRef == null ? void 0 : caseRef.uuid) || null;
17227
17292
  if (newCaseId) {
17228
17293
  setCaseId(newCaseId);
17229
- setSubmittedProductName((_d = anchorGroup == null ? void 0 : anchorGroup.product_name) != null ? _d : "");
17294
+ setSubmittedProductName((_a3 = anchorGroup == null ? void 0 : anchorGroup.product_name) != null ? _a3 : "");
17230
17295
  setIsSubmitted(true);
17231
17296
  } else {
17232
- import_react_native44.Alert.alert(t("submit"), t("unableToSubmit") || "Unable to submit request. Please try again.");
17297
+ alertSubmitFailed();
17233
17298
  }
17234
17299
  } catch (error) {
17235
17300
  console.warn("Error submitting request:", error);
17236
- import_react_native44.Alert.alert(t("submit"), (error == null ? void 0 : error.message) || t("unableToSubmit") || "Unable to submit request.");
17301
+ alertSubmitFailed(error == null ? void 0 : error.message);
17237
17302
  } finally {
17238
17303
  setIsSubmitting(false);
17239
17304
  }
@@ -17256,11 +17321,13 @@ function Form({ onCreateRequest }) {
17256
17321
  consentClient,
17257
17322
  groupDataElements,
17258
17323
  uploadedDocs,
17259
- t
17324
+ alertSubmitFailed
17260
17325
  ]);
17261
17326
  const handleSubmitClick = (0, import_react29.useCallback)(() => {
17262
- if (!isFormValid) return;
17263
- if (requestType === "erasure" /* ERASURE */) {
17327
+ if (!isFormValid) {
17328
+ return;
17329
+ }
17330
+ if (isErasureRequestType(requestType)) {
17264
17331
  setIsErasureConsentModalOpen(true);
17265
17332
  return;
17266
17333
  }
@@ -17349,7 +17416,7 @@ function Form({ onCreateRequest }) {
17349
17416
  if (groupPurposes.length === 0) {
17350
17417
  return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_react_native44.Text, { style: [styles33.placeholder, { color: colors.textSecondary }], children: t("noPurposesAvailable") || "No purposes available" });
17351
17418
  }
17352
- const isErasure = requestType === "erasure" /* ERASURE */;
17419
+ const isErasure = isErasureRequestType(requestType);
17353
17420
  const allPurposesSelected = groupPurposes.every(
17354
17421
  (p) => (p.data_elements || []).every((de) => {
17355
17422
  var _a3;
@@ -17469,18 +17536,18 @@ function Form({ onCreateRequest }) {
17469
17536
  ] }),
17470
17537
  selectedGroup ? /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(import_react_native44.View, { style: styles33.section, children: [
17471
17538
  /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_react_native44.Text, { style: [styles33.sectionLabel, { color: colors.textSecondary }], children: t("requestDetails") }),
17472
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_react_native44.View, { style: [styles33.sectionCard, elevation.card, { backgroundColor: colors.surface }], children: requestType === "CORRECTION" /* CORRECTION */ ? renderCorrectionFields() : renderPurposeFields() })
17539
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_react_native44.View, { style: [styles33.sectionCard, elevation.card, { backgroundColor: colors.surface }], children: isRequestType(requestType, "CORRECTION" /* CORRECTION */) ? renderCorrectionFields() : renderPurposeFields() })
17473
17540
  ] }) : /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(import_react_native44.View, { style: [styles33.hintCard, { backgroundColor: colors.surfaceAlt }], children: [
17474
17541
  /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Icon, { name: "circle-alert", size: 18, color: colors.textSecondary }),
17475
17542
  /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_react_native44.Text, { style: [styles33.hintText, { color: colors.textSecondary }], children: t("selectProductFirst", { defaultValue: "Select a product to continue" }) })
17476
17543
  ] }),
17477
- requestType === "ACCESS" /* ACCESS */ && selectedGroup ? /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(import_react_native44.View, { style: styles33.section, children: [
17544
+ isRequestType(requestType, "ACCESS" /* ACCESS */) && selectedGroup ? /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(import_react_native44.View, { style: styles33.section, children: [
17478
17545
  /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_react_native44.Text, { style: [styles33.sectionLabel, { color: colors.textSecondary }], children: t("timePeriod") }),
17479
17546
  /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(PCSelect, { value: timePeriod, options: timePeriodOptions, onChange: setTimePeriod, placeholder: t("timePeriod") })
17480
17547
  ] }) : null
17481
17548
  ] });
17482
17549
  }
17483
- if (requestType === "grievance" /* GRIEVANCE */) {
17550
+ if (isRequestType(requestType, "grievance" /* GRIEVANCE */)) {
17484
17551
  if (grievanceOptions.length === 0) {
17485
17552
  return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_react_native44.View, { style: styles33.stepBody, children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_react_native44.Text, { style: [styles33.placeholder, { color: colors.textSecondary }], children: t("noPurposesAvailable") || "No grievance types available" }) });
17486
17553
  }
@@ -17496,7 +17563,7 @@ function Form({ onCreateRequest }) {
17496
17563
  ] })
17497
17564
  ] }) });
17498
17565
  }
17499
- if (requestType === "nomination" /* NOMINATION */) {
17566
+ if (isRequestType(requestType, "nomination" /* NOMINATION */)) {
17500
17567
  return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_react_native44.View, { style: styles33.stepBody, children: /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(import_react_native44.View, { style: styles33.section, children: [
17501
17568
  /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_react_native44.Text, { style: [styles33.sectionLabel, { color: colors.textSecondary }], children: t("enterNomineeDetails") }),
17502
17569
  /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(import_react_native44.View, { style: [styles33.sectionCard, elevation.card, { backgroundColor: colors.surface }], children: [
@@ -18474,10 +18541,26 @@ var styles35 = import_react_native46.StyleSheet.create({
18474
18541
  });
18475
18542
 
18476
18543
  // src/RedactoPrivacyCenter/components/SlimTopBar.tsx
18477
- var import_react34 = require("react");
18544
+ var import_react35 = require("react");
18478
18545
  var import_react_native49 = require("react-native");
18479
18546
  var import_react_i18next19 = require("react-i18next");
18480
18547
 
18548
+ // src/RedactoPrivacyCenter/context/ProfileSwitchContext.tsx
18549
+ var import_react32 = require("react");
18550
+ var import_jsx_runtime46 = require("react/jsx-runtime");
18551
+ var ProfileSwitchContext = (0, import_react32.createContext)({
18552
+ switchProfile: null
18553
+ });
18554
+ function ProfileSwitchProvider({
18555
+ switchProfile,
18556
+ children
18557
+ }) {
18558
+ return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(ProfileSwitchContext.Provider, { value: { switchProfile }, children });
18559
+ }
18560
+ function useProfileSwitch() {
18561
+ return (0, import_react32.useContext)(ProfileSwitchContext);
18562
+ }
18563
+
18481
18564
  // src/RedactoPrivacyCenter/lib/navigation.ts
18482
18565
  function navigateBack(onBack) {
18483
18566
  var _a3, _b;
@@ -18501,12 +18584,12 @@ function navigateBack(onBack) {
18501
18584
 
18502
18585
  // src/RedactoPrivacyCenter/components/NotificationHub/NotificationBell.tsx
18503
18586
  var import_react_native47 = require("react-native");
18504
- var import_jsx_runtime46 = require("react/jsx-runtime");
18587
+ var import_jsx_runtime47 = require("react/jsx-runtime");
18505
18588
  var NotificationBell = ({ count, onPress }) => {
18506
18589
  const { colors } = useTheme();
18507
18590
  const showBadge = count > 0;
18508
18591
  const badgeLabel = count > 99 ? "99+" : String(count);
18509
- return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(
18592
+ return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(
18510
18593
  import_react_native47.TouchableOpacity,
18511
18594
  {
18512
18595
  onPress,
@@ -18516,8 +18599,8 @@ var NotificationBell = ({ count, onPress }) => {
18516
18599
  accessibilityRole: "button",
18517
18600
  accessibilityLabel: showBadge ? `Notifications, ${count} unread` : "Notifications",
18518
18601
  children: [
18519
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Icon, { name: "bell", size: 22, color: colors.text }),
18520
- showBadge ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_react_native47.View, { style: [styles36.badge, { backgroundColor: colors.error, borderColor: colors.canvasSubtle }], children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_react_native47.Text, { style: styles36.badgeText, numberOfLines: 1, children: badgeLabel }) }) : null
18602
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Icon, { name: "bell", size: 22, color: colors.text }),
18603
+ showBadge ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_react_native47.View, { style: [styles36.badge, { backgroundColor: colors.error, borderColor: colors.canvasSubtle }], children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_react_native47.Text, { style: styles36.badgeText, numberOfLines: 1, children: badgeLabel }) }) : null
18521
18604
  ]
18522
18605
  }
18523
18606
  );
@@ -18549,27 +18632,27 @@ var styles36 = import_react_native47.StyleSheet.create({
18549
18632
  });
18550
18633
 
18551
18634
  // src/RedactoPrivacyCenter/components/NotificationHub/useUnreadCount.ts
18552
- var import_react32 = require("react");
18635
+ var import_react33 = require("react");
18553
18636
  function useUnreadCount() {
18554
18637
  const { accessToken, refreshToken, onError, updateTokens, organizationId, workspaceId } = useAuth();
18555
18638
  const { consentClient } = useBaseUrl();
18556
- const [count, setCount] = (0, import_react32.useState)(0);
18557
- const authContext = (0, import_react32.useMemo)(
18639
+ const [count, setCount] = (0, import_react33.useState)(0);
18640
+ const authContext = (0, import_react33.useMemo)(
18558
18641
  () => ({ accessToken, refreshToken, onError, updateTokens }),
18559
18642
  [accessToken, refreshToken, onError, updateTokens]
18560
18643
  );
18561
- const loadRef = (0, import_react32.useRef)();
18644
+ const loadRef = (0, import_react33.useRef)();
18562
18645
  loadRef.current = async () => {
18563
18646
  if (!organizationId || !workspaceId) return;
18564
18647
  if (isRefreshBlocked(authContext)) return;
18565
18648
  const res = await fetchUnreadCount(organizationId, workspaceId, authContext, consentClient);
18566
18649
  if (res && typeof res.count === "number") setCount(res.count);
18567
18650
  };
18568
- (0, import_react32.useEffect)(() => {
18651
+ (0, import_react33.useEffect)(() => {
18569
18652
  var _a3;
18570
18653
  (_a3 = loadRef.current) == null ? void 0 : _a3.call(loadRef);
18571
18654
  }, [organizationId, workspaceId]);
18572
- (0, import_react32.useEffect)(() => {
18655
+ (0, import_react33.useEffect)(() => {
18573
18656
  const id = setInterval(() => {
18574
18657
  var _a3;
18575
18658
  (_a3 = loadRef.current) == null ? void 0 : _a3.call(loadRef);
@@ -18580,17 +18663,17 @@ function useUnreadCount() {
18580
18663
  }
18581
18664
 
18582
18665
  // src/RedactoPrivacyCenter/components/NavDrawer.tsx
18583
- var import_react33 = require("react");
18666
+ var import_react34 = require("react");
18584
18667
  var import_react_native48 = require("react-native");
18585
18668
  var import_react_i18next18 = require("react-i18next");
18586
- var import_jsx_runtime47 = require("react/jsx-runtime");
18669
+ var import_jsx_runtime48 = require("react/jsx-runtime");
18587
18670
  var NavDrawer = ({ visible, onClose, onBack }) => {
18588
18671
  const { t } = (0, import_react_i18next18.useTranslation)();
18589
18672
  const { colors, branding } = useTheme();
18590
18673
  const { organizationName, email } = useAuth();
18591
18674
  const { currentPage, navigateTo } = useInternalNavigation();
18592
- const [locale, setLocale] = (0, import_react33.useState)(i18n_default.language || "en");
18593
- const items = (0, import_react33.useMemo)(
18675
+ const [locale, setLocale] = (0, import_react34.useState)(i18n_default.language || "en");
18676
+ const items = (0, import_react34.useMemo)(
18594
18677
  () => [
18595
18678
  { page: "home", label: t("privacyCenter") || "Home", icon: "shield", tone: "primary" },
18596
18679
  { page: "consent-manager", label: t("manageConsent") || "Consents", icon: "shield-check", tone: "primary" },
@@ -18605,18 +18688,18 @@ var NavDrawer = ({ visible, onClose, onBack }) => {
18605
18688
  i18n_default.changeLanguage(value);
18606
18689
  };
18607
18690
  const brandName = (branding == null ? void 0 : branding.brand_name) || organizationName || t("privacyCenter") || "Privacy Center";
18608
- return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(BottomSheet, { visible, onClose, title: t("menu") || "Menu", children: /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(import_react_native48.View, { style: styles37.body, children: [
18609
- /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(import_react_native48.View, { style: [styles37.identity, { backgroundColor: colors.surfaceAlt }], children: [
18610
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(PCAvatar, { name: brandName, imageUrl: branding == null ? void 0 : branding.icon_url, size: 40 }),
18611
- /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(import_react_native48.View, { style: styles37.identityText, children: [
18612
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_react_native48.Text, { style: [styles37.brandName, { color: colors.text }], numberOfLines: 1, children: brandName }),
18613
- email ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_react_native48.Text, { style: [styles37.email, { color: colors.textSecondary }], numberOfLines: 1, children: email }) : null
18691
+ return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(BottomSheet, { visible, onClose, title: t("menu") || "Menu", children: /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(import_react_native48.View, { style: styles37.body, children: [
18692
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(import_react_native48.View, { style: [styles37.identity, { backgroundColor: colors.surfaceAlt }], children: [
18693
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(PCAvatar, { name: brandName, imageUrl: branding == null ? void 0 : branding.icon_url, size: 40 }),
18694
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(import_react_native48.View, { style: styles37.identityText, children: [
18695
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_react_native48.Text, { style: [styles37.brandName, { color: colors.text }], numberOfLines: 1, children: brandName }),
18696
+ email ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_react_native48.Text, { style: [styles37.email, { color: colors.textSecondary }], numberOfLines: 1, children: email }) : null
18614
18697
  ] })
18615
18698
  ] }),
18616
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_react_native48.View, { style: [styles37.menuGroup, { borderColor: colors.border, backgroundColor: colors.surface }], children: items.map((item, index) => {
18699
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_react_native48.View, { style: [styles37.menuGroup, { borderColor: colors.border, backgroundColor: colors.surface }], children: items.map((item, index) => {
18617
18700
  const isActive = currentPage === item.page;
18618
- return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(import_react_native48.View, { children: [
18619
- /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(
18701
+ return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(import_react_native48.View, { children: [
18702
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(
18620
18703
  import_react_native48.TouchableOpacity,
18621
18704
  {
18622
18705
  style: styles37.menuItem,
@@ -18629,8 +18712,8 @@ var NavDrawer = ({ visible, onClose, onBack }) => {
18629
18712
  accessibilityState: { selected: isActive },
18630
18713
  accessibilityLabel: item.label,
18631
18714
  children: [
18632
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(IconTile, { name: item.icon, tone: item.tone, size: "sm" }),
18633
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
18715
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(IconTile, { name: item.icon, tone: item.tone, size: "sm" }),
18716
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
18634
18717
  import_react_native48.Text,
18635
18718
  {
18636
18719
  style: [styles37.menuLabel, { color: isActive ? colors.primary : colors.text }],
@@ -18638,14 +18721,14 @@ var NavDrawer = ({ visible, onClose, onBack }) => {
18638
18721
  children: item.label
18639
18722
  }
18640
18723
  ),
18641
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Icon, { name: "chevron-right", size: 18, color: colors.textSecondary })
18724
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(Icon, { name: "chevron-right", size: 18, color: colors.textSecondary })
18642
18725
  ]
18643
18726
  }
18644
18727
  ),
18645
- index < items.length - 1 ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_react_native48.View, { style: [styles37.separator, { backgroundColor: colors.hairline }] }) : null
18728
+ index < items.length - 1 ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_react_native48.View, { style: [styles37.separator, { backgroundColor: colors.hairline }] }) : null
18646
18729
  ] }, item.page);
18647
18730
  }) }),
18648
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
18731
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
18649
18732
  PCSelect,
18650
18733
  {
18651
18734
  label: t("language"),
@@ -18655,7 +18738,7 @@ var NavDrawer = ({ visible, onClose, onBack }) => {
18655
18738
  placeholder: t("language")
18656
18739
  }
18657
18740
  ),
18658
- onBack ? /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(
18741
+ onBack ? /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(
18659
18742
  import_react_native48.TouchableOpacity,
18660
18743
  {
18661
18744
  style: [styles37.actionButton, { borderColor: colors.border, backgroundColor: colors.surface }],
@@ -18666,7 +18749,7 @@ var NavDrawer = ({ visible, onClose, onBack }) => {
18666
18749
  activeOpacity: 0.7,
18667
18750
  accessibilityRole: "button",
18668
18751
  children: [
18669
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
18752
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
18670
18753
  Icon,
18671
18754
  {
18672
18755
  name: onBack === "signout" ? "log-out" : "arrow-left",
@@ -18674,11 +18757,11 @@ var NavDrawer = ({ visible, onClose, onBack }) => {
18674
18757
  color: onBack === "signout" ? colors.error : colors.text
18675
18758
  }
18676
18759
  ),
18677
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_react_native48.Text, { style: [styles37.actionLabel, { color: onBack === "signout" ? colors.error : colors.text }], children: onBack === "signout" ? t("signOut") || "Sign Out" : t("back") || "Back" })
18760
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_react_native48.Text, { style: [styles37.actionLabel, { color: onBack === "signout" ? colors.error : colors.text }], children: onBack === "signout" ? t("signOut") || "Sign Out" : t("back") || "Back" })
18678
18761
  ]
18679
18762
  }
18680
18763
  ) : null,
18681
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Footer, { inline: true })
18764
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(Footer, { inline: true })
18682
18765
  ] }) });
18683
18766
  };
18684
18767
  var styles37 = import_react_native48.StyleSheet.create({
@@ -18740,7 +18823,7 @@ var styles37 = import_react_native48.StyleSheet.create({
18740
18823
  });
18741
18824
 
18742
18825
  // src/RedactoPrivacyCenter/components/SlimTopBar.tsx
18743
- var import_jsx_runtime48 = require("react/jsx-runtime");
18826
+ var import_jsx_runtime49 = require("react/jsx-runtime");
18744
18827
  var SlimTopBar = ({ mode = "primary", onBack }) => {
18745
18828
  const { t } = (0, import_react_i18next19.useTranslation)();
18746
18829
  const { currentPage, navigateTo } = useInternalNavigation();
@@ -18748,10 +18831,11 @@ var SlimTopBar = ({ mode = "primary", onBack }) => {
18748
18831
  const { organizationName } = useAuth();
18749
18832
  const unreadCount = useUnreadCount();
18750
18833
  const insets = useSafeInsets();
18751
- const [menuOpen, setMenuOpen] = (0, import_react34.useState)(false);
18834
+ const [menuOpen, setMenuOpen] = (0, import_react35.useState)(false);
18835
+ const { switchProfile } = useProfileSwitch();
18752
18836
  const pageChrome = PAGE_CHROME_BY_PAGE[currentPage];
18753
18837
  const isDetail = mode === "detail";
18754
- const brandLabel = (0, import_react34.useMemo)(
18838
+ const brandLabel = (0, import_react35.useMemo)(
18755
18839
  () => (branding == null ? void 0 : branding.brand_name) || organizationName || t("privacyCenter") || "Privacy Center",
18756
18840
  [branding == null ? void 0 : branding.brand_name, organizationName, t]
18757
18841
  );
@@ -18766,16 +18850,16 @@ var SlimTopBar = ({ mode = "primary", onBack }) => {
18766
18850
  }
18767
18851
  navigateBack(onBack);
18768
18852
  };
18769
- return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(import_jsx_runtime48.Fragment, { children: [
18770
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
18853
+ return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)(import_jsx_runtime49.Fragment, { children: [
18854
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
18771
18855
  import_react_native49.View,
18772
18856
  {
18773
18857
  style: [
18774
18858
  styles38.container,
18775
18859
  { backgroundColor: colors.canvasSubtle, borderBottomColor: colors.hairline, paddingTop: insets.top + spacing.xs }
18776
18860
  ],
18777
- children: isDetail ? /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(import_react_native49.View, { style: styles38.detailRow, children: [
18778
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
18861
+ children: isDetail ? /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)(import_react_native49.View, { style: styles38.detailRow, children: [
18862
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
18779
18863
  import_react_native49.TouchableOpacity,
18780
18864
  {
18781
18865
  style: styles38.iconButton,
@@ -18784,27 +18868,39 @@ var SlimTopBar = ({ mode = "primary", onBack }) => {
18784
18868
  hitSlop: DEFAULT_HIT_SLOP,
18785
18869
  accessibilityRole: "button",
18786
18870
  accessibilityLabel: t("back") || "Back",
18787
- children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(Icon, { name: "arrow-left", size: 22, color: colors.text })
18871
+ children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(Icon, { name: "arrow-left", size: 22, color: colors.text })
18788
18872
  }
18789
18873
  ),
18790
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_react_native49.Text, { style: [styles38.detailTitle, { color: colors.text }], numberOfLines: 1, children: t((pageChrome == null ? void 0 : pageChrome.titleKey) || "privacyCenter") }),
18791
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_react_native49.View, { style: styles38.placeholder })
18792
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(import_react_native49.View, { style: styles38.row, children: [
18793
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_react_native49.View, { style: styles38.brandWrap, children: (branding == null ? void 0 : branding.logo_url) ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
18874
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_react_native49.Text, { style: [styles38.detailTitle, { color: colors.text }], numberOfLines: 1, children: t((pageChrome == null ? void 0 : pageChrome.titleKey) || "privacyCenter") }),
18875
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_react_native49.View, { style: styles38.placeholder })
18876
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)(import_react_native49.View, { style: styles38.row, children: [
18877
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_react_native49.View, { style: styles38.brandWrap, children: (branding == null ? void 0 : branding.logo_url) ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
18794
18878
  BrandImage,
18795
18879
  {
18796
18880
  uri: branding.logo_url,
18797
18881
  height: 24,
18798
18882
  maxWidth: 124,
18799
- fallback: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(PCAvatar, { name: brandLabel, imageUrl: branding == null ? void 0 : branding.icon_url, size: 24 })
18883
+ fallback: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(PCAvatar, { name: brandLabel, imageUrl: branding == null ? void 0 : branding.icon_url, size: 24 })
18800
18884
  }
18801
- ) : /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(import_react_native49.View, { style: styles38.brandLockup, children: [
18802
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(PCAvatar, { name: brandLabel, imageUrl: branding == null ? void 0 : branding.icon_url, size: 24 }),
18803
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_react_native49.Text, { style: [styles38.brandText, { color: colors.text }], numberOfLines: 1, children: brandLabel })
18885
+ ) : /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)(import_react_native49.View, { style: styles38.brandLockup, children: [
18886
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(PCAvatar, { name: brandLabel, imageUrl: branding == null ? void 0 : branding.icon_url, size: 24 }),
18887
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_react_native49.Text, { style: [styles38.brandText, { color: colors.text }], numberOfLines: 1, children: brandLabel })
18804
18888
  ] }) }),
18805
- /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(import_react_native49.View, { style: styles38.actions, children: [
18806
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(NotificationBell, { count: unreadCount, onPress: () => navigateTo("notifications") }),
18807
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
18889
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)(import_react_native49.View, { style: styles38.actions, children: [
18890
+ switchProfile ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
18891
+ import_react_native49.TouchableOpacity,
18892
+ {
18893
+ style: styles38.iconButton,
18894
+ onPress: switchProfile,
18895
+ activeOpacity: 0.7,
18896
+ hitSlop: DEFAULT_HIT_SLOP,
18897
+ accessibilityRole: "button",
18898
+ accessibilityLabel: t("switchProfile"),
18899
+ children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(Icon, { name: "users", size: 22, color: colors.text })
18900
+ }
18901
+ ) : null,
18902
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(NotificationBell, { count: unreadCount, onPress: () => navigateTo("notifications") }),
18903
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
18808
18904
  import_react_native49.TouchableOpacity,
18809
18905
  {
18810
18906
  style: styles38.iconButton,
@@ -18813,14 +18909,14 @@ var SlimTopBar = ({ mode = "primary", onBack }) => {
18813
18909
  hitSlop: DEFAULT_HIT_SLOP,
18814
18910
  accessibilityRole: "button",
18815
18911
  accessibilityLabel: t("menu") || "Menu",
18816
- children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(Icon, { name: "menu", size: 22, color: colors.text })
18912
+ children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(Icon, { name: "menu", size: 22, color: colors.text })
18817
18913
  }
18818
18914
  )
18819
18915
  ] })
18820
18916
  ] })
18821
18917
  }
18822
18918
  ),
18823
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(NavDrawer, { visible: menuOpen, onClose: () => setMenuOpen(false), onBack })
18919
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(NavDrawer, { visible: menuOpen, onClose: () => setMenuOpen(false), onBack })
18824
18920
  ] });
18825
18921
  };
18826
18922
  var styles38 = import_react_native49.StyleSheet.create({
@@ -18881,18 +18977,18 @@ var styles38 = import_react_native49.StyleSheet.create({
18881
18977
 
18882
18978
  // src/RedactoPrivacyCenter/components/PrivacyCenterEmptyState.tsx
18883
18979
  var import_react_i18next20 = require("react-i18next");
18884
- var import_jsx_runtime49 = require("react/jsx-runtime");
18980
+ var import_jsx_runtime50 = require("react/jsx-runtime");
18885
18981
  function PrivacyCenterEmptyState() {
18886
18982
  const { t } = (0, import_react_i18next20.useTranslation)();
18887
- return /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(PCEmpty, { iconName: "shield", title: t("noDataTitle"), description: t("noDataDescription") });
18983
+ return /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(PCEmpty, { iconName: "shield", title: t("noDataTitle"), description: t("noDataDescription") });
18888
18984
  }
18889
18985
 
18890
18986
  // src/RedactoPrivacyCenter/components/PrivacyCenterSessionExpired.tsx
18891
18987
  var import_react_i18next21 = require("react-i18next");
18892
- var import_jsx_runtime50 = require("react/jsx-runtime");
18988
+ var import_jsx_runtime51 = require("react/jsx-runtime");
18893
18989
  function PrivacyCenterSessionExpired() {
18894
18990
  const { t } = (0, import_react_i18next21.useTranslation)();
18895
- return /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
18991
+ return /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
18896
18992
  PCEmpty,
18897
18993
  {
18898
18994
  iconName: "shield",
@@ -18906,22 +19002,6 @@ function PrivacyCenterSessionExpired() {
18906
19002
  var import_react36 = require("react");
18907
19003
  var import_react_native51 = require("react-native");
18908
19004
 
18909
- // src/RedactoPrivacyCenter/context/ProfileSwitchContext.tsx
18910
- var import_react35 = require("react");
18911
- var import_jsx_runtime51 = require("react/jsx-runtime");
18912
- var ProfileSwitchContext = (0, import_react35.createContext)({
18913
- switchProfile: null
18914
- });
18915
- function ProfileSwitchProvider({
18916
- switchProfile,
18917
- children
18918
- }) {
18919
- return /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(ProfileSwitchContext.Provider, { value: { switchProfile }, children });
18920
- }
18921
- function useProfileSwitch() {
18922
- return (0, import_react35.useContext)(ProfileSwitchContext);
18923
- }
18924
-
18925
19005
  // src/RedactoPrivacyCenter/components/SelectUser.tsx
18926
19006
  var import_react_native50 = require("react-native");
18927
19007
  var import_react_i18next22 = require("react-i18next");
@@ -21683,6 +21763,7 @@ function Navbar({ mode = "primary", onBack }) {
21683
21763
  const [menuOpen, setMenuOpen] = (0, import_react46.useState)(false);
21684
21764
  const unreadCount = useUnreadCount();
21685
21765
  const { status: pageStatus } = usePageStatus();
21766
+ const { switchProfile } = useProfileSwitch();
21686
21767
  const pageChrome = PAGE_CHROME_BY_PAGE[currentPage] || PAGE_CHROME_BY_PAGE["consent-manager"];
21687
21768
  const isDetail = mode === "detail";
21688
21769
  (0, import_react46.useEffect)(() => {
@@ -21785,6 +21866,36 @@ function Navbar({ mode = "primary", onBack }) {
21785
21866
  ) : null,
21786
21867
  /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(import_react_native69.View, { style: styles57.brandWrap, children: (branding == null ? void 0 : branding.logo_url) ? /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(BrandImage, { uri: branding.logo_url, height: 34, maxWidth: 170, fallback: brandLockup }) : brandLockup }),
21787
21868
  /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)(import_react_native69.View, { style: styles57.actions, children: [
21869
+ switchProfile ? /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
21870
+ import_react_native69.TouchableOpacity,
21871
+ {
21872
+ style: styles57.iconButton,
21873
+ onPress: switchProfile,
21874
+ activeOpacity: 0.7,
21875
+ hitSlop: DEFAULT_HIT_SLOP,
21876
+ accessibilityRole: "button",
21877
+ accessibilityLabel: t("switchProfile"),
21878
+ children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
21879
+ import_react_native69.View,
21880
+ {
21881
+ style: [
21882
+ styles57.iconCircle,
21883
+ { backgroundColor: colors.surface, borderColor: colors.border }
21884
+ ],
21885
+ children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(import_react_native_svg6.default, { width: 18, height: 18, viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
21886
+ import_react_native_svg6.Path,
21887
+ {
21888
+ d: "M16 3h5v5 M21 3l-7 7 M8 21H3v-5 M3 21l7-7",
21889
+ stroke: colors.text,
21890
+ strokeWidth: 2,
21891
+ strokeLinecap: "round",
21892
+ strokeLinejoin: "round"
21893
+ }
21894
+ ) })
21895
+ }
21896
+ )
21897
+ }
21898
+ ) : null,
21788
21899
  /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(NotificationBell, { count: unreadCount, onPress: () => navigateTo("notifications") }),
21789
21900
  /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(PCSelect, { value: locale, options: languageOptions, onChange: handleLanguageChange, placeholder: t("language"), compact: true }),
21790
21901
  /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
@@ -21861,6 +21972,21 @@ var styles57 = import_react_native69.StyleSheet.create({
21861
21972
  alignItems: "center",
21862
21973
  justifyContent: "center"
21863
21974
  },
21975
+ iconButton: {
21976
+ width: MIN_TAP_TARGET,
21977
+ height: MIN_TAP_TARGET,
21978
+ alignItems: "center",
21979
+ justifyContent: "center"
21980
+ },
21981
+ // Matches the Flutter navbar's 34pt bordered circle.
21982
+ iconCircle: {
21983
+ width: 34,
21984
+ height: 34,
21985
+ borderRadius: 17,
21986
+ borderWidth: 1,
21987
+ alignItems: "center",
21988
+ justifyContent: "center"
21989
+ },
21864
21990
  pageHeader: {
21865
21991
  marginTop: spacing.sm
21866
21992
  },