@usercentrics/react-native-sdk 2.33.2 → 2.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/build.gradle.kts +5 -2
- package/android/src/main/java/com/usercentrics/reactnative/RNUsercentricsModule.kt +1 -1
- package/android/src/main/java/com/usercentrics/reactnative/api/UsercentricsProxy.kt +4 -2
- package/android/src/main/java/com/usercentrics/reactnative/extensions/SecondLayerTabExtensions.kt +15 -0
- package/android/src/test/java/com/usercentrics/reactnative/extensions/SecondLayerTabExtensionsTest.kt +51 -0
- package/ios/Extensions/SecondLayerTab+Dict.swift +16 -0
- package/ios/Manager/UsercentricsManager.swift +3 -1
- package/ios/RNUsercentricsModule.swift +2 -1
- package/lib/NativeUsercentrics.d.ts +4 -2
- package/lib/NativeUsercentrics.js.map +1 -1
- package/lib/Usercentrics.d.ts +7 -2
- package/lib/Usercentrics.js +9 -3
- package/lib/Usercentrics.js.map +1 -1
- package/lib/models/SecondLayerTab.d.ts +12 -0
- package/lib/models/SecondLayerTab.js +14 -0
- package/lib/models/SecondLayerTab.js.map +1 -0
- package/lib/models/index.d.ts +1 -0
- package/lib/models/index.js +1 -0
- package/lib/models/index.js.map +1 -1
- package/package.json +2 -2
- package/src/NativeUsercentrics.ts +2 -1
- package/src/Usercentrics.tsx +9 -2
- package/src/__tests__/index.test.ts +70 -0
- package/src/models/SecondLayerTab.tsx +13 -0
- package/src/models/index.tsx +1 -0
package/android/build.gradle.kts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
val usercentricsVersion = "2.
|
|
2
|
-
|
|
1
|
+
val usercentricsVersion = "2.35.0"
|
|
2
|
+
// Pinned instead of "+": a dynamic version also matches pre-releases, and react-android 0.89.0-rc.1
|
|
3
|
+
// (published 2026-11-10) is built with Kotlin 2.3, which the Kotlin compiler used by the sample (2.1)
|
|
4
|
+
// cannot read, so every build broke. Bump this deliberately when the sample moves to a newer React Native.
|
|
5
|
+
val reactNativeVersion = "0.88.1"
|
|
3
6
|
|
|
4
7
|
fun BooleanProperty(name: String): Boolean {
|
|
5
8
|
return project.hasProperty(name) && project.property(name) == "true"
|
|
@@ -64,7 +64,7 @@ internal class RNUsercentricsModule(
|
|
|
64
64
|
val bannerSettings = options?.bannerSettingsFromMap(context)
|
|
65
65
|
|
|
66
66
|
val activity = reactContextProvider.activity()!!
|
|
67
|
-
usercentricsProxy.showSecondLayer(activity, bannerSettings, promise)
|
|
67
|
+
usercentricsProxy.showSecondLayer(activity, bannerSettings, options.secondLayerTab(), promise)
|
|
68
68
|
} catch (e: Exception) {
|
|
69
69
|
promise.reject(e)
|
|
70
70
|
}
|
|
@@ -6,6 +6,7 @@ import com.facebook.react.bridge.Promise
|
|
|
6
6
|
import com.usercentrics.reactnative.extensions.toWritableMap
|
|
7
7
|
import com.usercentrics.sdk.*
|
|
8
8
|
import com.usercentrics.sdk.errors.UsercentricsError
|
|
9
|
+
import com.usercentrics.sdk.models.settings.SecondLayerTab
|
|
9
10
|
|
|
10
11
|
interface UsercentricsProxy {
|
|
11
12
|
|
|
@@ -21,7 +22,7 @@ interface UsercentricsProxy {
|
|
|
21
22
|
onSubscribeClicked: (String?) -> Unit,
|
|
22
23
|
promise: Promise,
|
|
23
24
|
)
|
|
24
|
-
fun showSecondLayer(activity: Activity, bannerSettings: BannerSettings?, promise: Promise)
|
|
25
|
+
fun showSecondLayer(activity: Activity, bannerSettings: BannerSettings?, tab: SecondLayerTab?, promise: Promise)
|
|
25
26
|
}
|
|
26
27
|
|
|
27
28
|
internal class UsercentricsProxyImpl : UsercentricsProxy {
|
|
@@ -59,9 +60,10 @@ internal class UsercentricsProxyImpl : UsercentricsProxy {
|
|
|
59
60
|
override fun showSecondLayer(
|
|
60
61
|
activity: Activity,
|
|
61
62
|
bannerSettings: BannerSettings?,
|
|
63
|
+
tab: SecondLayerTab?,
|
|
62
64
|
promise: Promise,
|
|
63
65
|
) {
|
|
64
|
-
UsercentricsBanner(activity, bannerSettings).showSecondLayer {
|
|
66
|
+
UsercentricsBanner(activity, bannerSettings).showSecondLayer(tab) {
|
|
65
67
|
promise.resolve(it?.toWritableMap())
|
|
66
68
|
}
|
|
67
69
|
}
|
package/android/src/main/java/com/usercentrics/reactnative/extensions/SecondLayerTabExtensions.kt
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
package com.usercentrics.reactnative.extensions
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.ReadableMap
|
|
4
|
+
import com.facebook.react.bridge.ReadableType
|
|
5
|
+
import com.usercentrics.sdk.models.settings.SecondLayerTab
|
|
6
|
+
|
|
7
|
+
// The tab travels inside the options map. A missing, null, non-string or unknown value falls back
|
|
8
|
+
// to the default tab, like a tab the layout does not have.
|
|
9
|
+
internal fun ReadableMap?.secondLayerTab(): SecondLayerTab? {
|
|
10
|
+
if (this == null || !hasKey("tab") || getType("tab") != ReadableType.String) {
|
|
11
|
+
return null
|
|
12
|
+
}
|
|
13
|
+
val value = getString("tab") ?: return null
|
|
14
|
+
return runCatching { SecondLayerTab.valueOf(value) }.getOrNull()
|
|
15
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
package com.usercentrics.reactnative.extensions
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.JavaOnlyMap
|
|
4
|
+
import com.usercentrics.sdk.models.settings.SecondLayerTab
|
|
5
|
+
import org.junit.Assert.assertEquals
|
|
6
|
+
import org.junit.Assert.assertNull
|
|
7
|
+
import org.junit.Test
|
|
8
|
+
|
|
9
|
+
class SecondLayerTabExtensionsTest {
|
|
10
|
+
|
|
11
|
+
@Test
|
|
12
|
+
fun `secondLayerTab maps SERVICES and PARTNERS`() {
|
|
13
|
+
assertEquals(SecondLayerTab.SERVICES, JavaOnlyMap().apply { putString("tab", "SERVICES") }.secondLayerTab())
|
|
14
|
+
assertEquals(SecondLayerTab.PARTNERS, JavaOnlyMap().apply { putString("tab", "PARTNERS") }.secondLayerTab())
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
@Test
|
|
18
|
+
fun `secondLayerTab keeps the banner settings keys independent of the tab`() {
|
|
19
|
+
val map = JavaOnlyMap().apply {
|
|
20
|
+
putString("variant", "A")
|
|
21
|
+
putString("tab", "PARTNERS")
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
assertEquals(SecondLayerTab.PARTNERS, map.secondLayerTab())
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
@Test
|
|
28
|
+
fun `secondLayerTab falls back to the default tab for a null map`() {
|
|
29
|
+
val map: JavaOnlyMap? = null
|
|
30
|
+
|
|
31
|
+
assertNull(map.secondLayerTab())
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
@Test
|
|
35
|
+
fun `secondLayerTab falls back to the default tab for a missing key`() {
|
|
36
|
+
assertNull(JavaOnlyMap().secondLayerTab())
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
@Test
|
|
40
|
+
fun `secondLayerTab falls back to the default tab for a null value`() {
|
|
41
|
+
assertNull(JavaOnlyMap().apply { putNull("tab") }.secondLayerTab())
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
@Test
|
|
45
|
+
fun `secondLayerTab falls back to the default tab for an unknown or non-string value`() {
|
|
46
|
+
assertNull(JavaOnlyMap().apply { putString("tab", "UNKNOWN") }.secondLayerTab())
|
|
47
|
+
assertNull(JavaOnlyMap().apply { putString("tab", "services") }.secondLayerTab())
|
|
48
|
+
assertNull(JavaOnlyMap().apply { putInt("tab", 1) }.secondLayerTab())
|
|
49
|
+
assertNull(JavaOnlyMap().apply { putBoolean("tab", true) }.secondLayerTab())
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import Usercentrics
|
|
3
|
+
|
|
4
|
+
extension SecondLayerTab {
|
|
5
|
+
// An unknown or missing value falls back to the default tab, like a tab the layout does not have.
|
|
6
|
+
static func from(enumString: String?) -> SecondLayerTab? {
|
|
7
|
+
switch enumString {
|
|
8
|
+
case "SERVICES":
|
|
9
|
+
return SecondLayerTab.services
|
|
10
|
+
case "PARTNERS":
|
|
11
|
+
return SecondLayerTab.partners
|
|
12
|
+
default:
|
|
13
|
+
return nil
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -18,6 +18,7 @@ public protocol UsercentricsManager {
|
|
|
18
18
|
func notifySubscriptionLapsed(onSuccess: @escaping (() -> Void), onError: @escaping ((Error) -> Void))
|
|
19
19
|
|
|
20
20
|
func showSecondLayer(bannerSettings: BannerSettings?,
|
|
21
|
+
tab: SecondLayerTab?,
|
|
21
22
|
dismissViewHandler: @escaping (UsercentricsConsentUserResponse) -> Void)
|
|
22
23
|
|
|
23
24
|
func getControllerId() -> String
|
|
@@ -87,8 +88,9 @@ final class UsercentricsManagerImplementation: UsercentricsManager {
|
|
|
87
88
|
}
|
|
88
89
|
|
|
89
90
|
func showSecondLayer(bannerSettings: BannerSettings?,
|
|
91
|
+
tab: SecondLayerTab?,
|
|
90
92
|
dismissViewHandler: @escaping (UsercentricsConsentUserResponse) -> Void) {
|
|
91
|
-
UsercentricsBanner(bannerSettings: bannerSettings).showSecondLayer(completionHandler: dismissViewHandler)
|
|
93
|
+
UsercentricsBanner(bannerSettings: bannerSettings).showSecondLayer(tab: tab, completionHandler: dismissViewHandler)
|
|
92
94
|
}
|
|
93
95
|
|
|
94
96
|
func restoreUserSession(controllerId: String, onSuccess: @escaping ((UsercentricsReadyStatus) -> Void), onFailure: @escaping ((Error) -> Void)) {
|
|
@@ -98,7 +98,8 @@ class RNUsercentricsModule: RCTEventEmitter {
|
|
|
98
98
|
return
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
-
self.usercentricsManager.showSecondLayer(bannerSettings: BannerSettings(from: dict)
|
|
101
|
+
self.usercentricsManager.showSecondLayer(bannerSettings: BannerSettings(from: dict),
|
|
102
|
+
tab: SecondLayerTab.from(enumString: dict["tab"] as? String)) { response in
|
|
102
103
|
resolve(response.toDictionary())
|
|
103
104
|
}
|
|
104
105
|
}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { TurboModule } from 'react-native';
|
|
2
|
-
import type { UsercentricsOptions, UsercentricsReadyStatus, BannerSettings, UsercentricsConsentUserResponse, UsercentricsServiceConsent, UsercentricsCMPData, AdditionalConsentModeData, TCFData, CCPAData, GppData, UserDecision, TCFUserDecisions, TCFUserDecisionOnPurpose, TCFUserDecisionOnVendor } from './models';
|
|
2
|
+
import type { UsercentricsOptions, UsercentricsReadyStatus, BannerSettings, UsercentricsConsentUserResponse, UsercentricsServiceConsent, UsercentricsCMPData, AdditionalConsentModeData, TCFData, CCPAData, GppData, UserDecision, TCFUserDecisions, TCFUserDecisionOnPurpose, TCFUserDecisionOnVendor, SecondLayerTab } from './models';
|
|
3
3
|
export interface Spec extends TurboModule {
|
|
4
4
|
configure(options: UsercentricsOptions): void;
|
|
5
5
|
isReady(): Promise<UsercentricsReadyStatus>;
|
|
6
6
|
showFirstLayer(options?: BannerSettings): Promise<UsercentricsConsentUserResponse>;
|
|
7
|
-
showSecondLayer(options?: BannerSettings
|
|
7
|
+
showSecondLayer(options?: BannerSettings & {
|
|
8
|
+
tab?: SecondLayerTab;
|
|
9
|
+
}): Promise<UsercentricsConsentUserResponse>;
|
|
8
10
|
restoreUserSession(controllerId: string): Promise<UsercentricsReadyStatus>;
|
|
9
11
|
getControllerId(): Promise<string>;
|
|
10
12
|
clearUserSession(): Promise<UsercentricsReadyStatus>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NativeUsercentrics.js","sourceRoot":"","sources":["../src/NativeUsercentrics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAe,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"NativeUsercentrics.js","sourceRoot":"","sources":["../src/NativeUsercentrics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAe,MAAM,cAAc,CAAC;AA8E/E,yDAAyD;AACzD,MAAM,oBAAoB,GAAG,mBAAmB,CAAC,GAAG,CAAO,sBAAsB,CAAC,IAAI,aAAa,CAAC,oBAAoB,CAAC;AAEzH,IAAI,CAAC,oBAAoB,EAAE,CAAC;IAC1B,MAAM,IAAI,KAAK,CACb,0DAA0D;QAC1D,sDAAsD;QACtD,wCAAwC;QACxC,0DAA0D,CAC3D,CAAC;AACJ,CAAC;AAED,eAAe,oBAA4B,CAAC"}
|
package/lib/Usercentrics.d.ts
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import { EmitterSubscription } from 'react-native';
|
|
2
|
-
import { AdditionalConsentModeData, BannerSettings, CCPAData, GppData, GppSectionChangePayload, TCFData, TCFDecisionUILayer, TCFUserDecisionOnPurpose, TCFUserDecisionOnVendor, TCFUserDecisions, UsercentricsAnalyticsEventType, UsercentricsCMPData, UsercentricsConsentType, UsercentricsConsentUserResponse, UsercentricsOptions, UsercentricsReadyStatus, UsercentricsServiceConsent, UserDecision } from './models';
|
|
2
|
+
import { AdditionalConsentModeData, BannerSettings, CCPAData, GppData, GppSectionChangePayload, SecondLayerTab, TCFData, TCFDecisionUILayer, TCFUserDecisionOnPurpose, TCFUserDecisionOnVendor, TCFUserDecisions, UsercentricsAnalyticsEventType, UsercentricsCMPData, UsercentricsConsentType, UsercentricsConsentUserResponse, UsercentricsOptions, UsercentricsReadyStatus, UsercentricsServiceConsent, UserDecision } from './models';
|
|
3
3
|
export declare const Usercentrics: {
|
|
4
4
|
configure: (options: UsercentricsOptions) => void;
|
|
5
5
|
status: () => Promise<UsercentricsReadyStatus>;
|
|
6
6
|
showFirstLayer: (options?: BannerSettings) => Promise<UsercentricsConsentUserResponse>;
|
|
7
|
-
|
|
7
|
+
/**
|
|
8
|
+
* Shows the second layer, optionally opened directly on [tab]: `SecondLayerTab.services` for
|
|
9
|
+
* GDPR/CCPA layouts, `SecondLayerTab.partners` for TCF layouts. A tab the layout does not have,
|
|
10
|
+
* or no tab, opens the default tab.
|
|
11
|
+
*/
|
|
12
|
+
showSecondLayer: (options?: BannerSettings, tab?: SecondLayerTab) => Promise<UsercentricsConsentUserResponse>;
|
|
8
13
|
restoreUserSession: (controllerId: string) => Promise<UsercentricsReadyStatus>;
|
|
9
14
|
getControllerId: () => Promise<string>;
|
|
10
15
|
getABTestingVariant: () => Promise<string | null>;
|
package/lib/Usercentrics.js
CHANGED
|
@@ -14,9 +14,15 @@ export const Usercentrics = {
|
|
|
14
14
|
await RNUsercentricsModule.isReady();
|
|
15
15
|
return RNUsercentricsModule.showFirstLayer(options);
|
|
16
16
|
},
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
/**
|
|
18
|
+
* Shows the second layer, optionally opened directly on [tab]: `SecondLayerTab.services` for
|
|
19
|
+
* GDPR/CCPA layouts, `SecondLayerTab.partners` for TCF layouts. A tab the layout does not have,
|
|
20
|
+
* or no tab, opens the default tab.
|
|
21
|
+
*/
|
|
22
|
+
showSecondLayer: async (options, tab) => {
|
|
23
|
+
await RNUsercentricsModule.isReady();
|
|
24
|
+
// The tab travels inside the options map, so the native module signatures stay unchanged.
|
|
25
|
+
return RNUsercentricsModule.showSecondLayer(tab ? { ...options, tab } : options);
|
|
20
26
|
},
|
|
21
27
|
restoreUserSession: async (controllerId) => {
|
|
22
28
|
await RNUsercentricsModule.isReady();
|
package/lib/Usercentrics.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Usercentrics.js","sourceRoot":"","sources":["../src/Usercentrics.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAsB,kBAAkB,EAAE,aAAa,EAAC,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"Usercentrics.js","sourceRoot":"","sources":["../src/Usercentrics.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A tab of the second layer that can be opened directly.
|
|
3
|
+
*
|
|
4
|
+
* - `services`: the Services tab of GDPR and CCPA layouts.
|
|
5
|
+
* - `partners`: the Vendors tab of TCF layouts.
|
|
6
|
+
*
|
|
7
|
+
* A tab the current layout does not have, or no tab at all, opens the default tab.
|
|
8
|
+
*/
|
|
9
|
+
export declare enum SecondLayerTab {
|
|
10
|
+
services = "SERVICES",
|
|
11
|
+
partners = "PARTNERS"
|
|
12
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A tab of the second layer that can be opened directly.
|
|
3
|
+
*
|
|
4
|
+
* - `services`: the Services tab of GDPR and CCPA layouts.
|
|
5
|
+
* - `partners`: the Vendors tab of TCF layouts.
|
|
6
|
+
*
|
|
7
|
+
* A tab the current layout does not have, or no tab at all, opens the default tab.
|
|
8
|
+
*/
|
|
9
|
+
export var SecondLayerTab;
|
|
10
|
+
(function (SecondLayerTab) {
|
|
11
|
+
SecondLayerTab["services"] = "SERVICES";
|
|
12
|
+
SecondLayerTab["partners"] = "PARTNERS";
|
|
13
|
+
})(SecondLayerTab || (SecondLayerTab = {}));
|
|
14
|
+
//# sourceMappingURL=SecondLayerTab.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SecondLayerTab.js","sourceRoot":"","sources":["../../src/models/SecondLayerTab.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,CAAN,IAAY,cAIX;AAJD,WAAY,cAAc;IAEtB,uCAAqB,CAAA;IACrB,uCAAqB,CAAA;AACzB,CAAC,EAJW,cAAc,KAAd,cAAc,QAIzB"}
|
package/lib/models/index.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ export * from './CCPAData';
|
|
|
4
4
|
export * from './FirstLayerSettings';
|
|
5
5
|
export * from './NetworkMode';
|
|
6
6
|
export * from './SecondLayerSettings';
|
|
7
|
+
export * from './SecondLayerTab';
|
|
7
8
|
export * from './TCFData';
|
|
8
9
|
export * from './TCFDecisionUILayer';
|
|
9
10
|
export * from './TCFUserDecisions';
|
package/lib/models/index.js
CHANGED
|
@@ -4,6 +4,7 @@ export * from './CCPAData';
|
|
|
4
4
|
export * from './FirstLayerSettings';
|
|
5
5
|
export * from './NetworkMode';
|
|
6
6
|
export * from './SecondLayerSettings';
|
|
7
|
+
export * from './SecondLayerTab';
|
|
7
8
|
export * from './TCFData';
|
|
8
9
|
export * from './TCFDecisionUILayer';
|
|
9
10
|
export * from './TCFUserDecisions';
|
package/lib/models/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/models/index.tsx"],"names":[],"mappings":"AAAA,cAAc,2BAA2B,CAAC;AAC1C,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC;AAC3B,cAAc,sBAAsB,CAAC;AACrC,cAAc,eAAe,CAAC;AAC9B,cAAc,uBAAuB,CAAC;AACtC,cAAc,WAAW,CAAC;AAC1B,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,mCAAmC,CAAC;AAClD,cAAc,2BAA2B,CAAC;AAC1C,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,uBAAuB,CAAC;AACtC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kCAAkC,CAAC;AACjD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,gBAAgB,CAAC;AAC/B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,gBAAgB,CAAC;AAC/B,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAA;AACxC,cAAc,WAAW,CAAA;AACzB,cAAc,2BAA2B,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/models/index.tsx"],"names":[],"mappings":"AAAA,cAAc,2BAA2B,CAAC;AAC1C,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC;AAC3B,cAAc,sBAAsB,CAAC;AACrC,cAAc,eAAe,CAAC;AAC9B,cAAc,uBAAuB,CAAC;AACtC,cAAc,kBAAkB,CAAC;AACjC,cAAc,WAAW,CAAC;AAC1B,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,mCAAmC,CAAC;AAClD,cAAc,2BAA2B,CAAC;AAC1C,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,uBAAuB,CAAC;AACtC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kCAAkC,CAAC;AACjD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,gBAAgB,CAAC;AAC/B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,gBAAgB,CAAC;AAC/B,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAA;AACxC,cAAc,WAAW,CAAA;AACzB,cAAc,2BAA2B,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@usercentrics/react-native-sdk",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.35.0",
|
|
4
4
|
"description": "Usercentrics SDK",
|
|
5
5
|
"homepage": "https://usercentrics.com",
|
|
6
6
|
"main": "lib/index.js",
|
|
7
7
|
"types": "lib/index.d.ts",
|
|
8
8
|
"author": "Usercentrics <developer@usercentrics.com>",
|
|
9
9
|
"iosPackageName": "react-native-usercentrics",
|
|
10
|
-
"iosPackageVersion": "2.
|
|
10
|
+
"iosPackageVersion": "2.35.0",
|
|
11
11
|
"license": "SEE LICENSE IN LICENSE",
|
|
12
12
|
"files": [
|
|
13
13
|
"android",
|
|
@@ -14,6 +14,7 @@ import type {
|
|
|
14
14
|
TCFUserDecisions,
|
|
15
15
|
TCFUserDecisionOnPurpose,
|
|
16
16
|
TCFUserDecisionOnVendor,
|
|
17
|
+
SecondLayerTab,
|
|
17
18
|
} from './models';
|
|
18
19
|
|
|
19
20
|
export interface Spec extends TurboModule {
|
|
@@ -23,7 +24,7 @@ export interface Spec extends TurboModule {
|
|
|
23
24
|
|
|
24
25
|
// UI Methods
|
|
25
26
|
showFirstLayer(options?: BannerSettings): Promise<UsercentricsConsentUserResponse>;
|
|
26
|
-
showSecondLayer(options?: BannerSettings): Promise<UsercentricsConsentUserResponse>;
|
|
27
|
+
showSecondLayer(options?: BannerSettings & { tab?: SecondLayerTab }): Promise<UsercentricsConsentUserResponse>;
|
|
27
28
|
|
|
28
29
|
// Session Management
|
|
29
30
|
restoreUserSession(controllerId: string): Promise<UsercentricsReadyStatus>;
|
package/src/Usercentrics.tsx
CHANGED
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
CCPAData,
|
|
6
6
|
GppData,
|
|
7
7
|
GppSectionChangePayload,
|
|
8
|
+
SecondLayerTab,
|
|
8
9
|
TCFData,
|
|
9
10
|
TCFDecisionUILayer,
|
|
10
11
|
TCFUserDecisionOnPurpose,
|
|
@@ -40,9 +41,15 @@ export const Usercentrics = {
|
|
|
40
41
|
return RNUsercentricsModule.showFirstLayer(options);
|
|
41
42
|
},
|
|
42
43
|
|
|
43
|
-
|
|
44
|
+
/**
|
|
45
|
+
* Shows the second layer, optionally opened directly on [tab]: `SecondLayerTab.services` for
|
|
46
|
+
* GDPR/CCPA layouts, `SecondLayerTab.partners` for TCF layouts. A tab the layout does not have,
|
|
47
|
+
* or no tab, opens the default tab.
|
|
48
|
+
*/
|
|
49
|
+
showSecondLayer: async (options?: BannerSettings, tab?: SecondLayerTab): Promise<UsercentricsConsentUserResponse> => {
|
|
44
50
|
await RNUsercentricsModule.isReady();
|
|
45
|
-
|
|
51
|
+
// The tab travels inside the options map, so the native module signatures stay unchanged.
|
|
52
|
+
return RNUsercentricsModule.showSecondLayer(tab ? {...options, tab} : options);
|
|
46
53
|
},
|
|
47
54
|
|
|
48
55
|
restoreUserSession: async (controllerId: string): Promise<UsercentricsReadyStatus> => {
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
BannerSettings,
|
|
5
5
|
NetworkMode,
|
|
6
6
|
PurposeListStyle,
|
|
7
|
+
SecondLayerTab,
|
|
7
8
|
TCFData,
|
|
8
9
|
TCFDecisionUILayer,
|
|
9
10
|
UsercentricsConsentType,
|
|
@@ -41,6 +42,7 @@ jest.mock("react-native", () => {
|
|
|
41
42
|
isReady: jest.fn(),
|
|
42
43
|
showCMP: jest.fn(),
|
|
43
44
|
showFirstLayer: jest.fn(),
|
|
45
|
+
showSecondLayer: jest.fn(),
|
|
44
46
|
restoreUserSession: jest.fn(),
|
|
45
47
|
getControllerId: jest.fn(),
|
|
46
48
|
getABTestingVariant: jest.fn(),
|
|
@@ -272,6 +274,74 @@ describe('Test Usercentrics Module', () => {
|
|
|
272
274
|
expect(call.initCustomization).toBe(initCustomization);
|
|
273
275
|
})
|
|
274
276
|
|
|
277
|
+
test('testShowSecondLayerWithoutTabPassesOptionsUnchanged', async () => {
|
|
278
|
+
const response = new UsercentricsConsentUserResponse(
|
|
279
|
+
"abc",
|
|
280
|
+
UsercentricsUserInteraction.acceptAll,
|
|
281
|
+
[]
|
|
282
|
+
)
|
|
283
|
+
|
|
284
|
+
RNUsercentricsModule.showSecondLayer.mockImplementationOnce(
|
|
285
|
+
(): Promise<any> => Promise.resolve(response)
|
|
286
|
+
)
|
|
287
|
+
|
|
288
|
+
const bannerSettings: BannerSettings = {
|
|
289
|
+
secondLayerStyleSettings: {
|
|
290
|
+
showCloseButton: true
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
const data = await Usercentrics.showSecondLayer(bannerSettings)
|
|
295
|
+
expect(data).toBe(response);
|
|
296
|
+
|
|
297
|
+
const calls = RNUsercentricsModule.showSecondLayer.mock.calls;
|
|
298
|
+
const call = calls[calls.length - 1][0];
|
|
299
|
+
expect(call).toBe(bannerSettings);
|
|
300
|
+
expect(call.tab).toBeUndefined();
|
|
301
|
+
})
|
|
302
|
+
|
|
303
|
+
test('testShowSecondLayerWithTab', async () => {
|
|
304
|
+
const response = new UsercentricsConsentUserResponse(
|
|
305
|
+
"abc",
|
|
306
|
+
UsercentricsUserInteraction.acceptAll,
|
|
307
|
+
[]
|
|
308
|
+
)
|
|
309
|
+
|
|
310
|
+
const bannerSettings: BannerSettings = {
|
|
311
|
+
secondLayerStyleSettings: {
|
|
312
|
+
showCloseButton: true
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
for (const [tab, expected] of [
|
|
317
|
+
[SecondLayerTab.services, "SERVICES"],
|
|
318
|
+
[SecondLayerTab.partners, "PARTNERS"]
|
|
319
|
+
] as const) {
|
|
320
|
+
RNUsercentricsModule.showSecondLayer.mockImplementationOnce(
|
|
321
|
+
(): Promise<any> => Promise.resolve(response)
|
|
322
|
+
)
|
|
323
|
+
|
|
324
|
+
const data = await Usercentrics.showSecondLayer(bannerSettings, tab)
|
|
325
|
+
expect(data).toBe(response);
|
|
326
|
+
|
|
327
|
+
const calls = RNUsercentricsModule.showSecondLayer.mock.calls;
|
|
328
|
+
expect(calls[calls.length - 1][0]).toEqual({...bannerSettings, tab: expected});
|
|
329
|
+
}
|
|
330
|
+
})
|
|
331
|
+
|
|
332
|
+
test('testShowSecondLayerWithTabAndNoOptions', async () => {
|
|
333
|
+
RNUsercentricsModule.showSecondLayer.mockImplementationOnce(
|
|
334
|
+
(): Promise<any> => Promise.resolve(
|
|
335
|
+
new UsercentricsConsentUserResponse("abc", UsercentricsUserInteraction.acceptAll, [])
|
|
336
|
+
)
|
|
337
|
+
)
|
|
338
|
+
|
|
339
|
+
await Usercentrics.showSecondLayer(undefined, SecondLayerTab.partners)
|
|
340
|
+
|
|
341
|
+
const calls = RNUsercentricsModule.showSecondLayer.mock.calls;
|
|
342
|
+
expect(calls[calls.length - 1][0]).toEqual({tab: "PARTNERS"});
|
|
343
|
+
})
|
|
344
|
+
|
|
275
345
|
test('testRestoreUserSession', async () => {
|
|
276
346
|
const readyStatus = new UsercentricsReadyStatus(
|
|
277
347
|
true,
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A tab of the second layer that can be opened directly.
|
|
3
|
+
*
|
|
4
|
+
* - `services`: the Services tab of GDPR and CCPA layouts.
|
|
5
|
+
* - `partners`: the Vendors tab of TCF layouts.
|
|
6
|
+
*
|
|
7
|
+
* A tab the current layout does not have, or no tab at all, opens the default tab.
|
|
8
|
+
*/
|
|
9
|
+
export enum SecondLayerTab {
|
|
10
|
+
|
|
11
|
+
services = "SERVICES",
|
|
12
|
+
partners = "PARTNERS"
|
|
13
|
+
}
|
package/src/models/index.tsx
CHANGED
|
@@ -4,6 +4,7 @@ export * from './CCPAData';
|
|
|
4
4
|
export * from './FirstLayerSettings';
|
|
5
5
|
export * from './NetworkMode';
|
|
6
6
|
export * from './SecondLayerSettings';
|
|
7
|
+
export * from './SecondLayerTab';
|
|
7
8
|
export * from './TCFData';
|
|
8
9
|
export * from './TCFDecisionUILayer';
|
|
9
10
|
export * from './TCFUserDecisions';
|