@cxpinsight/react-native 0.2.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 (253) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +131 -0
  3. package/babel.js +101 -0
  4. package/instrumented/Pressable.d.ts +2 -0
  5. package/instrumented/Pressable.js +2 -0
  6. package/instrumented/ScrollView.d.ts +2 -0
  7. package/instrumented/ScrollView.js +2 -0
  8. package/instrumented/TextInput.d.ts +2 -0
  9. package/instrumented/TextInput.js +2 -0
  10. package/instrumented/TouchableOpacity.d.ts +2 -0
  11. package/instrumented/TouchableOpacity.js +2 -0
  12. package/lib/CXPinsight.d.ts +113 -0
  13. package/lib/CXPinsight.d.ts.map +1 -0
  14. package/lib/CXPinsight.js +831 -0
  15. package/lib/CXPinsight.js.map +1 -0
  16. package/lib/CXPinsightProvider.d.ts +19 -0
  17. package/lib/CXPinsightProvider.d.ts.map +1 -0
  18. package/lib/CXPinsightProvider.js +382 -0
  19. package/lib/CXPinsightProvider.js.map +1 -0
  20. package/lib/core/autoScreenTracker.d.ts +20 -0
  21. package/lib/core/autoScreenTracker.d.ts.map +1 -0
  22. package/lib/core/autoScreenTracker.js +66 -0
  23. package/lib/core/autoScreenTracker.js.map +1 -0
  24. package/lib/core/deepLinkTracker.d.ts +17 -0
  25. package/lib/core/deepLinkTracker.d.ts.map +1 -0
  26. package/lib/core/deepLinkTracker.js +81 -0
  27. package/lib/core/deepLinkTracker.js.map +1 -0
  28. package/lib/core/deviceInfo.d.ts +14 -0
  29. package/lib/core/deviceInfo.d.ts.map +1 -0
  30. package/lib/core/deviceInfo.js +166 -0
  31. package/lib/core/deviceInfo.js.map +1 -0
  32. package/lib/core/eventQueue.d.ts +23 -0
  33. package/lib/core/eventQueue.d.ts.map +1 -0
  34. package/lib/core/eventQueue.js +240 -0
  35. package/lib/core/eventQueue.js.map +1 -0
  36. package/lib/core/lifecycle.d.ts +18 -0
  37. package/lib/core/lifecycle.d.ts.map +1 -0
  38. package/lib/core/lifecycle.js +127 -0
  39. package/lib/core/lifecycle.js.map +1 -0
  40. package/lib/core/mobileRecorder.d.ts +15 -0
  41. package/lib/core/mobileRecorder.d.ts.map +1 -0
  42. package/lib/core/mobileRecorder.js +231 -0
  43. package/lib/core/mobileRecorder.js.map +1 -0
  44. package/lib/core/network.d.ts +10 -0
  45. package/lib/core/network.d.ts.map +1 -0
  46. package/lib/core/network.js +74 -0
  47. package/lib/core/network.js.map +1 -0
  48. package/lib/core/networkCapture.d.ts +22 -0
  49. package/lib/core/networkCapture.d.ts.map +1 -0
  50. package/lib/core/networkCapture.js +100 -0
  51. package/lib/core/networkCapture.js.map +1 -0
  52. package/lib/core/scrollCapture.d.ts +48 -0
  53. package/lib/core/scrollCapture.d.ts.map +1 -0
  54. package/lib/core/scrollCapture.js +221 -0
  55. package/lib/core/scrollCapture.js.map +1 -0
  56. package/lib/core/session.d.ts +15 -0
  57. package/lib/core/session.d.ts.map +1 -0
  58. package/lib/core/session.js +157 -0
  59. package/lib/core/session.js.map +1 -0
  60. package/lib/core/storage.d.ts +11 -0
  61. package/lib/core/storage.d.ts.map +1 -0
  62. package/lib/core/storage.js +59 -0
  63. package/lib/core/storage.js.map +1 -0
  64. package/lib/core/triggerEngine.d.ts +56 -0
  65. package/lib/core/triggerEngine.d.ts.map +1 -0
  66. package/lib/core/triggerEngine.js +432 -0
  67. package/lib/core/triggerEngine.js.map +1 -0
  68. package/lib/index.d.ts +7 -0
  69. package/lib/index.d.ts.map +1 -0
  70. package/lib/index.js +11 -0
  71. package/lib/index.js.map +1 -0
  72. package/lib/instrumented/Pressable.d.ts +9 -0
  73. package/lib/instrumented/Pressable.d.ts.map +1 -0
  74. package/lib/instrumented/Pressable.js +96 -0
  75. package/lib/instrumented/Pressable.js.map +1 -0
  76. package/lib/instrumented/ScrollView.d.ts +6 -0
  77. package/lib/instrumented/ScrollView.d.ts.map +1 -0
  78. package/lib/instrumented/ScrollView.js +101 -0
  79. package/lib/instrumented/ScrollView.js.map +1 -0
  80. package/lib/instrumented/TextInput.d.ts +9 -0
  81. package/lib/instrumented/TextInput.d.ts.map +1 -0
  82. package/lib/instrumented/TextInput.js +75 -0
  83. package/lib/instrumented/TextInput.js.map +1 -0
  84. package/lib/instrumented/TouchableOpacity.d.ts +11 -0
  85. package/lib/instrumented/TouchableOpacity.d.ts.map +1 -0
  86. package/lib/instrumented/TouchableOpacity.js +96 -0
  87. package/lib/instrumented/TouchableOpacity.js.map +1 -0
  88. package/lib/instrumented/index.d.ts +19 -0
  89. package/lib/instrumented/index.d.ts.map +1 -0
  90. package/lib/instrumented/index.js +28 -0
  91. package/lib/instrumented/index.js.map +1 -0
  92. package/lib/instrumented/interactionObserver.d.ts +29 -0
  93. package/lib/instrumented/interactionObserver.d.ts.map +1 -0
  94. package/lib/instrumented/interactionObserver.js +38 -0
  95. package/lib/instrumented/interactionObserver.js.map +1 -0
  96. package/lib/setup/AccessibilityScanner.d.ts +32 -0
  97. package/lib/setup/AccessibilityScanner.d.ts.map +1 -0
  98. package/lib/setup/AccessibilityScanner.js +127 -0
  99. package/lib/setup/AccessibilityScanner.js.map +1 -0
  100. package/lib/setup/ElementIdentifier.d.ts +65 -0
  101. package/lib/setup/ElementIdentifier.d.ts.map +1 -0
  102. package/lib/setup/ElementIdentifier.js +114 -0
  103. package/lib/setup/ElementIdentifier.js.map +1 -0
  104. package/lib/setup/ElementRegistry.d.ts +22 -0
  105. package/lib/setup/ElementRegistry.d.ts.map +1 -0
  106. package/lib/setup/ElementRegistry.js +47 -0
  107. package/lib/setup/ElementRegistry.js.map +1 -0
  108. package/lib/setup/SetupCodeEntry.d.ts +15 -0
  109. package/lib/setup/SetupCodeEntry.d.ts.map +1 -0
  110. package/lib/setup/SetupCodeEntry.js +198 -0
  111. package/lib/setup/SetupCodeEntry.js.map +1 -0
  112. package/lib/setup/SetupController.d.ts +29 -0
  113. package/lib/setup/SetupController.d.ts.map +1 -0
  114. package/lib/setup/SetupController.js +189 -0
  115. package/lib/setup/SetupController.js.map +1 -0
  116. package/lib/setup/SetupOverlay.d.ts +10 -0
  117. package/lib/setup/SetupOverlay.d.ts.map +1 -0
  118. package/lib/setup/SetupOverlay.js +408 -0
  119. package/lib/setup/SetupOverlay.js.map +1 -0
  120. package/lib/setup/TapInterceptor.d.ts +19 -0
  121. package/lib/setup/TapInterceptor.d.ts.map +1 -0
  122. package/lib/setup/TapInterceptor.js +98 -0
  123. package/lib/setup/TapInterceptor.js.map +1 -0
  124. package/lib/setup/TouchObserver.d.ts +25 -0
  125. package/lib/setup/TouchObserver.d.ts.map +1 -0
  126. package/lib/setup/TouchObserver.js +88 -0
  127. package/lib/setup/TouchObserver.js.map +1 -0
  128. package/lib/setup/TouchPatcher.d.ts +27 -0
  129. package/lib/setup/TouchPatcher.d.ts.map +1 -0
  130. package/lib/setup/TouchPatcher.js +182 -0
  131. package/lib/setup/TouchPatcher.js.map +1 -0
  132. package/lib/setup/index.d.ts +13 -0
  133. package/lib/setup/index.d.ts.map +1 -0
  134. package/lib/setup/index.js +45 -0
  135. package/lib/setup/index.js.map +1 -0
  136. package/lib/setup/useCXPElement.d.ts +25 -0
  137. package/lib/setup/useCXPElement.d.ts.map +1 -0
  138. package/lib/setup/useCXPElement.js +33 -0
  139. package/lib/setup/useCXPElement.js.map +1 -0
  140. package/lib/survey/SurveyModal.d.ts +10 -0
  141. package/lib/survey/SurveyModal.d.ts.map +1 -0
  142. package/lib/survey/SurveyModal.js +1650 -0
  143. package/lib/survey/SurveyModal.js.map +1 -0
  144. package/lib/survey/expressionEval.d.ts +10 -0
  145. package/lib/survey/expressionEval.d.ts.map +1 -0
  146. package/lib/survey/expressionEval.js +287 -0
  147. package/lib/survey/expressionEval.js.map +1 -0
  148. package/lib/survey/frequencyCap.d.ts +15 -0
  149. package/lib/survey/frequencyCap.d.ts.map +1 -0
  150. package/lib/survey/frequencyCap.js +116 -0
  151. package/lib/survey/frequencyCap.js.map +1 -0
  152. package/lib/survey/handsFreeVoice.d.ts +30 -0
  153. package/lib/survey/handsFreeVoice.d.ts.map +1 -0
  154. package/lib/survey/handsFreeVoice.js +312 -0
  155. package/lib/survey/handsFreeVoice.js.map +1 -0
  156. package/lib/survey/interpolate.d.ts +6 -0
  157. package/lib/survey/interpolate.d.ts.map +1 -0
  158. package/lib/survey/interpolate.js +61 -0
  159. package/lib/survey/interpolate.js.map +1 -0
  160. package/lib/survey/pagesFromV1.d.ts +6 -0
  161. package/lib/survey/pagesFromV1.d.ts.map +1 -0
  162. package/lib/survey/pagesFromV1.js +83 -0
  163. package/lib/survey/pagesFromV1.js.map +1 -0
  164. package/lib/survey/questions/CSATQuestion.d.ts +16 -0
  165. package/lib/survey/questions/CSATQuestion.d.ts.map +1 -0
  166. package/lib/survey/questions/CSATQuestion.js +37 -0
  167. package/lib/survey/questions/CSATQuestion.js.map +1 -0
  168. package/lib/survey/questions/DateQuestion.d.ts +20 -0
  169. package/lib/survey/questions/DateQuestion.d.ts.map +1 -0
  170. package/lib/survey/questions/DateQuestion.js +103 -0
  171. package/lib/survey/questions/DateQuestion.js.map +1 -0
  172. package/lib/survey/questions/ImagePickerQuestion.d.ts +33 -0
  173. package/lib/survey/questions/ImagePickerQuestion.d.ts.map +1 -0
  174. package/lib/survey/questions/ImagePickerQuestion.js +68 -0
  175. package/lib/survey/questions/ImagePickerQuestion.js.map +1 -0
  176. package/lib/survey/questions/ImageQuestion.d.ts +26 -0
  177. package/lib/survey/questions/ImageQuestion.d.ts.map +1 -0
  178. package/lib/survey/questions/ImageQuestion.js +24 -0
  179. package/lib/survey/questions/ImageQuestion.js.map +1 -0
  180. package/lib/survey/questions/MatrixCell.d.ts +45 -0
  181. package/lib/survey/questions/MatrixCell.d.ts.map +1 -0
  182. package/lib/survey/questions/MatrixCell.js +54 -0
  183. package/lib/survey/questions/MatrixCell.js.map +1 -0
  184. package/lib/survey/questions/MatrixDropdownQuestion.d.ts +29 -0
  185. package/lib/survey/questions/MatrixDropdownQuestion.d.ts.map +1 -0
  186. package/lib/survey/questions/MatrixDropdownQuestion.js +42 -0
  187. package/lib/survey/questions/MatrixDropdownQuestion.js.map +1 -0
  188. package/lib/survey/questions/MatrixDynamicQuestion.d.ts +26 -0
  189. package/lib/survey/questions/MatrixDynamicQuestion.d.ts.map +1 -0
  190. package/lib/survey/questions/MatrixDynamicQuestion.js +52 -0
  191. package/lib/survey/questions/MatrixDynamicQuestion.js.map +1 -0
  192. package/lib/survey/questions/MatrixQuestion.d.ts +38 -0
  193. package/lib/survey/questions/MatrixQuestion.d.ts.map +1 -0
  194. package/lib/survey/questions/MatrixQuestion.js +64 -0
  195. package/lib/survey/questions/MatrixQuestion.js.map +1 -0
  196. package/lib/survey/questions/MultiTextQuestion.d.ts +19 -0
  197. package/lib/survey/questions/MultiTextQuestion.d.ts.map +1 -0
  198. package/lib/survey/questions/MultiTextQuestion.js +64 -0
  199. package/lib/survey/questions/MultiTextQuestion.js.map +1 -0
  200. package/lib/survey/questions/MultipleChoiceQuestion.d.ts +25 -0
  201. package/lib/survey/questions/MultipleChoiceQuestion.d.ts.map +1 -0
  202. package/lib/survey/questions/MultipleChoiceQuestion.js +111 -0
  203. package/lib/survey/questions/MultipleChoiceQuestion.js.map +1 -0
  204. package/lib/survey/questions/NPSQuestion.d.ts +18 -0
  205. package/lib/survey/questions/NPSQuestion.d.ts.map +1 -0
  206. package/lib/survey/questions/NPSQuestion.js +62 -0
  207. package/lib/survey/questions/NPSQuestion.js.map +1 -0
  208. package/lib/survey/questions/PanelDynamicQuestion.d.ts +50 -0
  209. package/lib/survey/questions/PanelDynamicQuestion.d.ts.map +1 -0
  210. package/lib/survey/questions/PanelDynamicQuestion.js +62 -0
  211. package/lib/survey/questions/PanelDynamicQuestion.js.map +1 -0
  212. package/lib/survey/questions/RankingQuestion.d.ts +34 -0
  213. package/lib/survey/questions/RankingQuestion.d.ts.map +1 -0
  214. package/lib/survey/questions/RankingQuestion.js +85 -0
  215. package/lib/survey/questions/RankingQuestion.js.map +1 -0
  216. package/lib/survey/questions/RatingQuestion.d.ts +20 -0
  217. package/lib/survey/questions/RatingQuestion.d.ts.map +1 -0
  218. package/lib/survey/questions/RatingQuestion.js +53 -0
  219. package/lib/survey/questions/RatingQuestion.js.map +1 -0
  220. package/lib/survey/questions/TextQuestion.d.ts +17 -0
  221. package/lib/survey/questions/TextQuestion.d.ts.map +1 -0
  222. package/lib/survey/questions/TextQuestion.js +46 -0
  223. package/lib/survey/questions/TextQuestion.js.map +1 -0
  224. package/lib/survey/styleContract.d.ts +230 -0
  225. package/lib/survey/styleContract.d.ts.map +1 -0
  226. package/lib/survey/styleContract.js +365 -0
  227. package/lib/survey/styleContract.js.map +1 -0
  228. package/lib/survey/themePalette.d.ts +56 -0
  229. package/lib/survey/themePalette.d.ts.map +1 -0
  230. package/lib/survey/themePalette.js +63 -0
  231. package/lib/survey/themePalette.js.map +1 -0
  232. package/lib/survey/translationLookup.d.ts +4 -0
  233. package/lib/survey/translationLookup.d.ts.map +1 -0
  234. package/lib/survey/translationLookup.js +62 -0
  235. package/lib/survey/translationLookup.js.map +1 -0
  236. package/lib/survey/validate.d.ts +3 -0
  237. package/lib/survey/validate.d.ts.map +1 -0
  238. package/lib/survey/validate.js +159 -0
  239. package/lib/survey/validate.js.map +1 -0
  240. package/lib/survey/variablesResolver.d.ts +10 -0
  241. package/lib/survey/variablesResolver.d.ts.map +1 -0
  242. package/lib/survey/variablesResolver.js +107 -0
  243. package/lib/survey/variablesResolver.js.map +1 -0
  244. package/lib/survey/voiceParsers.d.ts +47 -0
  245. package/lib/survey/voiceParsers.d.ts.map +1 -0
  246. package/lib/survey/voiceParsers.js +310 -0
  247. package/lib/survey/voiceParsers.js.map +1 -0
  248. package/lib/types.d.ts +349 -0
  249. package/lib/types.d.ts.map +1 -0
  250. package/lib/types.js +20 -0
  251. package/lib/types.js.map +1 -0
  252. package/metro.js +55 -0
  253. package/package.json +78 -0
