@axyle/expo-sdk 1.0.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.
Files changed (43) hide show
  1. package/CONFIG.md +117 -0
  2. package/README.md +534 -0
  3. package/dist/client.d.ts +93 -0
  4. package/dist/client.js +416 -0
  5. package/dist/config.example.d.ts +8 -0
  6. package/dist/config.example.js +13 -0
  7. package/dist/configLoader.d.ts +10 -0
  8. package/dist/configLoader.js +22 -0
  9. package/dist/constants.d.ts +38 -0
  10. package/dist/constants.js +42 -0
  11. package/dist/context.d.ts +36 -0
  12. package/dist/context.js +216 -0
  13. package/dist/core.d.ts +9 -0
  14. package/dist/core.js +45 -0
  15. package/dist/hooks/useFeatureTracking.d.ts +34 -0
  16. package/dist/hooks/useFeatureTracking.js +60 -0
  17. package/dist/hooks/useOnboardingTracking.d.ts +85 -0
  18. package/dist/hooks/useOnboardingTracking.js +172 -0
  19. package/dist/hooks/useScreenTracking.d.ts +23 -0
  20. package/dist/hooks/useScreenTracking.js +52 -0
  21. package/dist/hooks/useScrollTracking.d.ts +39 -0
  22. package/dist/hooks/useScrollTracking.js +146 -0
  23. package/dist/index.d.ts +140 -0
  24. package/dist/index.js +171 -0
  25. package/dist/integrations/expoRouter.d.ts +42 -0
  26. package/dist/integrations/expoRouter.js +66 -0
  27. package/dist/integrations/reactNavigation.d.ts +27 -0
  28. package/dist/integrations/reactNavigation.js +101 -0
  29. package/dist/queue.d.ts +52 -0
  30. package/dist/queue.js +143 -0
  31. package/dist/session.d.ts +44 -0
  32. package/dist/session.js +139 -0
  33. package/dist/sessionAnalytics.d.ts +43 -0
  34. package/dist/sessionAnalytics.js +74 -0
  35. package/dist/storage.d.ts +67 -0
  36. package/dist/storage.js +210 -0
  37. package/dist/transport.d.ts +41 -0
  38. package/dist/transport.js +158 -0
  39. package/dist/types.d.ts +102 -0
  40. package/dist/types.js +5 -0
  41. package/dist/utils.d.ts +39 -0
  42. package/dist/utils.js +116 -0
  43. package/package.json +44 -0
