@redacto.io/consent-sdk-react-native 5.0.0-beta.9 → 5.0.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.
@@ -11859,7 +11859,11 @@ var resolveContactFromJwt = (decoded) => {
11859
11859
  }
11860
11860
  const userData = decoded.user_data || {};
11861
11861
  const candidate = decoded.contact || decoded.primary_email || userData.primary_email || userData.primary_mobile || userData.org_user_id;
11862
- return typeof candidate === "string" && candidate.trim() !== "" ? candidate : null;
11862
+ if (typeof candidate !== "string") {
11863
+ return null;
11864
+ }
11865
+ const contact = candidate.trim();
11866
+ return contact === "" ? null : contact;
11863
11867
  };
11864
11868
  var isJwtExpired = (token, bufferSeconds = 30) => {
11865
11869
  if (!token || typeof token !== "string") return true;
@@ -12001,6 +12005,23 @@ var formatDateTime = (timestamp) => {
12001
12005
  hours = hours % 12 || 12;
12002
12006
  return `${month} ${day}, ${year} at ${hours}:${minutes} ${ampm}`;
12003
12007
  };
12008
+ var extractCaseRef = (response) => {
12009
+ if (!response || typeof response !== "object") {
12010
+ return null;
12011
+ }
12012
+ const wrapper = response;
12013
+ const candidates = [wrapper.detail, response];
12014
+ for (const candidate of candidates) {
12015
+ if (!candidate || typeof candidate !== "object") {
12016
+ continue;
12017
+ }
12018
+ const { case_id: caseId, uuid } = candidate;
12019
+ if (caseId || uuid) {
12020
+ return { case_id: caseId != null ? caseId : "", uuid: uuid != null ? uuid : "" };
12021
+ }
12022
+ }
12023
+ return null;
12024
+ };
12004
12025
  var generateUuid = () => {
12005
12026
  return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
12006
12027
  const r = Math.random() * 16 | 0;
@@ -12020,9 +12041,10 @@ function extractJwtAuthData(token) {
12020
12041
  if (!decoded) {
12021
12042
  return { email: null, organizationId: null, workspaceId: null, organizationName: null };
12022
12043
  }
12023
- const contact = resolveContactFromJwt(decoded) || getStoredValue("email");
12044
+ const contact = resolveContactFromJwt(decoded);
12024
12045
  return {
12025
- email: typeof contact === "string" && contact.trim() !== "" ? contact : null,
12046
+ // `resolveContactFromJwt` already returns a trimmed, non-empty string or null.
12047
+ email: contact,
12026
12048
  organizationId: decoded.organisation_uuid || null,
12027
12049
  workspaceId: decoded.workspace_uuid || null,
12028
12050
  organizationName: decoded.organisation_name || null
@@ -12031,7 +12053,11 @@ function extractJwtAuthData(token) {
12031
12053
  function syncJwtDataToStore(token) {
12032
12054
  const authData = extractJwtAuthData(token);
12033
12055
  setStoredValue("access_token", token);
12034
- if (authData.email) setStoredValue("email", authData.email);
12056
+ if (authData.email) {
12057
+ setStoredValue("email", authData.email);
12058
+ } else {
12059
+ removeStoredValue("email");
12060
+ }
12035
12061
  if (authData.organizationId) setStoredValue("pc_org_id", authData.organizationId);
12036
12062
  if (authData.workspaceId) setStoredValue("pc_workspace_id", authData.workspaceId);
12037
12063
  return authData;
@@ -14728,6 +14754,11 @@ var useTimePeriodOptions = () => {
14728
14754
  );
14729
14755
  };
14730
14756
  var MAX_DISPLAYED_PURPOSE_NAMES_IN_ERASURE_MODAL = 3;
14757
+ var PRODUCT_SCOPED_REQUEST_TYPES = [
14758
+ "ACCESS" /* ACCESS */,
14759
+ "erasure" /* ERASURE */,
14760
+ "CORRECTION" /* CORRECTION */
14761
+ ];
14731
14762
  var SEARCH_DEBOUNCE_DELAY = 500;
14732
14763
  var FORM_PICKER_GROUP_LIMIT = 100;
14733
14764
  var LEGACY_PRODUCT_GROUP_UUID = "__legacy_flat_purposes__";
@@ -16571,6 +16602,25 @@ var uploadFileWithS2S = async ({
16571
16602
  }
16572
16603
  };
16573
16604
 
16605
+ // src/RedactoPrivacyCenter/lib/requestType.ts
16606
+ var isRequestType = (requestType, expected) => typeof requestType === "string" && requestType.toLowerCase() === expected.toLowerCase();
16607
+ var isProductScopedRequestType = (requestType) => PRODUCT_SCOPED_REQUEST_TYPES.some((type) => isRequestType(requestType, type));
16608
+
16609
+ // src/RedactoPrivacyCenter/lib/erasureConsent.ts
16610
+ var isErasureRequestType = (requestType) => isRequestType(requestType, "erasure" /* ERASURE */);
16611
+ var resolveErasurePurposeNames = (purposeNames, fallback) => {
16612
+ if (purposeNames.length === 0 || purposeNames.length > MAX_DISPLAYED_PURPOSE_NAMES_IN_ERASURE_MODAL) {
16613
+ return fallback;
16614
+ }
16615
+ return purposeNames.join(", ");
16616
+ };
16617
+ var erasureConsentPayload = (requestType, revokeConsentOnFulfilment) => {
16618
+ if (!isErasureRequestType(requestType)) {
16619
+ return {};
16620
+ }
16621
+ return { revoke_consent_on_fulfilment: revokeConsentOnFulfilment };
16622
+ };
16623
+
16574
16624
  // src/RedactoPrivacyCenter/lib/filePicker.ts
16575
16625
  import { Alert as Alert4 } from "react-native";
16576
16626
  async function pickFile() {
@@ -16807,12 +16857,6 @@ var buildGroupDataElements = (group) => {
16807
16857
  // src/RedactoPrivacyCenter/components/Form.tsx
16808
16858
  import { Fragment as Fragment9, jsx as jsx43, jsxs as jsxs27 } from "react/jsx-runtime";
16809
16859
  var TOTAL_STEPS = 3;
16810
- var PRODUCT_SCOPED_REQUEST_TYPES = /* @__PURE__ */ new Set([
16811
- "ACCESS" /* ACCESS */,
16812
- "erasure" /* ERASURE */,
16813
- "CORRECTION" /* CORRECTION */
16814
- ]);
16815
- var isProductScopedRequestType = (rt) => PRODUCT_SCOPED_REQUEST_TYPES.has(rt);
16816
16860
  function Form({ onCreateRequest }) {
16817
16861
  const { t } = useTranslation15();
16818
16862
  const { accessToken, refreshToken, email, organizationId, workspaceId, updateTokens, onError } = useAuth();
@@ -16956,7 +17000,7 @@ function Form({ onCreateRequest }) {
16956
17000
  setSelectedProductKey(null);
16957
17001
  }
16958
17002
  setNominationData({ nominee_email: "", nominee_mobile: "" });
16959
- if (requestType === "grievance" /* GRIEVANCE */ && grievanceOptions.length > 0) {
17003
+ if (isRequestType(requestType, "grievance" /* GRIEVANCE */) && grievanceOptions.length > 0) {
16960
17004
  const resetGrievances = grievanceOptions.reduce(
16961
17005
  (acc, option) => {
16962
17006
  acc[option.value] = false;
@@ -16985,12 +17029,10 @@ function Form({ onCreateRequest }) {
16985
17029
  () => groupPurposes.filter((p) => selectedPurposes.has(p.uuid)).map((p) => p.name).filter(Boolean),
16986
17030
  [groupPurposes, selectedPurposes]
16987
17031
  );
16988
- const selectedErasurePurposeNames = useMemo14(() => {
16989
- if (selectedErasurePurposeList.length === 0 || selectedErasurePurposeList.length > MAX_DISPLAYED_PURPOSE_NAMES_IN_ERASURE_MODAL) {
16990
- return t("revokeConsentModalYourPurposes");
16991
- }
16992
- return selectedErasurePurposeList.join(", ");
16993
- }, [selectedErasurePurposeList, t]);
17032
+ const selectedErasurePurposeNames = useMemo14(
17033
+ () => resolveErasurePurposeNames(selectedErasurePurposeList, t("revokeConsentModalYourPurposes")),
17034
+ [selectedErasurePurposeList, t]
17035
+ );
16994
17036
  const togglePurpose = useCallback10(
16995
17037
  (purpose) => {
16996
17038
  const uuid = purpose.uuid;
@@ -17097,7 +17139,7 @@ function Form({ onCreateRequest }) {
17097
17139
  if (isProductScopedRequestType(requestType)) {
17098
17140
  if (allGroups.length === 0) return false;
17099
17141
  if (!selectedGroup) return false;
17100
- if (requestType === "CORRECTION" /* CORRECTION */) {
17142
+ if (isRequestType(requestType, "CORRECTION" /* CORRECTION */)) {
17101
17143
  if (selectedCorrectionFields.size === 0) return false;
17102
17144
  return Array.from(selectedCorrectionFields).every((fieldUuid) => {
17103
17145
  var _a3, _b;
@@ -17105,15 +17147,15 @@ function Form({ onCreateRequest }) {
17105
17147
  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()));
17106
17148
  });
17107
17149
  }
17108
- if (requestType === "ACCESS" /* ACCESS */ || requestType === "erasure" /* ERASURE */) {
17150
+ if (isRequestType(requestType, "ACCESS" /* ACCESS */) || isErasureRequestType(requestType)) {
17109
17151
  return selectedPurposes.size > 0;
17110
17152
  }
17111
17153
  return false;
17112
17154
  }
17113
- if (requestType === "grievance" /* GRIEVANCE */) {
17155
+ if (isRequestType(requestType, "grievance" /* GRIEVANCE */)) {
17114
17156
  return Object.values(selectedGrievances).some(Boolean);
17115
17157
  }
17116
- if (requestType === "nomination" /* NOMINATION */) {
17158
+ if (isRequestType(requestType, "nomination" /* NOMINATION */)) {
17117
17159
  return Boolean(nominationData.nominee_email);
17118
17160
  }
17119
17161
  return false;
@@ -17127,7 +17169,10 @@ function Form({ onCreateRequest }) {
17127
17169
  selectedGrievances,
17128
17170
  nominationData
17129
17171
  ]);
17130
- const isFormValid = useMemo14(() => detailsValid && confirmChecked, [detailsValid, confirmChecked]);
17172
+ const isFormValid = useMemo14(
17173
+ () => Boolean(contact.trim()) && detailsValid && confirmChecked,
17174
+ [contact, detailsValid, confirmChecked]
17175
+ );
17131
17176
  const handleUpload = useCallback10(async () => {
17132
17177
  if (!organizationId || !workspaceId) return;
17133
17178
  const caseUuid = formDataResponse == null ? void 0 : formDataResponse.uuid;
@@ -17179,9 +17224,18 @@ function Form({ onCreateRequest }) {
17179
17224
  const removeUploadedDoc = useCallback10((uuid) => {
17180
17225
  setUploadedDocs((prev) => prev.filter((d) => d.uuid !== uuid));
17181
17226
  }, []);
17227
+ const alertSubmitFailed = useCallback10(
17228
+ (message) => {
17229
+ Alert5.alert(t("submit"), message || t("unableToSubmit") || "Unable to submit request. Please try again.");
17230
+ },
17231
+ [t]
17232
+ );
17182
17233
  const handleSubmit = useCallback10(async (revoke = false) => {
17183
- var _a3, _b, _c, _d;
17184
- if (!organizationId || !workspaceId || !contact || !requestType || !formDataResponse) return;
17234
+ var _a3;
17235
+ if (!organizationId || !workspaceId || !contact || !requestType || !formDataResponse) {
17236
+ alertSubmitFailed();
17237
+ return;
17238
+ }
17185
17239
  setRevokeConsentOnFulfilment(revoke);
17186
17240
  setIsSubmitting(true);
17187
17241
  try {
@@ -17208,27 +17262,27 @@ function Form({ onCreateRequest }) {
17208
17262
  purposes: updatePurposes,
17209
17263
  correction_data: correctionData,
17210
17264
  grievance_types: grievanceTypes,
17211
- ...requestType === "nomination" /* NOMINATION */ ? { nomination_data: nominationData } : {}
17265
+ ...isRequestType(requestType, "nomination" /* NOMINATION */) ? { nomination_data: nominationData } : {}
17212
17266
  },
17213
- time_period: requestType === "ACCESS" /* ACCESS */ ? parseInt(timePeriod || "30", 10) : 0,
17267
+ time_period: isRequestType(requestType, "ACCESS" /* ACCESS */) ? parseInt(timePeriod || "30", 10) : 0,
17214
17268
  requestor_note: additionalNote || "",
17215
- ...requestType === "erasure" /* ERASURE */ ? { revoke_consent_on_fulfilment: revoke } : {},
17269
+ ...erasureConsentPayload(requestType, revoke),
17216
17270
  ...anchorGroup ? { product_uuid: anchorGroup.product_uuid } : {},
17217
17271
  ...(anchorGroup == null ? void 0 : anchorGroup.nominator) ? { data_principal_uuid: anchorGroup.nominator.uuid } : {}
17218
17272
  };
17219
17273
  const response = await createCaseRequest(organizationId, workspaceId, request, false, false, authContext, consentClient);
17220
- const responseAny = response;
17221
- 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;
17274
+ const caseRef = extractCaseRef(response);
17275
+ const newCaseId = (caseRef == null ? void 0 : caseRef.case_id) || (caseRef == null ? void 0 : caseRef.uuid) || null;
17222
17276
  if (newCaseId) {
17223
17277
  setCaseId(newCaseId);
17224
- setSubmittedProductName((_d = anchorGroup == null ? void 0 : anchorGroup.product_name) != null ? _d : "");
17278
+ setSubmittedProductName((_a3 = anchorGroup == null ? void 0 : anchorGroup.product_name) != null ? _a3 : "");
17225
17279
  setIsSubmitted(true);
17226
17280
  } else {
17227
- Alert5.alert(t("submit"), t("unableToSubmit") || "Unable to submit request. Please try again.");
17281
+ alertSubmitFailed();
17228
17282
  }
17229
17283
  } catch (error) {
17230
17284
  console.warn("Error submitting request:", error);
17231
- Alert5.alert(t("submit"), (error == null ? void 0 : error.message) || t("unableToSubmit") || "Unable to submit request.");
17285
+ alertSubmitFailed(error == null ? void 0 : error.message);
17232
17286
  } finally {
17233
17287
  setIsSubmitting(false);
17234
17288
  }
@@ -17251,11 +17305,13 @@ function Form({ onCreateRequest }) {
17251
17305
  consentClient,
17252
17306
  groupDataElements,
17253
17307
  uploadedDocs,
17254
- t
17308
+ alertSubmitFailed
17255
17309
  ]);
17256
17310
  const handleSubmitClick = useCallback10(() => {
17257
- if (!isFormValid) return;
17258
- if (requestType === "erasure" /* ERASURE */) {
17311
+ if (!isFormValid) {
17312
+ return;
17313
+ }
17314
+ if (isErasureRequestType(requestType)) {
17259
17315
  setIsErasureConsentModalOpen(true);
17260
17316
  return;
17261
17317
  }
@@ -17344,7 +17400,7 @@ function Form({ onCreateRequest }) {
17344
17400
  if (groupPurposes.length === 0) {
17345
17401
  return /* @__PURE__ */ jsx43(Text25, { style: [styles33.placeholder, { color: colors.textSecondary }], children: t("noPurposesAvailable") || "No purposes available" });
17346
17402
  }
17347
- const isErasure = requestType === "erasure" /* ERASURE */;
17403
+ const isErasure = isErasureRequestType(requestType);
17348
17404
  const allPurposesSelected = groupPurposes.every(
17349
17405
  (p) => (p.data_elements || []).every((de) => {
17350
17406
  var _a3;
@@ -17464,18 +17520,18 @@ function Form({ onCreateRequest }) {
17464
17520
  ] }),
17465
17521
  selectedGroup ? /* @__PURE__ */ jsxs27(View32, { style: styles33.section, children: [
17466
17522
  /* @__PURE__ */ jsx43(Text25, { style: [styles33.sectionLabel, { color: colors.textSecondary }], children: t("requestDetails") }),
17467
- /* @__PURE__ */ jsx43(View32, { style: [styles33.sectionCard, elevation.card, { backgroundColor: colors.surface }], children: requestType === "CORRECTION" /* CORRECTION */ ? renderCorrectionFields() : renderPurposeFields() })
17523
+ /* @__PURE__ */ jsx43(View32, { style: [styles33.sectionCard, elevation.card, { backgroundColor: colors.surface }], children: isRequestType(requestType, "CORRECTION" /* CORRECTION */) ? renderCorrectionFields() : renderPurposeFields() })
17468
17524
  ] }) : /* @__PURE__ */ jsxs27(View32, { style: [styles33.hintCard, { backgroundColor: colors.surfaceAlt }], children: [
17469
17525
  /* @__PURE__ */ jsx43(Icon, { name: "circle-alert", size: 18, color: colors.textSecondary }),
17470
17526
  /* @__PURE__ */ jsx43(Text25, { style: [styles33.hintText, { color: colors.textSecondary }], children: t("selectProductFirst", { defaultValue: "Select a product to continue" }) })
17471
17527
  ] }),
17472
- requestType === "ACCESS" /* ACCESS */ && selectedGroup ? /* @__PURE__ */ jsxs27(View32, { style: styles33.section, children: [
17528
+ isRequestType(requestType, "ACCESS" /* ACCESS */) && selectedGroup ? /* @__PURE__ */ jsxs27(View32, { style: styles33.section, children: [
17473
17529
  /* @__PURE__ */ jsx43(Text25, { style: [styles33.sectionLabel, { color: colors.textSecondary }], children: t("timePeriod") }),
17474
17530
  /* @__PURE__ */ jsx43(PCSelect, { value: timePeriod, options: timePeriodOptions, onChange: setTimePeriod, placeholder: t("timePeriod") })
17475
17531
  ] }) : null
17476
17532
  ] });
17477
17533
  }
17478
- if (requestType === "grievance" /* GRIEVANCE */) {
17534
+ if (isRequestType(requestType, "grievance" /* GRIEVANCE */)) {
17479
17535
  if (grievanceOptions.length === 0) {
17480
17536
  return /* @__PURE__ */ jsx43(View32, { style: styles33.stepBody, children: /* @__PURE__ */ jsx43(Text25, { style: [styles33.placeholder, { color: colors.textSecondary }], children: t("noPurposesAvailable") || "No grievance types available" }) });
17481
17537
  }
@@ -17491,7 +17547,7 @@ function Form({ onCreateRequest }) {
17491
17547
  ] })
17492
17548
  ] }) });
17493
17549
  }
17494
- if (requestType === "nomination" /* NOMINATION */) {
17550
+ if (isRequestType(requestType, "nomination" /* NOMINATION */)) {
17495
17551
  return /* @__PURE__ */ jsx43(View32, { style: styles33.stepBody, children: /* @__PURE__ */ jsxs27(View32, { style: styles33.section, children: [
17496
17552
  /* @__PURE__ */ jsx43(Text25, { style: [styles33.sectionLabel, { color: colors.textSecondary }], children: t("enterNomineeDetails") }),
17497
17553
  /* @__PURE__ */ jsxs27(View32, { style: [styles33.sectionCard, elevation.card, { backgroundColor: colors.surface }], children: [
@@ -18473,6 +18529,22 @@ import { useMemo as useMemo18, useState as useState21 } from "react";
18473
18529
  import { StyleSheet as StyleSheet39, Text as Text29, TouchableOpacity as TouchableOpacity14, View as View37 } from "react-native";
18474
18530
  import { useTranslation as useTranslation18 } from "react-i18next";
18475
18531
 
18532
+ // src/RedactoPrivacyCenter/context/ProfileSwitchContext.tsx
18533
+ import { createContext as createContext7, useContext as useContext7 } from "react";
18534
+ import { jsx as jsx46 } from "react/jsx-runtime";
18535
+ var ProfileSwitchContext = createContext7({
18536
+ switchProfile: null
18537
+ });
18538
+ function ProfileSwitchProvider({
18539
+ switchProfile,
18540
+ children
18541
+ }) {
18542
+ return /* @__PURE__ */ jsx46(ProfileSwitchContext.Provider, { value: { switchProfile }, children });
18543
+ }
18544
+ function useProfileSwitch() {
18545
+ return useContext7(ProfileSwitchContext);
18546
+ }
18547
+
18476
18548
  // src/RedactoPrivacyCenter/lib/navigation.ts
18477
18549
  function navigateBack(onBack) {
18478
18550
  var _a3, _b;
@@ -18496,7 +18568,7 @@ function navigateBack(onBack) {
18496
18568
 
18497
18569
  // src/RedactoPrivacyCenter/components/NotificationHub/NotificationBell.tsx
18498
18570
  import { StyleSheet as StyleSheet37, Text as Text27, TouchableOpacity as TouchableOpacity12, View as View35 } from "react-native";
18499
- import { jsx as jsx46, jsxs as jsxs29 } from "react/jsx-runtime";
18571
+ import { jsx as jsx47, jsxs as jsxs29 } from "react/jsx-runtime";
18500
18572
  var NotificationBell = ({ count, onPress }) => {
18501
18573
  const { colors } = useTheme();
18502
18574
  const showBadge = count > 0;
@@ -18511,8 +18583,8 @@ var NotificationBell = ({ count, onPress }) => {
18511
18583
  accessibilityRole: "button",
18512
18584
  accessibilityLabel: showBadge ? `Notifications, ${count} unread` : "Notifications",
18513
18585
  children: [
18514
- /* @__PURE__ */ jsx46(Icon, { name: "bell", size: 22, color: colors.text }),
18515
- showBadge ? /* @__PURE__ */ jsx46(View35, { style: [styles36.badge, { backgroundColor: colors.error, borderColor: colors.canvasSubtle }], children: /* @__PURE__ */ jsx46(Text27, { style: styles36.badgeText, numberOfLines: 1, children: badgeLabel }) }) : null
18586
+ /* @__PURE__ */ jsx47(Icon, { name: "bell", size: 22, color: colors.text }),
18587
+ showBadge ? /* @__PURE__ */ jsx47(View35, { style: [styles36.badge, { backgroundColor: colors.error, borderColor: colors.canvasSubtle }], children: /* @__PURE__ */ jsx47(Text27, { style: styles36.badgeText, numberOfLines: 1, children: badgeLabel }) }) : null
18516
18588
  ]
18517
18589
  }
18518
18590
  );
@@ -18578,7 +18650,7 @@ function useUnreadCount() {
18578
18650
  import { useMemo as useMemo17, useState as useState20 } from "react";
18579
18651
  import { StyleSheet as StyleSheet38, Text as Text28, TouchableOpacity as TouchableOpacity13, View as View36 } from "react-native";
18580
18652
  import { useTranslation as useTranslation17 } from "react-i18next";
18581
- import { jsx as jsx47, jsxs as jsxs30 } from "react/jsx-runtime";
18653
+ import { jsx as jsx48, jsxs as jsxs30 } from "react/jsx-runtime";
18582
18654
  var NavDrawer = ({ visible, onClose, onBack }) => {
18583
18655
  const { t } = useTranslation17();
18584
18656
  const { colors, branding } = useTheme();
@@ -18600,15 +18672,15 @@ var NavDrawer = ({ visible, onClose, onBack }) => {
18600
18672
  i18n_default.changeLanguage(value);
18601
18673
  };
18602
18674
  const brandName = (branding == null ? void 0 : branding.brand_name) || organizationName || t("privacyCenter") || "Privacy Center";
18603
- return /* @__PURE__ */ jsx47(BottomSheet, { visible, onClose, title: t("menu") || "Menu", children: /* @__PURE__ */ jsxs30(View36, { style: styles37.body, children: [
18675
+ return /* @__PURE__ */ jsx48(BottomSheet, { visible, onClose, title: t("menu") || "Menu", children: /* @__PURE__ */ jsxs30(View36, { style: styles37.body, children: [
18604
18676
  /* @__PURE__ */ jsxs30(View36, { style: [styles37.identity, { backgroundColor: colors.surfaceAlt }], children: [
18605
- /* @__PURE__ */ jsx47(PCAvatar, { name: brandName, imageUrl: branding == null ? void 0 : branding.icon_url, size: 40 }),
18677
+ /* @__PURE__ */ jsx48(PCAvatar, { name: brandName, imageUrl: branding == null ? void 0 : branding.icon_url, size: 40 }),
18606
18678
  /* @__PURE__ */ jsxs30(View36, { style: styles37.identityText, children: [
18607
- /* @__PURE__ */ jsx47(Text28, { style: [styles37.brandName, { color: colors.text }], numberOfLines: 1, children: brandName }),
18608
- email ? /* @__PURE__ */ jsx47(Text28, { style: [styles37.email, { color: colors.textSecondary }], numberOfLines: 1, children: email }) : null
18679
+ /* @__PURE__ */ jsx48(Text28, { style: [styles37.brandName, { color: colors.text }], numberOfLines: 1, children: brandName }),
18680
+ email ? /* @__PURE__ */ jsx48(Text28, { style: [styles37.email, { color: colors.textSecondary }], numberOfLines: 1, children: email }) : null
18609
18681
  ] })
18610
18682
  ] }),
18611
- /* @__PURE__ */ jsx47(View36, { style: [styles37.menuGroup, { borderColor: colors.border, backgroundColor: colors.surface }], children: items.map((item, index) => {
18683
+ /* @__PURE__ */ jsx48(View36, { style: [styles37.menuGroup, { borderColor: colors.border, backgroundColor: colors.surface }], children: items.map((item, index) => {
18612
18684
  const isActive = currentPage === item.page;
18613
18685
  return /* @__PURE__ */ jsxs30(View36, { children: [
18614
18686
  /* @__PURE__ */ jsxs30(
@@ -18624,8 +18696,8 @@ var NavDrawer = ({ visible, onClose, onBack }) => {
18624
18696
  accessibilityState: { selected: isActive },
18625
18697
  accessibilityLabel: item.label,
18626
18698
  children: [
18627
- /* @__PURE__ */ jsx47(IconTile, { name: item.icon, tone: item.tone, size: "sm" }),
18628
- /* @__PURE__ */ jsx47(
18699
+ /* @__PURE__ */ jsx48(IconTile, { name: item.icon, tone: item.tone, size: "sm" }),
18700
+ /* @__PURE__ */ jsx48(
18629
18701
  Text28,
18630
18702
  {
18631
18703
  style: [styles37.menuLabel, { color: isActive ? colors.primary : colors.text }],
@@ -18633,14 +18705,14 @@ var NavDrawer = ({ visible, onClose, onBack }) => {
18633
18705
  children: item.label
18634
18706
  }
18635
18707
  ),
18636
- /* @__PURE__ */ jsx47(Icon, { name: "chevron-right", size: 18, color: colors.textSecondary })
18708
+ /* @__PURE__ */ jsx48(Icon, { name: "chevron-right", size: 18, color: colors.textSecondary })
18637
18709
  ]
18638
18710
  }
18639
18711
  ),
18640
- index < items.length - 1 ? /* @__PURE__ */ jsx47(View36, { style: [styles37.separator, { backgroundColor: colors.hairline }] }) : null
18712
+ index < items.length - 1 ? /* @__PURE__ */ jsx48(View36, { style: [styles37.separator, { backgroundColor: colors.hairline }] }) : null
18641
18713
  ] }, item.page);
18642
18714
  }) }),
18643
- /* @__PURE__ */ jsx47(
18715
+ /* @__PURE__ */ jsx48(
18644
18716
  PCSelect,
18645
18717
  {
18646
18718
  label: t("language"),
@@ -18661,7 +18733,7 @@ var NavDrawer = ({ visible, onClose, onBack }) => {
18661
18733
  activeOpacity: 0.7,
18662
18734
  accessibilityRole: "button",
18663
18735
  children: [
18664
- /* @__PURE__ */ jsx47(
18736
+ /* @__PURE__ */ jsx48(
18665
18737
  Icon,
18666
18738
  {
18667
18739
  name: onBack === "signout" ? "log-out" : "arrow-left",
@@ -18669,11 +18741,11 @@ var NavDrawer = ({ visible, onClose, onBack }) => {
18669
18741
  color: onBack === "signout" ? colors.error : colors.text
18670
18742
  }
18671
18743
  ),
18672
- /* @__PURE__ */ jsx47(Text28, { style: [styles37.actionLabel, { color: onBack === "signout" ? colors.error : colors.text }], children: onBack === "signout" ? t("signOut") || "Sign Out" : t("back") || "Back" })
18744
+ /* @__PURE__ */ jsx48(Text28, { style: [styles37.actionLabel, { color: onBack === "signout" ? colors.error : colors.text }], children: onBack === "signout" ? t("signOut") || "Sign Out" : t("back") || "Back" })
18673
18745
  ]
18674
18746
  }
18675
18747
  ) : null,
18676
- /* @__PURE__ */ jsx47(Footer, { inline: true })
18748
+ /* @__PURE__ */ jsx48(Footer, { inline: true })
18677
18749
  ] }) });
18678
18750
  };
18679
18751
  var styles37 = StyleSheet38.create({
@@ -18735,7 +18807,7 @@ var styles37 = StyleSheet38.create({
18735
18807
  });
18736
18808
 
18737
18809
  // src/RedactoPrivacyCenter/components/SlimTopBar.tsx
18738
- import { Fragment as Fragment11, jsx as jsx48, jsxs as jsxs31 } from "react/jsx-runtime";
18810
+ import { Fragment as Fragment11, jsx as jsx49, jsxs as jsxs31 } from "react/jsx-runtime";
18739
18811
  var SlimTopBar = ({ mode = "primary", onBack }) => {
18740
18812
  const { t } = useTranslation18();
18741
18813
  const { currentPage, navigateTo } = useInternalNavigation();
@@ -18744,6 +18816,7 @@ var SlimTopBar = ({ mode = "primary", onBack }) => {
18744
18816
  const unreadCount = useUnreadCount();
18745
18817
  const insets = useSafeInsets();
18746
18818
  const [menuOpen, setMenuOpen] = useState21(false);
18819
+ const { switchProfile } = useProfileSwitch();
18747
18820
  const pageChrome = PAGE_CHROME_BY_PAGE[currentPage];
18748
18821
  const isDetail = mode === "detail";
18749
18822
  const brandLabel = useMemo18(
@@ -18762,7 +18835,7 @@ var SlimTopBar = ({ mode = "primary", onBack }) => {
18762
18835
  navigateBack(onBack);
18763
18836
  };
18764
18837
  return /* @__PURE__ */ jsxs31(Fragment11, { children: [
18765
- /* @__PURE__ */ jsx48(
18838
+ /* @__PURE__ */ jsx49(
18766
18839
  View37,
18767
18840
  {
18768
18841
  style: [
@@ -18770,7 +18843,7 @@ var SlimTopBar = ({ mode = "primary", onBack }) => {
18770
18843
  { backgroundColor: colors.canvasSubtle, borderBottomColor: colors.hairline, paddingTop: insets.top + spacing.xs }
18771
18844
  ],
18772
18845
  children: isDetail ? /* @__PURE__ */ jsxs31(View37, { style: styles38.detailRow, children: [
18773
- /* @__PURE__ */ jsx48(
18846
+ /* @__PURE__ */ jsx49(
18774
18847
  TouchableOpacity14,
18775
18848
  {
18776
18849
  style: styles38.iconButton,
@@ -18779,27 +18852,39 @@ var SlimTopBar = ({ mode = "primary", onBack }) => {
18779
18852
  hitSlop: DEFAULT_HIT_SLOP,
18780
18853
  accessibilityRole: "button",
18781
18854
  accessibilityLabel: t("back") || "Back",
18782
- children: /* @__PURE__ */ jsx48(Icon, { name: "arrow-left", size: 22, color: colors.text })
18855
+ children: /* @__PURE__ */ jsx49(Icon, { name: "arrow-left", size: 22, color: colors.text })
18783
18856
  }
18784
18857
  ),
18785
- /* @__PURE__ */ jsx48(Text29, { style: [styles38.detailTitle, { color: colors.text }], numberOfLines: 1, children: t((pageChrome == null ? void 0 : pageChrome.titleKey) || "privacyCenter") }),
18786
- /* @__PURE__ */ jsx48(View37, { style: styles38.placeholder })
18858
+ /* @__PURE__ */ jsx49(Text29, { style: [styles38.detailTitle, { color: colors.text }], numberOfLines: 1, children: t((pageChrome == null ? void 0 : pageChrome.titleKey) || "privacyCenter") }),
18859
+ /* @__PURE__ */ jsx49(View37, { style: styles38.placeholder })
18787
18860
  ] }) : /* @__PURE__ */ jsxs31(View37, { style: styles38.row, children: [
18788
- /* @__PURE__ */ jsx48(View37, { style: styles38.brandWrap, children: (branding == null ? void 0 : branding.logo_url) ? /* @__PURE__ */ jsx48(
18861
+ /* @__PURE__ */ jsx49(View37, { style: styles38.brandWrap, children: (branding == null ? void 0 : branding.logo_url) ? /* @__PURE__ */ jsx49(
18789
18862
  BrandImage,
18790
18863
  {
18791
18864
  uri: branding.logo_url,
18792
18865
  height: 24,
18793
18866
  maxWidth: 124,
18794
- fallback: /* @__PURE__ */ jsx48(PCAvatar, { name: brandLabel, imageUrl: branding == null ? void 0 : branding.icon_url, size: 24 })
18867
+ fallback: /* @__PURE__ */ jsx49(PCAvatar, { name: brandLabel, imageUrl: branding == null ? void 0 : branding.icon_url, size: 24 })
18795
18868
  }
18796
18869
  ) : /* @__PURE__ */ jsxs31(View37, { style: styles38.brandLockup, children: [
18797
- /* @__PURE__ */ jsx48(PCAvatar, { name: brandLabel, imageUrl: branding == null ? void 0 : branding.icon_url, size: 24 }),
18798
- /* @__PURE__ */ jsx48(Text29, { style: [styles38.brandText, { color: colors.text }], numberOfLines: 1, children: brandLabel })
18870
+ /* @__PURE__ */ jsx49(PCAvatar, { name: brandLabel, imageUrl: branding == null ? void 0 : branding.icon_url, size: 24 }),
18871
+ /* @__PURE__ */ jsx49(Text29, { style: [styles38.brandText, { color: colors.text }], numberOfLines: 1, children: brandLabel })
18799
18872
  ] }) }),
18800
18873
  /* @__PURE__ */ jsxs31(View37, { style: styles38.actions, children: [
18801
- /* @__PURE__ */ jsx48(NotificationBell, { count: unreadCount, onPress: () => navigateTo("notifications") }),
18802
- /* @__PURE__ */ jsx48(
18874
+ switchProfile ? /* @__PURE__ */ jsx49(
18875
+ TouchableOpacity14,
18876
+ {
18877
+ style: styles38.iconButton,
18878
+ onPress: switchProfile,
18879
+ activeOpacity: 0.7,
18880
+ hitSlop: DEFAULT_HIT_SLOP,
18881
+ accessibilityRole: "button",
18882
+ accessibilityLabel: t("switchProfile"),
18883
+ children: /* @__PURE__ */ jsx49(Icon, { name: "users", size: 22, color: colors.text })
18884
+ }
18885
+ ) : null,
18886
+ /* @__PURE__ */ jsx49(NotificationBell, { count: unreadCount, onPress: () => navigateTo("notifications") }),
18887
+ /* @__PURE__ */ jsx49(
18803
18888
  TouchableOpacity14,
18804
18889
  {
18805
18890
  style: styles38.iconButton,
@@ -18808,14 +18893,14 @@ var SlimTopBar = ({ mode = "primary", onBack }) => {
18808
18893
  hitSlop: DEFAULT_HIT_SLOP,
18809
18894
  accessibilityRole: "button",
18810
18895
  accessibilityLabel: t("menu") || "Menu",
18811
- children: /* @__PURE__ */ jsx48(Icon, { name: "menu", size: 22, color: colors.text })
18896
+ children: /* @__PURE__ */ jsx49(Icon, { name: "menu", size: 22, color: colors.text })
18812
18897
  }
18813
18898
  )
18814
18899
  ] })
18815
18900
  ] })
18816
18901
  }
18817
18902
  ),
18818
- /* @__PURE__ */ jsx48(NavDrawer, { visible: menuOpen, onClose: () => setMenuOpen(false), onBack })
18903
+ /* @__PURE__ */ jsx49(NavDrawer, { visible: menuOpen, onClose: () => setMenuOpen(false), onBack })
18819
18904
  ] });
18820
18905
  };
18821
18906
  var styles38 = StyleSheet39.create({
@@ -18876,18 +18961,18 @@ var styles38 = StyleSheet39.create({
18876
18961
 
18877
18962
  // src/RedactoPrivacyCenter/components/PrivacyCenterEmptyState.tsx
18878
18963
  import { useTranslation as useTranslation19 } from "react-i18next";
18879
- import { jsx as jsx49 } from "react/jsx-runtime";
18964
+ import { jsx as jsx50 } from "react/jsx-runtime";
18880
18965
  function PrivacyCenterEmptyState() {
18881
18966
  const { t } = useTranslation19();
18882
- return /* @__PURE__ */ jsx49(PCEmpty, { iconName: "shield", title: t("noDataTitle"), description: t("noDataDescription") });
18967
+ return /* @__PURE__ */ jsx50(PCEmpty, { iconName: "shield", title: t("noDataTitle"), description: t("noDataDescription") });
18883
18968
  }
18884
18969
 
18885
18970
  // src/RedactoPrivacyCenter/components/PrivacyCenterSessionExpired.tsx
18886
18971
  import { useTranslation as useTranslation20 } from "react-i18next";
18887
- import { jsx as jsx50 } from "react/jsx-runtime";
18972
+ import { jsx as jsx51 } from "react/jsx-runtime";
18888
18973
  function PrivacyCenterSessionExpired() {
18889
18974
  const { t } = useTranslation20();
18890
- return /* @__PURE__ */ jsx50(
18975
+ return /* @__PURE__ */ jsx51(
18891
18976
  PCEmpty,
18892
18977
  {
18893
18978
  iconName: "shield",
@@ -18901,22 +18986,6 @@ function PrivacyCenterSessionExpired() {
18901
18986
  import { useCallback as useCallback11, useEffect as useEffect16, useState as useState22 } from "react";
18902
18987
  import { StyleSheet as StyleSheet41, View as View39 } from "react-native";
18903
18988
 
18904
- // src/RedactoPrivacyCenter/context/ProfileSwitchContext.tsx
18905
- import { createContext as createContext7, useContext as useContext7 } from "react";
18906
- import { jsx as jsx51 } from "react/jsx-runtime";
18907
- var ProfileSwitchContext = createContext7({
18908
- switchProfile: null
18909
- });
18910
- function ProfileSwitchProvider({
18911
- switchProfile,
18912
- children
18913
- }) {
18914
- return /* @__PURE__ */ jsx51(ProfileSwitchContext.Provider, { value: { switchProfile }, children });
18915
- }
18916
- function useProfileSwitch() {
18917
- return useContext7(ProfileSwitchContext);
18918
- }
18919
-
18920
18989
  // src/RedactoPrivacyCenter/components/SelectUser.tsx
18921
18990
  import { ScrollView as ScrollView8, StyleSheet as StyleSheet40, Text as Text30, TouchableOpacity as TouchableOpacity15, View as View38 } from "react-native";
18922
18991
  import { useTranslation as useTranslation21 } from "react-i18next";
@@ -21692,6 +21761,7 @@ function Navbar({ mode = "primary", onBack }) {
21692
21761
  const [menuOpen, setMenuOpen] = useState26(false);
21693
21762
  const unreadCount = useUnreadCount();
21694
21763
  const { status: pageStatus } = usePageStatus();
21764
+ const { switchProfile } = useProfileSwitch();
21695
21765
  const pageChrome = PAGE_CHROME_BY_PAGE[currentPage] || PAGE_CHROME_BY_PAGE["consent-manager"];
21696
21766
  const isDetail = mode === "detail";
21697
21767
  useEffect22(() => {
@@ -21794,6 +21864,36 @@ function Navbar({ mode = "primary", onBack }) {
21794
21864
  ) : null,
21795
21865
  /* @__PURE__ */ jsx71(View55, { style: styles57.brandWrap, children: (branding == null ? void 0 : branding.logo_url) ? /* @__PURE__ */ jsx71(BrandImage, { uri: branding.logo_url, height: 34, maxWidth: 170, fallback: brandLockup }) : brandLockup }),
21796
21866
  /* @__PURE__ */ jsxs48(View55, { style: styles57.actions, children: [
21867
+ switchProfile ? /* @__PURE__ */ jsx71(
21868
+ TouchableOpacity25,
21869
+ {
21870
+ style: styles57.iconButton,
21871
+ onPress: switchProfile,
21872
+ activeOpacity: 0.7,
21873
+ hitSlop: DEFAULT_HIT_SLOP,
21874
+ accessibilityRole: "button",
21875
+ accessibilityLabel: t("switchProfile"),
21876
+ children: /* @__PURE__ */ jsx71(
21877
+ View55,
21878
+ {
21879
+ style: [
21880
+ styles57.iconCircle,
21881
+ { backgroundColor: colors.surface, borderColor: colors.border }
21882
+ ],
21883
+ children: /* @__PURE__ */ jsx71(Svg4, { width: 18, height: 18, viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsx71(
21884
+ Path4,
21885
+ {
21886
+ d: "M16 3h5v5 M21 3l-7 7 M8 21H3v-5 M3 21l7-7",
21887
+ stroke: colors.text,
21888
+ strokeWidth: 2,
21889
+ strokeLinecap: "round",
21890
+ strokeLinejoin: "round"
21891
+ }
21892
+ ) })
21893
+ }
21894
+ )
21895
+ }
21896
+ ) : null,
21797
21897
  /* @__PURE__ */ jsx71(NotificationBell, { count: unreadCount, onPress: () => navigateTo("notifications") }),
21798
21898
  /* @__PURE__ */ jsx71(PCSelect, { value: locale, options: languageOptions, onChange: handleLanguageChange, placeholder: t("language"), compact: true }),
21799
21899
  /* @__PURE__ */ jsx71(
@@ -21870,6 +21970,21 @@ var styles57 = StyleSheet58.create({
21870
21970
  alignItems: "center",
21871
21971
  justifyContent: "center"
21872
21972
  },
21973
+ iconButton: {
21974
+ width: MIN_TAP_TARGET,
21975
+ height: MIN_TAP_TARGET,
21976
+ alignItems: "center",
21977
+ justifyContent: "center"
21978
+ },
21979
+ // Matches the Flutter navbar's 34pt bordered circle.
21980
+ iconCircle: {
21981
+ width: 34,
21982
+ height: 34,
21983
+ borderRadius: 17,
21984
+ borderWidth: 1,
21985
+ alignItems: "center",
21986
+ justifyContent: "center"
21987
+ },
21873
21988
  pageHeader: {
21874
21989
  marginTop: spacing.sm
21875
21990
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redacto.io/consent-sdk-react-native",
3
- "version": "5.0.0-beta.9",
3
+ "version": "5.0.0",
4
4
  "description": "React Native SDK for integrating Redacto consent notices and privacy center in mobile apps.",
5
5
  "keywords": [
6
6
  "consent",