@@ -0,0 +1,48 @@
1
+ /**
2
+ * scrollCapture — global scroll-depth capture from the app's ORGANIC ScrollViews.
3
+ *
4
+ * Why this exists
5
+ * ---------------
6
+ * Scroll depth used to require the app to swap `import { ScrollView } from
7
+ * 'react-native'` for the SDK's `instrumented/ScrollView`. That is app-code
8
+ * restructuring to fit the SDK: a screen using a plain `<ScrollView>` silently
9
+ * reported `percent_scrolled: 0` forever, so a "scrolled to 100%" definition
10
+ * could never fire. The install snippet has to be sufficient on its own.
11
+ *
12
+ * How it works
13
+ * ------------
14
+ * React Native's index exposes ScrollView through a GETTER (index.js:109), and
15
+ * Metro's Babel interop compiles `<ScrollView>` to a property read on the module
16
+ * object at render time — not a value captured at import time. So redefining
17
+ * that getter reaches screens that already imported ScrollView, including ones
18
+ * imported before init() ran.
19
+ *
20
+ * The replacement is an ordinary composed component: it renders the real
21
+ * ScrollView and chains `onScroll`. The app's own handler always runs, and
22
+ * nothing about its behaviour changes.
23
+ *
24
+ * An earlier attempt patched `ScrollView.prototype.render`, which does NOT work:
25
+ * `react-native` exports `ScrollViewWrapper`, a FUNCTION component, so there is
26
+ * no prototype.render to patch and capture silently stayed off. Left as a note
27
+ * so nobody tries the prototype route again.
28
+ *
29
+ * Both axes
30
+ * ---------
31
+ * Horizontal movement (carousels, swipe decks) reports as `swipe`, vertical as
32
+ * `scroll`. Whichever axis actually has scrollable range is measured, so a
33
+ * horizontal carousel isn't reported as a 0% vertical scroll.
34
+ *
35
+ * Safety
36
+ * ------
37
+ * Every step is guarded. If the export shape changes in a future RN version the
38
+ * patch degrades to a no-op and the app is untouched.
39
+ */
40
+ /**
41
+ * Replace react-native's ScrollView export with a capturing wrapper. Idempotent.
42
+ * Called once from CXPinsight.init(). Returns false if the export can't be
43
+ * replaced, in which case capture is simply off.
44
+ */
45
+ export declare function installScrollCapture(): boolean;
46
+ /** Test/diagnostic helper. */
47
+ export declare function isScrollCaptureInstalled(): boolean;
48
+ //# sourceMappingURL=scrollCapture.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scrollCapture.d.ts","sourceRoot":"","sources":["../../src/core/scrollCapture.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAuIH;;;;GAIG;AACH,wBAAgB,oBAAoB,IAAI,OAAO,CAgC9C;AAED,8BAA8B;AAC9B,wBAAgB,wBAAwB,IAAI,OAAO,CAElD"}
@@ -0,0 +1,221 @@
1
+ "use strict";
2
+ /**
3
+ * scrollCapture — global scroll-depth capture from the app's ORGANIC ScrollViews.
4
+ *
5
+ * Why this exists
6
+ * ---------------
7
+ * Scroll depth used to require the app to swap `import { ScrollView } from
8
+ * 'react-native'` for the SDK's `instrumented/ScrollView`. That is app-code
9
+ * restructuring to fit the SDK: a screen using a plain `<ScrollView>` silently
10
+ * reported `percent_scrolled: 0` forever, so a "scrolled to 100%" definition
11
+ * could never fire. The install snippet has to be sufficient on its own.
12
+ *
13
+ * How it works
14
+ * ------------
15
+ * React Native's index exposes ScrollView through a GETTER (index.js:109), and
16
+ * Metro's Babel interop compiles `<ScrollView>` to a property read on the module
17
+ * object at render time — not a value captured at import time. So redefining
18
+ * that getter reaches screens that already imported ScrollView, including ones
19
+ * imported before init() ran.
20
+ *
21
+ * The replacement is an ordinary composed component: it renders the real
22
+ * ScrollView and chains `onScroll`. The app's own handler always runs, and
23
+ * nothing about its behaviour changes.
24
+ *
25
+ * An earlier attempt patched `ScrollView.prototype.render`, which does NOT work:
26
+ * `react-native` exports `ScrollViewWrapper`, a FUNCTION component, so there is
27
+ * no prototype.render to patch and capture silently stayed off. Left as a note
28
+ * so nobody tries the prototype route again.
29
+ *
30
+ * Both axes
31
+ * ---------
32
+ * Horizontal movement (carousels, swipe decks) reports as `swipe`, vertical as
33
+ * `scroll`. Whichever axis actually has scrollable range is measured, so a
34
+ * horizontal carousel isn't reported as a 0% vertical scroll.
35
+ *
36
+ * Safety
37
+ * ------
38
+ * Every step is guarded. If the export shape changes in a future RN version the
39
+ * patch degrades to a no-op and the app is untouched.
40
+ */
41
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
42
+ if (k2 === undefined) k2 = k;
43
+ var desc = Object.getOwnPropertyDescriptor(m, k);
44
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
45
+ desc = { enumerable: true, get: function() { return m[k]; } };
46
+ }
47
+ Object.defineProperty(o, k2, desc);
48
+ }) : (function(o, m, k, k2) {
49
+ if (k2 === undefined) k2 = k;
50
+ o[k2] = m[k];
51
+ }));
52
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
53
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
54
+ }) : function(o, v) {
55
+ o["default"] = v;
56
+ });
57
+ var __importStar = (this && this.__importStar) || (function () {
58
+ var ownKeys = function(o) {
59
+ ownKeys = Object.getOwnPropertyNames || function (o) {
60
+ var ar = [];
61
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
62
+ return ar;
63
+ };
64
+ return ownKeys(o);
65
+ };
66
+ return function (mod) {
67
+ if (mod && mod.__esModule) return mod;
68
+ var result = {};
69
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
70
+ __setModuleDefault(result, mod);
71
+ return result;
72
+ };
73
+ })();
74
+ Object.defineProperty(exports, "__esModule", { value: true });
75
+ exports.installScrollCapture = installScrollCapture;
76
+ exports.isScrollCaptureInstalled = isScrollCaptureInstalled;
77
+ const React = __importStar(require("react"));
78
+ const interactionObserver_1 = require("../instrumented/interactionObserver");
79
+ /** Don't report more than ~2.5×/sec while dragging. Matches the cadence the
80
+ * instrumented component used, so event volume is unchanged. */
81
+ const SCROLL_NOTIFY_MS = 400;
82
+ let installed = false;
83
+ /** Depth along one axis as 0–100, clamped. Mirrors web's scrollPercent. */
84
+ function pctOf(offset, content, layout) {
85
+ return Math.round(Math.min(100, Math.max(0, (offset / Math.max(1, content - layout)) * 100)));
86
+ }
87
+ /**
88
+ * Emit one scroll/swipe interaction.
89
+ * `force` bypasses the throttle — used for scroll-end, so the terminal position
90
+ * (the 100% a scroll-depth rule is usually waiting for) is never throttled away.
91
+ */
92
+ function report(e, props, lastAt, force) {
93
+ const ne = e?.nativeEvent;
94
+ if (!ne)
95
+ return;
96
+ const off = ne.contentOffset || { x: 0, y: 0 };
97
+ const cs = ne.contentSize || { width: 0, height: 0 };
98
+ const lm = ne.layoutMeasurement || { width: 0, height: 0 };
99
+ const xRange = (cs.width ?? 0) - (lm.width ?? 0);
100
+ const yRange = (cs.height ?? 0) - (lm.height ?? 0);
101
+ // Nothing scrollable on either axis — a short list that fits the screen
102
+ // shouldn't emit a misleading 100%.
103
+ if (xRange <= 0 && yRange <= 0)
104
+ return;
105
+ const horizontal = xRange > yRange;
106
+ const pct = horizontal
107
+ ? pctOf(off.x ?? 0, cs.width ?? 0, lm.width ?? 0)
108
+ : pctOf(off.y ?? 0, cs.height ?? 0, lm.height ?? 0);
109
+ const now = Date.now();
110
+ if (!force && now - lastAt.current < SCROLL_NOTIFY_MS)
111
+ return;
112
+ lastAt.current = now;
113
+ (0, interactionObserver_1.notifyInteraction)({
114
+ testID: props.testID,
115
+ accessibilityLabel: props.accessibilityLabel,
116
+ nativeID: props.nativeID,
117
+ elementType: 'scroll_view',
118
+ // CXPinsight.ts parses `percent_scrolled` out of this field.
119
+ text: `${pct}%`,
120
+ interactive: true,
121
+ // Horizontal movement is a swipe/slide, not a scroll — distinct interaction,
122
+ // and the two mean different things in a definition.
123
+ interactionType: horizontal ? 'swipe' : 'scroll',
124
+ });
125
+ }
126
+ /** Build the capturing replacement around whatever component RN exports. */
127
+ function makeCapturingScrollView(Original) {
128
+ const Capturing = React.forwardRef((props, ref) => {
129
+ const lastAt = React.useRef(0);
130
+ const onScroll = React.useCallback((e) => {
131
+ try {
132
+ report(e, props, lastAt, false);
133
+ }
134
+ catch { /* never break scrolling */ }
135
+ props.onScroll?.(e);
136
+ }, [props]);
137
+ const onScrollEndDrag = React.useCallback((e) => {
138
+ try {
139
+ report(e, props, lastAt, true);
140
+ }
141
+ catch { /* ignore */ }
142
+ props.onScrollEndDrag?.(e);
143
+ }, [props]);
144
+ const onMomentumScrollEnd = React.useCallback((e) => {
145
+ try {
146
+ report(e, props, lastAt, true);
147
+ }
148
+ catch { /* ignore */ }
149
+ props.onMomentumScrollEnd?.(e);
150
+ }, [props]);
151
+ return React.createElement(Original, {
152
+ ...props,
153
+ ref,
154
+ // On iOS, RN's default sends onScroll only once per gesture. 16ms gives
155
+ // usable mid-scroll resolution; our own 400ms throttle above keeps event
156
+ // volume the same either way. An app-supplied value always wins.
157
+ scrollEventThrottle: props.scrollEventThrottle ?? 16,
158
+ onScroll,
159
+ onScrollEndDrag,
160
+ onMomentumScrollEnd,
161
+ });
162
+ });
163
+ Capturing.displayName = 'ScrollView';
164
+ // Carry over statics (ScrollView.Context and friends) so code reading them
165
+ // off the export keeps working.
166
+ try {
167
+ for (const k of Object.keys(Original)) {
168
+ if (!(k in Capturing)) {
169
+ Capturing[k] =
170
+ Original[k];
171
+ }
172
+ }
173
+ const ctx = Original.Context;
174
+ if (ctx)
175
+ Capturing.Context = ctx;
176
+ }
177
+ catch { /* statics are best-effort */ }
178
+ return Capturing;
179
+ }
180
+ /**
181
+ * Replace react-native's ScrollView export with a capturing wrapper. Idempotent.
182
+ * Called once from CXPinsight.init(). Returns false if the export can't be
183
+ * replaced, in which case capture is simply off.
184
+ */
185
+ function installScrollCapture() {
186
+ if (installed)
187
+ return true;
188
+ try {
189
+ // Required lazily so importing this module never forces react-native to
190
+ // load in a non-RN context (tests, tooling).
191
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
192
+ const RN = require('react-native');
193
+ if (!RN)
194
+ return false;
195
+ const Original = RN.ScrollView;
196
+ if (typeof Original !== 'function')
197
+ return false;
198
+ const Capturing = makeCapturingScrollView(Original);
199
+ // The index defines ScrollView as a getter, so a plain assignment is
200
+ // ignored — redefine the property instead.
201
+ Object.defineProperty(RN, 'ScrollView', {
202
+ configurable: true,
203
+ enumerable: true,
204
+ get: () => Capturing,
205
+ });
206
+ // Confirm it actually took; a frozen/non-configurable export would leave
207
+ // the original in place and we must not claim success.
208
+ if (RN.ScrollView !== Capturing)
209
+ return false;
210
+ installed = true;
211
+ return true;
212
+ }
213
+ catch {
214
+ return false;
215
+ }
216
+ }
217
+ /** Test/diagnostic helper. */
218
+ function isScrollCaptureInstalled() {
219
+ return installed;
220
+ }
221
+ //# sourceMappingURL=scrollCapture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scrollCapture.js","sourceRoot":"","sources":["../../src/core/scrollCapture.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /** Whether the last initSession() created a NEW session (vs restored one). */
2
+ export declare function wasSessionNew(): boolean;
3
+ /** Register a callback fired when an inactive session rolls over to a fresh one, so the
4
+ * SDK can start a NEW recording (a session should map to one recording, like web). */
5
+ export declare function setRolloverHandler(cb: ((newSessionId: string, prevSessionId: string) => void) | null): void;
6
+ /** Initialize or restore session. Creates new if expired/missing. */
7
+ export declare function initSession(timeout?: number): Promise<string>;
8
+ /** Get current session ID */
9
+ export declare function getSessionId(): string;
10
+ /** Touch session — extend it, or roll over to a fresh session if it's been inactive
11
+ * longer than the timeout. Called on every tracked interaction. */
12
+ export declare function touchSession(): void;
13
+ /** Destroy session and clean up */
14
+ export declare function destroySession(): Promise<void>;
15
+ //# sourceMappingURL=session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/core/session.ts"],"names":[],"mappings":"AAaA,8EAA8E;AAC9E,wBAAgB,aAAa,IAAI,OAAO,CAEvC;AAED;uFACuF;AACvF,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,CAAC,CAAC,YAAY,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,IAAI,GAAG,IAAI,CAE3G;AAiBD,qEAAqE;AACrE,wBAAsB,WAAW,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CA2BnE;AAED,6BAA6B;AAC7B,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAeD;oEACoE;AACpE,wBAAgB,YAAY,IAAI,IAAI,CAcnC;AAED,mCAAmC;AACnC,wBAAsB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CAKpD"}
@@ -0,0 +1,157 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.wasSessionNew = wasSessionNew;
37
+ exports.setRolloverHandler = setRolloverHandler;
38
+ exports.initSession = initSession;
39
+ exports.getSessionId = getSessionId;
40
+ exports.touchSession = touchSession;
41
+ exports.destroySession = destroySession;
42
+ const react_native_1 = require("react-native");
43
+ const types_1 = require("../types");
44
+ const storage = __importStar(require("./storage"));
45
+ const DEFAULT_TIMEOUT = 30 * 60 * 1000; // 30 minutes
46
+ let currentSession = null;
47
+ let sessionTimeout = DEFAULT_TIMEOUT;
48
+ let appStateSubscription = null;
49
+ let lastSessionWasNew = false;
50
+ let onRollover = null;
51
+ /** Whether the last initSession() created a NEW session (vs restored one). */
52
+ function wasSessionNew() {
53
+ return lastSessionWasNew;
54
+ }
55
+ /** Register a callback fired when an inactive session rolls over to a fresh one, so the
56
+ * SDK can start a NEW recording (a session should map to one recording, like web). */
57
+ function setRolloverHandler(cb) {
58
+ onRollover = cb;
59
+ }
60
+ function generateSessionId() {
61
+ const ts = Date.now();
62
+ const rand = Math.random().toString(36).substring(2, 11); // 9 chars
63
+ return `cxp_${ts}_${rand}`;
64
+ }
65
+ /** Start a brand-new session (called when the previous one expired from inactivity). */
66
+ function rollNewSession(now) {
67
+ const prevId = currentSession?.sessionId ?? '';
68
+ currentSession = { sessionId: generateSessionId(), startedAt: now, lastActiveAt: now };
69
+ lastSessionWasNew = true;
70
+ void storage.set(types_1.STORAGE_KEYS.SESSION, currentSession);
71
+ try {
72
+ onRollover?.(currentSession.sessionId, prevId);
73
+ }
74
+ catch { /* best-effort */ }
75
+ }
76
+ /** Initialize or restore session. Creates new if expired/missing. */
77
+ async function initSession(timeout) {
78
+ if (timeout)
79
+ sessionTimeout = timeout;
80
+ const saved = await storage.get(types_1.STORAGE_KEYS.SESSION);
81
+ const now = Date.now();
82
+ if (saved && now - saved.lastActiveAt < sessionTimeout) {
83
+ currentSession = { ...saved, lastActiveAt: now };
84
+ await storage.set(types_1.STORAGE_KEYS.SESSION, currentSession);
85
+ lastSessionWasNew = false;
86
+ }
87
+ else {
88
+ currentSession = {
89
+ sessionId: generateSessionId(),
90
+ startedAt: now,
91
+ lastActiveAt: now,
92
+ };
93
+ await storage.set(types_1.STORAGE_KEYS.SESSION, currentSession);
94
+ lastSessionWasNew = true;
95
+ }
96
+ lastPersistedAt = now;
97
+ // Listen to AppState to detect background/foreground transitions
98
+ appStateSubscription?.remove();
99
+ appStateSubscription = react_native_1.AppState.addEventListener('change', handleAppStateChange);
100
+ return currentSession.sessionId;
101
+ }
102
+ /** Get current session ID */
103
+ function getSessionId() {
104
+ return currentSession?.sessionId ?? '';
105
+ }
106
+ // Persisting the session record on every tracked interaction meant an
107
+ // AsyncStorage write per tap, per scroll sample, per screen — bridge traffic and
108
+ // disk I/O proportional to how actively the user is using the app, to store a
109
+ // timestamp whose only job is deciding whether ~30 minutes have passed. The web
110
+ // SDK throttles the same bookkeeping to once per five seconds; match it.
111
+ //
112
+ // The in-memory lastActiveAt still updates on every call, so rollover timing is
113
+ // unchanged. Only the write is throttled, and a stale-by-<5s timestamp cannot
114
+ // change a 30-minute verdict. handleAppStateChange persists unthrottled when the
115
+ // app leaves the foreground, which is when the value actually has to survive.
116
+ const PERSIST_THROTTLE_MS = 5000;
117
+ let lastPersistedAt = 0;
118
+ /** Touch session — extend it, or roll over to a fresh session if it's been inactive
119
+ * longer than the timeout. Called on every tracked interaction. */
120
+ function touchSession() {
121
+ if (!currentSession)
122
+ return;
123
+ const now = Date.now();
124
+ if (now - currentSession.lastActiveAt >= sessionTimeout) {
125
+ // Inactivity gap exceeded the timeout → this activity belongs to a NEW session.
126
+ rollNewSession(now);
127
+ lastPersistedAt = now;
128
+ return;
129
+ }
130
+ currentSession.lastActiveAt = now;
131
+ if (now - lastPersistedAt >= PERSIST_THROTTLE_MS) {
132
+ lastPersistedAt = now;
133
+ void storage.set(types_1.STORAGE_KEYS.SESSION, currentSession);
134
+ }
135
+ }
136
+ /** Destroy session and clean up */
137
+ async function destroySession() {
138
+ currentSession = null;
139
+ appStateSubscription?.remove();
140
+ appStateSubscription = null;
141
+ await storage.remove(types_1.STORAGE_KEYS.SESSION);
142
+ }
143
+ function handleAppStateChange(state) {
144
+ if (state === 'active' && currentSession) {
145
+ const now = Date.now();
146
+ if (now - currentSession.lastActiveAt >= sessionTimeout) {
147
+ // Returned to foreground after the timeout — start a fresh session + recording.
148
+ rollNewSession(now);
149
+ }
150
+ else {
151
+ currentSession.lastActiveAt = now;
152
+ lastPersistedAt = now;
153
+ void storage.set(types_1.STORAGE_KEYS.SESSION, currentSession);
154
+ }
155
+ }
156
+ }
157
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/core/session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /** Typed get from AsyncStorage */
2
+ export declare function get<T>(key: string): Promise<T | null>;
3
+ /** Typed set to AsyncStorage */
4
+ export declare function set(key: string, value: unknown): Promise<void>;
5
+ /** Remove a single key */
6
+ export declare function remove(key: string): Promise<void>;
7
+ /** Remove multiple keys */
8
+ export declare function multiRemove(keys: string[]): Promise<void>;
9
+ /** Get all keys matching a prefix */
10
+ export declare function getKeysWithPrefix(prefix: string): Promise<string[]>;
11
+ //# sourceMappingURL=storage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/core/storage.ts"],"names":[],"mappings":"AAEA,kCAAkC;AAClC,wBAAsB,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAO3D;AAED,gCAAgC;AAChC,wBAAsB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAMpE;AAED,0BAA0B;AAC1B,wBAAsB,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAMvD;AAED,2BAA2B;AAC3B,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAM/D;AAED,qCAAqC;AACrC,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAOzE"}
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.get = get;
7
+ exports.set = set;
8
+ exports.remove = remove;
9
+ exports.multiRemove = multiRemove;
10
+ exports.getKeysWithPrefix = getKeysWithPrefix;
11
+ const async_storage_1 = __importDefault(require("@react-native-async-storage/async-storage"));
12
+ /** Typed get from AsyncStorage */
13
+ async function get(key) {
14
+ try {
15
+ const value = await async_storage_1.default.getItem(key);
16
+ return value ? JSON.parse(value) : null;
17
+ }
18
+ catch {
19
+ return null;
20
+ }
21
+ }
22
+ /** Typed set to AsyncStorage */
23
+ async function set(key, value) {
24
+ try {
25
+ await async_storage_1.default.setItem(key, JSON.stringify(value));
26
+ }
27
+ catch {
28
+ // Silently fail — storage is best-effort
29
+ }
30
+ }
31
+ /** Remove a single key */
32
+ async function remove(key) {
33
+ try {
34
+ await async_storage_1.default.removeItem(key);
35
+ }
36
+ catch {
37
+ // Silently fail
38
+ }
39
+ }
40
+ /** Remove multiple keys */
41
+ async function multiRemove(keys) {
42
+ try {
43
+ await async_storage_1.default.multiRemove(keys);
44
+ }
45
+ catch {
46
+ // Silently fail
47
+ }
48
+ }
49
+ /** Get all keys matching a prefix */
50
+ async function getKeysWithPrefix(prefix) {
51
+ try {
52
+ const allKeys = await async_storage_1.default.getAllKeys();
53
+ return allKeys.filter((k) => k.startsWith(prefix));
54
+ }
55
+ catch {
56
+ return [];
57
+ }
58
+ }
59
+ //# sourceMappingURL=storage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.js","sourceRoot":"","sources":["../../src/core/storage.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,8FAAqE;AAErE,kCAAkC;AAC3B,KAAK,cAAiB,GAAW;IACtC,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,uBAAY,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC9C,OAAO,KAAK,CAAC,CAAC,CAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAO,CAAC,CAAC,CAAC,IAAI,CAAC;IACjD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,gCAAgC;AACzB,KAAK,cAAc,GAAW,EAAE,KAAc;IACnD,IAAI,CAAC;QACH,MAAM,uBAAY,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;IACzD,CAAC;IAAC,MAAM,CAAC;QACP,yCAAyC;IAC3C,CAAC;AACH,CAAC;AAED,0BAA0B;AACnB,KAAK,iBAAiB,GAAW;IACtC,IAAI,CAAC;QACH,MAAM,uBAAY,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;IACrC,CAAC;IAAC,MAAM,CAAC;QACP,gBAAgB;IAClB,CAAC;AACH,CAAC;AAED,2BAA2B;AACpB,KAAK,sBAAsB,IAAc;IAC9C,IAAI,CAAC;QACH,MAAM,uBAAY,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IACvC,CAAC;IAAC,MAAM,CAAC;QACP,gBAAgB;IAClB,CAAC;AACH,CAAC;AAED,qCAAqC;AAC9B,KAAK,4BAA4B,MAAc;IACpD,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,uBAAY,CAAC,UAAU,EAAE,CAAC;QAChD,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;IACrD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC"}
@@ -0,0 +1,56 @@
1
+ /** Remote trigger config fetched from server */
2
+ export interface TriggerConfig {
3
+ configId: string;
4
+ triggerType: 'screen_view' | 'event_match' | 'app_lifecycle';
5
+ screenName?: string;
6
+ eventName?: string;
7
+ lifecycleEvent?: string;
8
+ conditions?: {
9
+ delaySeconds?: number;
10
+ minAppOpens?: number;
11
+ minSessionDuration?: number;
12
+ platforms?: string[];
13
+ };
14
+ matchConditions?: Array<{
15
+ attr: string;
16
+ op?: string;
17
+ value: unknown;
18
+ }>;
19
+ matchLogic?: 'any' | 'all';
20
+ sequence?: {
21
+ definitionId: string;
22
+ mode: 'or' | 'and-any-order' | 'and-ordered';
23
+ windowSeconds: number;
24
+ sequenceTotal: number;
25
+ sequenceIndex: number;
26
+ };
27
+ actionType: 'show_survey';
28
+ linkedSurveyId: string;
29
+ displayPreferences?: {
30
+ frequency?: 'once' | 'daily' | 'weekly' | 'monthly' | 'always';
31
+ maxImpressions?: number;
32
+ cooldownDays?: number;
33
+ userSamplingPercent?: number;
34
+ };
35
+ }
36
+ /** Fetch trigger configs from server and cache locally. */
37
+ export declare function loadTriggerConfigs(applicationId: string, debug?: boolean): Promise<void>;
38
+ /** Register the function used to present surveys */
39
+ export declare function registerSurveyTrigger(fn: (surveyId: string, options?: {
40
+ skipFrequencyCap?: boolean;
41
+ }) => void): void;
42
+ /** Unregister */
43
+ export declare function unregisterSurveyTrigger(): void;
44
+ /** Called when a screen is viewed — checks for matching screen_view triggers */
45
+ export declare function onScreenView(screenName: string): Promise<void>;
46
+ /** Called when a custom event is tracked — checks for matching event_match triggers.
47
+ * `context` is the ATTRIBUTE CONTEXT (bare event keys plus the namespaced bag
48
+ * event/device/user/session) built by track(). A trigger's `matchConditions` fire
49
+ * the survey ONLY if the context satisfies them — now over any attribute, e.g.
50
+ * "scroll to 100 on Profile" AND "user.plan == pro". The geo and location
51
+ * namespaces are server-tier (P3) and skipped here so a geo rule isn't silently
52
+ * hidden before the server enforces it. */
53
+ export declare function onEventTracked(eventName: string, context?: Record<string, unknown>): Promise<void>;
54
+ /** Clear all trigger state (called on SDK reset) */
55
+ export declare function clearTriggerState(): Promise<void>;
56
+ //# sourceMappingURL=triggerEngine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"triggerEngine.d.ts","sourceRoot":"","sources":["../../src/core/triggerEngine.ts"],"names":[],"mappings":"AAGA,gDAAgD;AAChD,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,aAAa,GAAG,aAAa,GAAG,eAAe,CAAC;IAC7D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE;QACX,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,kBAAkB,CAAC,EAAE,MAAM,CAAC;QAC5B,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;KACtB,CAAC;IAGF,eAAe,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAIvE,UAAU,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC;IAM3B,QAAQ,CAAC,EAAE;QACT,YAAY,EAAE,MAAM,CAAC;QACrB,IAAI,EAAE,IAAI,GAAG,eAAe,GAAG,aAAa,CAAC;QAC7C,aAAa,EAAE,MAAM,CAAC;QACtB,aAAa,EAAE,MAAM,CAAC;QACtB,aAAa,EAAE,MAAM,CAAC;KACvB,CAAC;IACF,UAAU,EAAE,aAAa,CAAC;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,kBAAkB,CAAC,EAAE;QACnB,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAC;QAC/D,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,mBAAmB,CAAC,EAAE,MAAM,CAAC;KAC9B,CAAC;CACH;AA4BD,2DAA2D;AAC3D,wBAAsB,kBAAkB,CACtC,aAAa,EAAE,MAAM,EACrB,KAAK,CAAC,EAAE,OAAO,GACd,OAAO,CAAC,IAAI,CAAC,CAkEf;AAED,oDAAoD;AACpD,wBAAgB,qBAAqB,CAAC,EAAE,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;IAAE,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAAE,KAAK,IAAI,GAAG,IAAI,CAEpH;AAED,iBAAiB;AACjB,wBAAgB,uBAAuB,IAAI,IAAI,CAE9C;AAED,gFAAgF;AAChF,wBAAsB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAepE;AAkCD;;;;;;4CAM4C;AAC5C,wBAAsB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CA8BxG;AAwND,oDAAoD;AACpD,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CAMvD"}