@litemetrics/react-native 0.1.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/dist/index.cjs ADDED
@@ -0,0 +1,224 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ LitemetricsProvider: () => LitemetricsProvider,
24
+ createRNTracker: () => createRNTracker,
25
+ useAppStateTracking: () => useAppStateTracking,
26
+ useLitemetrics: () => useLitemetrics,
27
+ useNavigationTracking: () => useNavigationTracking
28
+ });
29
+ module.exports = __toCommonJS(index_exports);
30
+
31
+ // src/context.tsx
32
+ var import_react = require("react");
33
+
34
+ // src/tracker.ts
35
+ var sessionId = null;
36
+ var visitorId = null;
37
+ var userId = null;
38
+ function generateId() {
39
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
40
+ const r = Math.random() * 16 | 0;
41
+ const v = c === "x" ? r : r & 3 | 8;
42
+ return v.toString(16);
43
+ });
44
+ }
45
+ function createRNTracker(config) {
46
+ const { siteId, endpoint, debug = false } = config;
47
+ if (!sessionId) sessionId = generateId();
48
+ if (!visitorId) visitorId = generateId().slice(0, 16);
49
+ const queue = [];
50
+ let flushTimer = null;
51
+ function getContext() {
52
+ return {
53
+ timezone: typeof Intl !== "undefined" ? Intl.DateTimeFormat().resolvedOptions().timeZone : void 0
54
+ };
55
+ }
56
+ function flush() {
57
+ if (queue.length === 0) return;
58
+ const events = queue.splice(0);
59
+ if (debug) {
60
+ console.log("[litemetrics:rn] sending", events.length, "events");
61
+ }
62
+ fetch(endpoint, {
63
+ method: "POST",
64
+ headers: { "Content-Type": "application/json" },
65
+ body: JSON.stringify({ events })
66
+ }).catch((err) => {
67
+ if (debug) console.warn("[litemetrics:rn] send failed", err);
68
+ queue.unshift(...events);
69
+ });
70
+ }
71
+ function send(event) {
72
+ queue.push(event);
73
+ if (queue.length >= (config.batchSize ?? 10)) {
74
+ flush();
75
+ }
76
+ }
77
+ flushTimer = setInterval(flush, config.flushInterval ?? 5e3);
78
+ return {
79
+ track(name, properties) {
80
+ const event = {
81
+ type: "event",
82
+ siteId,
83
+ timestamp: Date.now(),
84
+ sessionId,
85
+ visitorId,
86
+ name,
87
+ properties,
88
+ ...getContext()
89
+ };
90
+ if (userId) event.userId = userId;
91
+ send(event);
92
+ },
93
+ identify(id, traits) {
94
+ userId = id;
95
+ const event = {
96
+ type: "identify",
97
+ siteId,
98
+ timestamp: Date.now(),
99
+ sessionId,
100
+ visitorId,
101
+ userId: id,
102
+ traits,
103
+ ...getContext()
104
+ };
105
+ send(event);
106
+ },
107
+ page(screenName) {
108
+ const event = {
109
+ type: "pageview",
110
+ siteId,
111
+ timestamp: Date.now(),
112
+ sessionId,
113
+ visitorId,
114
+ url: screenName,
115
+ title: screenName,
116
+ ...getContext()
117
+ };
118
+ if (userId) event.userId = userId;
119
+ send(event);
120
+ },
121
+ reset() {
122
+ sessionId = generateId();
123
+ visitorId = generateId().slice(0, 16);
124
+ userId = null;
125
+ },
126
+ destroy() {
127
+ flush();
128
+ if (flushTimer) {
129
+ clearInterval(flushTimer);
130
+ flushTimer = null;
131
+ }
132
+ }
133
+ };
134
+ }
135
+
136
+ // src/context.tsx
137
+ var import_jsx_runtime = require("react/jsx-runtime");
138
+ var LitemetricsRNContext = (0, import_react.createContext)(null);
139
+ function LitemetricsProvider({ children, ...config }) {
140
+ const trackerRef = (0, import_react.useRef)(null);
141
+ if (!trackerRef.current) {
142
+ trackerRef.current = createRNTracker(config);
143
+ }
144
+ (0, import_react.useEffect)(() => {
145
+ return () => {
146
+ trackerRef.current?.destroy();
147
+ };
148
+ }, []);
149
+ const value = (0, import_react.useMemo)(
150
+ () => ({
151
+ tracker: trackerRef.current,
152
+ siteId: config.siteId
153
+ }),
154
+ [config.siteId]
155
+ );
156
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LitemetricsRNContext.Provider, { value, children });
157
+ }
158
+ function useLitemetricsRNContext() {
159
+ const ctx = (0, import_react.useContext)(LitemetricsRNContext);
160
+ if (!ctx) {
161
+ throw new Error("useLitemetrics must be used within <LitemetricsProvider>");
162
+ }
163
+ return ctx;
164
+ }
165
+
166
+ // src/hooks.ts
167
+ var import_react2 = require("react");
168
+ function useLitemetrics() {
169
+ const { tracker } = useLitemetricsRNContext();
170
+ return {
171
+ track: tracker.track.bind(tracker),
172
+ identify: tracker.identify.bind(tracker),
173
+ page: tracker.page.bind(tracker),
174
+ reset: tracker.reset.bind(tracker)
175
+ };
176
+ }
177
+ function useNavigationTracking() {
178
+ const { tracker } = useLitemetricsRNContext();
179
+ const routeNameRef = (0, import_react2.useRef)(void 0);
180
+ const navigationRef = (0, import_react2.useRef)(null);
181
+ const onStateChange = (0, import_react2.useCallback)(() => {
182
+ const currentRoute = navigationRef.current?.getCurrentRoute?.();
183
+ const currentRouteName = currentRoute?.name;
184
+ if (currentRouteName && currentRouteName !== routeNameRef.current) {
185
+ routeNameRef.current = currentRouteName;
186
+ tracker.page(currentRouteName);
187
+ }
188
+ }, [tracker]);
189
+ return { onStateChange, navigationRef };
190
+ }
191
+ function useAppStateTracking() {
192
+ const { tracker } = useLitemetricsRNContext();
193
+ const appStateRef = (0, import_react2.useRef)("active");
194
+ (0, import_react2.useEffect)(() => {
195
+ let AppState;
196
+ let subscription;
197
+ try {
198
+ AppState = require("react-native").AppState;
199
+ } catch {
200
+ return;
201
+ }
202
+ appStateRef.current = AppState.currentState;
203
+ subscription = AppState.addEventListener("change", (nextState) => {
204
+ if (appStateRef.current.match(/inactive|background/) && nextState === "active") {
205
+ tracker.track("app_foreground");
206
+ } else if (nextState.match(/inactive|background/)) {
207
+ tracker.track("app_background");
208
+ }
209
+ appStateRef.current = nextState;
210
+ });
211
+ return () => {
212
+ subscription?.remove();
213
+ };
214
+ }, [tracker]);
215
+ }
216
+ // Annotate the CommonJS export names for ESM import in node:
217
+ 0 && (module.exports = {
218
+ LitemetricsProvider,
219
+ createRNTracker,
220
+ useAppStateTracking,
221
+ useLitemetrics,
222
+ useNavigationTracking
223
+ });
224
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/context.tsx","../src/tracker.ts","../src/hooks.ts"],"sourcesContent":["export { LitemetricsProvider } from './context';\nexport type { LitemetricsProviderProps } from './context';\nexport { useLitemetrics, useNavigationTracking, useAppStateTracking } from './hooks';\nexport { createRNTracker } from './tracker';\nexport type { RNTrackerInstance } from './tracker';\n","import { createContext, useContext, useEffect, useRef, useMemo } from \"react\";\nimport type { TrackerConfig } from \"@litemetrics/core\";\nimport { createRNTracker, type RNTrackerInstance } from \"./tracker\";\n\ninterface LitemetricsRNContextValue {\n tracker: RNTrackerInstance;\n siteId: string;\n}\n\nconst LitemetricsRNContext = createContext<LitemetricsRNContextValue | null>(null);\n\nexport interface LitemetricsProviderProps\n extends Omit<TrackerConfig, \"autoTrack\" | \"autoSpa\"> {\n children: React.ReactNode;\n}\n\nexport function LitemetricsProvider({ children, ...config }: LitemetricsProviderProps) {\n const trackerRef = useRef<RNTrackerInstance | null>(null);\n\n if (!trackerRef.current) {\n trackerRef.current = createRNTracker(config);\n }\n\n useEffect(() => {\n return () => {\n trackerRef.current?.destroy();\n };\n }, []);\n\n const value = useMemo<LitemetricsRNContextValue>(\n () => ({\n tracker: trackerRef.current!,\n siteId: config.siteId,\n }),\n [config.siteId]\n );\n\n return (\n <LitemetricsRNContext.Provider value={value}>\n {children}\n </LitemetricsRNContext.Provider>\n );\n}\n\nexport function useLitemetricsRNContext(): LitemetricsRNContextValue {\n const ctx = useContext(LitemetricsRNContext);\n if (!ctx) {\n throw new Error(\"useLitemetrics must be used within <LitemetricsProvider>\");\n }\n return ctx;\n}\n","import type {\n TrackerConfig,\n ClientEvent,\n PageviewEvent,\n CustomEvent,\n IdentifyEvent,\n ClientContext,\n} from '@litemetrics/core';\n\nexport interface RNTrackerInstance {\n track(name: string, properties?: Record<string, unknown>): void;\n identify(userId: string, traits?: Record<string, unknown>): void;\n page(screenName: string): void;\n reset(): void;\n destroy(): void;\n}\n\nlet sessionId: string | null = null;\nlet visitorId: string | null = null;\nlet userId: string | null = null;\n\nfunction generateId(): string {\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n\nexport function createRNTracker(config: TrackerConfig): RNTrackerInstance {\n const { siteId, endpoint, debug = false } = config;\n\n if (!sessionId) sessionId = generateId();\n if (!visitorId) visitorId = generateId().slice(0, 16);\n\n const queue: ClientEvent[] = [];\n let flushTimer: ReturnType<typeof setInterval> | null = null;\n\n function getContext(): ClientContext {\n return {\n timezone:\n typeof Intl !== 'undefined'\n ? Intl.DateTimeFormat().resolvedOptions().timeZone\n : undefined,\n };\n }\n\n function flush() {\n if (queue.length === 0) return;\n const events = queue.splice(0);\n\n if (debug) {\n console.log('[litemetrics:rn] sending', events.length, 'events');\n }\n\n fetch(endpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ events }),\n }).catch((err) => {\n if (debug) console.warn('[litemetrics:rn] send failed', err);\n // Push back to queue for retry\n queue.unshift(...events);\n });\n }\n\n function send(event: ClientEvent) {\n queue.push(event);\n if (queue.length >= (config.batchSize ?? 10)) {\n flush();\n }\n }\n\n // Start flush timer\n flushTimer = setInterval(flush, config.flushInterval ?? 5000);\n\n return {\n track(name: string, properties?: Record<string, unknown>) {\n const event: CustomEvent & ClientContext = {\n type: 'event',\n siteId,\n timestamp: Date.now(),\n sessionId: sessionId!,\n visitorId: visitorId!,\n name,\n properties,\n ...getContext(),\n };\n if (userId) (event as any).userId = userId;\n send(event);\n },\n\n identify(id: string, traits?: Record<string, unknown>) {\n userId = id;\n const event: IdentifyEvent & ClientContext = {\n type: 'identify',\n siteId,\n timestamp: Date.now(),\n sessionId: sessionId!,\n visitorId: visitorId!,\n userId: id,\n traits,\n ...getContext(),\n };\n send(event);\n },\n\n page(screenName: string) {\n const event: PageviewEvent & ClientContext = {\n type: 'pageview',\n siteId,\n timestamp: Date.now(),\n sessionId: sessionId!,\n visitorId: visitorId!,\n url: screenName,\n title: screenName,\n ...getContext(),\n };\n if (userId) (event as any).userId = userId;\n send(event);\n },\n\n reset() {\n sessionId = generateId();\n visitorId = generateId().slice(0, 16);\n userId = null;\n },\n\n destroy() {\n flush();\n if (flushTimer) {\n clearInterval(flushTimer);\n flushTimer = null;\n }\n },\n };\n}\n","import { useEffect, useRef, useCallback } from 'react';\nimport { useLitemetricsRNContext } from './context';\n\n/**\n * Access the Litemetrics tracker instance in React Native.\n *\n * @example\n * ```tsx\n * function Button() {\n * const { track } = useLitemetrics();\n * return <Pressable onPress={() => track('tap', { screen: 'home' })}><Text>Tap</Text></Pressable>;\n * }\n * ```\n */\nexport function useLitemetrics() {\n const { tracker } = useLitemetricsRNContext();\n\n return {\n track: tracker.track.bind(tracker),\n identify: tracker.identify.bind(tracker),\n page: tracker.page.bind(tracker),\n reset: tracker.reset.bind(tracker),\n };\n}\n\n/**\n * Track React Navigation screen changes.\n * Returns `onStateChange` and `ref` props for NavigationContainer.\n *\n * @example\n * ```tsx\n * import { NavigationContainer } from '@react-navigation/native';\n *\n * function App() {\n * const { onStateChange, navigationRef } = useNavigationTracking();\n * return (\n * <LitemetricsProvider siteId=\"xxx\" endpoint=\"https://api.example.com/collect\">\n * <NavigationContainer ref={navigationRef} onStateChange={onStateChange}>\n * <Stack.Navigator>...</Stack.Navigator>\n * </NavigationContainer>\n * </LitemetricsProvider>\n * );\n * }\n * ```\n */\nexport function useNavigationTracking() {\n const { tracker } = useLitemetricsRNContext();\n const routeNameRef = useRef<string | undefined>(undefined);\n const navigationRef = useRef<any>(null);\n\n const onStateChange = useCallback(() => {\n const currentRoute = navigationRef.current?.getCurrentRoute?.();\n const currentRouteName = currentRoute?.name;\n\n if (currentRouteName && currentRouteName !== routeNameRef.current) {\n routeNameRef.current = currentRouteName;\n tracker.page(currentRouteName);\n }\n }, [tracker]);\n\n return { onStateChange, navigationRef };\n}\n\n/**\n * Track app foreground/background state changes.\n * Sends events when the app goes to background and comes back.\n *\n * @example\n * ```tsx\n * function App() {\n * useAppStateTracking();\n * return <MainScreen />;\n * }\n * ```\n */\nexport function useAppStateTracking() {\n const { tracker } = useLitemetricsRNContext();\n const appStateRef = useRef<string>('active');\n\n useEffect(() => {\n let AppState: any;\n let subscription: any;\n\n // Dynamic import to avoid crash if not in RN environment\n try {\n AppState = require('react-native').AppState;\n } catch {\n return;\n }\n\n appStateRef.current = AppState.currentState;\n\n subscription = AppState.addEventListener('change', (nextState: string) => {\n if (appStateRef.current.match(/inactive|background/) && nextState === 'active') {\n tracker.track('app_foreground');\n } else if (nextState.match(/inactive|background/)) {\n tracker.track('app_background');\n }\n appStateRef.current = nextState;\n });\n\n return () => {\n subscription?.remove();\n };\n }, [tracker]);\n}\n"],"mappings":"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","names":["import_react"]}
@@ -0,0 +1,74 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { TrackerConfig } from '@litemetrics/core';
3
+ import * as react from 'react';
4
+
5
+ interface RNTrackerInstance {
6
+ track(name: string, properties?: Record<string, unknown>): void;
7
+ identify(userId: string, traits?: Record<string, unknown>): void;
8
+ page(screenName: string): void;
9
+ reset(): void;
10
+ destroy(): void;
11
+ }
12
+ declare function createRNTracker(config: TrackerConfig): RNTrackerInstance;
13
+
14
+ interface LitemetricsProviderProps extends Omit<TrackerConfig, "autoTrack" | "autoSpa"> {
15
+ children: React.ReactNode;
16
+ }
17
+ declare function LitemetricsProvider({ children, ...config }: LitemetricsProviderProps): react_jsx_runtime.JSX.Element;
18
+
19
+ /**
20
+ * Access the Litemetrics tracker instance in React Native.
21
+ *
22
+ * @example
23
+ * ```tsx
24
+ * function Button() {
25
+ * const { track } = useLitemetrics();
26
+ * return <Pressable onPress={() => track('tap', { screen: 'home' })}><Text>Tap</Text></Pressable>;
27
+ * }
28
+ * ```
29
+ */
30
+ declare function useLitemetrics(): {
31
+ track: (name: string, properties?: Record<string, unknown>) => void;
32
+ identify: (userId: string, traits?: Record<string, unknown>) => void;
33
+ page: (screenName: string) => void;
34
+ reset: () => void;
35
+ };
36
+ /**
37
+ * Track React Navigation screen changes.
38
+ * Returns `onStateChange` and `ref` props for NavigationContainer.
39
+ *
40
+ * @example
41
+ * ```tsx
42
+ * import { NavigationContainer } from '@react-navigation/native';
43
+ *
44
+ * function App() {
45
+ * const { onStateChange, navigationRef } = useNavigationTracking();
46
+ * return (
47
+ * <LitemetricsProvider siteId="xxx" endpoint="https://api.example.com/collect">
48
+ * <NavigationContainer ref={navigationRef} onStateChange={onStateChange}>
49
+ * <Stack.Navigator>...</Stack.Navigator>
50
+ * </NavigationContainer>
51
+ * </LitemetricsProvider>
52
+ * );
53
+ * }
54
+ * ```
55
+ */
56
+ declare function useNavigationTracking(): {
57
+ onStateChange: () => void;
58
+ navigationRef: react.RefObject<any>;
59
+ };
60
+ /**
61
+ * Track app foreground/background state changes.
62
+ * Sends events when the app goes to background and comes back.
63
+ *
64
+ * @example
65
+ * ```tsx
66
+ * function App() {
67
+ * useAppStateTracking();
68
+ * return <MainScreen />;
69
+ * }
70
+ * ```
71
+ */
72
+ declare function useAppStateTracking(): void;
73
+
74
+ export { LitemetricsProvider, type LitemetricsProviderProps, type RNTrackerInstance, createRNTracker, useAppStateTracking, useLitemetrics, useNavigationTracking };
@@ -0,0 +1,74 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { TrackerConfig } from '@litemetrics/core';
3
+ import * as react from 'react';
4
+
5
+ interface RNTrackerInstance {
6
+ track(name: string, properties?: Record<string, unknown>): void;
7
+ identify(userId: string, traits?: Record<string, unknown>): void;
8
+ page(screenName: string): void;
9
+ reset(): void;
10
+ destroy(): void;
11
+ }
12
+ declare function createRNTracker(config: TrackerConfig): RNTrackerInstance;
13
+
14
+ interface LitemetricsProviderProps extends Omit<TrackerConfig, "autoTrack" | "autoSpa"> {
15
+ children: React.ReactNode;
16
+ }
17
+ declare function LitemetricsProvider({ children, ...config }: LitemetricsProviderProps): react_jsx_runtime.JSX.Element;
18
+
19
+ /**
20
+ * Access the Litemetrics tracker instance in React Native.
21
+ *
22
+ * @example
23
+ * ```tsx
24
+ * function Button() {
25
+ * const { track } = useLitemetrics();
26
+ * return <Pressable onPress={() => track('tap', { screen: 'home' })}><Text>Tap</Text></Pressable>;
27
+ * }
28
+ * ```
29
+ */
30
+ declare function useLitemetrics(): {
31
+ track: (name: string, properties?: Record<string, unknown>) => void;
32
+ identify: (userId: string, traits?: Record<string, unknown>) => void;
33
+ page: (screenName: string) => void;
34
+ reset: () => void;
35
+ };
36
+ /**
37
+ * Track React Navigation screen changes.
38
+ * Returns `onStateChange` and `ref` props for NavigationContainer.
39
+ *
40
+ * @example
41
+ * ```tsx
42
+ * import { NavigationContainer } from '@react-navigation/native';
43
+ *
44
+ * function App() {
45
+ * const { onStateChange, navigationRef } = useNavigationTracking();
46
+ * return (
47
+ * <LitemetricsProvider siteId="xxx" endpoint="https://api.example.com/collect">
48
+ * <NavigationContainer ref={navigationRef} onStateChange={onStateChange}>
49
+ * <Stack.Navigator>...</Stack.Navigator>
50
+ * </NavigationContainer>
51
+ * </LitemetricsProvider>
52
+ * );
53
+ * }
54
+ * ```
55
+ */
56
+ declare function useNavigationTracking(): {
57
+ onStateChange: () => void;
58
+ navigationRef: react.RefObject<any>;
59
+ };
60
+ /**
61
+ * Track app foreground/background state changes.
62
+ * Sends events when the app goes to background and comes back.
63
+ *
64
+ * @example
65
+ * ```tsx
66
+ * function App() {
67
+ * useAppStateTracking();
68
+ * return <MainScreen />;
69
+ * }
70
+ * ```
71
+ */
72
+ declare function useAppStateTracking(): void;
73
+
74
+ export { LitemetricsProvider, type LitemetricsProviderProps, type RNTrackerInstance, createRNTracker, useAppStateTracking, useLitemetrics, useNavigationTracking };
package/dist/index.js ADDED
@@ -0,0 +1,200 @@
1
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
+ }) : x)(function(x) {
4
+ if (typeof require !== "undefined") return require.apply(this, arguments);
5
+ throw Error('Dynamic require of "' + x + '" is not supported');
6
+ });
7
+
8
+ // src/context.tsx
9
+ import { createContext, useContext, useEffect, useRef, useMemo } from "react";
10
+
11
+ // src/tracker.ts
12
+ var sessionId = null;
13
+ var visitorId = null;
14
+ var userId = null;
15
+ function generateId() {
16
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
17
+ const r = Math.random() * 16 | 0;
18
+ const v = c === "x" ? r : r & 3 | 8;
19
+ return v.toString(16);
20
+ });
21
+ }
22
+ function createRNTracker(config) {
23
+ const { siteId, endpoint, debug = false } = config;
24
+ if (!sessionId) sessionId = generateId();
25
+ if (!visitorId) visitorId = generateId().slice(0, 16);
26
+ const queue = [];
27
+ let flushTimer = null;
28
+ function getContext() {
29
+ return {
30
+ timezone: typeof Intl !== "undefined" ? Intl.DateTimeFormat().resolvedOptions().timeZone : void 0
31
+ };
32
+ }
33
+ function flush() {
34
+ if (queue.length === 0) return;
35
+ const events = queue.splice(0);
36
+ if (debug) {
37
+ console.log("[litemetrics:rn] sending", events.length, "events");
38
+ }
39
+ fetch(endpoint, {
40
+ method: "POST",
41
+ headers: { "Content-Type": "application/json" },
42
+ body: JSON.stringify({ events })
43
+ }).catch((err) => {
44
+ if (debug) console.warn("[litemetrics:rn] send failed", err);
45
+ queue.unshift(...events);
46
+ });
47
+ }
48
+ function send(event) {
49
+ queue.push(event);
50
+ if (queue.length >= (config.batchSize ?? 10)) {
51
+ flush();
52
+ }
53
+ }
54
+ flushTimer = setInterval(flush, config.flushInterval ?? 5e3);
55
+ return {
56
+ track(name, properties) {
57
+ const event = {
58
+ type: "event",
59
+ siteId,
60
+ timestamp: Date.now(),
61
+ sessionId,
62
+ visitorId,
63
+ name,
64
+ properties,
65
+ ...getContext()
66
+ };
67
+ if (userId) event.userId = userId;
68
+ send(event);
69
+ },
70
+ identify(id, traits) {
71
+ userId = id;
72
+ const event = {
73
+ type: "identify",
74
+ siteId,
75
+ timestamp: Date.now(),
76
+ sessionId,
77
+ visitorId,
78
+ userId: id,
79
+ traits,
80
+ ...getContext()
81
+ };
82
+ send(event);
83
+ },
84
+ page(screenName) {
85
+ const event = {
86
+ type: "pageview",
87
+ siteId,
88
+ timestamp: Date.now(),
89
+ sessionId,
90
+ visitorId,
91
+ url: screenName,
92
+ title: screenName,
93
+ ...getContext()
94
+ };
95
+ if (userId) event.userId = userId;
96
+ send(event);
97
+ },
98
+ reset() {
99
+ sessionId = generateId();
100
+ visitorId = generateId().slice(0, 16);
101
+ userId = null;
102
+ },
103
+ destroy() {
104
+ flush();
105
+ if (flushTimer) {
106
+ clearInterval(flushTimer);
107
+ flushTimer = null;
108
+ }
109
+ }
110
+ };
111
+ }
112
+
113
+ // src/context.tsx
114
+ import { jsx } from "react/jsx-runtime";
115
+ var LitemetricsRNContext = createContext(null);
116
+ function LitemetricsProvider({ children, ...config }) {
117
+ const trackerRef = useRef(null);
118
+ if (!trackerRef.current) {
119
+ trackerRef.current = createRNTracker(config);
120
+ }
121
+ useEffect(() => {
122
+ return () => {
123
+ trackerRef.current?.destroy();
124
+ };
125
+ }, []);
126
+ const value = useMemo(
127
+ () => ({
128
+ tracker: trackerRef.current,
129
+ siteId: config.siteId
130
+ }),
131
+ [config.siteId]
132
+ );
133
+ return /* @__PURE__ */ jsx(LitemetricsRNContext.Provider, { value, children });
134
+ }
135
+ function useLitemetricsRNContext() {
136
+ const ctx = useContext(LitemetricsRNContext);
137
+ if (!ctx) {
138
+ throw new Error("useLitemetrics must be used within <LitemetricsProvider>");
139
+ }
140
+ return ctx;
141
+ }
142
+
143
+ // src/hooks.ts
144
+ import { useEffect as useEffect2, useRef as useRef2, useCallback } from "react";
145
+ function useLitemetrics() {
146
+ const { tracker } = useLitemetricsRNContext();
147
+ return {
148
+ track: tracker.track.bind(tracker),
149
+ identify: tracker.identify.bind(tracker),
150
+ page: tracker.page.bind(tracker),
151
+ reset: tracker.reset.bind(tracker)
152
+ };
153
+ }
154
+ function useNavigationTracking() {
155
+ const { tracker } = useLitemetricsRNContext();
156
+ const routeNameRef = useRef2(void 0);
157
+ const navigationRef = useRef2(null);
158
+ const onStateChange = useCallback(() => {
159
+ const currentRoute = navigationRef.current?.getCurrentRoute?.();
160
+ const currentRouteName = currentRoute?.name;
161
+ if (currentRouteName && currentRouteName !== routeNameRef.current) {
162
+ routeNameRef.current = currentRouteName;
163
+ tracker.page(currentRouteName);
164
+ }
165
+ }, [tracker]);
166
+ return { onStateChange, navigationRef };
167
+ }
168
+ function useAppStateTracking() {
169
+ const { tracker } = useLitemetricsRNContext();
170
+ const appStateRef = useRef2("active");
171
+ useEffect2(() => {
172
+ let AppState;
173
+ let subscription;
174
+ try {
175
+ AppState = __require("react-native").AppState;
176
+ } catch {
177
+ return;
178
+ }
179
+ appStateRef.current = AppState.currentState;
180
+ subscription = AppState.addEventListener("change", (nextState) => {
181
+ if (appStateRef.current.match(/inactive|background/) && nextState === "active") {
182
+ tracker.track("app_foreground");
183
+ } else if (nextState.match(/inactive|background/)) {
184
+ tracker.track("app_background");
185
+ }
186
+ appStateRef.current = nextState;
187
+ });
188
+ return () => {
189
+ subscription?.remove();
190
+ };
191
+ }, [tracker]);
192
+ }
193
+ export {
194
+ LitemetricsProvider,
195
+ createRNTracker,
196
+ useAppStateTracking,
197
+ useLitemetrics,
198
+ useNavigationTracking
199
+ };
200
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/context.tsx","../src/tracker.ts","../src/hooks.ts"],"sourcesContent":["import { createContext, useContext, useEffect, useRef, useMemo } from \"react\";\nimport type { TrackerConfig } from \"@litemetrics/core\";\nimport { createRNTracker, type RNTrackerInstance } from \"./tracker\";\n\ninterface LitemetricsRNContextValue {\n tracker: RNTrackerInstance;\n siteId: string;\n}\n\nconst LitemetricsRNContext = createContext<LitemetricsRNContextValue | null>(null);\n\nexport interface LitemetricsProviderProps\n extends Omit<TrackerConfig, \"autoTrack\" | \"autoSpa\"> {\n children: React.ReactNode;\n}\n\nexport function LitemetricsProvider({ children, ...config }: LitemetricsProviderProps) {\n const trackerRef = useRef<RNTrackerInstance | null>(null);\n\n if (!trackerRef.current) {\n trackerRef.current = createRNTracker(config);\n }\n\n useEffect(() => {\n return () => {\n trackerRef.current?.destroy();\n };\n }, []);\n\n const value = useMemo<LitemetricsRNContextValue>(\n () => ({\n tracker: trackerRef.current!,\n siteId: config.siteId,\n }),\n [config.siteId]\n );\n\n return (\n <LitemetricsRNContext.Provider value={value}>\n {children}\n </LitemetricsRNContext.Provider>\n );\n}\n\nexport function useLitemetricsRNContext(): LitemetricsRNContextValue {\n const ctx = useContext(LitemetricsRNContext);\n if (!ctx) {\n throw new Error(\"useLitemetrics must be used within <LitemetricsProvider>\");\n }\n return ctx;\n}\n","import type {\n TrackerConfig,\n ClientEvent,\n PageviewEvent,\n CustomEvent,\n IdentifyEvent,\n ClientContext,\n} from '@litemetrics/core';\n\nexport interface RNTrackerInstance {\n track(name: string, properties?: Record<string, unknown>): void;\n identify(userId: string, traits?: Record<string, unknown>): void;\n page(screenName: string): void;\n reset(): void;\n destroy(): void;\n}\n\nlet sessionId: string | null = null;\nlet visitorId: string | null = null;\nlet userId: string | null = null;\n\nfunction generateId(): string {\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n\nexport function createRNTracker(config: TrackerConfig): RNTrackerInstance {\n const { siteId, endpoint, debug = false } = config;\n\n if (!sessionId) sessionId = generateId();\n if (!visitorId) visitorId = generateId().slice(0, 16);\n\n const queue: ClientEvent[] = [];\n let flushTimer: ReturnType<typeof setInterval> | null = null;\n\n function getContext(): ClientContext {\n return {\n timezone:\n typeof Intl !== 'undefined'\n ? Intl.DateTimeFormat().resolvedOptions().timeZone\n : undefined,\n };\n }\n\n function flush() {\n if (queue.length === 0) return;\n const events = queue.splice(0);\n\n if (debug) {\n console.log('[litemetrics:rn] sending', events.length, 'events');\n }\n\n fetch(endpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ events }),\n }).catch((err) => {\n if (debug) console.warn('[litemetrics:rn] send failed', err);\n // Push back to queue for retry\n queue.unshift(...events);\n });\n }\n\n function send(event: ClientEvent) {\n queue.push(event);\n if (queue.length >= (config.batchSize ?? 10)) {\n flush();\n }\n }\n\n // Start flush timer\n flushTimer = setInterval(flush, config.flushInterval ?? 5000);\n\n return {\n track(name: string, properties?: Record<string, unknown>) {\n const event: CustomEvent & ClientContext = {\n type: 'event',\n siteId,\n timestamp: Date.now(),\n sessionId: sessionId!,\n visitorId: visitorId!,\n name,\n properties,\n ...getContext(),\n };\n if (userId) (event as any).userId = userId;\n send(event);\n },\n\n identify(id: string, traits?: Record<string, unknown>) {\n userId = id;\n const event: IdentifyEvent & ClientContext = {\n type: 'identify',\n siteId,\n timestamp: Date.now(),\n sessionId: sessionId!,\n visitorId: visitorId!,\n userId: id,\n traits,\n ...getContext(),\n };\n send(event);\n },\n\n page(screenName: string) {\n const event: PageviewEvent & ClientContext = {\n type: 'pageview',\n siteId,\n timestamp: Date.now(),\n sessionId: sessionId!,\n visitorId: visitorId!,\n url: screenName,\n title: screenName,\n ...getContext(),\n };\n if (userId) (event as any).userId = userId;\n send(event);\n },\n\n reset() {\n sessionId = generateId();\n visitorId = generateId().slice(0, 16);\n userId = null;\n },\n\n destroy() {\n flush();\n if (flushTimer) {\n clearInterval(flushTimer);\n flushTimer = null;\n }\n },\n };\n}\n","import { useEffect, useRef, useCallback } from 'react';\nimport { useLitemetricsRNContext } from './context';\n\n/**\n * Access the Litemetrics tracker instance in React Native.\n *\n * @example\n * ```tsx\n * function Button() {\n * const { track } = useLitemetrics();\n * return <Pressable onPress={() => track('tap', { screen: 'home' })}><Text>Tap</Text></Pressable>;\n * }\n * ```\n */\nexport function useLitemetrics() {\n const { tracker } = useLitemetricsRNContext();\n\n return {\n track: tracker.track.bind(tracker),\n identify: tracker.identify.bind(tracker),\n page: tracker.page.bind(tracker),\n reset: tracker.reset.bind(tracker),\n };\n}\n\n/**\n * Track React Navigation screen changes.\n * Returns `onStateChange` and `ref` props for NavigationContainer.\n *\n * @example\n * ```tsx\n * import { NavigationContainer } from '@react-navigation/native';\n *\n * function App() {\n * const { onStateChange, navigationRef } = useNavigationTracking();\n * return (\n * <LitemetricsProvider siteId=\"xxx\" endpoint=\"https://api.example.com/collect\">\n * <NavigationContainer ref={navigationRef} onStateChange={onStateChange}>\n * <Stack.Navigator>...</Stack.Navigator>\n * </NavigationContainer>\n * </LitemetricsProvider>\n * );\n * }\n * ```\n */\nexport function useNavigationTracking() {\n const { tracker } = useLitemetricsRNContext();\n const routeNameRef = useRef<string | undefined>(undefined);\n const navigationRef = useRef<any>(null);\n\n const onStateChange = useCallback(() => {\n const currentRoute = navigationRef.current?.getCurrentRoute?.();\n const currentRouteName = currentRoute?.name;\n\n if (currentRouteName && currentRouteName !== routeNameRef.current) {\n routeNameRef.current = currentRouteName;\n tracker.page(currentRouteName);\n }\n }, [tracker]);\n\n return { onStateChange, navigationRef };\n}\n\n/**\n * Track app foreground/background state changes.\n * Sends events when the app goes to background and comes back.\n *\n * @example\n * ```tsx\n * function App() {\n * useAppStateTracking();\n * return <MainScreen />;\n * }\n * ```\n */\nexport function useAppStateTracking() {\n const { tracker } = useLitemetricsRNContext();\n const appStateRef = useRef<string>('active');\n\n useEffect(() => {\n let AppState: any;\n let subscription: any;\n\n // Dynamic import to avoid crash if not in RN environment\n try {\n AppState = require('react-native').AppState;\n } catch {\n return;\n }\n\n appStateRef.current = AppState.currentState;\n\n subscription = AppState.addEventListener('change', (nextState: string) => {\n if (appStateRef.current.match(/inactive|background/) && nextState === 'active') {\n tracker.track('app_foreground');\n } else if (nextState.match(/inactive|background/)) {\n tracker.track('app_background');\n }\n appStateRef.current = nextState;\n });\n\n return () => {\n subscription?.remove();\n };\n }, [tracker]);\n}\n"],"mappings":"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","names":["useEffect","useRef","useRef","useEffect"]}
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@litemetrics/react-native",
3
+ "version": "0.1.0",
4
+ "description": "React Native / Expo bindings for Litemetrics analytics",
5
+ "license": "MIT",
6
+ "author": "Metehan Kurucu",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/metehankurucu/litemetrics",
10
+ "directory": "packages/react-native"
11
+ },
12
+ "keywords": ["analytics", "litemetrics", "react-native", "expo", "tracking"],
13
+ "type": "module",
14
+ "main": "./dist/index.cjs",
15
+ "module": "./dist/index.js",
16
+ "types": "./dist/index.d.ts",
17
+ "exports": {
18
+ ".": {
19
+ "types": "./dist/index.d.ts",
20
+ "import": "./dist/index.js",
21
+ "require": "./dist/index.cjs"
22
+ }
23
+ },
24
+ "files": ["dist"],
25
+ "publishConfig": {
26
+ "access": "public"
27
+ },
28
+ "scripts": {
29
+ "build": "tsup",
30
+ "dev": "tsup --watch",
31
+ "typecheck": "tsc --noEmit",
32
+ "clean": "rm -rf dist"
33
+ },
34
+ "dependencies": {
35
+ "@litemetrics/core": "0.1.0"
36
+ },
37
+ "peerDependencies": {
38
+ "react": ">=18",
39
+ "react-native": ">=0.72"
40
+ },
41
+ "devDependencies": {
42
+ "@types/react": "^19",
43
+ "react": "^19",
44
+ "tsup": "^8",
45
+ "typescript": "^5.7"
46
+ }
47
+ }