@redacto.io/consent-sdk-react-native 2.0.0 → 2.1.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.
Files changed (2) hide show
  1. package/README.md +187 -44
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,18 +1,95 @@
1
1
  # @redacto.io/consent-sdk-react-native
2
2
 
3
- React Native SDK for Redacto consent management. Port of [`@redacto.io/consent-sdk-react`](../consent-sdk-react) with the same API surface.
3
+ React Native SDK for Redacto's Consent Management Platform. Provides consent notice components and a full Privacy Center for end-user consent / DSR management on iOS and Android.
4
+
5
+ ## Entry Points
6
+
7
+ | Import path | What you get |
8
+ | -------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
9
+ | `@redacto.io/consent-sdk-react-native` | Consent notice components: `RedactoNoticeConsent`, `RedactoNoticeConsentInline` |
10
+ | `@redacto.io/consent-sdk-react-native/privacy-center` | Privacy Center: certified `RedactoPrivacyCenter`, composable components, UI primitives, headless API client and hooks |
11
+
12
+ The notice entry point depends only on `react-native-svg`. The Privacy Center entry point depends on the optional peers listed below.
4
13
 
5
14
  ## Installation
6
15
 
7
16
  ```sh
8
17
  pnpm add @redacto.io/consent-sdk-react-native react-native-svg
9
- # Optional – required for TTS audio playback
10
- pnpm add expo-av
11
18
  ```
12
19
 