@@ -0,0 +1,216 @@
1
+ "use strict";
2
+ /**
3
+ * Device and app context collection using Expo APIs
4
+ */
5
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ var desc = Object.getOwnPropertyDescriptor(m, k);
8
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
9
+ desc = { enumerable: true, get: function() { return m[k]; } };
10
+ }
11
+ Object.defineProperty(o, k2, desc);
12
+ }) : (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ o[k2] = m[k];
15
+ }));
16
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
17
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
18
+ }) : function(o, v) {
19
+ o["default"] = v;
20
+ });
21
+ var __importStar = (this && this.__importStar) || (function () {
22
+ var ownKeys = function(o) {
23
+ ownKeys = Object.getOwnPropertyNames || function (o) {
24
+ var ar = [];
25
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
26
+ return ar;
27
+ };
28
+ return ownKeys(o);
29
+ };
30
+ return function (mod) {
31
+ if (mod && mod.__esModule) return mod;
32
+ var result = {};
33
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
34
+ __setModuleDefault(result, mod);
35
+ return result;
36
+ };
37
+ })();
38
+ var __importDefault = (this && this.__importDefault) || function (mod) {
39
+ return (mod && mod.__esModule) ? mod : { "default": mod };
40
+ };
41
+ Object.defineProperty(exports, "__esModule", { value: true });
42
+ exports.ContextCollector = void 0;
43
+ const Application = __importStar(require("expo-application"));
44
+ const expo_constants_1 = __importDefault(require("expo-constants"));
45
+ const Device = __importStar(require("expo-device"));
46
+ const react_native_1 = require("react-native");
47
+ class ContextCollector {
48
+ /**
49
+ * Get device and app context
50
+ * Caches result for performance
51
+ */
52
+ static async getContext(environment) {
53
+ // Return cached context if available
54
+ if (this.cachedContext) {
55
+ return this.cachedContext;
56
+ }
57
+ try {
58
+ const { width, height } = react_native_1.Dimensions.get("window");
59
+ const scale = react_native_1.Dimensions.get("window").scale;
60
+ const context = {
61
+ app: {
62
+ name: Application.applicationName || "Unknown",
63
+ version: Application.nativeApplicationVersion || "0.0.0",
64
+ build: Application.nativeBuildVersion || "0",
65
+ namespace: Application.applicationId || "unknown",
66
+ },
67
+ device: {
68
+ id: await this.getDeviceId(),
69
+ manufacturer: Device.manufacturer || null,
70
+ model: Device.modelName || null,
71
+ name: Device.deviceName || null,
72
+ type: this.getDeviceType(),
73
+ brand: Device.brand || null,
74
+ },
75
+ os: {
76
+ name: react_native_1.Platform.OS,
77
+ version: react_native_1.Platform.Version.toString(),
78
+ },
79
+ screen: {
80
+ width,
81
+ height,
82
+ density: scale,
83
+ },
84
+ locale: this.getLocale(),
85
+ timezone: this.getTimezone(),
86
+ environment,
87
+ };
88
+ // Cache the context
89
+ this.cachedContext = context;
90
+ return context;
91
+ }
92
+ catch (error) {
93
+ console.error("[Axyle] Failed to collect context:", error);
94
+ // Return minimal context on error
95
+ return this.getMinimalContext(environment);
96
+ }
97
+ }
98
+ /**
99
+ * Get device ID (may be null on some platforms)
100
+ */
101
+ static async getDeviceId() {
102
+ try {
103
+ // Use Android ID on Android, IDFV on iOS
104
+ if (react_native_1.Platform.OS === "android") {
105
+ return expo_constants_1.default.sessionId || null;
106
+ }
107
+ else if (react_native_1.Platform.OS === "ios") {
108
+ return expo_constants_1.default.sessionId || null;
109
+ }
110
+ return null;
111
+ }
112
+ catch (error) {
113
+ return null;
114
+ }
115
+ }
116
+ /**
117
+ * Determine device type
118
+ */
119
+ static getDeviceType() {
120
+ try {
121
+ if (Device.deviceType === Device.DeviceType.PHONE) {
122
+ return "PHONE";
123
+ }
124
+ else if (Device.deviceType === Device.DeviceType.TABLET) {
125
+ return "TABLET";
126
+ }
127
+ else if (Device.deviceType === Device.DeviceType.DESKTOP) {
128
+ return "DESKTOP";
129
+ }
130
+ else if (Device.deviceType === Device.DeviceType.TV) {
131
+ return "TV";
132
+ }
133
+ return "UNKNOWN";
134
+ }
135
+ catch (error) {
136
+ return "UNKNOWN";
137
+ }
138
+ }
139
+ /**
140
+ * Get device locale
141
+ */
142
+ static getLocale() {
143
+ try {
144
+ // Try to get locale from Intl API (works on most platforms)
145
+ if (typeof Intl !== "undefined" && Intl.DateTimeFormat) {
146
+ const locale = Intl.DateTimeFormat().resolvedOptions().locale;
147
+ if (locale)
148
+ return locale;
149
+ }
150
+ return "en-US";
151
+ }
152
+ catch (error) {
153
+ return "en-US";
154
+ }
155
+ }
156
+ /**
157
+ * Get device timezone
158
+ */
159
+ static getTimezone() {
160
+ try {
161
+ // Get timezone offset in minutes
162
+ const offset = new Date().getTimezoneOffset();
163
+ const hours = Math.abs(Math.floor(offset / 60));
164
+ const minutes = Math.abs(offset % 60);
165
+ const sign = offset <= 0 ? "+" : "-";
166
+ return `UTC${sign}${hours.toString().padStart(2, "0")}:${minutes
167
+ .toString()
168
+ .padStart(2, "0")}`;
169
+ }
170
+ catch (error) {
171
+ return "UTC";
172
+ }
173
+ }
174
+ /**
175
+ * Get minimal context as fallback
176
+ */
177
+ static getMinimalContext(environment) {
178
+ const { width, height } = react_native_1.Dimensions.get("window");
179
+ return {
180
+ app: {
181
+ name: "Unknown",
182
+ version: "0.0.0",
183
+ build: "0",
184
+ namespace: "unknown",
185
+ },
186
+ device: {
187
+ id: null,
188
+ manufacturer: null,
189
+ model: null,
190
+ name: null,
191
+ type: "UNKNOWN",
192
+ brand: null,
193
+ },
194
+ os: {
195
+ name: react_native_1.Platform.OS,
196
+ version: react_native_1.Platform.Version.toString(),
197
+ },
198
+ screen: {
199
+ width,
200
+ height,
201
+ density: 1,
202
+ },
203
+ locale: "en-US",
204
+ timezone: "UTC",
205
+ environment,
206
+ };
207
+ }
208
+ /**
209
+ * Clear cached context (useful for testing or when app info changes)
210
+ */
211
+ static clearCache() {
212
+ this.cachedContext = null;
213
+ }
214
+ }
215
+ exports.ContextCollector = ContextCollector;
216
+ ContextCollector.cachedContext = null;
package/dist/core.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Core SDK module - exports the singleton client instance
3
+ * This module is used to avoid circular dependencies between index.ts and integrations
4
+ */
5
+ import { AxyleClient } from "./client";
6
+ import type { EventProperties } from "./types";
7
+ export declare const client: AxyleClient;
8
+ export declare function track(eventName: string, properties?: EventProperties): void;
9
+ export declare function isInitialized(): boolean;
package/dist/core.js ADDED
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ /**
3
+ * Core SDK module - exports the singleton client instance
4
+ * This module is used to avoid circular dependencies between index.ts and integrations
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.client = void 0;
8
+ exports.track = track;
9
+ exports.isInitialized = isInitialized;
10
+ const client_1 = require("./client");
11
+ // Create and export singleton instance
12
+ exports.client = new client_1.AxyleClient();
13
+ // Maximum retries when SDK is not initialized
14
+ const MAX_INIT_RETRIES = 50; // 5 seconds max (50 * 100ms)
15
+ // Export a track function that can be used by integrations
16
+ // Note: client.track is async, but we call it without awaiting to avoid blocking
17
+ function track(eventName, properties) {
18
+ // Check if initialized before tracking
19
+ if (!exports.client.isInitialized) {
20
+ // Queue the event to be tracked once initialized
21
+ let retryCount = 0;
22
+ const checkAndTrack = () => {
23
+ if (exports.client.isInitialized) {
24
+ exports.client.track(eventName, properties).catch(() => {
25
+ // Silently handle errors - track already handles errors internally
26
+ });
27
+ }
28
+ else if (retryCount < MAX_INIT_RETRIES) {
29
+ retryCount++;
30
+ setTimeout(checkAndTrack, 100);
31
+ }
32
+ // After max retries, silently drop the event
33
+ };
34
+ checkAndTrack();
35
+ return;
36
+ }
37
+ // Fire and forget - track is async but we don't need to wait for it
38
+ exports.client.track(eventName, properties).catch(() => {
39
+ // Silently handle errors - track already handles errors internally
40
+ });
41
+ }
42
+ // Export isInitialized getter for integrations to check
43
+ function isInitialized() {
44
+ return exports.client.isInitialized;
45
+ }
@@ -0,0 +1,34 @@
1
+ /**
2
+ * React hook and utilities for feature usage tracking
3
+ */
4
+ /**
5
+ * Track when a feature is used
6
+ *
7
+ * @example
8
+ * ```tsx
9
+ * function ProfileScreen() {
10
+ * const handleEditProfile = () => {
11
+ * trackFeatureUsage('edit_profile', { screen: 'Profile' });
12
+ * // ... edit profile logic
13
+ * };
14
+ *
15
+ * return <Button onPress={handleEditProfile}>Edit Profile</Button>;
16
+ * }
17
+ * ```
18
+ */
19
+ export declare function trackFeatureUsage(featureName: string, properties?: Record<string, any>): void;
20
+ /**
21
+ * Track feature usage with additional context
22
+ */
23
+ export declare function trackFeatureUsageWithContext(featureName: string, context: {
24
+ screen?: string;
25
+ category?: string;
26
+ action?: string;
27
+ value?: number | string;
28
+ [key: string]: any;
29
+ }): void;
30
+ /**
31
+ * Hook to automatically track feature usage on component mount
32
+ * Useful for tracking feature discovery/views
33
+ */
34
+ export declare function useFeatureViewTracking(featureName: string, properties?: Record<string, any>): void;
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ /**
3
+ * React hook and utilities for feature usage tracking
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.trackFeatureUsage = trackFeatureUsage;
7
+ exports.trackFeatureUsageWithContext = trackFeatureUsageWithContext;
8
+ exports.useFeatureViewTracking = useFeatureViewTracking;
9
+ const react_1 = require("react");
10
+ const core_1 = require("../core");
11
+ /**
12
+ * Track when a feature is used
13
+ *
14
+ * @example
15
+ * ```tsx
16
+ * function ProfileScreen() {
17
+ * const handleEditProfile = () => {
18
+ * trackFeatureUsage('edit_profile', { screen: 'Profile' });
19
+ * // ... edit profile logic
20
+ * };
21
+ *
22
+ * return <Button onPress={handleEditProfile}>Edit Profile</Button>;
23
+ * }
24
+ * ```
25
+ */
26
+ function trackFeatureUsage(featureName, properties) {
27
+ (0, core_1.track)("Feature Used", {
28
+ feature: featureName,
29
+ ...properties,
30
+ });
31
+ }
32
+ /**
33
+ * Track feature usage with additional context
34
+ */
35
+ function trackFeatureUsageWithContext(featureName, context) {
36
+ (0, core_1.track)("Feature Used", {
37
+ feature: featureName,
38
+ feature_category: context.category,
39
+ feature_action: context.action,
40
+ feature_value: context.value,
41
+ screen: context.screen,
42
+ ...context,
43
+ });
44
+ }
45
+ /**
46
+ * Hook to automatically track feature usage on component mount
47
+ * Useful for tracking feature discovery/views
48
+ */
49
+ function useFeatureViewTracking(featureName, properties) {
50
+ const hasTracked = (0, react_1.useRef)(false);
51
+ (0, react_1.useEffect)(() => {
52
+ if (!hasTracked.current) {
53
+ (0, core_1.track)("Feature Viewed", {
54
+ feature: featureName,
55
+ ...properties,
56
+ });
57
+ hasTracked.current = true;
58
+ }
59
+ }, [featureName, properties]);
60
+ }
@@ -0,0 +1,85 @@
1
+ /**
2
+ * React hook for user flow tracking
3
+ * Generic flow tracking that can be used for onboarding, checkout, tutorials, etc.
4
+ */
5
+ export interface FlowTrackingOptions {
6
+ /** Flow identifier (e.g., 'onboarding', 'checkout', 'tutorial') */
7
+ flowId: string;
8
+ /** Flow type/category (e.g., 'onboarding', 'checkout', 'tutorial', 'feature-discovery') */
9
+ flowType?: string;
10
+ /** Current step/screen in the flow */
11
+ step: number;
12
+ /** Total number of steps in the flow */
13
+ totalSteps: number;
14
+ /** Step/screen name */
15
+ stepName: string;
16
+ /** Additional properties to track */
17
+ properties?: Record<string, any>;
18
+ }
19
+ /**
20
+ * Hook to track user flow progress and drop-offs
21
+ * Works for any multi-step flow: onboarding, checkout, tutorials, etc.
22
+ *
23
+ * @example
24
+ * ```tsx
25
+ * // Onboarding example
26
+ * function OnboardingStep1() {
27
+ * useFlowTracking({
28
+ * flowId: 'welcome-onboarding',
29
+ * flowType: 'onboarding',
30
+ * step: 1,
31
+ * totalSteps: 5,
32
+ * stepName: 'Welcome'
33
+ * });
34
+ * return <View>...</View>;
35
+ * }
36
+ *
37
+ * // Checkout example
38
+ * function CheckoutStep2() {
39
+ * useFlowTracking({
40
+ * flowId: 'checkout-process',
41
+ * flowType: 'checkout',
42
+ * step: 2,
43
+ * totalSteps: 4,
44
+ * stepName: 'Shipping Info'
45
+ * });
46
+ * return <View>...</View>;
47
+ * }
48
+ * ```
49
+ */
50
+ export declare function useFlowTracking(options: FlowTrackingOptions): void;
51
+ /**
52
+ * Helper function to track flow completion
53
+ * Call this when user completes the entire flow
54
+ *
55
+ * @example
56
+ * ```tsx
57
+ * trackFlowCompleted('welcome-onboarding', 5, { flowType: 'onboarding' });
58
+ * ```
59
+ */
60
+ export declare function trackFlowCompleted(flowId: string, totalSteps: number, properties?: Record<string, any>): void;
61
+ /**
62
+ * Helper function to track flow abandonment
63
+ * Call this when user explicitly exits a flow
64
+ *
65
+ * @example
66
+ * ```tsx
67
+ * trackFlowAbandoned('checkout-process', 2, 4, {
68
+ * flowType: 'checkout',
69
+ * stepName: 'Shipping Info'
70
+ * });
71
+ * ```
72
+ */
73
+ export declare function trackFlowAbandoned(flowId: string, currentStep: number, totalSteps: number, properties?: Record<string, any>): void;
74
+ /**
75
+ * @deprecated Use useFlowTracking instead
76
+ */
77
+ export declare const useOnboardingTracking: typeof useFlowTracking;
78
+ /**
79
+ * @deprecated Use trackFlowCompleted instead
80
+ */
81
+ export declare const trackOnboardingCompleted: (flowId: string, totalSteps: number, properties?: Record<string, any>) => void;
82
+ /**
83
+ * @deprecated Use trackFlowAbandoned instead
84
+ */
85
+ export declare const trackOnboardingAbandoned: (flowId: string, currentStep: number, totalSteps: number, properties?: Record<string, any>) => void;
@@ -0,0 +1,172 @@
1
+ "use strict";
2
+ /**
3
+ * React hook for user flow tracking
4
+ * Generic flow tracking that can be used for onboarding, checkout, tutorials, etc.
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.trackOnboardingAbandoned = exports.trackOnboardingCompleted = exports.useOnboardingTracking = void 0;
8
+ exports.useFlowTracking = useFlowTracking;
9
+ exports.trackFlowCompleted = trackFlowCompleted;
10
+ exports.trackFlowAbandoned = trackFlowAbandoned;
11
+ const react_1 = require("react");
12
+ const core_1 = require("../core");
13
+ /**
14
+ * Hook to track user flow progress and drop-offs
15
+ * Works for any multi-step flow: onboarding, checkout, tutorials, etc.
16
+ *
17
+ * @example
18
+ * ```tsx
19
+ * // Onboarding example
20
+ * function OnboardingStep1() {
21
+ * useFlowTracking({
22
+ * flowId: 'welcome-onboarding',
23
+ * flowType: 'onboarding',
24
+ * step: 1,
25
+ * totalSteps: 5,
26
+ * stepName: 'Welcome'
27
+ * });
28
+ * return <View>...</View>;
29
+ * }
30
+ *
31
+ * // Checkout example
32
+ * function CheckoutStep2() {
33
+ * useFlowTracking({
34
+ * flowId: 'checkout-process',
35
+ * flowType: 'checkout',
36
+ * step: 2,
37
+ * totalSteps: 4,
38
+ * stepName: 'Shipping Info'
39
+ * });
40
+ * return <View>...</View>;
41
+ * }
42
+ * ```
43
+ */
44
+ function useFlowTracking(options) {
45
+ const { flowId, flowType, step, totalSteps, stepName, properties = {}, } = options;
46
+ const hasTracked = (0, react_1.useRef)(false);
47
+ const stepStartTime = (0, react_1.useRef)(null);
48
+ const flowStartTime = (0, react_1.useRef)(null);
49
+ (0, react_1.useEffect)(() => {
50
+ const startTime = Date.now();
51
+ stepStartTime.current = startTime;
52
+ // Track flow start on first step
53
+ if (step === 1 && !hasTracked.current) {
54
+ flowStartTime.current = startTime;
55
+ (0, core_1.track)("Flow Started", {
56
+ flow_id: flowId,
57
+ flow_type: flowType || "custom",
58
+ flow_start_time: startTime,
59
+ total_steps: totalSteps,
60
+ ...properties,
61
+ });
62
+ }
63
+ // Track step view
64
+ if (!hasTracked.current) {
65
+ (0, core_1.track)("Flow Step Viewed", {
66
+ flow_id: flowId,
67
+ flow_type: flowType || "custom",
68
+ step: step,
69
+ step_name: stepName,
70
+ total_steps: totalSteps,
71
+ step_start_time: startTime,
72
+ progress_percentage: Math.round((step / totalSteps) * 100),
73
+ ...properties,
74
+ });
75
+ hasTracked.current = true;
76
+ }
77
+ // Track step completion and potential drop-off when component unmounts
78
+ return () => {
79
+ if (stepStartTime.current !== null) {
80
+ const endTime = Date.now();
81
+ const stepDuration = endTime - stepStartTime.current;
82
+ // Track step completion
83
+ (0, core_1.track)("Flow Step Completed", {
84
+ flow_id: flowId,
85
+ flow_type: flowType || "custom",
86
+ step: step,
87
+ step_name: stepName,
88
+ step_duration_ms: stepDuration,
89
+ step_duration_seconds: Math.round(stepDuration / 1000),
90
+ progress_percentage: Math.round((step / totalSteps) * 100),
91
+ ...properties,
92
+ });
93
+ // If not the last step, this could be a drop-off
94
+ if (step < totalSteps) {
95
+ (0, core_1.track)("Flow Step Exited", {
96
+ flow_id: flowId,
97
+ flow_type: flowType || "custom",
98
+ step: step,
99
+ step_name: stepName,
100
+ next_step: step + 1,
101
+ is_drop_off: true,
102
+ step_duration_ms: stepDuration,
103
+ ...properties,
104
+ });
105
+ }
106
+ }
107
+ };
108
+ }, [flowId, flowType, step, totalSteps, stepName, properties]);
109
+ }
110
+ /**
111
+ * Helper function to track flow completion
112
+ * Call this when user completes the entire flow
113
+ *
114
+ * @example
115
+ * ```tsx
116
+ * trackFlowCompleted('welcome-onboarding', 5, { flowType: 'onboarding' });
117
+ * ```
118
+ */
119
+ function trackFlowCompleted(flowId, totalSteps, properties) {
120
+ (0, core_1.track)("Flow Completed", {
121
+ flow_id: flowId,
122
+ flow_type: properties?.flowType || "custom",
123
+ total_steps: totalSteps,
124
+ completed_at: Date.now(),
125
+ ...properties,
126
+ });
127
+ }
128
+ /**
129
+ * Helper function to track flow abandonment
130
+ * Call this when user explicitly exits a flow
131
+ *
132
+ * @example
133
+ * ```tsx
134
+ * trackFlowAbandoned('checkout-process', 2, 4, {
135
+ * flowType: 'checkout',
136
+ * stepName: 'Shipping Info'
137
+ * });
138
+ * ```
139
+ */
140
+ function trackFlowAbandoned(flowId, currentStep, totalSteps, properties) {
141
+ (0, core_1.track)("Flow Abandoned", {
142
+ flow_id: flowId,
143
+ flow_type: properties?.flowType || "custom",
144
+ abandoned_at_step: currentStep,
145
+ abandoned_step_name: properties?.stepName || `Step ${currentStep}`,
146
+ total_steps: totalSteps,
147
+ progress_percentage: Math.round((currentStep / totalSteps) * 100),
148
+ abandoned_at: Date.now(),
149
+ ...properties,
150
+ });
151
+ }
152
+ // Legacy exports for backward compatibility (deprecated)
153
+ /**
154
+ * @deprecated Use useFlowTracking instead
155
+ */
156
+ exports.useOnboardingTracking = useFlowTracking;
157
+ /**
158
+ * @deprecated Use trackFlowCompleted instead
159
+ */
160
+ const trackOnboardingCompleted = (flowId, totalSteps, properties) => trackFlowCompleted(flowId, totalSteps, {
161
+ ...properties,
162
+ flowType: "onboarding",
163
+ });
164
+ exports.trackOnboardingCompleted = trackOnboardingCompleted;
165
+ /**
166
+ * @deprecated Use trackFlowAbandoned instead
167
+ */
168
+ const trackOnboardingAbandoned = (flowId, currentStep, totalSteps, properties) => trackFlowAbandoned(flowId, currentStep, totalSteps, {
169
+ ...properties,
170
+ flowType: "onboarding",
171
+ });
172
+ exports.trackOnboardingAbandoned = trackOnboardingAbandoned;
@@ -0,0 +1,23 @@
1
+ /**
2
+ * React hook for automatic screen tracking with time tracking
3
+ */
4
+ export interface ScreenTrackingOptions {
5
+ /** Screen name to track */
6
+ screenName: string;
7
+ /** Additional properties to track with screen view */
8
+ properties?: Record<string, any>;
9
+ /** Whether to track time spent on screen (default: true) */
10
+ trackTime?: boolean;
11
+ }
12
+ /**
13
+ * Hook to automatically track screen views with time tracking
14
+ *
15
+ * @example
16
+ * ```tsx
17
+ * function HomeScreen() {
18
+ * useScreenTracking({ screenName: 'Home' });
19
+ * return <View>...</View>;
20
+ * }
21
+ * ```
22
+ */
23
+ export declare function useScreenTracking(options: ScreenTrackingOptions): void;