cm-sdk-react-native-v3 3.6.1 → 3.6.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/src/index.tsx CHANGED
@@ -1,4 +1,4 @@
1
- import { NativeModules, Platform, NativeEventEmitter } from 'react-native';
1
+ import { NativeModules, Platform, NativeEventEmitter, processColor } from 'react-native';
2
2
  import NativeCmSdkReactNativeV3, {
3
3
  type ConsentReceivedEvent,
4
4
  type ErrorEvent,
@@ -6,29 +6,37 @@ import NativeCmSdkReactNativeV3, {
6
6
  type ATTStatusChangeEvent,
7
7
  type UrlConfig,
8
8
  type WebViewConfig,
9
+ type WebViewRect,
10
+ type WebViewBackgroundStyle,
11
+ WebViewPosition,
12
+ BackgroundStyleType,
13
+ BlurEffectStyle,
14
+ ATTStatus,
9
15
  type UserStatus,
10
16
  type GoogleConsentModeStatus,
17
+ type CmSdkReactNativeV3Module,
11
18
  } from './NativeCmSdkReactNativeV3';
12
19
 
20
+ // Re-export enums/constants for consumers
21
+ export { WebViewPosition, BackgroundStyleType, BlurEffectStyle, ATTStatus };
22
+
13
23
  const LINKING_ERROR =
14
24
  `The package 'react-native-cm-sdk-react-native-v3' doesn't seem to be linked. Make sure: \n\n` +
15
25
  Platform.select({ ios: "- You have run 'pod install'\n", default: '' }) +
16
26
  '- You rebuilt the app after installing the package\n' +
17
27
  '- You are not using Expo Go\n';
18
28
 
19
- // Use TurboModule if available (New Architecture), fallback to legacy NativeModules
20
- const CmSdkReactNativeV3 = NativeCmSdkReactNativeV3 ?? (NativeModules.CmSdkReactNativeV3
21
- ? NativeModules.CmSdkReactNativeV3
22
- : new Proxy(
23
- {},
24
- {
25
- get() {
26
- throw new Error(LINKING_ERROR);
27
- },
28
- }
29
- ));
30
-
31
- export const isTurboModuleEnabled = NativeCmSdkReactNativeV3 != null;
29
+ const CmSdkReactNativeV3: CmSdkReactNativeV3Module =
30
+ NativeCmSdkReactNativeV3 ??
31
+ (NativeModules.CmSdkReactNativeV3 as CmSdkReactNativeV3Module | undefined) ??
32
+ (new Proxy(
33
+ {},
34
+ {
35
+ get() {
36
+ throw new Error(LINKING_ERROR);
37
+ },
38
+ }
39
+ ) as CmSdkReactNativeV3Module);
32
40
 
33
41
  const eventEmitter = new NativeEventEmitter(CmSdkReactNativeV3);
34
42
 
@@ -70,10 +78,22 @@ export const setUrlConfig = (config: UrlConfig): Promise<void> => {
70
78
  };
71
79
 
72
80
  export const setWebViewConfig = (config: WebViewConfig): Promise<void> => {
73
- return CmSdkReactNativeV3.setWebViewConfig(config);
81
+ const normalized = normalizeWebViewConfig(config);
82
+ return CmSdkReactNativeV3.setWebViewConfig(normalized);
74
83
  };
75
84
 
76
- export const setATTStatus = (status: number): Promise<void> => {
85
+ export const setATTStatus = (status: ATTStatus | number): Promise<void> => {
86
+ const allowed = new Set<ATTStatus>([
87
+ ATTStatus.NotDetermined,
88
+ ATTStatus.Restricted,
89
+ ATTStatus.Denied,
90
+ ATTStatus.Authorized,
91
+ ]);
92
+ if (!allowed.has(status as ATTStatus)) {
93
+ throw new Error(
94
+ `[cm-sdk-react-native-v3] Invalid ATT status ${status}. Use ATTStatus enum (0–3 from Apple's ATTrackingManagerAuthorizationStatus).`
95
+ );
96
+ }
77
97
  return CmSdkReactNativeV3.setATTStatus(status);
78
98
  };
79
99
 
@@ -91,6 +111,96 @@ export const getUserStatus = (): Promise<UserStatus> => {
91
111
  return CmSdkReactNativeV3.getUserStatus();
92
112
  };
93
113
 
114
+ // Helpers
115
+ const normalizeWebViewConfig = (config: WebViewConfig): WebViewConfig => {
116
+ const position = (config.position as WebViewPosition | undefined) ?? WebViewPosition.FullScreen;
117
+ const allowedPositions = [
118
+ WebViewPosition.FullScreen,
119
+ WebViewPosition.HalfScreenTop,
120
+ WebViewPosition.HalfScreenBottom,
121
+ WebViewPosition.Custom,
122
+ ];
123
+ if (!allowedPositions.includes(position)) {
124
+ throw new Error(`Invalid WebView position: ${position}`);
125
+ }
126
+
127
+ if (position === WebViewPosition.Custom) {
128
+ if (!config.customRect) {
129
+ throw new Error('customRect is required when position is "custom"');
130
+ }
131
+ if (Platform.OS === 'android') {
132
+ console.warn(
133
+ '[cm-sdk-react-native-v3] Android native SDK currently ignores customRect/position "custom"; it will fall back to full screen.'
134
+ );
135
+ }
136
+ }
137
+
138
+ const backgroundStyle = (() => {
139
+ if (!config.backgroundStyle) {
140
+ return {
141
+ type: BackgroundStyleType.Dimmed,
142
+ color: normalizeColor('black'),
143
+ opacity: 0.5,
144
+ } as WebViewBackgroundStyle;
145
+ }
146
+ const { type } = config.backgroundStyle;
147
+ switch (type) {
148
+ case BackgroundStyleType.Dimmed:
149
+ return {
150
+ type,
151
+ color: normalizeColor(config.backgroundStyle.color ?? 'black'),
152
+ opacity: config.backgroundStyle.opacity ?? 0.5,
153
+ } as WebViewBackgroundStyle;
154
+ case BackgroundStyleType.Color:
155
+ if (!config.backgroundStyle.color) throw new Error('color is required for backgroundStyle "color"');
156
+ return { type, color: normalizeColor(config.backgroundStyle.color) } as WebViewBackgroundStyle;
157
+ case BackgroundStyleType.Blur: {
158
+ const blurStyle =
159
+ config.backgroundStyle.blurEffectStyle ?? (Platform.OS === 'ios'
160
+ ? BlurEffectStyle.Dark
161
+ : BlurEffectStyle.Dark);
162
+ if (
163
+ blurStyle !== BlurEffectStyle.Dark &&
164
+ blurStyle !== BlurEffectStyle.Light &&
165
+ blurStyle !== BlurEffectStyle.ExtraLight
166
+ ) {
167
+ throw new Error(`Invalid blurEffectStyle: ${blurStyle}`);
168
+ }
169
+ if (Platform.OS === 'android') {
170
+ console.warn('[cm-sdk-react-native-v3] Android native SDK currently ignores blur backgrounds; using dimmed.');
171
+ }
172
+ return { type, blurEffectStyle: blurStyle } as WebViewBackgroundStyle;
173
+ }
174
+ case BackgroundStyleType.None:
175
+ return { type } as WebViewBackgroundStyle;
176
+ default:
177
+ throw new Error(`Invalid backgroundStyle type: ${(config.backgroundStyle as any).type}`);
178
+ }
179
+ })();
180
+
181
+ if (Platform.OS === 'android' && config.backgroundStyle) {
182
+ console.warn(
183
+ '[cm-sdk-react-native-v3] Android native SDK currently ignores backgroundStyle overrides; it always uses a dimmed background.'
184
+ );
185
+ }
186
+
187
+ return {
188
+ position,
189
+ customRect: config.customRect,
190
+ cornerRadius: config.cornerRadius ?? 5,
191
+ respectsSafeArea: config.respectsSafeArea ?? true,
192
+ allowsOrientationChanges: config.allowsOrientationChanges ?? true,
193
+ backgroundStyle,
194
+ };
195
+ };
196
+
197
+ const normalizeColor = (color: string | number | undefined) => {
198
+ if (color === undefined) return undefined;
199
+ const processed = processColor(color);
200
+ if (processed == null) throw new Error(`Invalid color value: ${color}`);
201
+ return processed;
202
+ };
203
+
94
204
  export const getStatusForPurpose = (purposeId: string): Promise<string> => {
95
205
  return CmSdkReactNativeV3.getStatusForPurpose(purposeId);
96
206
  };
@@ -140,27 +250,6 @@ export const acceptAll = (): Promise<boolean> => {
140
250
  return CmSdkReactNativeV3.acceptAll();
141
251
  };
142
252
 
143
- // Helper function to check if New Architecture is enabled
144
- export const isNewArchitectureEnabled = (): boolean => {
145
- // Check multiple indicators for New Architecture
146
- // 1. Check if our module was loaded via TurboModuleRegistry
147
- if (NativeCmSdkReactNativeV3 != null) {
148
- return true;
149
- }
150
-
151
- // 2. Check for bridgeless mode (official RN flag)
152
- if ((global as any).RN$Bridgeless === true) {
153
- return true;
154
- }
155
-
156
- // 3. Check for TurboModule interop flag
157
- if ((global as any).RN$TurboInterop === true) {
158
- return true;
159
- }
160
-
161
- return false;
162
- };
163
-
164
253
  // Re-export types for consumer convenience
165
254
  export type {
166
255
  ConsentReceivedEvent,
@@ -168,9 +257,31 @@ export type {
168
257
  LinkClickEvent,
169
258
  ATTStatusChangeEvent,
170
259
  UrlConfig,
260
+ WebViewRect,
261
+ WebViewBackgroundStyle,
171
262
  WebViewConfig,
172
263
  UserStatus,
173
264
  GoogleConsentModeStatus,
174
265
  };
175
266
 
267
+ /**
268
+ * Helper factory to build strongly-typed background styles.
269
+ */
270
+ export const BackgroundStyle = {
271
+ dimmed: (color?: string | number, opacity?: number): WebViewBackgroundStyle => ({
272
+ type: BackgroundStyleType.Dimmed,
273
+ color,
274
+ opacity,
275
+ }),
276
+ color: (color: string | number): WebViewBackgroundStyle => ({
277
+ type: BackgroundStyleType.Color,
278
+ color,
279
+ }),
280
+ blur: (blurEffectStyle: BlurEffectStyle = BlurEffectStyle.Dark): WebViewBackgroundStyle => ({
281
+ type: BackgroundStyleType.Blur,
282
+ blurEffectStyle,
283
+ }),
284
+ none: (): WebViewBackgroundStyle => ({ type: BackgroundStyleType.None }),
285
+ } as const;
286
+
176
287
  export default CmSdkReactNativeV3;