react-native-netmera 2.1.0-alpha04 → 2.1.0-alpha05
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/lib/module/NetmeraAnalyticProvider.js +7 -10
- package/lib/module/NetmeraAnalyticProvider.js.map +1 -1
- package/lib/module/autotracking/useNavigationTracking.js +14 -52
- package/lib/module/autotracking/useNavigationTracking.js.map +1 -1
- package/lib/module/autotracking/useTapTracking.js +4 -10
- package/lib/module/autotracking/useTapTracking.js.map +1 -1
- package/lib/typescript/src/NetmeraAnalyticProvider.d.ts +14 -9
- package/lib/typescript/src/NetmeraAnalyticProvider.d.ts.map +1 -1
- package/lib/typescript/src/autotracking/useNavigationTracking.d.ts +8 -7
- package/lib/typescript/src/autotracking/useNavigationTracking.d.ts.map +1 -1
- package/lib/typescript/src/autotracking/useTapTracking.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/NetmeraAnalyticProvider.tsx +19 -16
- package/src/autotracking/useNavigationTracking.ts +14 -65
- package/src/autotracking/useTapTracking.ts +3 -16
|
@@ -11,16 +11,12 @@ import { useTapTracking } from "./autotracking/useTapTracking.js";
|
|
|
11
11
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
12
12
|
/**
|
|
13
13
|
* Wraps your app to enable automatic screen tracking and tap tracking.
|
|
14
|
-
*
|
|
15
|
-
* <NetmeraAnalyticProvider>
|
|
16
|
-
* <NavigationContainer>…</NavigationContainer>
|
|
17
|
-
* </NetmeraAnalyticProvider>
|
|
14
|
+
* Place it outside your NavigationContainer (or Static Navigation component).
|
|
18
15
|
*/
|
|
19
16
|
export function NetmeraAnalyticProvider({
|
|
20
17
|
children,
|
|
21
18
|
navigationRef
|
|
22
19
|
}) {
|
|
23
|
-
const viewRef = useRef(null);
|
|
24
20
|
const [config, setConfig] = useState(null);
|
|
25
21
|
const appliedConfigRef = useRef(null);
|
|
26
22
|
const applyConfig = cfg => {
|
|
@@ -28,8 +24,8 @@ export function NetmeraAnalyticProvider({
|
|
|
28
24
|
if (prev?.isScreenFlowEnabled === cfg.isScreenFlowEnabled && prev?.isInputActionEnabled === cfg.isInputActionEnabled && prev?.shouldCollectValues === cfg.shouldCollectValues) return;
|
|
29
25
|
appliedConfigRef.current = cfg;
|
|
30
26
|
setConfig(cfg);
|
|
31
|
-
console.log('[NMAutotrack] screen tracking
|
|
32
|
-
console.log('[NMAutotrack] input action tracking
|
|
27
|
+
console.log('[NMAutotrack] screen tracking', cfg.isScreenFlowEnabled ? 'enabled' : 'disabled');
|
|
28
|
+
console.log('[NMAutotrack] input action tracking', cfg.isInputActionEnabled ? 'enabled' : 'disabled');
|
|
33
29
|
};
|
|
34
30
|
useEffect(() => {
|
|
35
31
|
NativeModules.RNNetmera?.getAutoTrackConfig?.()?.then(cfg => {
|
|
@@ -46,14 +42,15 @@ export function NetmeraAnalyticProvider({
|
|
|
46
42
|
const screenFlowEnabled = config?.isScreenFlowEnabled ?? false;
|
|
47
43
|
const inputActionEnabled = config?.isInputActionEnabled ?? false;
|
|
48
44
|
const shouldCollectValues = config?.shouldCollectValues ?? false;
|
|
49
|
-
|
|
50
|
-
|
|
45
|
+
|
|
46
|
+
// Navigation tracking is needed whenever either flag is on: screen events
|
|
47
|
+
// need it for trackView, action events need it for the screen-name prefix.
|
|
48
|
+
useNavigationTracking(navigationRef, screenFlowEnabled || inputActionEnabled, screenFlowEnabled);
|
|
51
49
|
const {
|
|
52
50
|
onTouchStart,
|
|
53
51
|
onTouchEnd
|
|
54
52
|
} = useTapTracking(inputActionEnabled, shouldCollectValues);
|
|
55
53
|
return /*#__PURE__*/_jsx(View, {
|
|
56
|
-
ref: navigationEnabled ? viewRef : undefined,
|
|
57
54
|
style: styles.container,
|
|
58
55
|
onTouchStart: onTouchStart,
|
|
59
56
|
onTouchEnd: onTouchEnd,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["React","useEffect","useRef","useState","NativeEventEmitter","NativeModules","StyleSheet","View","useNavigationTracking","useTapTracking","jsx","_jsx","NetmeraAnalyticProvider","children","navigationRef","
|
|
1
|
+
{"version":3,"names":["React","useEffect","useRef","useState","NativeEventEmitter","NativeModules","StyleSheet","View","useNavigationTracking","useTapTracking","jsx","_jsx","NetmeraAnalyticProvider","children","navigationRef","config","setConfig","appliedConfigRef","applyConfig","cfg","prev","current","isScreenFlowEnabled","isInputActionEnabled","shouldCollectValues","console","log","RNNetmera","getAutoTrackConfig","then","catch","_err","emitter","RNNetmeraRCTEventEmitter","subscription","addListener","remove","screenFlowEnabled","inputActionEnabled","onTouchStart","onTouchEnd","style","styles","container","create","flex"],"sourceRoot":"../../src","sources":["NetmeraAnalyticProvider.tsx"],"mappings":";;AAAA;AACA;AACA;;AAEA,OAAOA,KAAK,IAAIC,SAAS,EAAEC,MAAM,EAAEC,QAAQ,QAAQ,OAAO;AAC1D,SACEC,kBAAkB,EAClBC,aAAa,EACbC,UAAU,EACVC,IAAI,QACC,cAAc;AACrB,SAASC,qBAAqB,QAAQ,yCAAsC;AAC5E,SAASC,cAAc,QAAQ,kCAA+B;AAAC,SAAAC,GAAA,IAAAC,IAAA;AAiC/D;AACA;AACA;AACA;AACA,OAAO,SAASC,uBAAuBA,CAAC;EACtCC,QAAQ;EACRC;AAC4B,CAAC,EAAE;EAC/B,MAAM,CAACC,MAAM,EAAEC,SAAS,CAAC,GAAGb,QAAQ,CAAyB,IAAI,CAAC;EAClE,MAAMc,gBAAgB,GAAGf,MAAM,CAAyB,IAAI,CAAC;EAE7D,MAAMgB,WAAW,GAAIC,GAAoB,IAAK;IAC5C,MAAMC,IAAI,GAAGH,gBAAgB,CAACI,OAAO;IACrC,IACED,IAAI,EAAEE,mBAAmB,KAAKH,GAAG,CAACG,mBAAmB,IACrDF,IAAI,EAAEG,oBAAoB,KAAKJ,GAAG,CAACI,oBAAoB,IACvDH,IAAI,EAAEI,mBAAmB,KAAKL,GAAG,CAACK,mBAAmB,EAErD;IACFP,gBAAgB,CAACI,OAAO,GAAGF,GAAG;IAC9BH,SAAS,CAACG,GAAG,CAAC;IACdM,OAAO,CAACC,GAAG,CACT,+BAA+B,EAC/BP,GAAG,CAACG,mBAAmB,GAAG,SAAS,GAAG,UACxC,CAAC;IACDG,OAAO,CAACC,GAAG,CACT,qCAAqC,EACrCP,GAAG,CAACI,oBAAoB,GAAG,SAAS,GAAG,UACzC,CAAC;EACH,CAAC;EAEDtB,SAAS,CAAC,MAAM;IACdI,aAAa,CAACsB,SAAS,EAAEC,kBAAkB,GAAG,CAAC,EAC3CC,IAAI,CAAEV,GAA2B,IAAK;MACtC,IAAIA,GAAG,EAAED,WAAW,CAACC,GAAG,CAAC;IAC3B,CAAC,CAAC,EACAW,KAAK,CAAEC,IAAa,IAAK,CAAC,CAAC,CAAC;EAClC,CAAC,EAAE,EAAE,CAAC;EAEN9B,SAAS,CAAC,MAAM;IACd,MAAM+B,OAAO,GAAG,IAAI5B,kBAAkB,CACpCC,aAAa,CAAC4B,wBAChB,CAAC;IACD,MAAMC,YAAY,GAAGF,OAAO,CAACG,WAAW,CACtC,yBAAyB,EACxBhB,GAAoB,IAAK;MACxB,IAAIA,GAAG,EAAED,WAAW,CAACC,GAAG,CAAC;IAC3B,CACF,CAAC;IACD,OAAO,MAAMe,YAAY,CAACE,MAAM,CAAC,CAAC;EACpC,CAAC,EAAE,EAAE,CAAC;EAEN,MAAMC,iBAAiB,GAAGtB,MAAM,EAAEO,mBAAmB,IAAI,KAAK;EAC9D,MAAMgB,kBAAkB,GAAGvB,MAAM,EAAEQ,oBAAoB,IAAI,KAAK;EAChE,MAAMC,mBAAmB,GAAGT,MAAM,EAAES,mBAAmB,IAAI,KAAK;;EAEhE;EACA;EACAhB,qBAAqB,CACnBM,aAAa,EACbuB,iBAAiB,IAAIC,kBAAkB,EACvCD,iBACF,CAAC;EACD,MAAM;IAAEE,YAAY;IAAEC;EAAW,CAAC,GAAG/B,cAAc,CACjD6B,kBAAkB,EAClBd,mBACF,CAAC;EAED,oBACEb,IAAA,CAACJ,IAAI;IACHkC,KAAK,EAAEC,MAAM,CAACC,SAAU;IACxBJ,YAAY,EAAEA,YAAa;IAC3BC,UAAU,EAAEA,UAAW;IAAA3B,QAAA,EAEtBA;EAAQ,CACL,CAAC;AAEX;AAEA,MAAM6B,MAAM,GAAGpC,UAAU,CAACsC,MAAM,CAAC;EAC/BD,SAAS,EAAE;IAAEE,IAAI,EAAE;EAAE;AACvB,CAAC,CAAC","ignoreList":[]}
|
|
@@ -4,71 +4,34 @@
|
|
|
4
4
|
* Copyright (c) 2026 Netmera Research.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import
|
|
7
|
+
import { useEffect, useRef } from 'react';
|
|
8
8
|
import { setCurrentScreen } from "./NetmeraNavigationState.js";
|
|
9
9
|
import { RNNetmera } from "../utils/RNNetmera.js";
|
|
10
10
|
|
|
11
|
-
//
|
|
12
|
-
const CONTEXT_PROVIDER_TAG = 10;
|
|
13
|
-
const NAV_SEARCH_DEPTH = 25;
|
|
14
|
-
|
|
15
|
-
// Duck-type check: React Navigation v5/v6/v7 all expose this surface on the container ref.
|
|
11
|
+
// Duck-type check: React Navigation v5/v6/v7 all expose this surface.
|
|
16
12
|
function isNavContainerRef(value) {
|
|
17
13
|
return value != null && typeof value.addListener === 'function' && typeof value.getCurrentRoute === 'function' && typeof value.isReady === 'function';
|
|
18
14
|
}
|
|
19
15
|
|
|
20
|
-
// DFS through child fibers to find NavigationContainerRefContext.Provider.
|
|
21
|
-
// Siblings walk at the same depth — they sit at the same level in the tree.
|
|
22
|
-
function findNavContainerRef(fiber, depth = 0) {
|
|
23
|
-
if (!fiber || depth > NAV_SEARCH_DEPTH) return null;
|
|
24
|
-
if (fiber.tag === CONTEXT_PROVIDER_TAG && isNavContainerRef(fiber.memoizedProps?.value)) {
|
|
25
|
-
return fiber.memoizedProps.value;
|
|
26
|
-
}
|
|
27
|
-
return findNavContainerRef(fiber.child, depth + 1) ?? findNavContainerRef(fiber.sibling, depth);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
16
|
/**
|
|
31
17
|
* Subscribes to React Navigation screen changes and keeps NetmeraNavigationState
|
|
32
|
-
* up to date.
|
|
18
|
+
* up to date.
|
|
33
19
|
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
20
|
+
* Requires a valid navigation container ref — pass the same ref to both
|
|
21
|
+
* NetmeraAnalyticProvider and NavigationContainer (or the component created
|
|
22
|
+
* by createStaticNavigation).
|
|
36
23
|
*
|
|
37
|
-
* Silently no-ops
|
|
38
|
-
* Respects the
|
|
24
|
+
* Silently no-ops when navigationRef is absent or not yet populated.
|
|
25
|
+
* Respects the enabled flag — screen changes are ignored when disabled.
|
|
39
26
|
*/
|
|
40
|
-
export function useNavigationTracking(
|
|
41
|
-
// React 18: capture own fiber during render via ReactCurrentOwner.
|
|
42
|
-
// React 19 removed ReactCurrentOwner — this silently yields null, which is fine
|
|
43
|
-
// because the Fabric path (viewRef.__internalInstanceHandle) covers React 19.
|
|
27
|
+
export function useNavigationTracking(navigationRef, enabled, screenLogEnabled) {
|
|
44
28
|
const screenLogEnabledRef = useRef(screenLogEnabled);
|
|
45
29
|
useEffect(() => {
|
|
46
30
|
screenLogEnabledRef.current = screenLogEnabled;
|
|
47
31
|
}, [screenLogEnabled]);
|
|
48
|
-
const selfFiberRef = useRef(null);
|
|
49
|
-
if (selfFiberRef.current === null) {
|
|
50
|
-
try {
|
|
51
|
-
const R = React;
|
|
52
|
-
selfFiberRef.current = R.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED?.ReactCurrentOwner?.current ?? null;
|
|
53
|
-
} catch (_) {}
|
|
54
|
-
}
|
|
55
32
|
useEffect(() => {
|
|
56
|
-
if (!enabled) return;
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
// Path 1 — New Arch: ReactNativeElement exposes its fiber via __internalInstanceHandle.
|
|
60
|
-
// Guard with 'child' in candidate to confirm it's a fiber, not another host object.
|
|
61
|
-
const candidate = viewRef.current?.__internalInstanceHandle;
|
|
62
|
-
const viewFiber = candidate != null && 'child' in candidate ? candidate : selfFiberRef.current?.child ?? null;
|
|
63
|
-
if (viewFiber) {
|
|
64
|
-
navRef = findNavContainerRef(viewFiber);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// Path 2 — Old Arch: use the ref passed explicitly via prop.
|
|
68
|
-
if (!navRef && isNavContainerRef(navigationRef?.current)) {
|
|
69
|
-
navRef = navigationRef.current;
|
|
70
|
-
}
|
|
71
|
-
if (!navRef) return;
|
|
33
|
+
if (!enabled || !isNavContainerRef(navigationRef?.current)) return;
|
|
34
|
+
const navRef = navigationRef.current;
|
|
72
35
|
const handleChange = () => {
|
|
73
36
|
try {
|
|
74
37
|
const route = navRef.getCurrentRoute();
|
|
@@ -82,9 +45,8 @@ export function useNavigationTracking(viewRef, navigationRef, enabled, screenLog
|
|
|
82
45
|
};
|
|
83
46
|
const unsubState = navRef.addListener('state', handleChange);
|
|
84
47
|
|
|
85
|
-
// NavigationContainer's effects run before ours (
|
|
86
|
-
// already
|
|
87
|
-
// listener is a safety net for async startup (deferred auth, deep links, etc.).
|
|
48
|
+
// NavigationContainer's effects (child) run before ours (parent), so the ref
|
|
49
|
+
// is already populated and isReady() reflects the real mount state.
|
|
88
50
|
let unsubReady;
|
|
89
51
|
if (navRef.isReady()) {
|
|
90
52
|
handleChange();
|
|
@@ -99,6 +61,6 @@ export function useNavigationTracking(viewRef, navigationRef, enabled, screenLog
|
|
|
99
61
|
unsubState?.();
|
|
100
62
|
unsubReady?.();
|
|
101
63
|
};
|
|
102
|
-
}, [enabled]);
|
|
64
|
+
}, [enabled, navigationRef]);
|
|
103
65
|
}
|
|
104
66
|
//# sourceMappingURL=useNavigationTracking.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["
|
|
1
|
+
{"version":3,"names":["useEffect","useRef","setCurrentScreen","RNNetmera","isNavContainerRef","value","addListener","getCurrentRoute","isReady","useNavigationTracking","navigationRef","enabled","screenLogEnabled","screenLogEnabledRef","current","navRef","handleChange","route","name","trackView","_","unsubState","unsubReady","undefined"],"sourceRoot":"../../../src","sources":["autotracking/useNavigationTracking.ts"],"mappings":";;AAAA;AACA;AACA;;AAEA,SAASA,SAAS,EAAEC,MAAM,QAAQ,OAAO;AAEzC,SAASC,gBAAgB,QAAQ,6BAA0B;AAC3D,SAASC,SAAS,QAAQ,uBAAoB;;AAE9C;AACA,SAASC,iBAAiBA,CAACC,KAAU,EAAW;EAC9C,OACEA,KAAK,IAAI,IAAI,IACb,OAAOA,KAAK,CAACC,WAAW,KAAK,UAAU,IACvC,OAAOD,KAAK,CAACE,eAAe,KAAK,UAAU,IAC3C,OAAOF,KAAK,CAACG,OAAO,KAAK,UAAU;AAEvC;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,qBAAqBA,CACnCC,aAA+C,EAC/CC,OAAgB,EAChBC,gBAAyB,EACnB;EACN,MAAMC,mBAAmB,GAAGZ,MAAM,CAACW,gBAAgB,CAAC;EAEpDZ,SAAS,CAAC,MAAM;IACda,mBAAmB,CAACC,OAAO,GAAGF,gBAAgB;EAChD,CAAC,EAAE,CAACA,gBAAgB,CAAC,CAAC;EAEtBZ,SAAS,CAAC,MAAM;IACd,IAAI,CAACW,OAAO,IAAI,CAACP,iBAAiB,CAACM,aAAa,EAAEI,OAAO,CAAC,EAAE;IAE5D,MAAMC,MAAM,GAAGL,aAAa,CAAEI,OAAO;IAErC,MAAME,YAAY,GAAGA,CAAA,KAAM;MACzB,IAAI;QACF,MAAMC,KAAK,GAAGF,MAAM,CAACR,eAAe,CAAC,CAAC;QACtC,IAAIU,KAAK,EAAEC,IAAI,EAAE;UACfhB,gBAAgB,CAACe,KAAK,CAACC,IAAI,CAAC;UAC5B,IAAIL,mBAAmB,CAACC,OAAO,EAAE;YAC/BX,SAAS,CAACgB,SAAS,CAACF,KAAK,CAACC,IAAI,CAAC;UACjC;QACF;MACF,CAAC,CAAC,OAAOE,CAAC,EAAE,CAAC;IACf,CAAC;IAED,MAAMC,UAAU,GAAGN,MAAM,CAACT,WAAW,CAAC,OAAO,EAAEU,YAAY,CAAC;;IAE5D;IACA;IACA,IAAIM,UAAoC;IACxC,IAAIP,MAAM,CAACP,OAAO,CAAC,CAAC,EAAE;MACpBQ,YAAY,CAAC,CAAC;IAChB,CAAC,MAAM;MACLM,UAAU,GAAGP,MAAM,CAACT,WAAW,CAAC,OAAO,EAAE,MAAM;QAC7CU,YAAY,CAAC,CAAC;QACdM,UAAU,GAAG,CAAC;QACdA,UAAU,GAAGC,SAAS;MACxB,CAAC,CAAC;IACJ;IAEA,OAAO,MAAM;MACXF,UAAU,GAAG,CAAC;MACdC,UAAU,GAAG,CAAC;IAChB,CAAC;EACH,CAAC,EAAE,CAACX,OAAO,EAAED,aAAa,CAAC,CAAC;AAC9B","ignoreList":[]}
|
|
@@ -14,10 +14,8 @@ const TAP_THRESHOLD = 10; // px — above this distance the gesture is a scroll,
|
|
|
14
14
|
// ── Fiber predicates ──────────────────────────────────────────────────────────
|
|
15
15
|
|
|
16
16
|
// Skip onStartShouldSetResponder — it matches ScrollViews, which are not interactive targets.
|
|
17
|
-
// onChangeText covers TextInput — its touch end event is consumed natively on Android Fabric,
|
|
18
|
-
// so we need to recognise it during onTouchStart (see targetFiber fallback below).
|
|
19
17
|
function isInteractive(props) {
|
|
20
|
-
return !!(props?.onPress || props?.onClick || props?.onValueChange
|
|
18
|
+
return !!(props?.onPress || props?.onClick || props?.onValueChange);
|
|
21
19
|
}
|
|
22
20
|
|
|
23
21
|
// Switch has onValueChange + boolean value, but no onPress/onClick.
|
|
@@ -160,9 +158,8 @@ export function useTapTracking(enabled, shouldCollectValues) {
|
|
|
160
158
|
const onTouchStart = useCallback(e => {
|
|
161
159
|
if (!enabledRef.current) return;
|
|
162
160
|
let switchValue;
|
|
163
|
-
const startFiber = e._targetInst;
|
|
164
161
|
try {
|
|
165
|
-
let fiber =
|
|
162
|
+
let fiber = e._targetInst;
|
|
166
163
|
for (let d = 0; d < MAX_FIBER_DEPTH && fiber; d++, fiber = fiber.return) {
|
|
167
164
|
if (isSwitch(fiber.memoizedProps)) {
|
|
168
165
|
// Capture the committed value before any event fires — reliable first-tap baseline.
|
|
@@ -174,10 +171,7 @@ export function useTapTracking(enabled, shouldCollectValues) {
|
|
|
174
171
|
touchStartRef.current = {
|
|
175
172
|
x: e.nativeEvent.pageX,
|
|
176
173
|
y: e.nativeEvent.pageY,
|
|
177
|
-
switchValue
|
|
178
|
-
// Android Fabric (New Arch) consumes the ACTION_UP event for TextInput natively,
|
|
179
|
-
// so onTouchEnd._targetInst can be null. Fall back to the fiber captured here.
|
|
180
|
-
targetFiber: startFiber
|
|
174
|
+
switchValue
|
|
181
175
|
};
|
|
182
176
|
}, []);
|
|
183
177
|
const onTouchEnd = useCallback(e => {
|
|
@@ -189,7 +183,7 @@ export function useTapTracking(enabled, shouldCollectValues) {
|
|
|
189
183
|
if (dx > TAP_THRESHOLD || dy > TAP_THRESHOLD) return;
|
|
190
184
|
}
|
|
191
185
|
try {
|
|
192
|
-
let node = e._targetInst
|
|
186
|
+
let node = e._targetInst;
|
|
193
187
|
if (!node) return;
|
|
194
188
|
|
|
195
189
|
// Pass 1: walk up to find the first interactive ancestor.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["useCallback","useEffect","useRef","getCurrentScreen","RNNetmera","MAX_FIBER_DEPTH","MAX_TEXT_DEPTH","TAP_THRESHOLD","isInteractive","props","onPress","onClick","onValueChange","
|
|
1
|
+
{"version":3,"names":["useCallback","useEffect","useRef","getCurrentScreen","RNNetmera","MAX_FIBER_DEPTH","MAX_TEXT_DEPTH","TAP_THRESHOLD","isInteractive","props","onPress","onClick","onValueChange","isSwitch","value","isInsideSelectionControl","fiber","node","return","d","memoizedProps","onSelect","textFromChildren","children","depth","undefined","t","trim","length","String","Array","isArray","child","resolveIdentifier","accessibilityLabel","testID","placeholder","resolveListIndex","startFiber","p","index","cellKey","onUnmount","flatIndex","stateNode","sections","up","i","upProps","endsWith","idx","si","count","data","type","sectionIndex","itemIndex","buildPath","screen","listType","identifier","indexSuffix","base","useTapTracking","enabled","shouldCollectValues","enabledRef","shouldCollectValuesRef","touchStartRef","lastScreenRef","switchLastLoggedRef","Map","current","clear","onTouchStart","e","switchValue","_targetInst","_","x","nativeEvent","pageX","y","pageY","onTouchEnd","start","dx","Math","abs","dy","interactiveNode","identifierNode","isSwitchNode","listIndex","lastLogged","get","newValue","preTapValue","set","switchPath","trackAction","tapPath"],"sourceRoot":"../../../src","sources":["autotracking/useTapTracking.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -2,25 +2,30 @@ import React from 'react';
|
|
|
2
2
|
export interface NetmeraAnalyticProviderProps {
|
|
3
3
|
children: React.ReactNode;
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* Pass the navigation container ref so the provider can subscribe to screen
|
|
6
|
+
* changes. Required for screen tracking and for correct action event prefixes.
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
8
|
+
* Use the same ref for both this prop and your NavigationContainer (or the
|
|
9
|
+
* component returned by createStaticNavigation).
|
|
10
10
|
*
|
|
11
|
-
*
|
|
11
|
+
* React Navigation v7 Dynamic API:
|
|
12
|
+
* const navRef = useNavigationContainerRef();
|
|
12
13
|
* <NetmeraAnalyticProvider navigationRef={navRef}>
|
|
13
14
|
* <NavigationContainer ref={navRef}>…</NavigationContainer>
|
|
14
15
|
* </NetmeraAnalyticProvider>
|
|
16
|
+
*
|
|
17
|
+
* React Navigation v7 Static API:
|
|
18
|
+
* const navRef = useNavigationContainerRef();
|
|
19
|
+
* const Navigation = createStaticNavigation(RootStack);
|
|
20
|
+
* <NetmeraAnalyticProvider navigationRef={navRef}>
|
|
21
|
+
* <Navigation ref={navRef} />
|
|
22
|
+
* </NetmeraAnalyticProvider>
|
|
15
23
|
*/
|
|
16
24
|
navigationRef?: React.RefObject<any>;
|
|
17
25
|
}
|
|
18
26
|
/**
|
|
19
27
|
* Wraps your app to enable automatic screen tracking and tap tracking.
|
|
20
|
-
*
|
|
21
|
-
* <NetmeraAnalyticProvider>
|
|
22
|
-
* <NavigationContainer>…</NavigationContainer>
|
|
23
|
-
* </NetmeraAnalyticProvider>
|
|
28
|
+
* Place it outside your NavigationContainer (or Static Navigation component).
|
|
24
29
|
*/
|
|
25
30
|
export declare function NetmeraAnalyticProvider({ children, navigationRef, }: NetmeraAnalyticProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
26
31
|
//# sourceMappingURL=NetmeraAnalyticProvider.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NetmeraAnalyticProvider.d.ts","sourceRoot":"","sources":["../../../src/NetmeraAnalyticProvider.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAU3D,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B
|
|
1
|
+
{"version":3,"file":"NetmeraAnalyticProvider.d.ts","sourceRoot":"","sources":["../../../src/NetmeraAnalyticProvider.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAU3D,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B;;;;;;;;;;;;;;;;;;;OAmBG;IACH,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;CACtC;AAQD;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,EACtC,QAAQ,EACR,aAAa,GACd,EAAE,4BAA4B,2CAsE9B"}
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import type React from 'react';
|
|
2
2
|
/**
|
|
3
3
|
* Subscribes to React Navigation screen changes and keeps NetmeraNavigationState
|
|
4
|
-
* up to date.
|
|
4
|
+
* up to date.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
6
|
+
* Requires a valid navigation container ref — pass the same ref to both
|
|
7
|
+
* NetmeraAnalyticProvider and NavigationContainer (or the component created
|
|
8
|
+
* by createStaticNavigation).
|
|
8
9
|
*
|
|
9
|
-
* Silently no-ops
|
|
10
|
-
* Respects the
|
|
10
|
+
* Silently no-ops when navigationRef is absent or not yet populated.
|
|
11
|
+
* Respects the enabled flag — screen changes are ignored when disabled.
|
|
11
12
|
*/
|
|
12
|
-
export declare function useNavigationTracking(
|
|
13
|
+
export declare function useNavigationTracking(navigationRef: React.RefObject<any> | undefined, enabled: boolean, screenLogEnabled: boolean): void;
|
|
13
14
|
//# sourceMappingURL=useNavigationTracking.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useNavigationTracking.d.ts","sourceRoot":"","sources":["../../../../src/autotracking/useNavigationTracking.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useNavigationTracking.d.ts","sourceRoot":"","sources":["../../../../src/autotracking/useNavigationTracking.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAc/B;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CACnC,aAAa,EAAE,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,SAAS,EAC/C,OAAO,EAAE,OAAO,EAChB,gBAAgB,EAAE,OAAO,GACxB,IAAI,CA4CN"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useTapTracking.d.ts","sourceRoot":"","sources":["../../../../src/autotracking/useTapTracking.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"useTapTracking.d.ts","sourceRoot":"","sources":["../../../../src/autotracking/useTapTracking.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AA6J1D,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,mBAAmB,EAAE,OAAO;sBA6BtC,qBAAqB;oBAoBvB,qBAAqB;EA8FzD"}
|
package/package.json
CHANGED
|
@@ -15,16 +15,24 @@ import { useTapTracking } from './autotracking/useTapTracking';
|
|
|
15
15
|
export interface NetmeraAnalyticProviderProps {
|
|
16
16
|
children: React.ReactNode;
|
|
17
17
|
/**
|
|
18
|
-
*
|
|
19
|
-
*
|
|
18
|
+
* Pass the navigation container ref so the provider can subscribe to screen
|
|
19
|
+
* changes. Required for screen tracking and for correct action event prefixes.
|
|
20
20
|
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
21
|
+
* Use the same ref for both this prop and your NavigationContainer (or the
|
|
22
|
+
* component returned by createStaticNavigation).
|
|
23
23
|
*
|
|
24
|
-
*
|
|
24
|
+
* React Navigation v7 Dynamic API:
|
|
25
|
+
* const navRef = useNavigationContainerRef();
|
|
25
26
|
* <NetmeraAnalyticProvider navigationRef={navRef}>
|
|
26
27
|
* <NavigationContainer ref={navRef}>…</NavigationContainer>
|
|
27
28
|
* </NetmeraAnalyticProvider>
|
|
29
|
+
*
|
|
30
|
+
* React Navigation v7 Static API:
|
|
31
|
+
* const navRef = useNavigationContainerRef();
|
|
32
|
+
* const Navigation = createStaticNavigation(RootStack);
|
|
33
|
+
* <NetmeraAnalyticProvider navigationRef={navRef}>
|
|
34
|
+
* <Navigation ref={navRef} />
|
|
35
|
+
* </NetmeraAnalyticProvider>
|
|
28
36
|
*/
|
|
29
37
|
navigationRef?: React.RefObject<any>;
|
|
30
38
|
}
|
|
@@ -37,16 +45,12 @@ type AutoTrackConfig = {
|
|
|
37
45
|
|
|
38
46
|
/**
|
|
39
47
|
* Wraps your app to enable automatic screen tracking and tap tracking.
|
|
40
|
-
*
|
|
41
|
-
* <NetmeraAnalyticProvider>
|
|
42
|
-
* <NavigationContainer>…</NavigationContainer>
|
|
43
|
-
* </NetmeraAnalyticProvider>
|
|
48
|
+
* Place it outside your NavigationContainer (or Static Navigation component).
|
|
44
49
|
*/
|
|
45
50
|
export function NetmeraAnalyticProvider({
|
|
46
51
|
children,
|
|
47
52
|
navigationRef,
|
|
48
53
|
}: NetmeraAnalyticProviderProps) {
|
|
49
|
-
const viewRef = useRef<any>(null);
|
|
50
54
|
const [config, setConfig] = useState<AutoTrackConfig | null>(null);
|
|
51
55
|
const appliedConfigRef = useRef<AutoTrackConfig | null>(null);
|
|
52
56
|
|
|
@@ -61,11 +65,11 @@ export function NetmeraAnalyticProvider({
|
|
|
61
65
|
appliedConfigRef.current = cfg;
|
|
62
66
|
setConfig(cfg);
|
|
63
67
|
console.log(
|
|
64
|
-
'[NMAutotrack] screen tracking
|
|
68
|
+
'[NMAutotrack] screen tracking',
|
|
65
69
|
cfg.isScreenFlowEnabled ? 'enabled' : 'disabled'
|
|
66
70
|
);
|
|
67
71
|
console.log(
|
|
68
|
-
'[NMAutotrack] input action tracking
|
|
72
|
+
'[NMAutotrack] input action tracking',
|
|
69
73
|
cfg.isInputActionEnabled ? 'enabled' : 'disabled'
|
|
70
74
|
);
|
|
71
75
|
};
|
|
@@ -95,11 +99,11 @@ export function NetmeraAnalyticProvider({
|
|
|
95
99
|
const inputActionEnabled = config?.isInputActionEnabled ?? false;
|
|
96
100
|
const shouldCollectValues = config?.shouldCollectValues ?? false;
|
|
97
101
|
|
|
98
|
-
|
|
102
|
+
// Navigation tracking is needed whenever either flag is on: screen events
|
|
103
|
+
// need it for trackView, action events need it for the screen-name prefix.
|
|
99
104
|
useNavigationTracking(
|
|
100
|
-
viewRef,
|
|
101
105
|
navigationRef,
|
|
102
|
-
|
|
106
|
+
screenFlowEnabled || inputActionEnabled,
|
|
103
107
|
screenFlowEnabled
|
|
104
108
|
);
|
|
105
109
|
const { onTouchStart, onTouchEnd } = useTapTracking(
|
|
@@ -109,7 +113,6 @@ export function NetmeraAnalyticProvider({
|
|
|
109
113
|
|
|
110
114
|
return (
|
|
111
115
|
<View
|
|
112
|
-
ref={navigationEnabled ? viewRef : undefined}
|
|
113
116
|
style={styles.container}
|
|
114
117
|
onTouchStart={onTouchStart}
|
|
115
118
|
onTouchEnd={onTouchEnd}
|
|
@@ -2,15 +2,12 @@
|
|
|
2
2
|
* Copyright (c) 2026 Netmera Research.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import
|
|
5
|
+
import { useEffect, useRef } from 'react';
|
|
6
|
+
import type React from 'react';
|
|
6
7
|
import { setCurrentScreen } from './NetmeraNavigationState';
|
|
7
8
|
import { RNNetmera } from '../utils/RNNetmera';
|
|
8
9
|
|
|
9
|
-
//
|
|
10
|
-
const CONTEXT_PROVIDER_TAG = 10;
|
|
11
|
-
const NAV_SEARCH_DEPTH = 25;
|
|
12
|
-
|
|
13
|
-
// Duck-type check: React Navigation v5/v6/v7 all expose this surface on the container ref.
|
|
10
|
+
// Duck-type check: React Navigation v5/v6/v7 all expose this surface.
|
|
14
11
|
function isNavContainerRef(value: any): boolean {
|
|
15
12
|
return (
|
|
16
13
|
value != null &&
|
|
@@ -20,79 +17,32 @@ function isNavContainerRef(value: any): boolean {
|
|
|
20
17
|
);
|
|
21
18
|
}
|
|
22
19
|
|
|
23
|
-
// DFS through child fibers to find NavigationContainerRefContext.Provider.
|
|
24
|
-
// Siblings walk at the same depth — they sit at the same level in the tree.
|
|
25
|
-
function findNavContainerRef(fiber: any, depth = 0): any {
|
|
26
|
-
if (!fiber || depth > NAV_SEARCH_DEPTH) return null;
|
|
27
|
-
if (
|
|
28
|
-
fiber.tag === CONTEXT_PROVIDER_TAG &&
|
|
29
|
-
isNavContainerRef(fiber.memoizedProps?.value)
|
|
30
|
-
) {
|
|
31
|
-
return fiber.memoizedProps.value;
|
|
32
|
-
}
|
|
33
|
-
return (
|
|
34
|
-
findNavContainerRef(fiber.child, depth + 1) ??
|
|
35
|
-
findNavContainerRef(fiber.sibling, depth)
|
|
36
|
-
);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
20
|
/**
|
|
40
21
|
* Subscribes to React Navigation screen changes and keeps NetmeraNavigationState
|
|
41
|
-
* up to date.
|
|
22
|
+
* up to date.
|
|
42
23
|
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
24
|
+
* Requires a valid navigation container ref — pass the same ref to both
|
|
25
|
+
* NetmeraAnalyticProvider and NavigationContainer (or the component created
|
|
26
|
+
* by createStaticNavigation).
|
|
45
27
|
*
|
|
46
|
-
* Silently no-ops
|
|
47
|
-
* Respects the
|
|
28
|
+
* Silently no-ops when navigationRef is absent or not yet populated.
|
|
29
|
+
* Respects the enabled flag — screen changes are ignored when disabled.
|
|
48
30
|
*/
|
|
49
31
|
export function useNavigationTracking(
|
|
50
|
-
viewRef: React.RefObject<any>,
|
|
51
32
|
navigationRef: React.RefObject<any> | undefined,
|
|
52
33
|
enabled: boolean,
|
|
53
34
|
screenLogEnabled: boolean
|
|
54
35
|
): void {
|
|
55
|
-
// React 18: capture own fiber during render via ReactCurrentOwner.
|
|
56
|
-
// React 19 removed ReactCurrentOwner — this silently yields null, which is fine
|
|
57
|
-
// because the Fabric path (viewRef.__internalInstanceHandle) covers React 19.
|
|
58
36
|
const screenLogEnabledRef = useRef(screenLogEnabled);
|
|
59
37
|
|
|
60
38
|
useEffect(() => {
|
|
61
39
|
screenLogEnabledRef.current = screenLogEnabled;
|
|
62
40
|
}, [screenLogEnabled]);
|
|
63
41
|
|
|
64
|
-
const selfFiberRef = useRef<any>(null);
|
|
65
|
-
if (selfFiberRef.current === null) {
|
|
66
|
-
try {
|
|
67
|
-
const R = React as any;
|
|
68
|
-
selfFiberRef.current =
|
|
69
|
-
R.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED?.ReactCurrentOwner
|
|
70
|
-
?.current ?? null;
|
|
71
|
-
} catch (_) {}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
42
|
useEffect(() => {
|
|
75
|
-
if (!enabled) return;
|
|
76
|
-
let navRef: any = null;
|
|
77
|
-
|
|
78
|
-
// Path 1 — New Arch: ReactNativeElement exposes its fiber via __internalInstanceHandle.
|
|
79
|
-
// Guard with 'child' in candidate to confirm it's a fiber, not another host object.
|
|
80
|
-
const candidate = viewRef.current?.__internalInstanceHandle;
|
|
81
|
-
const viewFiber: any =
|
|
82
|
-
candidate != null && 'child' in candidate
|
|
83
|
-
? candidate
|
|
84
|
-
: (selfFiberRef.current?.child ?? null);
|
|
85
|
-
|
|
86
|
-
if (viewFiber) {
|
|
87
|
-
navRef = findNavContainerRef(viewFiber);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// Path 2 — Old Arch: use the ref passed explicitly via prop.
|
|
91
|
-
if (!navRef && isNavContainerRef(navigationRef?.current)) {
|
|
92
|
-
navRef = navigationRef!.current;
|
|
93
|
-
}
|
|
43
|
+
if (!enabled || !isNavContainerRef(navigationRef?.current)) return;
|
|
94
44
|
|
|
95
|
-
|
|
45
|
+
const navRef = navigationRef!.current;
|
|
96
46
|
|
|
97
47
|
const handleChange = () => {
|
|
98
48
|
try {
|
|
@@ -108,9 +58,8 @@ export function useNavigationTracking(
|
|
|
108
58
|
|
|
109
59
|
const unsubState = navRef.addListener('state', handleChange);
|
|
110
60
|
|
|
111
|
-
// NavigationContainer's effects run before ours (
|
|
112
|
-
// already
|
|
113
|
-
// listener is a safety net for async startup (deferred auth, deep links, etc.).
|
|
61
|
+
// NavigationContainer's effects (child) run before ours (parent), so the ref
|
|
62
|
+
// is already populated and isReady() reflects the real mount state.
|
|
114
63
|
let unsubReady: (() => void) | undefined;
|
|
115
64
|
if (navRef.isReady()) {
|
|
116
65
|
handleChange();
|
|
@@ -126,5 +75,5 @@ export function useNavigationTracking(
|
|
|
126
75
|
unsubState?.();
|
|
127
76
|
unsubReady?.();
|
|
128
77
|
};
|
|
129
|
-
}, [enabled]);
|
|
78
|
+
}, [enabled, navigationRef]);
|
|
130
79
|
}
|
|
@@ -14,15 +14,8 @@ const TAP_THRESHOLD = 10; // px — above this distance the gesture is a scroll,
|
|
|
14
14
|
// ── Fiber predicates ──────────────────────────────────────────────────────────
|
|
15
15
|
|
|
16
16
|
// Skip onStartShouldSetResponder — it matches ScrollViews, which are not interactive targets.
|
|
17
|
-
// onChangeText covers TextInput — its touch end event is consumed natively on Android Fabric,
|
|
18
|
-
// so we need to recognise it during onTouchStart (see targetFiber fallback below).
|
|
19
17
|
function isInteractive(props: any): boolean {
|
|
20
|
-
return !!(
|
|
21
|
-
props?.onPress ||
|
|
22
|
-
props?.onClick ||
|
|
23
|
-
props?.onValueChange ||
|
|
24
|
-
props?.onChangeText
|
|
25
|
-
);
|
|
18
|
+
return !!(props?.onPress || props?.onClick || props?.onValueChange);
|
|
26
19
|
}
|
|
27
20
|
|
|
28
21
|
// Switch has onValueChange + boolean value, but no onPress/onClick.
|
|
@@ -174,7 +167,6 @@ export function useTapTracking(enabled: boolean, shouldCollectValues: boolean) {
|
|
|
174
167
|
x: number;
|
|
175
168
|
y: number;
|
|
176
169
|
switchValue?: boolean;
|
|
177
|
-
targetFiber?: any;
|
|
178
170
|
} | null>(null);
|
|
179
171
|
const lastScreenRef = useRef<string | null | undefined>(undefined);
|
|
180
172
|
|
|
@@ -200,9 +192,8 @@ export function useTapTracking(enabled: boolean, shouldCollectValues: boolean) {
|
|
|
200
192
|
const onTouchStart = useCallback((e: GestureResponderEvent) => {
|
|
201
193
|
if (!enabledRef.current) return;
|
|
202
194
|
let switchValue: boolean | undefined;
|
|
203
|
-
const startFiber: any = (e as any)._targetInst;
|
|
204
195
|
try {
|
|
205
|
-
let fiber: any =
|
|
196
|
+
let fiber: any = (e as any)._targetInst;
|
|
206
197
|
for (let d = 0; d < MAX_FIBER_DEPTH && fiber; d++, fiber = fiber.return) {
|
|
207
198
|
if (isSwitch(fiber.memoizedProps)) {
|
|
208
199
|
// Capture the committed value before any event fires — reliable first-tap baseline.
|
|
@@ -215,9 +206,6 @@ export function useTapTracking(enabled: boolean, shouldCollectValues: boolean) {
|
|
|
215
206
|
x: e.nativeEvent.pageX,
|
|
216
207
|
y: e.nativeEvent.pageY,
|
|
217
208
|
switchValue,
|
|
218
|
-
// Android Fabric (New Arch) consumes the ACTION_UP event for TextInput natively,
|
|
219
|
-
// so onTouchEnd._targetInst can be null. Fall back to the fiber captured here.
|
|
220
|
-
targetFiber: startFiber,
|
|
221
209
|
};
|
|
222
210
|
}, []);
|
|
223
211
|
|
|
@@ -231,8 +219,7 @@ export function useTapTracking(enabled: boolean, shouldCollectValues: boolean) {
|
|
|
231
219
|
}
|
|
232
220
|
|
|
233
221
|
try {
|
|
234
|
-
let node: any =
|
|
235
|
-
(e as any)._targetInst ?? touchStartRef.current?.targetFiber;
|
|
222
|
+
let node: any = (e as any)._targetInst;
|
|
236
223
|
if (!node) return;
|
|
237
224
|
|
|
238
225
|
// Pass 1: walk up to find the first interactive ancestor.
|