securiti-consent-sdk 1.132.1 → 1.132.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Description
1
+ # React Native Consent SDK Documentation
2
2
 
3
3
  A React Native Library for managing user consent preferences and compliance with privacy regulations. Integrates with Securiti's Consent Management Platform.
4
4
 
@@ -7,39 +7,1408 @@ A React Native Library for managing user consent preferences and compliance with
7
7
  - Android API 24+
8
8
  - React Native 0.73.0+
9
9
 
10
- ## Structure
11
- - [`android/`](android): All your `android`-specific implementations.
12
- - [`build.gradle`](android/build.gradle): The gradle build file. This contains four important pieces:
13
- 1. Standard react-native library boilerplate code
14
- 2. Configures Kotlin (`apply plugin: 'org.jetbrains.kotlin.android'`)
15
- 3. Adds all Nitrogen files (`apply from: '.../NitroSecuritiConsentSdk+autolinking.gradle'`)
16
- 4. Triggers the native C++ build (via CMake/`externalNativeBuild`)
17
- 5. Make sure you add this repositories block above the 'dependencies' block in your application's [`build.gradle`](android/build.gradle) file:
10
+
11
+ ## Table of Contents
12
+
13
+ 1. [Important](#important)
14
+ 2. [Step 1: Installation Steps](#step-1-installation-steps)
15
+ 3. [Step 2: Android Installation Steps](#step-2-android-installation-steps)
16
+ 4. [iOS Installation Steps](#ios-installation-steps)
17
+ 5. [Methods](#methods)
18
+ - [initialize(options)](#initializeoptions)
19
+ - [getConsentByPurposeId(purposeId)](#getconsentbypurposeidpurposeid)
20
+ - [getConsentByPermissionId(permissionId)](#getconsentbypermissionidpermissionid)
21
+ - [getPermissions()](#getpermissions)
22
+ - [getPurposes()](#getpurposes)
23
+ - [getSdksInPurpose(purposeId)](#getsdksinpurposepurposeid)
24
+ - [setPurposeConsent(purpose, consent)](#setpurposeconsentpurpose-consent)
25
+ - [setPermissionConsent(appPermission, consent)](#setpermissionconsentapppermission-consent)
26
+ - [resetConsents()](#resetconsents)
27
+ - [isReady(callback)](#isreadycallback)
28
+ - [getBannerConfig()](#getbannerconfig)
29
+ - [options()](#options)
30
+ - [getSettingsPrompt()](#getsettingsprompt)
31
+ - [uploadConsents(request)](#uploadconsentsrequest)
32
+ - [presentConsentBanner()](#presentconsentbanner)
33
+ - [presentPreferenceCenter()](#presentpreferencecenter)
34
+ 6. [Types and Properties](#types-and-properties)
35
+ 7. [Using Methods](#using-methods)
36
+
37
+ ---
38
+
39
+ ## Important
40
+
41
+ This document contains information related to the React Native Consent SDK by Securiti, including installation, configuration, and usage of all available methods. The SDK name and API are subject to change.
42
+
43
+ ---
44
+
45
+ ## Step 1: Installation Steps
46
+
47
+ 1. Add the SDK to your `package.json`:
48
+ ```sh
49
+ npm i react-native-nitro-modules
50
+ npm i securiti-consent-sdk@latest
51
+ ```
52
+ 2. Run:
53
+ ```sh
54
+ npm install
55
+ ```
56
+ 3. Ensure `node_modules/securiti-consent-sdk` exists.
57
+
58
+ ---
59
+
60
+ ## Step 2: Android Installation Steps
61
+
62
+ 1. In your app's `android/app/build.gradle`, add the following above the `dependencies` block:
18
63
  ```gradle
19
64
  repositories {
20
- mavenCentral()
21
- google()
22
- maven {
23
- url = uri("https://cdn-qa.securiti.xyz/consent/maven")
24
- }
65
+ google()
66
+ mavenCentral()
67
+ maven {
68
+ url 'https://cdn-prod.securiti.ai/consent/maven'
69
+ }
25
70
  }
26
71
  ```
27
72
 
28
- - [`CMakeLists.txt`](android/CMakeLists.txt): The CMake build file to build C++ code. This contains four important pieces:
29
- 1. Creates a library called `NitroSecuritiConsentSdk` (same as in `nitro.json`)
30
- 2. Adds all Nitrogen files (`include(.../NitroSecuritiConsentSdk+autolinking.cmake)`)
31
- 3. Adds all custom C++ files (only `HybridTestObjectCpp.cpp`)
32
- 4. Adds a `cpp-adapter.cpp` file, which autolinks all C++ HybridObjects (only `HybridTestObjectCpp`)
33
- - [`src/main/java/com/margelo/nitro/securiticonsentsdk/`](android/src/main/java/com/margelo/nitro/securiticonsentsdk/): All Kotlin implementations.
34
- - [`NitroSecuritiConsentSdkPackage.java`](android/src/main/java/com/margelo/nitro/securiticonsentsdk/NitroSecuritiConsentSdkPackage.java): The react-native package. You need this because the react-native CLI only adds libraries if they have a `*Package.java` file. In here, you can autolink all Kotlin HybridObjects.
35
- - [`cpp/`](cpp): All your cross-platform implementations. (only `HybridTestObjectCpp.cpp`)
36
- - [`ios/`](ios): All your iOS-specific implementations.
37
- - [`nitrogen/`](nitrogen): All files generated by nitrogen. You should commit this folder to git.
38
- - [`src/`](src): The TypeScript codebase. This defines all HybridObjects and loads them at runtime.
39
- - [`specs/`](src/specs): All HybridObject types. Nitrogen will run on all `*.nitro.ts` files.
40
- - [`nitro.json`](nitro.json): The configuration file for nitrogen. This will define all native namespaces, as well as the library name.
41
- - [`NitroSecuritiConsentSdk.podspec`](NitroSecuritiConsentSdk.podspec): The iOS podspec build file to build the iOS code. This contains three important pieces:
42
- 1. Specifies the Pod's name. This must be identical to the name specified in `nitro.json`.
43
- 2. Adds all of your `.swift` or `.cpp` files (implementations).
44
- 3. Adds all Nitrogen files (`add_nitrogen_files(s)`)
45
- - [`package.json`](package.json): The npm package.json file. `react-native-nitro-modules` should be a `peerDependency`.
73
+ ---
74
+
75
+ ## iOS Installation Steps
76
+
77
+ 1. In your iOS folder "ios", run the command:
78
+ ```sh
79
+ pod install
80
+ ```
81
+
82
+ ---
83
+
84
+ ## Methods
85
+
86
+ ### initialize(options)
87
+
88
+ **Description:**
89
+ Initializes the Consent SDK with configuration options. Must be called before using any other SDK methods.
90
+
91
+ **Parameters:**
92
+
93
+ | Parameter | Type | Required | Description |
94
+ |-----------|-----------------|----------|---------------------------------------------|
95
+ | options | CmpSDKOptions | Yes | Configuration options for the SDK |
96
+
97
+ **CmpSDKOptions:**
98
+
99
+ | Option | Type | Required | Description |
100
+ |-----------------------|---------|----------|---------------------------------------------|
101
+ | appURL | string | Yes | Base URL for the Securiti application |
102
+ | cdnURL | string | Yes | URL for the Securiti CDN resources |
103
+ | tenantID | string | Yes | Your tenant identifier from Securiti |
104
+ | appID | string | Yes | Your application identifier from Securiti |
105
+ | testingMode | boolean | Yes | Enable testing mode |
106
+ | loggerLevel | string | Yes | Log level: "DEBUG", "INFO", "WARNING", "ERROR" |
107
+ | consentsCheckInterval | number | Yes | Time in seconds between consent checks |
108
+ | subjectId | string | No | User identifier for consent tracking |
109
+ | languageCode | string | No | Language code for UI elements (e.g., "en") |
110
+ | locationCode | string | No | Location code for regional compliance (e.g., "US") |
111
+ | mode | string | No | Mode: "draft" or "live" |
112
+
113
+ **Return Value:**
114
+ `void`
115
+
116
+ **Example:**
117
+ ```js
118
+ import { initialize, LoggerLevel, ModeValues } from 'securiti-consent-sdk';
119
+
120
+ const options = {
121
+ appURL: 'your APP Url',
122
+ cdnURL: 'Your CDN Url',
123
+ tenantID: 'your-tenant-id',
124
+ appID: 'your-app-id',
125
+ testingMode: false,
126
+ loggerLevel: LoggerLevel.DEBUG,
127
+ consentsCheckInterval: 60,
128
+ subjectId: 'user-123',
129
+ languageCode: 'en',
130
+ locationCode: 'US',
131
+ mode: ModeValues.LIVE
132
+ };
133
+
134
+ initialize(options);
135
+ ```
136
+
137
+ ---
138
+
139
+ ### getConsentByPurposeId(purposeId)
140
+
141
+ **Description:**
142
+ Retrieves the consent status for a specific purpose by its ID.
143
+
144
+ **Parameters:**
145
+
146
+ | Parameter | Type | Description |
147
+ |-----------|--------|------------------------------------|
148
+ | purposeId | number | The unique identifier of the purpose|
149
+
150
+ **Return Value:**
151
+ `Promise<ConsentStatus>`
152
+
153
+ **ConsentStatus Values:**
154
+ - `granted`
155
+ - `declined`
156
+ - `not_determined`
157
+ - `withdrawn`
158
+
159
+ **Example:**
160
+ ```js
161
+ import { getConsentByPurposeId, ConsentStatusValues } from 'securiti-consent-sdk';
162
+
163
+ getConsentByPurposeId(12345)
164
+ .then((status) => {
165
+ if (status === ConsentStatusValues.GRANTED) {
166
+ // Consent is granted
167
+ }
168
+ });
169
+ ```
170
+
171
+ ---
172
+
173
+ ### getConsentByPermissionId(permissionId)
174
+
175
+ **Description:**
176
+ Retrieves the consent status for a specific app permission by its ID.
177
+
178
+ **Parameters:**
179
+
180
+ | Parameter | Type | Description |
181
+ |--------------|--------|---------------------------------------------|
182
+ | permissionId | string | The unique identifier of the permission |
183
+
184
+ **Return Value:**
185
+ `Promise<ConsentStatus>`
186
+
187
+ **ConsentStatus Values:**
188
+ Same as above.
189
+
190
+ **Example:**
191
+ ```js
192
+ import { getConsentByPermissionId, ConsentStatusValues } from 'securiti-consent-sdk';
193
+
194
+ getConsentByPermissionId('location')
195
+ .then((status) => {
196
+ if (status === ConsentStatusValues.GRANTED) {
197
+ // Permission consent is granted
198
+ }
199
+ });
200
+ ```
201
+
202
+ ---
203
+
204
+ ### getPermissions()
205
+
206
+ **Description:**
207
+ Retrieves all available app permissions defined in the consent configuration.
208
+
209
+ **Return Value:**
210
+ `Promise<AppPermission[]>`
211
+
212
+ **AppPermission Properties:**
213
+
214
+ | Property | Type | Description |
215
+ |-------------------------|---------|---------------------------------------------|
216
+ | id | number | The numeric identifier |
217
+ | name | string | The permission name |
218
+ | permissionId | string | The permission identifier string |
219
+ | description | string | Localized permission descriptions |
220
+ | group | string | The permission group name |
221
+ | groupId | number | The permission group identifier |
222
+ | consentStatus | string | The current consent status |
223
+ | nameMap | string | Localized permission names |
224
+ | isSettingsPromptEnabled | boolean | Whether settings prompt is enabled |
225
+
226
+ **Example:**
227
+ ```js
228
+ import { getPermissions, ConsentStatusValues } from 'securiti-consent-sdk';
229
+
230
+ getPermissions()
231
+ .then((permissions) => {
232
+ const grantedPermissions = permissions.filter(
233
+ permission => permission.consentStatus === ConsentStatusValues.GRANTED
234
+ );
235
+ });
236
+ ```
237
+
238
+ ---
239
+
240
+ ### getPurposes()
241
+
242
+ **Description:**
243
+ Retrieves all available purposes defined in the consent configuration.
244
+
245
+ **Return Value:**
246
+ `Promise<Purpose[]>`
247
+
248
+ **Purpose Properties:**
249
+
250
+ | Property | Type | Description |
251
+ |------------------|---------|---------------------------------------------|
252
+ | purposeId | number | The unique identifier for the purpose |
253
+ | purposeName | string | Localized purpose names |
254
+ | purposeDescription| string | Localized purpose descriptions |
255
+ | sdks | SDK[] | SDKs associated with this purpose |
256
+ | consentStatus | string | The current consent status |
257
+ | disableOptOut | boolean | Whether opt-out is disabled |
258
+ | optOutText | string | Localized opt-out text |
259
+ | hideDetails | boolean | Whether details should be hidden in the UI |
260
+ | isGADMapped | boolean | Whether mapped to Google Ads |
261
+ | gadDescription | string | Localized Google Ads description |
262
+
263
+ **Example:**
264
+ ```js
265
+ import { getPurposes, ConsentStatusValues } from 'securiti-consent-sdk';
266
+
267
+ getPurposes()
268
+ .then((purposes) => {
269
+ const grantedPurposes = purposes.filter(
270
+ purpose => purpose.consentStatus === ConsentStatusValues.GRANTED
271
+ );
272
+ });
273
+ ```
274
+
275
+ ---
276
+
277
+ ### getSdksInPurpose(purposeId)
278
+
279
+ **Description:**
280
+ Retrieves all SDKs associated with a specific purpose.
281
+
282
+ **Parameters:**
283
+
284
+ | Parameter | Type | Description |
285
+ |-----------|--------|------------------------------------|
286
+ | purposeId | number | The unique identifier of the purpose|
287
+
288
+ **Return Value:**
289
+ `Promise<SDK[]>`
290
+
291
+ **SDK Properties:**
292
+
293
+ | Property | Type | Description |
294
+ |---------------|---------|---------------------------------------------|
295
+ | sdkId | number | The unique identifier for the SDK |
296
+ | namespaceId | string | The namespace identifier string |
297
+ | sdkName | string | Localized SDK names |
298
+ | sdkDescription| string | Localized SDK descriptions |
299
+ | vendor | string | The vendor or provider of the SDK |
300
+ | logoBase64 | string | Base64-encoded logo image |
301
+ | website | string | The SDK vendor's website URL |
302
+ | matchedBy | string[]| How the SDK was matched in the application |
303
+ | collectingData| boolean | Whether the SDK is collecting data |
304
+
305
+ **Example:**
306
+ ```js
307
+ import { getSdksInPurpose } from 'securiti-consent-sdk';
308
+
309
+ getSdksInPurpose(12345)
310
+ .then((sdks) => {
311
+ // Use SDKs
312
+ });
313
+ ```
314
+
315
+ ---
316
+
317
+ ### setPurposeConsent(purpose, consent)
318
+
319
+ **Description:**
320
+ Sets the consent status for a specific purpose.
321
+
322
+ **Parameters:**
323
+
324
+ | Parameter | Type | Description |
325
+ |-----------|---------|---------------------------------------------|
326
+ | purpose | Purpose | The purpose object to set consent for |
327
+ | consent | string | The consent status to set |
328
+
329
+ **ConsentStatus Values:**
330
+ - `granted`
331
+ - `declined`
332
+ - `not_determined`
333
+ - `withdrawn`
334
+
335
+ **Return Value:**
336
+ `boolean`
337
+
338
+ **Example:**
339
+ ```js
340
+ import { setPurposeConsent, getPurposes, ConsentStatusValues } from 'securiti-consent-sdk';
341
+
342
+ getPurposes()
343
+ .then((purposes) => {
344
+ const analyticsPurpose = purposes.find(p => p.purposeId === 12345);
345
+ if (analyticsPurpose) {
346
+ const success = setPurposeConsent(analyticsPurpose, ConsentStatusValues.GRANTED);
347
+ }
348
+ });
349
+ ```
350
+
351
+ ---
352
+
353
+ ### setPermissionConsent(appPermission, consent)
354
+
355
+ **Description:**
356
+ Sets the consent status for a specific app permission.
357
+
358
+ **Parameters:**
359
+
360
+ | Parameter | Type | Description |
361
+ |---------------|--------------|---------------------------------------------|
362
+ | appPermission | AppPermission| The permission object to set consent for |
363
+ | consent | string | The consent status to set |
364
+
365
+ **ConsentStatus Values:**
366
+ Same as above.
367
+
368
+ **Return Value:**
369
+ `boolean`
370
+
371
+ **Example:**
372
+ ```js
373
+ import { setPermissionConsent, getPermissions, ConsentStatusValues } from 'securiti-consent-sdk';
374
+
375
+ getPermissions()
376
+ .then((permissions) => {
377
+ const locationPermission = permissions.find(p => p.permissionId === 'location');
378
+ if (locationPermission) {
379
+ const success = setPermissionConsent(locationPermission, ConsentStatusValues.GRANTED);
380
+ }
381
+ });
382
+ ```
383
+
384
+ ---
385
+
386
+ ### resetConsents()
387
+
388
+ **Description:**
389
+ Resets all consents to their default state.
390
+
391
+ **Parameters:**
392
+ None
393
+
394
+ **Return Value:**
395
+ `void`
396
+
397
+ **Example:**
398
+ ```js
399
+ import { resetConsents } from 'securiti-consent-sdk';
400
+
401
+ resetConsents();
402
+ ```
403
+
404
+ ---
405
+
406
+ ### isReady(callback)
407
+
408
+ **Description:**
409
+ Checks if the React Native SDK is ready to use (asynchronous version).
410
+
411
+ **Parameters:**
412
+
413
+ | Parameter | Type | Description |
414
+ |-----------|----------------------------|---------------------------------------------|
415
+ | callback | (status: boolean) => void | Callback function that receives the ready status |
416
+
417
+ **Return Value:**
418
+ `void`
419
+
420
+ **Example:**
421
+ ```js
422
+ import { isReady, presentConsentBanner } from 'securiti-consent-sdk';
423
+
424
+ isReady((isReady) => {
425
+ if (isReady) {
426
+ presentConsentBanner();
427
+ }
428
+ });
429
+ ```
430
+
431
+ ---
432
+
433
+ ### getBannerConfig()
434
+
435
+ **Description:**
436
+ Retrieves the banner configuration.
437
+
438
+ **Return Value:**
439
+ `Promise<BannerConfig | null>`
440
+
441
+ **BannerConfig Properties:**
442
+ (See [Types and Properties](#types-and-properties) section)
443
+
444
+ **Example:**
445
+ ```js
446
+ import { getBannerConfig } from 'securiti-consent-sdk';
447
+
448
+ getBannerConfig()
449
+ .then((config) => {
450
+ if (config) {
451
+ // Use config
452
+ }
453
+ });
454
+ ```
455
+
456
+ ---
457
+
458
+ ### options()
459
+
460
+ **Description:**
461
+ Retrieves the current SDK configuration options.
462
+
463
+ **Return Value:**
464
+ `CmpSDKOptions | null`
465
+
466
+ **Example:**
467
+ ```js
468
+ import { options } from 'securiti-consent-sdk';
469
+
470
+ const currentOptions = options();
471
+ ```
472
+
473
+ ---
474
+
475
+ ### getSettingsPrompt()
476
+
477
+ **Description:**
478
+ Retrieves the settings prompt configuration.
479
+
480
+ **Return Value:**
481
+ `Promise<SettingsPrompt | null>`
482
+
483
+ **SettingsPrompt Properties:**
484
+ (See [Types and Properties](#types-and-properties) section)
485
+
486
+ **Example:**
487
+ ```js
488
+ import { getSettingsPrompt } from 'securiti-consent-sdk';
489
+
490
+ getSettingsPrompt()
491
+ .then((prompt) => {
492
+ if (prompt) {
493
+ // Use prompt
494
+ }
495
+ });
496
+ ```
497
+
498
+ ---
499
+
500
+ ### uploadConsents(request)
501
+
502
+ **Description:**
503
+ Uploads consents to the server.
504
+
505
+ **Parameters:**
506
+
507
+ | Parameter | Type | Description |
508
+ |-----------|---------------------|---------------------------------------------|
509
+ | request | PostConsentsRequest | The consent data to upload |
510
+
511
+ **Return Value:**
512
+ `Promise<boolean>`
513
+
514
+ **Example:**
515
+ ```js
516
+ import { uploadConsents, ConsentStatusValues } from 'securiti-consent-sdk';
517
+
518
+ const timestamp = Date.now();
519
+ const consentRequest = {
520
+ uuid: 'user-123',
521
+ appUUID: 'app-456',
522
+ device: 'iPhone 12',
523
+ implicitConsent: false,
524
+ version: 1,
525
+ purposeConsents: [
526
+ {
527
+ purposeID: 12345,
528
+ consentStatus: ConsentStatusValues.GRANTED,
529
+ timestamp: timestamp,
530
+ isEssential: false
531
+ }
532
+ ],
533
+ permissions: [
534
+ {
535
+ permission: 'location',
536
+ consentStatus: ConsentStatusValues.GRANTED,
537
+ timestamp: timestamp
538
+ }
539
+ ],
540
+ isTestMode: false,
541
+ adId: 'advertising-id-789',
542
+ bannerInfo: 'Banner version 2.0',
543
+ sdkVersion: '1.132.0',
544
+ platform: 'iOS'
545
+ };
546
+
547
+ uploadConsents(consentRequest)
548
+ .then((success) => {
549
+ if (success) {
550
+ // Success
551
+ }
552
+ });
553
+ ```
554
+
555
+ ---
556
+
557
+ ### presentConsentBanner()
558
+
559
+ **Description:**
560
+ Displays the consent banner UI to the user.
561
+
562
+ **Parameters:**
563
+ None
564
+
565
+ **Return Value:**
566
+ `void`
567
+
568
+ **Example:**
569
+ ```js
570
+ import { presentConsentBanner } from 'securiti-consent-sdk';
571
+
572
+ presentConsentBanner();
573
+ ```
574
+
575
+ ---
576
+
577
+ ### presentPreferenceCenter()
578
+
579
+ **Description:**
580
+ Displays the preference center UI to the user.
581
+
582
+ **Parameters:**
583
+ None
584
+
585
+ **Return Value:**
586
+ `void`
587
+
588
+ **Example:**
589
+ ```js
590
+ import { presentPreferenceCenter } from 'securiti-consent-sdk';
591
+
592
+ presentPreferenceCenter();
593
+ ```
594
+
595
+ ---
596
+
597
+ ## Types and Properties
598
+
599
+ ### ConsentStatus Values
600
+
601
+ - `granted`
602
+ - `declined`
603
+ - `not_determined`
604
+ - `withdrawn`
605
+
606
+ ### CmpSDKOptions
607
+
608
+ See [initialize(options)](#initializeoptions).
609
+
610
+ ### AppPermission
611
+
612
+ See [getPermissions()](#getpermissions).
613
+
614
+ ### Purpose
615
+
616
+ See [getPurposes()](#getpurposes).
617
+
618
+ ### SDK
619
+
620
+ See [getSdksInPurpose(purposeId)](#getsdksinpurposepurposeid).
621
+
622
+ ### BannerConfig
623
+
624
+ | Property | Type | Description |
625
+ |----------------------------------|---------|---------------------------------------------|
626
+ | hideCloseButton | boolean | Whether to hide the close button |
627
+ | hideAcceptButton | boolean | Whether to hide the accept button |
628
+ | embedDSRPortalLink | boolean | Whether to embed DSR portal link |
629
+ | recordConsentUponAppStart | boolean | Whether to record consent on app start |
630
+ | hideToggleForEssentialCategories | boolean | Hide toggles for essential categories |
631
+ | name | string | The banner name |
632
+ | dsrPortalLink | string | Link to the DSR portal |
633
+ | complianceType | string | "notice-only", "opt-in", or "opt-out" |
634
+ | bannerReappearanceTime | string | When the banner should reappear |
635
+ | privacyNoticeLink | string | Link to privacy notice |
636
+ | accept | string | Localized accept button text |
637
+ | reject | string | Localized reject button text |
638
+ | bannerText | string | Localized banner text |
639
+ | bannerHeading | string | Localized banner heading |
640
+ | sdkTabHeading | string | Localized SDK tab heading |
641
+ | privacyNoticeText | string | Localized privacy notice text |
642
+ | preferenceCenterLink | string | Localized preference center link text |
643
+ | bannerPosition | string | "bottom" or "center" |
644
+ | buttonShape | string | "rounded", "square", "pill", "outlined" |
645
+ | customPaletteTheme | object | Custom color theme for banner |
646
+
647
+ ### SettingsPrompt
648
+
649
+ | Property | Type | Description |
650
+ |--------------------|-----------|---------------------------------------------|
651
+ | promptHeading | string | Localized prompt heading text |
652
+ | promptMessage | string | Localized prompt message text |
653
+ | settingsButtonText | string | Localized settings button text |
654
+ | notNowButtonText | string | Localized "not now" button text |
655
+ | permissions | string[] | Permissions with settings prompt enabled |
656
+
657
+ ### PostConsentsRequest
658
+
659
+ | Property | Type | Required | Description |
660
+ |------------------|-------------------|----------|---------------------------------------------|
661
+ | uuid | string | Yes | Unique user identifier |
662
+ | appUUID | string | Yes | Application UUID |
663
+ | device | string | Yes | Device information |
664
+ | implicitConsent | boolean | Yes | Whether consent was implicit |
665
+ | version | number | Yes | Version of consent data |
666
+ | purposeConsents | PurposeConsent[] | Yes | Array of purpose consent data |
667
+ | permissions | PermissionConsent[]| Yes | Array of permission consent data |
668
+ | isTestMode | boolean | Yes | Whether in test mode |
669
+ | adId | string | Yes | Advertising identifier |
670
+ | bannerInfo | string | Yes | Banner information |
671
+ | sdkVersion | string | No | SDK version |
672
+ | platform | string | No | Platform information |
673
+
674
+ ---
675
+
676
+ ## Using Methods
677
+
678
+ Example usage in a React Native app:
679
+
680
+ ```jsx
681
+ import React, { useEffect, useState } from 'react';
682
+ import {
683
+ View,
684
+ StyleSheet,
685
+ Text,
686
+ ScrollView,
687
+ ActivityIndicator,
688
+ SafeAreaView,
689
+ TouchableOpacity,
690
+ Platform,
691
+ Alert,
692
+ } from 'react-native';
693
+
694
+ // Import the functions from the library
695
+ import {
696
+ initialize,
697
+ presentConsentBanner,
698
+ presentPreferenceCenter,
699
+ isSdkReady,
700
+ isReady,
701
+ resetConsents,
702
+ getConsentByPurposeId,
703
+ getConsentByPermissionId,
704
+ getPermissions,
705
+ getPurposes,
706
+ getSdksInPurpose,
707
+ setPurposeConsent,
708
+ setPermissionConsent,
709
+ getBannerConfig,
710
+ getSettingsPrompt,
711
+ options,
712
+ LoggerLevel,
713
+ ConsentStatusValues,
714
+ } from 'securiti-consent-sdk';
715
+
716
+ // For types
717
+ import type {
718
+ Purpose,
719
+ AppPermission,
720
+ SDK,
721
+ BannerConfig,
722
+ SettingsPrompt,
723
+ CmpSDKOptions
724
+ } from 'securiti-consent-sdk';
725
+
726
+ // We'll use the isReady callback instead of native events
727
+
728
+ export default function App() {
729
+ const [sdkReady, setSdkReady] = useState(false);
730
+ const [isLoading, setIsLoading] = useState(false);
731
+ const [response, setResponse] = useState<null | any>(null);
732
+ const [purposes, setPurposes] = useState<Purpose[]>([]);
733
+ const [permissions, setPermissions] = useState<AppPermission[]>([]);
734
+
735
+ useEffect(() => {
736
+ // Initialize SDK with appropriate options based on platform
737
+ const initOptions: CmpSDKOptions = Platform.OS === 'android'
738
+ ? {
739
+ appURL: 'Your Android App URL',
740
+ cdnURL: 'Your Android CDN URL',
741
+ tenantID: 'Your Tenant ID',
742
+ appID: 'Your Android App ID',
743
+ testingMode: true,
744
+ loggerLevel: LoggerLevel.DEBUG,
745
+ consentsCheckInterval: 3600,
746
+ subjectId: 'reactNativeAndroidSubject',
747
+ languageCode: 'Your Language Code',
748
+ locationCode: 'Your Location Code',
749
+ }
750
+ : {
751
+ appURL: 'Your iOS App URL',
752
+ cdnURL: 'Your iOS CDN URL',
753
+ tenantID: 'Your Tenant ID',
754
+ appID: 'Your iOS App ID',
755
+ testingMode: true,
756
+ loggerLevel: LoggerLevel.DEBUG,
757
+ consentsCheckInterval: 3600,
758
+ subjectId: 'reactNativeiOSSubject',
759
+ languageCode: 'Your Language Code',
760
+ locationCode: 'Your Location Code',
761
+ };
762
+
763
+ initialize(initOptions);
764
+
765
+ // Use the isReady callback instead of events
766
+ isReady((status) => {
767
+ console.log('SDK ready callback received:', status);
768
+ setSdkReady(status);
769
+ if (status) {
770
+ loadInitialData();
771
+ }
772
+ });
773
+
774
+ // Also check using the synchronous method
775
+ checkSdkReadiness();
776
+
777
+ // No event listeners to clean up
778
+ return () => {};
779
+ }, []);
780
+
781
+ const checkSdkReadiness = () => {
782
+ // Synchronous check
783
+ try {
784
+ const ready = isSdkReady();
785
+ setSdkReady(ready);
786
+ console.log('SDK ready (sync check):', ready);
787
+
788
+ if (ready) {
789
+ handleShowBanner();
790
+ loadInitialData();
791
+ } else {
792
+ // Also try the callback-based method
793
+ isReady((ready) => {
794
+ console.log('SDK ready (callback):', ready);
795
+ setSdkReady(ready);
796
+ if (ready) {
797
+ handleShowBanner();
798
+ loadInitialData();
799
+ }
800
+ });
801
+ }
802
+ } catch (error) {
803
+ console.error('Error checking SDK readiness:', error);
804
+ }
805
+ };
806
+
807
+ const loadInitialData = async () => {
808
+ try {
809
+ setIsLoading(true);
810
+ console.log('Loading initial data...');
811
+
812
+ // Load purposes and permissions in parallel
813
+ const [purposesResult, permissionsResult] = await Promise.all([
814
+ getPurposes(),
815
+ getPermissions()
816
+ ]);
817
+
818
+ console.log('Purposes loaded:', purposesResult?.length || 0);
819
+ console.log('Permissions loaded:', permissionsResult?.length || 0);
820
+
821
+ setPurposes(purposesResult || []);
822
+ setPermissions(permissionsResult || []);
823
+ } catch (error) {
824
+ console.error('Failed to load initial data:', error);
825
+ Alert.alert('Error', 'Failed to load initial data');
826
+ } finally {
827
+ setIsLoading(false);
828
+ }
829
+ };
830
+
831
+ const handleShowBanner = () => {
832
+ try {
833
+ presentConsentBanner();
834
+ console.log('Consent banner presented');
835
+ } catch (error) {
836
+ console.error('Error presenting consent banner:', error);
837
+ Alert.alert('Error', 'Failed to show consent banner');
838
+ }
839
+ };
840
+
841
+ const handleShowPreferenceCenter = () => {
842
+ try {
843
+ presentPreferenceCenter();
844
+ console.log('Preference center presented');
845
+ } catch (error) {
846
+ console.error('Error presenting preference center:', error);
847
+ Alert.alert('Error', 'Failed to show preference center');
848
+ }
849
+ };
850
+
851
+ const handleResetConsents = () => {
852
+ setResponse(null);
853
+ try {
854
+ resetConsents();
855
+ setResponse({
856
+ message: 'Consents have been reset',
857
+ timestamp: new Date().toISOString()
858
+ });
859
+ loadInitialData(); // Refresh data
860
+ } catch (error) {
861
+ console.error('Error resetting consents:', error);
862
+ setResponse({ error: 'Failed to reset consents: ' + error });
863
+ }
864
+ };
865
+
866
+ const handleGetPurposes = async () => {
867
+ setResponse(null);
868
+ setIsLoading(true);
869
+ try {
870
+ const result = await getPurposes();
871
+ setResponse({
872
+ purposes: result,
873
+ timestamp: new Date().toISOString()
874
+ });
875
+ setPurposes(result || []);
876
+ } catch (error) {
877
+ console.error('Error getting purposes:', error);
878
+ setResponse({ error: 'Failed to get purposes: ' + error });
879
+ } finally {
880
+ setIsLoading(false);
881
+ }
882
+ };
883
+
884
+ const handleGetPermissions = async () => {
885
+ setResponse(null);
886
+ setIsLoading(true);
887
+ try {
888
+ const result = await getPermissions();
889
+ setResponse({
890
+ permissions: result,
891
+ timestamp: new Date().toISOString()
892
+ });
893
+ setPermissions(result || []);
894
+ } catch (error) {
895
+ console.error('Error getting permissions:', error);
896
+ setResponse({ error: 'Failed to get permissions: ' + error });
897
+ } finally {
898
+ setIsLoading(false);
899
+ }
900
+ };
901
+
902
+ const handleGetSdksInPurpose = async (purposeId: number) => {
903
+ setResponse(null);
904
+ setIsLoading(true);
905
+ try {
906
+ const result = await getSdksInPurpose(purposeId);
907
+ setResponse({
908
+ purposeId,
909
+ sdks: result,
910
+ timestamp: new Date().toISOString()
911
+ });
912
+ } catch (error) {
913
+ console.error('Error getting SDKs:', error);
914
+ setResponse({ error: `Failed to get SDKs for purpose ${purposeId}: ` + error });
915
+ } finally {
916
+ setIsLoading(false);
917
+ }
918
+ };
919
+
920
+ const handleGetBannerConfig = async () => {
921
+ setResponse(null);
922
+ setIsLoading(true);
923
+ try {
924
+ const result = await getBannerConfig(null);
925
+ setResponse({
926
+ bannerConfig: result,
927
+ timestamp: new Date().toISOString()
928
+ });
929
+ } catch (error) {
930
+ console.error('Error getting banner config:', error);
931
+ setResponse({ error: 'Failed to get banner config: ' + error });
932
+ } finally {
933
+ setIsLoading(false);
934
+ }
935
+ };
936
+
937
+ const handleGetSettingsPrompt = async () => {
938
+ setResponse(null);
939
+ setIsLoading(true);
940
+ try {
941
+ const result = await getSettingsPrompt();
942
+ setResponse({
943
+ settingsPrompt: result,
944
+ timestamp: new Date().toISOString()
945
+ });
946
+ } catch (error) {
947
+ console.error('Error getting settings prompt:', error);
948
+ setResponse({ error: 'Failed to get settings prompt: ' + error });
949
+ } finally {
950
+ setIsLoading(false);
951
+ }
952
+ };
953
+
954
+ const handleGetOptions = () => {
955
+ setResponse(null);
956
+ try {
957
+ const sdkOptions = options();
958
+ setResponse({
959
+ options: sdkOptions,
960
+ timestamp: new Date().toISOString()
961
+ });
962
+ } catch (error) {
963
+ console.error('Error getting options:', error);
964
+ setResponse({ error: 'Failed to get options: ' + error });
965
+ }
966
+ };
967
+
968
+ const handleGetConsentForPurpose = async (purposeId: number) => {
969
+ setResponse(null);
970
+ setIsLoading(true);
971
+ try {
972
+ const result = await getConsentByPurposeId(purposeId);
973
+ setResponse({
974
+ purposeId,
975
+ consentStatus: result,
976
+ timestamp: new Date().toISOString()
977
+ });
978
+ } catch (error) {
979
+ console.error('Error getting purpose consent:', error);
980
+ setResponse({ error: `Failed to get consent for purpose ${purposeId}: ` + error });
981
+ } finally {
982
+ setIsLoading(false);
983
+ }
984
+ };
985
+
986
+ const handleGetConsentForPermission = async (permissionId: string) => {
987
+ setResponse(null);
988
+ setIsLoading(true);
989
+ try {
990
+ const result = await getConsentByPermissionId(permissionId);
991
+ setResponse({
992
+ permissionId,
993
+ consentStatus: result,
994
+ timestamp: new Date().toISOString()
995
+ });
996
+ } catch (error) {
997
+ console.error('Error getting permission consent:', error);
998
+ setResponse({ error: `Failed to get consent for permission ${permissionId}: ` + error });
999
+ } finally {
1000
+ setIsLoading(false);
1001
+ }
1002
+ };
1003
+
1004
+ const handleSetConsentForPurpose = async (purpose: Purpose, consent: string) => {
1005
+ setResponse(null);
1006
+ setIsLoading(true);
1007
+ try {
1008
+ const success = setPurposeConsent(purpose, consent);
1009
+ console.log(`Set purpose consent result: ${success}`);
1010
+
1011
+ // Give time for consent to apply
1012
+ await new Promise(resolve => setTimeout(resolve, 500));
1013
+
1014
+ // Get updated status
1015
+ const newStatus = await getConsentByPurposeId(purpose.purposeId || 0);
1016
+
1017
+ setResponse({
1018
+ message: `Set consent for purpose ${purpose.purposeId} to ${consent}`,
1019
+ success,
1020
+ newStatus,
1021
+ timestamp: new Date().toISOString()
1022
+ });
1023
+
1024
+ // Refresh purposes list
1025
+ const updatedPurposes = await getPurposes();
1026
+ setPurposes(updatedPurposes || []);
1027
+ } catch (error) {
1028
+ console.error('Error setting purpose consent:', error);
1029
+ setResponse({ error: `Failed to set consent for purpose ${purpose.purposeId}: ` + error });
1030
+ } finally {
1031
+ setIsLoading(false);
1032
+ }
1033
+ };
1034
+
1035
+ const handleSetConsentForPermission = async (permission: AppPermission, consent: string) => {
1036
+ setResponse(null);
1037
+ setIsLoading(true);
1038
+ try {
1039
+ const success = setPermissionConsent(permission, consent);
1040
+ console.log(`Set permission consent result: ${success}`);
1041
+
1042
+ // Give time for consent to apply
1043
+ await new Promise(resolve => setTimeout(resolve, 500));
1044
+
1045
+ // Get updated status
1046
+ const newStatus = await getConsentByPermissionId(permission.permissionId || '');
1047
+
1048
+ setResponse({
1049
+ message: `Set consent for permission ${permission.permissionId} to ${consent}`,
1050
+ success,
1051
+ newStatus,
1052
+ timestamp: new Date().toISOString()
1053
+ });
1054
+
1055
+ // Refresh permissions list
1056
+ const updatedPermissions = await getPermissions();
1057
+ setPermissions(updatedPermissions || []);
1058
+ } catch (error) {
1059
+ console.error('Error setting permission consent:', error);
1060
+ setResponse({ error: `Failed to set consent for permission ${permission.permissionId}: ` + error });
1061
+ } finally {
1062
+ setIsLoading(false);
1063
+ }
1064
+ };
1065
+
1066
+
1067
+ const renderPurposeItem = (purpose: Purpose) => {
1068
+ const purposeName = purpose.purposeName?.['en'] || `Purpose ${purpose.purposeId}`;
1069
+
1070
+ return (
1071
+ <View style={styles.itemContainer} key={purpose.purposeId}>
1072
+ <Text style={styles.itemTitle}>{purposeName}</Text>
1073
+ <Text style={styles.itemSubtitle}>ID: {purpose.purposeId}</Text>
1074
+ <Text style={styles.itemSubtitle}>Status: {purpose.consentStatus || 'unknown'}</Text>
1075
+
1076
+ <View style={styles.buttonRow}>
1077
+ <TouchableOpacity
1078
+ style={[styles.smallButton, styles.detailButton]}
1079
+ onPress={() => handleGetConsentForPurpose(purpose.purposeId || 0)}
1080
+ >
1081
+ <Text style={styles.smallButtonText}>Get Status</Text>
1082
+ </TouchableOpacity>
1083
+
1084
+ <TouchableOpacity
1085
+ style={[styles.smallButton, styles.detailButton]}
1086
+ onPress={() => handleGetSdksInPurpose(purpose.purposeId || 0)}
1087
+ >
1088
+ <Text style={styles.smallButtonText}>Get SDKs</Text>
1089
+ </TouchableOpacity>
1090
+
1091
+ <TouchableOpacity
1092
+ style={[styles.smallButton, styles.grantButton]}
1093
+ onPress={() => handleSetConsentForPurpose(purpose, ConsentStatusValues.GRANTED)}
1094
+ >
1095
+ <Text style={styles.smallButtonText}>Grant</Text>
1096
+ </TouchableOpacity>
1097
+
1098
+ <TouchableOpacity
1099
+ style={[styles.smallButton, styles.declineButton]}
1100
+ onPress={() => handleSetConsentForPurpose(purpose, ConsentStatusValues.DECLINED)}
1101
+ >
1102
+ <Text style={styles.smallButtonText}>Decline</Text>
1103
+ </TouchableOpacity>
1104
+ </View>
1105
+ </View>
1106
+ );
1107
+ };
1108
+
1109
+ const renderPermissionItem = (permission: AppPermission) => {
1110
+ const permissionName = permission.name || permission.permissionId || 'Unknown Permission';
1111
+
1112
+ return (
1113
+ <View style={styles.itemContainer} key={permission.permissionId}>
1114
+ <Text style={styles.itemTitle}>{permissionName}</Text>
1115
+ <Text style={styles.itemSubtitle}>ID: {permission.permissionId}</Text>
1116
+ <Text style={styles.itemSubtitle}>Status: {permission.consentStatus || 'unknown'}</Text>
1117
+
1118
+ <View style={styles.buttonRow}>
1119
+ <TouchableOpacity
1120
+ style={[styles.smallButton, styles.detailButton]}
1121
+ onPress={() => handleGetConsentForPermission(permission.permissionId || '')}
1122
+ >
1123
+ <Text style={styles.smallButtonText}>Get Status</Text>
1124
+ </TouchableOpacity>
1125
+
1126
+ <TouchableOpacity
1127
+ style={[styles.smallButton, styles.grantButton]}
1128
+ onPress={() => handleSetConsentForPermission(permission, ConsentStatusValues.GRANTED)}
1129
+ >
1130
+ <Text style={styles.smallButtonText}>Grant</Text>
1131
+ </TouchableOpacity>
1132
+
1133
+ <TouchableOpacity
1134
+ style={[styles.smallButton, styles.declineButton]}
1135
+ onPress={() => handleSetConsentForPermission(permission, ConsentStatusValues.DECLINED)}
1136
+ >
1137
+ <Text style={styles.smallButtonText}>Decline</Text>
1138
+ </TouchableOpacity>
1139
+ </View>
1140
+ </View>
1141
+ );
1142
+ };
1143
+
1144
+ return (
1145
+ <SafeAreaView style={styles.container}>
1146
+ <ScrollView
1147
+ contentContainerStyle={styles.scrollContent}
1148
+ nestedScrollEnabled={true}>
1149
+ <View style={styles.header}>
1150
+ <Text style={styles.title}>Securiti Consent SDK Demo</Text>
1151
+ <Text style={styles.subtitle}>
1152
+ SDK Status: {sdkReady ? 'Ready' : 'Initializing...'}
1153
+ </Text>
1154
+ </View>
1155
+
1156
+ <View style={styles.section}>
1157
+ <Text style={styles.sectionTitle}>Banner Controls</Text>
1158
+ <View style={styles.buttonRow}>
1159
+ <TouchableOpacity
1160
+ style={[styles.button, styles.primaryButton]}
1161
+ onPress={handleShowPreferenceCenter}
1162
+ >
1163
+ <Text style={styles.buttonText}>Preference Center</Text>
1164
+ </TouchableOpacity>
1165
+ </View>
1166
+ </View>
1167
+
1168
+ <View style={styles.section}>
1169
+ <Text style={styles.sectionTitle}>Get Configuration</Text>
1170
+ <View style={styles.buttonRow}>
1171
+ <TouchableOpacity
1172
+ style={[styles.button, styles.secondaryButton]}
1173
+ onPress={handleGetBannerConfig}
1174
+ >
1175
+ <Text style={styles.buttonText}>Banner Config</Text>
1176
+ </TouchableOpacity>
1177
+
1178
+ <TouchableOpacity
1179
+ style={[styles.button, styles.secondaryButton]}
1180
+ onPress={handleGetSettingsPrompt}
1181
+ >
1182
+ <Text style={styles.buttonText}>Settings Prompt</Text>
1183
+ </TouchableOpacity>
1184
+
1185
+ <TouchableOpacity
1186
+ style={[styles.button, styles.secondaryButton]}
1187
+ onPress={handleGetOptions}
1188
+ >
1189
+ <Text style={styles.buttonText}>SDK Options</Text>
1190
+ </TouchableOpacity>
1191
+ </View>
1192
+ </View>
1193
+
1194
+ <View style={styles.section}>
1195
+ <Text style={styles.sectionTitle}>Manage Data</Text>
1196
+ <View style={styles.buttonRow}>
1197
+ <TouchableOpacity
1198
+ style={[styles.button, styles.secondaryButton]}
1199
+ onPress={handleGetPurposes}
1200
+ >
1201
+ <Text style={styles.buttonText}>Get Purposes</Text>
1202
+ </TouchableOpacity>
1203
+
1204
+ <TouchableOpacity
1205
+ style={[styles.button, styles.secondaryButton]}
1206
+ onPress={handleGetPermissions}
1207
+ >
1208
+ <Text style={styles.buttonText}>Get Permissions</Text>
1209
+ </TouchableOpacity>
1210
+
1211
+
1212
+ <TouchableOpacity
1213
+ style={[styles.button, styles.warningButton]}
1214
+ onPress={handleResetConsents}
1215
+ >
1216
+ <Text style={styles.buttonText}>Reset Consents</Text>
1217
+ </TouchableOpacity>
1218
+ </View>
1219
+ </View>
1220
+
1221
+ {isLoading && (
1222
+ <View style={styles.loaderContainer}>
1223
+ <ActivityIndicator size="large" color="#0000ff" />
1224
+ </View>
1225
+ )}
1226
+
1227
+ {response && (
1228
+ <View style={styles.responseContainer}>
1229
+ <Text style={styles.sectionTitle}>Response:</Text>
1230
+ <ScrollView
1231
+ style={styles.responseScrollView}
1232
+ contentContainerStyle={styles.responseScrollContent}
1233
+ nestedScrollEnabled={true}
1234
+ >
1235
+ <Text selectable={true} style={styles.responseText}>
1236
+ {JSON.stringify(response, null, 2)}
1237
+ </Text>
1238
+ </ScrollView>
1239
+ </View>
1240
+ )}
1241
+
1242
+ {/* Purposes Section */}
1243
+ <View style={styles.section}>
1244
+ <Text style={styles.sectionTitle}>Purposes</Text>
1245
+ {purposes.length === 0 ? (
1246
+ <Text style={styles.emptyText}>No purposes available</Text>
1247
+ ) : (
1248
+ purposes.map(renderPurposeItem)
1249
+ )}
1250
+ </View>
1251
+
1252
+ {/* Permissions Section */}
1253
+ <View style={styles.section}>
1254
+ <Text style={styles.sectionTitle}>Permissions</Text>
1255
+ {permissions.length === 0 ? (
1256
+ <Text style={styles.emptyText}>No permissions available</Text>
1257
+ ) : (
1258
+ permissions.map(renderPermissionItem)
1259
+ )}
1260
+ </View>
1261
+ </ScrollView>
1262
+ </SafeAreaView>
1263
+ );
1264
+ }
1265
+
1266
+ const styles = StyleSheet.create({
1267
+ container: {
1268
+ flex: 1,
1269
+ backgroundColor: '#f5f5f5',
1270
+ },
1271
+ scrollContent: {
1272
+ padding: 16,
1273
+ },
1274
+ header: {
1275
+ marginBottom: 20,
1276
+ alignItems: 'center',
1277
+ },
1278
+ title: {
1279
+ fontSize: 24,
1280
+ fontWeight: 'bold',
1281
+ marginBottom: 8,
1282
+ },
1283
+ subtitle: {
1284
+ fontSize: 16,
1285
+ color: '#666',
1286
+ marginBottom: 8,
1287
+ },
1288
+ section: {
1289
+ marginBottom: 24,
1290
+ backgroundColor: '#fff',
1291
+ borderRadius: 8,
1292
+ padding: 16,
1293
+ shadowColor: '#000',
1294
+ shadowOffset: { width: 0, height: 2 },
1295
+ shadowOpacity: 0.1,
1296
+ shadowRadius: 4,
1297
+ elevation: 2,
1298
+ },
1299
+ sectionTitle: {
1300
+ fontSize: 18,
1301
+ fontWeight: 'bold',
1302
+ marginBottom: 12,
1303
+ },
1304
+ buttonRow: {
1305
+ flexDirection: 'row',
1306
+ flexWrap: 'wrap',
1307
+ justifyContent: 'space-between',
1308
+ marginHorizontal: -4,
1309
+ },
1310
+ button: {
1311
+ margin: 4,
1312
+ padding: 12,
1313
+ borderRadius: 6,
1314
+ minWidth: 100,
1315
+ alignItems: 'center',
1316
+ },
1317
+ buttonText: {
1318
+ color: '#fff',
1319
+ fontWeight: 'bold',
1320
+ },
1321
+ primaryButton: {
1322
+ backgroundColor: '#2196F3',
1323
+ },
1324
+ secondaryButton: {
1325
+ backgroundColor: '#4CAF50',
1326
+ },
1327
+ actionButton: {
1328
+ backgroundColor: '#9C27B0',
1329
+ },
1330
+ warningButton: {
1331
+ backgroundColor: '#FF5722',
1332
+ },
1333
+ smallButton: {
1334
+ margin: 2,
1335
+ padding: 6,
1336
+ borderRadius: 4,
1337
+ minWidth: 60,
1338
+ alignItems: 'center',
1339
+ },
1340
+ smallButtonText: {
1341
+ fontSize: 12,
1342
+ color: '#fff',
1343
+ fontWeight: 'bold',
1344
+ },
1345
+ detailButton: {
1346
+ backgroundColor: '#607D8B',
1347
+ },
1348
+ grantButton: {
1349
+ backgroundColor: '#4CAF50',
1350
+ },
1351
+ declineButton: {
1352
+ backgroundColor: '#F44336',
1353
+ },
1354
+ loaderContainer: {
1355
+ padding: 20,
1356
+ alignItems: 'center',
1357
+ },
1358
+ responseContainer: {
1359
+ backgroundColor: '#fff',
1360
+ borderRadius: 8,
1361
+ padding: 16,
1362
+ marginBottom: 24,
1363
+ height: 300,
1364
+ },
1365
+ responseScrollView: {
1366
+ flex: 1,
1367
+ marginTop: 8,
1368
+ backgroundColor: '#f5f5f5',
1369
+ borderRadius: 4,
1370
+ borderWidth: 1,
1371
+ borderColor: '#e0e0e0',
1372
+ },
1373
+ responseScrollContent: {
1374
+ padding: 8,
1375
+ },
1376
+ responseText: {
1377
+ fontFamily: 'monospace',
1378
+ fontSize: 12,
1379
+ color: '#333',
1380
+ },
1381
+ itemContainer: {
1382
+ padding: 12,
1383
+ borderWidth: 1,
1384
+ borderColor: '#e0e0e0',
1385
+ borderRadius: 6,
1386
+ marginBottom: 8,
1387
+ },
1388
+ itemTitle: {
1389
+ fontSize: 16,
1390
+ fontWeight: 'bold',
1391
+ marginBottom: 4,
1392
+ },
1393
+ itemSubtitle: {
1394
+ fontSize: 14,
1395
+ color: '#666',
1396
+ marginBottom: 4,
1397
+ },
1398
+ emptyText: {
1399
+ padding: 16,
1400
+ textAlign: 'center',
1401
+ color: '#666',
1402
+ },
1403
+ });
1404
+ ```
1405
+
1406
+ Go to the terminal and run:
1407
+ ```
1408
+ npx react-native run-android
1409
+ ```
1410
+ or
1411
+ ```
1412
+ npx react-native run-ios
1413
+ ```
1414
+ to see the consent banner on app start, and the preference center on click of the "Open Preference Center" button.