clintplay-react-native 0.2.0 → 0.2.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
@@ -2,7 +2,7 @@
2
2
 
3
3
  Session capture SDK for React Native / Expo apps — companion to [`clintplay-sdk`](../sdk) (web). Captures lifecycle, screen dimensions, navigation, JS errors, network requests (Fetch & XHR/Axios), console output, touches (screen-relative & target-relative), and native visual wireframe replay on iOS and Android.
4
4
 
5
- > **Status:** `0.2.0` — Production-ready JS runtime and Native TurboModule. Supports native view hierarchy traversal on iOS (`ios/ClintplayRN.mm`) and Android (`android/.../ClintplayRNModule.kt`), visual wireframe session replay, network interception for `fetch` and `XMLHttpRequest`/Axios, automatic navigation tracking, and intelligent auto-masking for sensitive fields.
5
+ > **Status:** `0.2.2` — Production-ready JS runtime and Native TurboModule. Supports native view hierarchy traversal on iOS (`ios/ClintplayRN.mm`) and Android (`android/.../ClintplayRNModule.kt`), visual wireframe session replay, network interception for `fetch` and `XMLHttpRequest`/Axios, automatic navigation tracking, and intelligent auto-masking for sensitive fields.
6
6
 
7
7
  ## Install
8
8
 
@@ -12,7 +12,7 @@ pnpm add clintplay-react-native
12
12
  npm install clintplay-react-native
