@repliqo/sdk-react-native 0.1.2 → 0.1.3
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/dist/components/RepliqoScrollView.d.ts +26 -0
- package/dist/components/RepliqoScrollView.js +78 -0
- package/dist/core/client.d.ts +8 -0
- package/dist/core/client.js +16 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +4 -1
- package/package.json +1 -1
- package/src/components/RepliqoScrollView.tsx +62 -0
- package/src/core/client.ts +18 -1
- package/src/index.ts +3 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ScrollView, type ScrollViewProps } from 'react-native';
|
|
3
|
+
/**
|
|
4
|
+
* Drop-in replacement for React Native's ScrollView that automatically
|
|
5
|
+
* reports the scroll offset to Repliqo for accurate heatmaps.
|
|
6
|
+
*
|
|
7
|
+
* Without this, touch coordinates on scrollable screens are relative to
|
|
8
|
+
* the visible viewport. With this, they're relative to the full content,
|
|
9
|
+
* so heatmaps accurately show which content elements users touch.
|
|
10
|
+
*
|
|
11
|
+
* Usage — just replace `<ScrollView>` with `<RepliqoScrollView>`:
|
|
12
|
+
*
|
|
13
|
+
* ```tsx
|
|
14
|
+
* import { RepliqoScrollView } from '@repliqo/sdk-react-native';
|
|
15
|
+
*
|
|
16
|
+
* // Before:
|
|
17
|
+
* <ScrollView>...</ScrollView>
|
|
18
|
+
*
|
|
19
|
+
* // After:
|
|
20
|
+
* <RepliqoScrollView>...</RepliqoScrollView>
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* All ScrollView props are forwarded. Your existing `onScroll` handler
|
|
24
|
+
* still fires normally.
|
|
25
|
+
*/
|
|
26
|
+
export declare const RepliqoScrollView: React.ForwardRefExoticComponent<ScrollViewProps & React.RefAttributes<ScrollView>>;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.RepliqoScrollView = void 0;
|
|
37
|
+
const react_1 = __importStar(require("react"));
|
|
38
|
+
const react_native_1 = require("react-native");
|
|
39
|
+
const client_1 = require("../core/client");
|
|
40
|
+
/**
|
|
41
|
+
* Drop-in replacement for React Native's ScrollView that automatically
|
|
42
|
+
* reports the scroll offset to Repliqo for accurate heatmaps.
|
|
43
|
+
*
|
|
44
|
+
* Without this, touch coordinates on scrollable screens are relative to
|
|
45
|
+
* the visible viewport. With this, they're relative to the full content,
|
|
46
|
+
* so heatmaps accurately show which content elements users touch.
|
|
47
|
+
*
|
|
48
|
+
* Usage — just replace `<ScrollView>` with `<RepliqoScrollView>`:
|
|
49
|
+
*
|
|
50
|
+
* ```tsx
|
|
51
|
+
* import { RepliqoScrollView } from '@repliqo/sdk-react-native';
|
|
52
|
+
*
|
|
53
|
+
* // Before:
|
|
54
|
+
* <ScrollView>...</ScrollView>
|
|
55
|
+
*
|
|
56
|
+
* // After:
|
|
57
|
+
* <RepliqoScrollView>...</RepliqoScrollView>
|
|
58
|
+
* ```
|
|
59
|
+
*
|
|
60
|
+
* All ScrollView props are forwarded. Your existing `onScroll` handler
|
|
61
|
+
* still fires normally.
|
|
62
|
+
*/
|
|
63
|
+
exports.RepliqoScrollView = react_1.default.forwardRef(({ onScroll, ...props }, ref) => {
|
|
64
|
+
const handleScroll = (0, react_1.useCallback)((event) => {
|
|
65
|
+
// Report scroll offset to the SDK
|
|
66
|
+
try {
|
|
67
|
+
const offsetY = event.nativeEvent.contentOffset.y;
|
|
68
|
+
client_1.AppAnalytics.getInstance().setScrollOffset(offsetY);
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
// SDK not initialized, ignore
|
|
72
|
+
}
|
|
73
|
+
// Forward to the original onScroll handler
|
|
74
|
+
onScroll?.(event);
|
|
75
|
+
}, [onScroll]);
|
|
76
|
+
return (<react_native_1.ScrollView ref={ref} {...props} onScroll={handleScroll} scrollEventThrottle={props.scrollEventThrottle ?? 16}/>);
|
|
77
|
+
});
|
|
78
|
+
exports.RepliqoScrollView.displayName = 'RepliqoScrollView';
|
package/dist/core/client.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ export declare class AppAnalytics {
|
|
|
11
11
|
private sessionId;
|
|
12
12
|
private currentScreen;
|
|
13
13
|
private currentScreenEnteredAt;
|
|
14
|
+
private scrollOffsetY;
|
|
14
15
|
private logger;
|
|
15
16
|
private appStateSubscription;
|
|
16
17
|
private constructor();
|
|
@@ -23,6 +24,13 @@ export declare class AppAnalytics {
|
|
|
23
24
|
trackNavigation(fromScreen: string, toScreen: string): void;
|
|
24
25
|
trackCustomEvent(eventName: string, data?: Record<string, any>): void;
|
|
25
26
|
reportError(error: Error, metadata?: Record<string, any>): void;
|
|
27
|
+
/**
|
|
28
|
+
* Update the current scroll offset. Called by RepliqoScrollView
|
|
29
|
+
* or manually from the host app's ScrollView onScroll handler.
|
|
30
|
+
* The offset is added to touch Y coordinates for accurate heatmaps
|
|
31
|
+
* on scrollable screens.
|
|
32
|
+
*/
|
|
33
|
+
setScrollOffset(y: number): void;
|
|
26
34
|
onScreenEnter(screenName: string): void;
|
|
27
35
|
onScreenExit(screenName: string): void;
|
|
28
36
|
flush(): Promise<void>;
|
package/dist/core/client.js
CHANGED
|
@@ -17,6 +17,7 @@ class AppAnalytics {
|
|
|
17
17
|
this.sessionId = null;
|
|
18
18
|
this.currentScreen = null;
|
|
19
19
|
this.currentScreenEnteredAt = null;
|
|
20
|
+
this.scrollOffsetY = 0;
|
|
20
21
|
this.appStateSubscription = null;
|
|
21
22
|
this.config = (0, config_1.resolveConfig)(config);
|
|
22
23
|
this.logger = new logger_1.Logger(this.config.debug);
|
|
@@ -163,10 +164,14 @@ class AppAnalytics {
|
|
|
163
164
|
if (!this.config.enableTouchTracking) {
|
|
164
165
|
return;
|
|
165
166
|
}
|
|
167
|
+
// Adjust Y by the current scroll offset so touches map to content
|
|
168
|
+
// position, not just viewport position. This makes heatmaps accurate
|
|
169
|
+
// for scrollable screens.
|
|
170
|
+
const adjustedY = y + this.scrollOffsetY;
|
|
166
171
|
const event = {
|
|
167
172
|
type: 'touch',
|
|
168
173
|
screenName: screenName || this.currentScreen || undefined,
|
|
169
|
-
data: { x, y, ...extra },
|
|
174
|
+
data: { x, y: adjustedY, scrollOffsetY: this.scrollOffsetY, ...extra },
|
|
170
175
|
timestamp: new Date().toISOString(),
|
|
171
176
|
};
|
|
172
177
|
this.eventQueue.add(event);
|
|
@@ -210,9 +215,19 @@ class AppAnalytics {
|
|
|
210
215
|
}
|
|
211
216
|
this.errorTracker.reportError(error, metadata);
|
|
212
217
|
}
|
|
218
|
+
/**
|
|
219
|
+
* Update the current scroll offset. Called by RepliqoScrollView
|
|
220
|
+
* or manually from the host app's ScrollView onScroll handler.
|
|
221
|
+
* The offset is added to touch Y coordinates for accurate heatmaps
|
|
222
|
+
* on scrollable screens.
|
|
223
|
+
*/
|
|
224
|
+
setScrollOffset(y) {
|
|
225
|
+
this.scrollOffsetY = y;
|
|
226
|
+
}
|
|
213
227
|
onScreenEnter(screenName) {
|
|
214
228
|
this.currentScreen = screenName;
|
|
215
229
|
this.currentScreenEnteredAt = new Date().toISOString();
|
|
230
|
+
this.scrollOffsetY = 0; // Reset scroll on screen change
|
|
216
231
|
this.errorTracker?.setCurrentScreen(screenName);
|
|
217
232
|
this.snapshotCapture?.setCurrentScreen(screenName);
|
|
218
233
|
this.logger.log('Screen entered:', screenName);
|
package/dist/index.d.ts
CHANGED
|
@@ -11,5 +11,6 @@ export type { ScreenshotData, SnapshotPayload, } from './types/snapshot';
|
|
|
11
11
|
export type { CrashReport } from './types/crash';
|
|
12
12
|
export type { SnapshotCaptureConfig } from './snapshot/capture';
|
|
13
13
|
export type { ScreenshotResult } from './snapshot/captureScreenshot';
|
|
14
|
+
export { RepliqoScrollView } from './components/RepliqoScrollView';
|
|
14
15
|
export { DEFAULT_CONFIG } from './core/config';
|
|
15
16
|
export type { ResolvedConfig } from './core/config';
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DEFAULT_CONFIG = exports.captureNativeFrame = exports.isNativeScreenCaptureAvailable = exports.captureScreenshot = exports.SnapshotCapture = exports.ErrorTracker = exports.trackScreenExit = exports.trackScreenEnter = exports.trackScreenChange = exports.useNavigationTracker = exports.TouchTracker = exports.AppAnalytics = void 0;
|
|
3
|
+
exports.DEFAULT_CONFIG = exports.RepliqoScrollView = exports.captureNativeFrame = exports.isNativeScreenCaptureAvailable = exports.captureScreenshot = exports.SnapshotCapture = exports.ErrorTracker = exports.trackScreenExit = exports.trackScreenEnter = exports.trackScreenChange = exports.useNavigationTracker = exports.TouchTracker = exports.AppAnalytics = void 0;
|
|
4
4
|
// Main class
|
|
5
5
|
var client_1 = require("./core/client");
|
|
6
6
|
Object.defineProperty(exports, "AppAnalytics", { enumerable: true, get: function () { return client_1.AppAnalytics; } });
|
|
@@ -23,6 +23,9 @@ Object.defineProperty(exports, "captureScreenshot", { enumerable: true, get: fun
|
|
|
23
23
|
var NativeScreenCapture_1 = require("./snapshot/NativeScreenCapture");
|
|
24
24
|
Object.defineProperty(exports, "isNativeScreenCaptureAvailable", { enumerable: true, get: function () { return NativeScreenCapture_1.isNativeScreenCaptureAvailable; } });
|
|
25
25
|
Object.defineProperty(exports, "captureNativeFrame", { enumerable: true, get: function () { return NativeScreenCapture_1.captureNativeFrame; } });
|
|
26
|
+
// Components
|
|
27
|
+
var RepliqoScrollView_1 = require("./components/RepliqoScrollView");
|
|
28
|
+
Object.defineProperty(exports, "RepliqoScrollView", { enumerable: true, get: function () { return RepliqoScrollView_1.RepliqoScrollView; } });
|
|
26
29
|
// Config
|
|
27
30
|
var config_1 = require("./core/config");
|
|
28
31
|
Object.defineProperty(exports, "DEFAULT_CONFIG", { enumerable: true, get: function () { return config_1.DEFAULT_CONFIG; } });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@repliqo/sdk-react-native",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Session replay & analytics SDK for React Native. Captures screenshots (including modals/alerts), navigation, screen visits, and custom events.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import React, { useCallback } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
ScrollView,
|
|
4
|
+
type ScrollViewProps,
|
|
5
|
+
type NativeSyntheticEvent,
|
|
6
|
+
type NativeScrollEvent,
|
|
7
|
+
} from 'react-native';
|
|
8
|
+
import { AppAnalytics } from '../core/client';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Drop-in replacement for React Native's ScrollView that automatically
|
|
12
|
+
* reports the scroll offset to Repliqo for accurate heatmaps.
|
|
13
|
+
*
|
|
14
|
+
* Without this, touch coordinates on scrollable screens are relative to
|
|
15
|
+
* the visible viewport. With this, they're relative to the full content,
|
|
16
|
+
* so heatmaps accurately show which content elements users touch.
|
|
17
|
+
*
|
|
18
|
+
* Usage — just replace `<ScrollView>` with `<RepliqoScrollView>`:
|
|
19
|
+
*
|
|
20
|
+
* ```tsx
|
|
21
|
+
* import { RepliqoScrollView } from '@repliqo/sdk-react-native';
|
|
22
|
+
*
|
|
23
|
+
* // Before:
|
|
24
|
+
* <ScrollView>...</ScrollView>
|
|
25
|
+
*
|
|
26
|
+
* // After:
|
|
27
|
+
* <RepliqoScrollView>...</RepliqoScrollView>
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* All ScrollView props are forwarded. Your existing `onScroll` handler
|
|
31
|
+
* still fires normally.
|
|
32
|
+
*/
|
|
33
|
+
export const RepliqoScrollView = React.forwardRef<ScrollView, ScrollViewProps>(
|
|
34
|
+
({ onScroll, ...props }, ref) => {
|
|
35
|
+
const handleScroll = useCallback(
|
|
36
|
+
(event: NativeSyntheticEvent<NativeScrollEvent>) => {
|
|
37
|
+
// Report scroll offset to the SDK
|
|
38
|
+
try {
|
|
39
|
+
const offsetY = event.nativeEvent.contentOffset.y;
|
|
40
|
+
AppAnalytics.getInstance().setScrollOffset(offsetY);
|
|
41
|
+
} catch {
|
|
42
|
+
// SDK not initialized, ignore
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Forward to the original onScroll handler
|
|
46
|
+
onScroll?.(event);
|
|
47
|
+
},
|
|
48
|
+
[onScroll],
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<ScrollView
|
|
53
|
+
ref={ref}
|
|
54
|
+
{...props}
|
|
55
|
+
onScroll={handleScroll}
|
|
56
|
+
scrollEventThrottle={props.scrollEventThrottle ?? 16}
|
|
57
|
+
/>
|
|
58
|
+
);
|
|
59
|
+
},
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
RepliqoScrollView.displayName = 'RepliqoScrollView';
|
package/src/core/client.ts
CHANGED
|
@@ -28,6 +28,7 @@ export class AppAnalytics {
|
|
|
28
28
|
private sessionId: string | null = null;
|
|
29
29
|
private currentScreen: string | null = null;
|
|
30
30
|
private currentScreenEnteredAt: string | null = null;
|
|
31
|
+
private scrollOffsetY: number = 0;
|
|
31
32
|
private logger: Logger;
|
|
32
33
|
private appStateSubscription: { remove: () => void } | null = null;
|
|
33
34
|
|
|
@@ -246,10 +247,15 @@ export class AppAnalytics {
|
|
|
246
247
|
return;
|
|
247
248
|
}
|
|
248
249
|
|
|
250
|
+
// Adjust Y by the current scroll offset so touches map to content
|
|
251
|
+
// position, not just viewport position. This makes heatmaps accurate
|
|
252
|
+
// for scrollable screens.
|
|
253
|
+
const adjustedY = y + this.scrollOffsetY;
|
|
254
|
+
|
|
249
255
|
const event: AnalyticsEvent = {
|
|
250
256
|
type: 'touch',
|
|
251
257
|
screenName: screenName || this.currentScreen || undefined,
|
|
252
|
-
data: { x, y, ...extra },
|
|
258
|
+
data: { x, y: adjustedY, scrollOffsetY: this.scrollOffsetY, ...extra },
|
|
253
259
|
timestamp: new Date().toISOString(),
|
|
254
260
|
};
|
|
255
261
|
|
|
@@ -306,9 +312,20 @@ export class AppAnalytics {
|
|
|
306
312
|
this.errorTracker.reportError(error, metadata);
|
|
307
313
|
}
|
|
308
314
|
|
|
315
|
+
/**
|
|
316
|
+
* Update the current scroll offset. Called by RepliqoScrollView
|
|
317
|
+
* or manually from the host app's ScrollView onScroll handler.
|
|
318
|
+
* The offset is added to touch Y coordinates for accurate heatmaps
|
|
319
|
+
* on scrollable screens.
|
|
320
|
+
*/
|
|
321
|
+
setScrollOffset(y: number): void {
|
|
322
|
+
this.scrollOffsetY = y;
|
|
323
|
+
}
|
|
324
|
+
|
|
309
325
|
onScreenEnter(screenName: string): void {
|
|
310
326
|
this.currentScreen = screenName;
|
|
311
327
|
this.currentScreenEnteredAt = new Date().toISOString();
|
|
328
|
+
this.scrollOffsetY = 0; // Reset scroll on screen change
|
|
312
329
|
this.errorTracker?.setCurrentScreen(screenName);
|
|
313
330
|
this.snapshotCapture?.setCurrentScreen(screenName);
|
|
314
331
|
this.logger.log('Screen entered:', screenName);
|
package/src/index.ts
CHANGED
|
@@ -42,6 +42,9 @@ export type { CrashReport } from './types/crash';
|
|
|
42
42
|
export type { SnapshotCaptureConfig } from './snapshot/capture';
|
|
43
43
|
export type { ScreenshotResult } from './snapshot/captureScreenshot';
|
|
44
44
|
|
|
45
|
+
// Components
|
|
46
|
+
export { RepliqoScrollView } from './components/RepliqoScrollView';
|
|
47
|
+
|
|
45
48
|
// Config
|
|
46
49
|
export { DEFAULT_CONFIG } from './core/config';
|
|
47
50
|
export type { ResolvedConfig } from './core/config';
|