13
20
  > **Note:** `react-native-svg` must be linked for native builds. Follow the [react-native-svg setup guide](https://github.com/software-mansion/react-native-svg#installation).
14
21
 
15
- ## Components
22
+ ### Peer Dependencies
23
+
24
+ | Peer | Required for | Notes |
25
+ | -------------------------- | --------------------------- | ------------------------------------------------------ |
26
+ | `react` | All | `^18 \|\| ^19` |
27
+ | `react-native` | All | `>=0.72` |
28
+ | `react-native-svg` | All | `>=13` |
29
+ | `expo-audio` | Notice TTS playback | Optional. Required to enable text-to-speech audio |
30
+ | `@tanstack/react-query` | Privacy Center | Optional. Required for `/privacy-center` imports |
31
+ | `i18next`, `react-i18next` | Privacy Center | Optional. Required for `/privacy-center` imports |
32
+ | `dayjs` | Privacy Center | Optional. Required for `/privacy-center` imports |
33
+
34
+ If you only use the consent notice components, install just the SDK + `react-native-svg`. If you use the Privacy Center, install the optional peers as well:
35
+
36
+ ```sh
37
+ pnpm add @tanstack/react-query i18next react-i18next dayjs
38
+ ```
39
+
40
+ To enable TTS audio in the consent notice, install `expo-audio`:
41
+
42
+ ```sh
43
+ pnpm add expo-audio
44
+ ```
45
+
46
+ ## Backend Server Setup
47
+
48
+ The SDK never talks to Redacto with your CMS API key directly — your backend acts as a token broker. Obtain your **CMS-API-Key** from the Redacto Dashboard, store it in your backend's environment, and expose two endpoints to your mobile app:
49
+
50
+ 1. **Generate access token** — `POST /public/organisations/{org_uuid}/workspaces/{workspace_uuid}/tokens/generate-access-token`
51
+ 2. **Refresh access token** — `POST /consent/public/organisations/{org_uuid}/workspaces/{workspace_uuid}/tokens/refresh-token`
52
+
53
+ Both endpoints expect the `X-CMS-API-Key` header. Example (Express):
54
+
55
+ ```ts
56
+ import express from "express";
57
+ import axios from "axios";
58
+
59
+ const app = express();
60
+ app.use(express.json());
61
+
62
+ const CMS_API_KEY = process.env.CMS_API_KEY;
63
+
64
+ app.post("/api/consent/token", async (req, res) => {
65
+ const { email } = req.body;
66
+ const { organisation_uuid, workspace_uuid, base_url } = req.query;
67
+
68
+ const response = await axios.post(
69
+ `${base_url}/public/organisations/${organisation_uuid}/workspaces/${workspace_uuid}/tokens/generate-access-token`,
70
+ { email },
71
+ { headers: { "X-CMS-API-Key": CMS_API_KEY } }
72
+ );
73
+
74
+ res.json(response.data.detail); // { token, refresh_token, expires_at }
75
+ });
76
+
77
+ app.post("/api/consent/refresh-token", async (req, res) => {
78
+ const { refresh_token, organisation_uuid, workspace_uuid, base_url } = req.body;
79
+
80
+ const response = await axios.post(
81
+ `${base_url}/consent/public/organisations/${organisation_uuid}/workspaces/${workspace_uuid}/tokens/refresh-token`,
82
+ { refresh_token },
83
+ { headers: { "X-CMS-API-Key": CMS_API_KEY } }
84
+ );
85
+
86
+ res.json(response.data.detail);
87
+ });
88
+ ```
89
+
90
+ Never bundle `CMS_API_KEY` into the mobile app. In Expo apps, only non-sensitive values (UUIDs, URLs) belong in `EXPO_PUBLIC_*`.
91
+
92
+ ## Consent Notice Components
16
93
 
17
94
  ### `RedactoNoticeConsent`
18
95
 
@@ -27,29 +104,27 @@ import { RedactoNoticeConsent } from "@redacto.io/consent-sdk-react-native";
27
104
  refreshToken={refreshToken}
28
105
  onAccept={() => navigation.navigate("Dashboard")}
29
106
  onDecline={() => console.log("declined")}
30
- />
107
+ />;
31
108
  ```
32
109
 
33
110
  #### Props
34
111
 
35
- | Prop | Type | Required | Description |
36
- |------|------|----------|-------------|
37
- | `noticeId` | `string` | ✓ | UUID of the consent notice |
38
- | `accessToken` | `string` | ✓ | JWT access token |
39
- | `refreshToken` | `string` | ✓ | JWT refresh token |
40
- | `baseUrl` | `string` | | Override API base URL |
41
- | `settings` | `Partial<Settings>` | | UI customisation (colours, border radius, fonts) |
42
- | `language` | `string` | | Initial language code (e.g. `"en"`) |
43
- | `blockUI` | `boolean` | | Block the modal from being dismissed |
44
- | `applicationId` | `string` | | Application-specific UUID |
45
- | `validateAgainst` | `"all" \| "required"` | | Validation mode |
46
- | `includeFullyConsentedData` | `boolean` | | Include already-consented items |
47
- | `reviewModeButtonText` | `string` | | CTA text in review mode |
48
- | `onAccept` | `() => void` | ✓ | Called on successful consent |
49
- | `onDecline` | `() => void` | ✓ | Called when user declines |
50
- | `onError` | `(error: Error) => void` | | Called on API errors |
51
-
52
- ---
112
+ | Prop | Type | Required | Description |
113
+ | --------------------------- | ----------------------------- | -------- | -------------------------------------------------------- |
114
+ | `noticeId` | `string` | ✓ | UUID of the consent notice |
115
+ | `accessToken` | `string` | ✓ | JWT access token |
116
+ | `refreshToken` | `string` | ✓ | JWT refresh token |
117
+ | `baseUrl` | `string` | | Override API base URL |
118
+ | `settings` | `Partial<Settings>` | | UI customisation (colours, border radius, fonts) |
119
+ | `language` | `string` | | Initial language code (e.g. `"en"`) |
120
+ | `blockUI` | `boolean` | | Block the modal from being dismissed |
121
+ | `applicationId` | `string` | | Application-specific UUID |
122
+ | `validateAgainst` | `"all" \| "required"` | | Validation mode |
123
+ | `includeFullyConsentedData` | `boolean` | | Include already-consented items (review mode) |
124
+ | `reviewModeButtonText` | `string` | | CTA text in review mode |
125
+ | `onAccept` | `() => void` | ✓ | Called on successful consent |
126
+ | `onDecline` | `() => void` | ✓ | Called when user declines |
127
+ | `onError` | `(error: Error) => void` | | Called on API errors |
53
128
 
54
129
  ### `RedactoNoticeConsentInline`
55
130
 
@@ -65,41 +140,109 @@ import { RedactoNoticeConsentInline } from "@redacto.io/consent-sdk-react-native
65
140
  accessToken={accessToken}
66
141
  onAccept={() => console.log("accepted")}
67
142
  onValidationChange={(isValid) => setCanProceed(isValid)}
68
- />
143
+ />;
69
144
  ```
70
145
 
71
146
  #### Props
72
147
 
73
- | Prop | Type | Required | Description |
74
- |------|------|----------|-------------|
75
- | `org_uuid` | `string` | ✓ | Organisation UUID |
76
- | `workspace_uuid` | `string` | ✓ | Workspace UUID |
77
- | `notice_uuid` | `string` | ✓ | Notice UUID |
78
- | `accessToken` | `string` | | JWT access token (triggers auto-submit when set) |
79
- | `baseUrl` | `string` | | Override API base URL |
80
- | `language` | `string` | | Language code |
81
- | `settings` | `Partial<Settings>` | | UI customisation |
82
- | `applicationId` | `string` | | Application-specific UUID |
83
- | `onAccept` | `() => void` | | Called on successful consent |
84
- | `onDecline` | `() => void` | | Called when user declines |
85
- | `onError` | `(error: Error) => void` | | Called on errors |
86
- | `onValidationChange` | `(isValid: boolean) => void` | | Fires when validation state changes |
148
+ | Prop | Type | Required | Description |
149
+ | -------------------- | ---------------------------- | -------- | ------------------------------------------------- |
150
+ | `org_uuid` | `string` | ✓ | Organisation UUID |
151
+ | `workspace_uuid` | `string` | ✓ | Workspace UUID |
152
+ | `notice_uuid` | `string` | ✓ | Notice UUID |
153
+ | `accessToken` | `string` | | JWT access token (triggers auto-submit when set) |
154
+ | `baseUrl` | `string` | | Override API base URL |
155
+ | `language` | `string` | | Language code |
156
+ | `settings` | `Partial<Settings>` | | UI customisation |
157
+ | `applicationId` | `string` | | Application-specific UUID |
158
+ | `onAccept` | `() => void` | | Called on successful consent |
159
+ | `onDecline` | `() => void` | | Called when user declines |
160
+ | `onError` | `(error: Error) => void` | | Called on errors |
161
+ | `onValidationChange` | `(isValid: boolean) => void` | | Fires when validation state changes |
87
162
 
88
163
  ## TTS Audio
89
164
 
90
- If `expo-av` is installed, TTS playback is automatically enabled. Install it and configure audio mode in your app entry point:
165
+ If `expo-audio` is installed, the consent notice will dynamically load it and enable text-to-speech playback. The SDK calls `setAudioModeAsync` and creates an audio player internally — you don't need to set anything up beyond installing the package. See the [expo-audio docs](https://docs.expo.dev/versions/latest/sdk/audio/) if you need to customise audio session behaviour app-wide.
91
166
 
92
- ```ts
93
- import { Audio } from "expo-av";
94
- await Audio.setAudioModeAsync({ playsInSilentModeIOS: true });
167
+ If `expo-audio` is not installed, the notice still renders and functions; only the TTS button is disabled.
168
+
169
+ ## Privacy Center
170
+
171
+ The Privacy Center is a separate entry point (`@redacto.io/consent-sdk-react-native/privacy-center`) for letting end-users review and manage the consent they've given, see request activity, and file Data Subject Rights (DSR) cases — including in-app messaging on existing cases. It ships as a certified screen, composable components, UI primitives, and a headless core.
172
+
173
+ ### Certified UI
174
+
175
+ `RedactoPrivacyCenter` renders the full Privacy Center experience with built-in navigation, auth, theming, and i18n.
176
+
177
+ ```tsx
178
+ import { RedactoPrivacyCenter } from "@redacto.io/consent-sdk-react-native/privacy-center";
179
+
180
+ <RedactoPrivacyCenter
181
+ baseUrl={BASE_URL}
182
+ slug="acme-co"
183
+ accessToken={accessToken}
184
+ refreshToken={refreshToken}
185
+ theme="light"
186
+ initialPage="consent-manager"
187
+ onError={(error) => {
188
+ console.error(error);
189
+ return false;
190
+ }}
191
+ />;
95
192
  ```
96
193
 
97
- ## Configuration and env best practices
194
+ #### Props
195
+
196
+ | Prop | Type | Required | Default | Description |
197
+ | -------------- | ----------------------------------------------------------------------------- | -------- | -------------------- | ---------------------------------------- |
198
+ | `baseUrl` | `string` | ✓ | - | Consent server base URL |
199
+ | `slug` | `string` | ✓ | - | Workspace slug |
200
+ | `accessToken` | `string` | ✓ | - | JWT access token |
201
+ | `refreshToken` | `string` | ✓ | - | JWT refresh token |
202
+ | `onError` | `(error: Error) => boolean` | ✓ | - | Error handler; return `true` if handled |
203
+ | `theme` | `"light" \| "dark"` | | `"light"` | Theme variant |
204
+ | `initialPage` | `"consent-manager" \| "form" \| "activity" \| "case-details"` | | `"consent-manager"` | Page to render first |
205
+ | `onBack` | `"back" \| "signout"` | | - | Navbar back / signout control behaviour |
206
+
207
+ ### Composable Components
208
+
209
+ If you want to compose your own shell, import the screen-level building blocks instead of the certified component:
210
+
211
+ | Export | Purpose |
212
+ | ------------------ | ------------------------------------------------------ |
213
+ | `ConsentManager` | "Manage Consents" view |
214
+ | `Form`, `FormPage` | DSR / grievance form (component + full page wrapper) |
215
+ | `ActivitiesList` | List of past requests |
216
+ | `CaseHistory` | Per-product / per-purpose case history group |
217
+ | `CaseDetailsPage` | Case detail with messaging and document upload |
218
+ | `Navbar` | Top navigation bar |
219
+ | `SideMenu` | Drawer / side menu |
220
+ | `BottomTabBar` | Bottom tab navigation |
221
+ | `Footer` | Footer block |
222
+
223
+ These rely on the context providers (`AuthProvider`, `BaseUrlProvider`, `NavigationProvider`, `ThemeProvider`) — wrap them yourself if you compose the pages directly.
224
+
225
+ ### UI Primitives
226
+
227
+ For building custom screens that match Privacy Center styling, the package exports themed primitives: `PCButton`, `PCInput`, `PCSelect`, `PCModal`, `PCCheckbox`, `PCLoader`, `PCEmpty`, `PCBadge`.
228
+
229
+ ### Headless Core
230
+
231
+ For consumers who want fully custom UI, the headless core exposes the API client, orchestration helpers, hooks, and auth utilities:
232
+
233
+ - **API client**: `createConsentClient`
234
+ - **Orchestration helpers** (handle auth retry / token refresh internally): `getFormData`, `createCaseRequest`, `fetchProducts`, `fetchUserConsents`, `manageConsent`, `fetchActivities`, `fetchCaseHistory`, `getCaseMessages`, `sendCaseMessage`, `uploadCaseDocument`, `submitDocumentForRequest`, `createOtp`, `verifyOtp`, `exchangeToken`
235
+ - **Auth utilities**: `decodeJwtToken`, `isJwtExpired`, `ensureValidToken`, `signOutPrivacyCenter`, `compareEmails`, `getActivityTypeStatus`, `formatActivityType`
236
+ - **React Query hooks**: `useCaseHistory`, `useCaseMessages`
237
+ - **Context providers**: `AuthProvider` + `useAuth`, `BaseUrlProvider` + `useBaseUrl`, `NavigationProvider` + `useInternalNavigation`, `ThemeProvider` + `useTheme`
238
+ - **Types**: `Workspace`, `OrganizationDetail`, `DataElement`, `Purpose`, `UserConsent`, `Activity`, `CaseHistoryDetail`, `CaseMessage`, `MessageDocument`, `RequestTypeEnum`, `GrievanceTypeEnum`, `ConsentStatusEnum`, and more (see `privacy-center.ts` for the full export list)
239
+
240
+ ## Configuration and Env Best Practices
98
241
 
99
242
  - The SDK is runtime-configured via props and does not read from `.env` directly.
100
243
  - Keep API keys and server secrets on your backend only.
101
244
  - In Expo apps, values read from `EXPO_PUBLIC_*` are bundled into the app and should only contain non-sensitive config like UUIDs and URLs.
102
- - If you do not pass `baseUrl`, the SDK defaults to `https://api.redacto.io/consent` for both modal and inline components.
245
+ - If you do not pass `baseUrl`, the SDK defaults to `https://api.redacto.io/consent` for both notice and Privacy Center surfaces.
103
246
 
104
247
  ## License
105
248
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redacto.io/consent-sdk-react-native",
3
- "version": "2.0.0",
3
+ "version": "2.1.0",
4
4
  "description": "React Native SDK for integrating Redacto consent notices and privacy center in mobile apps.",
5
5
  "keywords": [
6
6
  "consent",