13
13
  ```
14
14
 
15
- Peer deps: `react >=18`, `react-native >=0.74`. Optional peer: `@react-native-async-storage/async-storage` (enables the offline retry queue when present). Tested against Expo SDK 54 / RN 0.81 with New Architecture enabled.
15
+ Peer deps: `react >=18`, `react-native >=0.74`. Optional peer: `@react-native-async-storage/async-storage` (enables the offline retry queue when present). Android verified on Expo SDK 57 / RN 0.86.3 with New Architecture (debug and release builds, and wireframe capture on an emulator); iOS not re-verified on that version.
16
16
 
17
17
  In your `app.json`, register the config plugin:
18
18
 
@@ -81,7 +81,7 @@ export default function RootLayout() {
81
81
  | `enabled` | `boolean` | `true` | Master killswitch. Set to `false` to disable all telemetry. |
82
82
  | `sampleRate` | `number` | `1.0` | Probabilistic sampling rate between `0.0` and `1.0`. |
83
83
  | `captureWireframe` | `boolean` | `false` | Enable native view-hierarchy visual wireframe capture for session replay. |
84
- | `wireframeIntervalMs` | `number` | `1000` | Wireframe snapshot interval in milliseconds. |
84
+ | `wireframeIntervalMs` | `number` | `1000` | Wireframe snapshot interval in milliseconds. A snapshot identical to the previous one is not re-sent (an unchanged screen is re-sent every 30 s), and a snapshot is also taken ~400 ms after every touch end and navigation, so screens visited for less than the interval still reach the replay. |
85
85
  | `captureNetwork` | `boolean` | `true` | Intercept `globalThis.fetch` and `XMLHttpRequest` (including Axios) requests. |
86
86
  | `captureConsole` | `boolean` | `false` | Intercept `console.warn` and `console.error` logs. |
87
87
  | `captureConsoleLog` | `boolean` | `false` | Intercept `console.log` logs when `captureConsole: true`. |
@@ -104,7 +104,7 @@ export default function RootLayout() {
104
104
  | `network` | `fetch` & `XMLHttpRequest` / Axios | **On** | HTTP method, URL (sanitized), status code, duration, and errors. Protected against double-counting. |
105
105
  | `navigation` | Navigation Trackers & `trackScreen` | **On (Tracker)** | Screen path changes (`to`, `from`). Automatic via `<ClintplayNavigationTracker />` or React Navigation listener. |
106
106
  | `touch` | `<ClintplayCaptureProvider>` | **Provider** | Tap / touch gestures with both screen-relative coordinates (`screenX`, `screenY`) and target-relative coordinates (`x`, `y`). |
107
- | `wireframe` | Native TurboModule | **Opt-in** | Visual UI hierarchy snapshots (view rects, styles, text, masking) across iOS and Android. |
107
+ | `wireframe` | Native TurboModule | **Opt-in** | Visual UI hierarchy snapshots (view rects, background colors, text with font size, color and alignment — plus weight on iOS, and bold on Android —, masking) across iOS and Android. Sent on change, after interactions, and every 30 s while unchanged. |
108
108
  | `log` | Console Interceptor | **Opt-in** | Console output (`warn`, `error`, and optional `log`). |
109
109
  | `identify` | `Clintplay.identify()` | **Manual** | Associating sessions with authenticated users and custom traits. |
110
110
 
@@ -1,19 +1,16 @@
1
- buildscript {
2
- // Match the consumer app's Kotlin version so we don't drag in a
3
- // conflicting toolchain. Most modern Expo SDK 54 / RN 0.81 apps
4
- // ship Kotlin 1.9.x.
5
- ext.kotlin_version = rootProject.ext.kotlin_version ?: '1.9.24'
6
-
7
- repositories {
8
- google()
9
- mavenCentral()
10
- }
11
- dependencies {
12
- classpath "com.android.tools.build:gradle:8.6.0"
13
- classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
14
- }
15
- }
16
-
1
+ // No `buildscript` block: this module is only built inside a host app, whose
2
+ // root build.gradle already puts the Android and Kotlin Gradle plugins on the
3
+ // classpath (bare RN and Expo templates alike). Don't read a Kotlin version from
4
+ // `rootProject.ext` either: Expo's template defines none, and in Groovy reading
5
+ // a missing `ext` property throws instead of returning null.
6
+
7
+ // On the classpath through the host's root build.gradle (resolved by the
8
+ // includeBuild in its settings.gradle). Runs the codegen for the
9
+ // `codegenConfig` in package.json (`ClintplayRNSpec`): autolinking adds that
10
+ // spec's `codegen/jni` folder to the app's CMake build and its C++
11
+ // ModuleProvider is what binds this TurboModule to JS, so without the plugin
12
+ // the app's CMake configure fails on a directory that was never generated.
13
+ apply plugin: 'com.facebook.react'
17
14
  apply plugin: 'com.android.library'
18
15
  apply plugin: 'org.jetbrains.kotlin.android'
19
16
 
@@ -2,13 +2,19 @@ package digital.clint.clintplay
2
2
 
3
3
  import android.app.Activity
4
4
  import android.content.Context
5
+ import android.graphics.Typeface
5
6
  import android.graphics.drawable.ColorDrawable
6
7
  import android.graphics.drawable.Drawable
7
8
  import android.os.Build
8
9
  import android.os.Handler
9
10
  import android.os.Looper
10
11
  import android.text.InputType
12
+ import android.text.Spanned
11
13
  import android.text.method.PasswordTransformationMethod
14
+ import android.text.style.AbsoluteSizeSpan
15
+ import android.text.style.ForegroundColorSpan
16
+ import android.text.style.StyleSpan
17
+ import android.view.Gravity
12
18
  import android.view.View
13
19
  import android.view.ViewGroup
14
20
  import android.view.WindowManager
@@ -37,9 +43,11 @@ import kotlin.math.round
37
43
  // coordinate conversion, background colors, extracted text, and
38
44
  // privacy auto-masking (clintplay-mask tags, password fields, and sensitive autofill hints).
39
45
  //
40
- // React Native's codegen emits `NativeClintplayRNSpec` from
41
- // `src/spec/NativeClintplayRN.ts` at build time. The TurboReactPackage
42
- // in `ClintplayRNPackage.kt` routes calls here.
46
+ // React Native's codegen emits `NativeClintplayRNSpec` and its C++ JSI glue
47
+ // from `src/spec/NativeClintplayRN.ts` at build time. This class does not
48
+ // extend that spec: the glue calls the methods below by name and JNI signature
49
+ // (`()Ljava/lang/String;`), so they must match the spec by hand. The
50
+ // TurboReactPackage in `ClintplayRNPackage.kt` routes calls here.
43
51
  @ReactModule(name = ClintplayRNModule.NAME)
44
52
  class ClintplayRNModule(reactContext: ReactApplicationContext) :
45
53
  ReactContextBaseJavaModule(reactContext), TurboModule {
@@ -112,6 +120,45 @@ class ClintplayRNModule(reactContext: ReactApplicationContext) :
112
120
  return false
113
121
  }
114
122
 
123
+ // React Native sets size and colour as spans on the text, so the spans at the first
124
+ // character win over the TextView's own defaults. Weight is only sent when bold is
125
+ // actually detected: RN carries it in its own CustomStyleSpan, which this does not read,
126
+ // and a guessed 400 would look measured. Best effort: the text alone already makes the
127
+ // replay readable.
128
+ private fun putTextStyle(node: JSONObject, view: TextView, density: Float) {
129
+ try {
130
+ val text = view.text
131
+ val safeDensity = if (density > 0f) density else 1f
132
+ var sizePx = view.textSize
133
+ var color = view.currentTextColor
134
+ var bold = view.typeface?.isBold == true
135
+ if (text is Spanned && text.isNotEmpty()) {
136
+ text.getSpans(0, 1, AbsoluteSizeSpan::class.java).lastOrNull()?.let { span ->
137
+ sizePx = if (span.dip) span.size * safeDensity else span.size.toFloat()
138
+ }
139
+ text.getSpans(0, 1, ForegroundColorSpan::class.java).lastOrNull()?.let { span ->
140
+ color = span.foregroundColor
141
+ }
142
+ if (text.getSpans(0, 1, StyleSpan::class.java).any { (it.style and Typeface.BOLD) != 0 }) {
143
+ bold = true
144
+ }
145
+ }
146
+ node.put("fontSize", round(sizePx / safeDensity * 10.0) / 10.0)
147
+ if (bold) node.put("fontWeight", 700)
148
+ node.put("color", formatColor(color))
149
+ val horizontal = Gravity.getAbsoluteGravity(view.gravity, view.layoutDirection) and
150
+ Gravity.HORIZONTAL_GRAVITY_MASK
151
+ node.put(
152
+ "textAlign",
153
+ when (horizontal) {
154
+ Gravity.CENTER_HORIZONTAL -> "center"
155
+ Gravity.RIGHT -> "right"
156
+ else -> "left"
157
+ },
158
+ )
159
+ } catch (_: Throwable) {}
160
+ }
161
+
115
162
  private fun serializeView(
116
163
  view: View?,
117
164
  nodeCounter: AtomicInteger,
@@ -206,6 +253,9 @@ class ClintplayRNModule(reactContext: ReactApplicationContext) :
206
253
  var extractedText: String? = null
207
254
  if (view is TextView) {
208
255
  extractedText = view.text?.toString()
256
+ if (!isMasked && !extractedText.isNullOrEmpty()) {
257
+ putTextStyle(nodeObj, view, density)
258
+ }
209
259
  }
210
260
 
211
261
  if (extractedText != null) {
@@ -278,7 +328,9 @@ class ClintplayRNModule(reactContext: ReactApplicationContext) :
278
328
 
279
329
  @ReactMethod(isBlockingSynchronousMethod = true)
280
330
  fun captureViewHierarchy(): String {
281
- val activity = currentActivity ?: return FALLBACK_JSON
331
+ // Not the inherited `currentActivity`: since RN 0.80 that is a deprecated
332
+ // protected Kotlin function, which property syntax does not resolve.
333
+ val activity = reactApplicationContext.currentActivity ?: return FALLBACK_JSON
282
334
 
283
335
  if (activity.isFinishing || activity.isDestroyed) {
284
336
  return FALLBACK_JSON
@@ -328,7 +380,7 @@ class ClintplayRNModule(reactContext: ReactApplicationContext) :
328
380
 
329
381
  companion object {
330
382
  const val NAME = "ClintplayRN"
331
- private const val VERSION = "0.2.0"
383
+ private const val VERSION = "0.2.2"
332
384
  private const val FALLBACK_JSON = "{\"version\":1,\"nodes\":[]}"
333
385
 
334
386
  private val NO_METHOD_SENTINEL = Any()
package/dist/index.d.mts CHANGED
@@ -7,6 +7,8 @@ interface SessionState {
7
7
  startedAt: number;
8
8
  lastActivity: number;
9
9
  userId: string | null;
10
+ tags: Set<string>;
11
+ metadata: Record<string, unknown>;
10
12
  }
11
13
  declare class SessionManager {
12
14
  private state;
@@ -15,13 +17,16 @@ declare class SessionManager {
15
17
  private create;
16
18
  current(): SessionState;
17
19
  touch(): void;
20
+ addTag(tag: string): boolean;
21
+ hasTag(tag: string): boolean;
22
+ setMetadata(data: Record<string, unknown>): void;
18
23
  setUser(userId: string | null): boolean;
19
24
  isStale(): boolean;
20
25
  rotateIfStale(): boolean;
21
26
  reset(): void;
22
27
  }
23
28
 
24
- type EventType = 'meta' | 'screen' | 'lifecycle' | 'navigation' | 'touch' | 'error' | 'log' | 'identify' | 'network' | 'wireframe';
29
+ type EventType = 'meta' | 'screen' | 'lifecycle' | 'navigation' | 'touch' | 'error' | 'log' | 'identify' | 'network' | 'wireframe' | 'metadata' | 'tag';
25
30
  interface DeviceInfo {
26
31
  platform: 'ios' | 'android' | 'web';
27
32
  osVersion?: string;
@@ -92,6 +97,18 @@ interface NetworkEvent {
92
97
  durationMs?: number;
93
98
  error?: string;
94
99
  }
100
+ interface MetadataEvent {
101
+ type: 'metadata';
102
+ ts: number;
103
+ data: Record<string, unknown>;
104
+ }
105
+ interface TagEvent {
106
+ type: 'tag';
107
+ ts: number;
108
+ data: {
109
+ tag: string;
110
+ };
111
+ }
95
112
  interface WireframeNode {
96
113
  id: number;
97
114
  type: string;
@@ -117,7 +134,7 @@ interface WireframeEvent {
117
134
  version: number;
118
135
  nodes: WireframeNode[];
119
136
  }
120
- type ReplayEvent = MetaEvent | ScreenEvent | LifecycleEvent | NavigationEvent | TouchEvent | ErrorEvent | LogEvent | IdentifyEvent | NetworkEvent | WireframeEvent;
137
+ type ReplayEvent = MetaEvent | ScreenEvent | LifecycleEvent | NavigationEvent | TouchEvent | ErrorEvent | LogEvent | IdentifyEvent | NetworkEvent | WireframeEvent | MetadataEvent | TagEvent;
121
138
  interface BackendEvent {
122
139
  type: string;
123
140
  timestamp: number;
@@ -186,6 +203,10 @@ interface Recorder {
186
203
  start(): void;
187
204
  stop(): void;
188
205
  takeWireframeSnapshot(): void;
206
+ /** Captura depois que a interação assenta (toque, navegação). Chamadas próximas viram uma. */
207
+ scheduleWireframeSnapshot(): void;
208
+ /** A próxima captura é enviada mesmo igual à anterior (sessão nova precisa da tela). */
209
+ resetWireframeBaseline(): void;
189
210
  }
190
211
 
191
212
  interface NetworkInterceptorDeps {
@@ -386,6 +407,13 @@ interface InternalConfig {
386
407
  debug: boolean;
387
408
  captureWireframe: boolean;
388
409
  }
410
+ declare const METADATA_MAX_KEYS = 50;
411
+ declare const METADATA_MAX_DEPTH = 3;
412
+ declare const METADATA_MAX_STRING_LENGTH = 1024;
413
+ declare const METADATA_MAX_BYTES = 8192;
414
+ declare const TAG_MAX_LENGTH = 128;
415
+ declare function sanitizeTag(rawTag: unknown): string | null;
416
+ declare function sanitizeMetadata(data: unknown): Record<string, unknown> | null;
389
417
  declare function formatEventForBatch(event: ReplayEvent | BackendEvent, defaultSessionId: string): BackendEvent;
390
418
  declare function init(rawConfig: ClintplayReactNativeConfig): typeof Clintplay;
391
419
  declare function identify(userId: string | number | null, traits?: Record<string, unknown>): void;
@@ -394,6 +422,8 @@ declare function reset(options?: {
394
422
  }): void;
395
423
  declare function trackScreen(path: string, from?: string): void;
396
424
  declare function reportError(err: unknown): void;
425
+ declare function setMetadata(data: Record<string, unknown>): void;
426
+ declare function tag(tagName: string): void;
397
427
  declare function flush(): Promise<void>;
398
428
  declare function stop(): Promise<void>;
399
429
  declare function current(): {
@@ -419,10 +449,12 @@ declare const Clintplay: {
419
449
  reset: typeof reset;
420
450
  trackScreen: typeof trackScreen;
421
451
  reportError: typeof reportError;
452
+ setMetadata: typeof setMetadata;
453
+ tag: typeof tag;
422
454
  flush: typeof flush;
423
455
  stop: typeof stop;
424
456
  current: typeof current;
425
457
  _getState: typeof _getState;
426
458
  };
427
459
 
428
- export { type BackendEvent, CLINTPLAY_MASK_ID, Clintplay, ClintplayCaptureProvider, type ClintplayCaptureProviderProps, ClintplayMaskImage, type ClintplayMaskImageProps, ClintplayMaskTextInput, type ClintplayMaskTextInputProps, ClintplayMaskView, type ClintplayMaskViewProps, ClintplayNavigationTracker, type ClintplayNavigationTrackerProps, type ClintplayReactNativeConfig, type DeviceInfo, type NavigationRouteLike, type NavigationStateLike, type NavigationStateListenerCallback, type NavigationStateListenerOptions, type ReplayBatch, type ReplayEvent, SDK_VERSION, type UseClintplayNavigationOptions, type UseClintplayNavigationResult, type WireframeEvent, type WireframeNode, _resetLastTrackedRoute, createClintplayNavigationStateListener, formatEventForBatch, getActiveRouteName, init, sanitizeRoute, useClintplayNavigationTracking };
460
+ export { type BackendEvent, CLINTPLAY_MASK_ID, Clintplay, ClintplayCaptureProvider, type ClintplayCaptureProviderProps, ClintplayMaskImage, type ClintplayMaskImageProps, ClintplayMaskTextInput, type ClintplayMaskTextInputProps, ClintplayMaskView, type ClintplayMaskViewProps, ClintplayNavigationTracker, type ClintplayNavigationTrackerProps, type ClintplayReactNativeConfig, type DeviceInfo, METADATA_MAX_BYTES, METADATA_MAX_DEPTH, METADATA_MAX_KEYS, METADATA_MAX_STRING_LENGTH, type MetadataEvent, type NavigationRouteLike, type NavigationStateLike, type NavigationStateListenerCallback, type NavigationStateListenerOptions, type ReplayBatch, type ReplayEvent, SDK_VERSION, TAG_MAX_LENGTH, type TagEvent, type UseClintplayNavigationOptions, type UseClintplayNavigationResult, type WireframeEvent, type WireframeNode, _resetLastTrackedRoute, createClintplayNavigationStateListener, formatEventForBatch, getActiveRouteName, init, sanitizeMetadata, sanitizeRoute, sanitizeTag, setMetadata, tag, useClintplayNavigationTracking };
package/dist/index.d.ts CHANGED
@@ -7,6 +7,8 @@ interface SessionState {
7
7
  startedAt: number;
8
8
  lastActivity: number;
9
9
  userId: string | null;
10
+ tags: Set<string>;
11
+ metadata: Record<string, unknown>;
10
12
  }
11
13
  declare class SessionManager {
12
14
  private state;
@@ -15,13 +17,16 @@ declare class SessionManager {
15
17
  private create;
16
18
  current(): SessionState;
17
19
  touch(): void;
20
+ addTag(tag: string): boolean;
21
+ hasTag(tag: string): boolean;
22
+ setMetadata(data: Record<string, unknown>): void;
18
23
  setUser(userId: string | null): boolean;
19
24
  isStale(): boolean;
20
25
  rotateIfStale(): boolean;
21
26
  reset(): void;
22
27
  }
23
28
 
24
- type EventType = 'meta' | 'screen' | 'lifecycle' | 'navigation' | 'touch' | 'error' | 'log' | 'identify' | 'network' | 'wireframe';
29
+ type EventType = 'meta' | 'screen' | 'lifecycle' | 'navigation' | 'touch' | 'error' | 'log' | 'identify' | 'network' | 'wireframe' | 'metadata' | 'tag';
25
30
  interface DeviceInfo {
26
31
  platform: 'ios' | 'android' | 'web';
27
32
  osVersion?: string;
@@ -92,6 +97,18 @@ interface NetworkEvent {
92
97
  durationMs?: number;
93
98
  error?: string;
94
99
  }
100
+ interface MetadataEvent {
101
+ type: 'metadata';
102
+ ts: number;
103
+ data: Record<string, unknown>;
104
+ }
105
+ interface TagEvent {
106
+ type: 'tag';
107
+ ts: number;
108
+ data: {
109
+ tag: string;
110
+ };
111
+ }
95
112
  interface WireframeNode {
96
113
  id: number;
97
114
  type: string;
@@ -117,7 +134,7 @@ interface WireframeEvent {
117
134
  version: number;
118
135
  nodes: WireframeNode[];
119
136
  }
120
- type ReplayEvent = MetaEvent | ScreenEvent | LifecycleEvent | NavigationEvent | TouchEvent | ErrorEvent | LogEvent | IdentifyEvent | NetworkEvent | WireframeEvent;
137
+ type ReplayEvent = MetaEvent | ScreenEvent | LifecycleEvent | NavigationEvent | TouchEvent | ErrorEvent | LogEvent | IdentifyEvent | NetworkEvent | WireframeEvent | MetadataEvent | TagEvent;
121
138
  interface BackendEvent {
122
139
  type: string;
123
140
  timestamp: number;
@@ -186,6 +203,10 @@ interface Recorder {
186
203
  start(): void;
187
204
  stop(): void;
188
205
  takeWireframeSnapshot(): void;
206
+ /** Captura depois que a interação assenta (toque, navegação). Chamadas próximas viram uma. */
207
+ scheduleWireframeSnapshot(): void;
208
+ /** A próxima captura é enviada mesmo igual à anterior (sessão nova precisa da tela). */
209
+ resetWireframeBaseline(): void;
189
210
  }
190
211
 
191
212
  interface NetworkInterceptorDeps {
@@ -386,6 +407,13 @@ interface InternalConfig {
386
407
  debug: boolean;
387
408
  captureWireframe: boolean;
388
409
  }
410
+ declare const METADATA_MAX_KEYS = 50;
411
+ declare const METADATA_MAX_DEPTH = 3;
412
+ declare const METADATA_MAX_STRING_LENGTH = 1024;
413
+ declare const METADATA_MAX_BYTES = 8192;
414
+ declare const TAG_MAX_LENGTH = 128;
415
+ declare function sanitizeTag(rawTag: unknown): string | null;
416
+ declare function sanitizeMetadata(data: unknown): Record<string, unknown> | null;
389
417
  declare function formatEventForBatch(event: ReplayEvent | BackendEvent, defaultSessionId: string): BackendEvent;
390
418
  declare function init(rawConfig: ClintplayReactNativeConfig): typeof Clintplay;
391
419
  declare function identify(userId: string | number | null, traits?: Record<string, unknown>): void;
@@ -394,6 +422,8 @@ declare function reset(options?: {
394
422
  }): void;
395
423
  declare function trackScreen(path: string, from?: string): void;
396
424
  declare function reportError(err: unknown): void;
425
+ declare function setMetadata(data: Record<string, unknown>): void;
426
+ declare function tag(tagName: string): void;
397
427
  declare function flush(): Promise<void>;
398
428
  declare function stop(): Promise<void>;
399
429
  declare function current(): {
@@ -419,10 +449,12 @@ declare const Clintplay: {
419
449
  reset: typeof reset;
420
450
  trackScreen: typeof trackScreen;
421
451
  reportError: typeof reportError;
452
+ setMetadata: typeof setMetadata;
453
+ tag: typeof tag;
422
454
  flush: typeof flush;
423
455
  stop: typeof stop;
424
456
  current: typeof current;
425
457
  _getState: typeof _getState;
426
458
  };
427
459
 
428
- export { type BackendEvent, CLINTPLAY_MASK_ID, Clintplay, ClintplayCaptureProvider, type ClintplayCaptureProviderProps, ClintplayMaskImage, type ClintplayMaskImageProps, ClintplayMaskTextInput, type ClintplayMaskTextInputProps, ClintplayMaskView, type ClintplayMaskViewProps, ClintplayNavigationTracker, type ClintplayNavigationTrackerProps, type ClintplayReactNativeConfig, type DeviceInfo, type NavigationRouteLike, type NavigationStateLike, type NavigationStateListenerCallback, type NavigationStateListenerOptions, type ReplayBatch, type ReplayEvent, SDK_VERSION, type UseClintplayNavigationOptions, type UseClintplayNavigationResult, type WireframeEvent, type WireframeNode, _resetLastTrackedRoute, createClintplayNavigationStateListener, formatEventForBatch, getActiveRouteName, init, sanitizeRoute, useClintplayNavigationTracking };
460
+ export { type BackendEvent, CLINTPLAY_MASK_ID, Clintplay, ClintplayCaptureProvider, type ClintplayCaptureProviderProps, ClintplayMaskImage, type ClintplayMaskImageProps, ClintplayMaskTextInput, type ClintplayMaskTextInputProps, ClintplayMaskView, type ClintplayMaskViewProps, ClintplayNavigationTracker, type ClintplayNavigationTrackerProps, type ClintplayReactNativeConfig, type DeviceInfo, METADATA_MAX_BYTES, METADATA_MAX_DEPTH, METADATA_MAX_KEYS, METADATA_MAX_STRING_LENGTH, type MetadataEvent, type NavigationRouteLike, type NavigationStateLike, type NavigationStateListenerCallback, type NavigationStateListenerOptions, type ReplayBatch, type ReplayEvent, SDK_VERSION, TAG_MAX_LENGTH, type TagEvent, type UseClintplayNavigationOptions, type UseClintplayNavigationResult, type WireframeEvent, type WireframeNode, _resetLastTrackedRoute, createClintplayNavigationStateListener, formatEventForBatch, getActiveRouteName, init, sanitizeMetadata, sanitizeRoute, sanitizeTag, setMetadata, tag, useClintplayNavigationTracking };