@userflow-tech/react-native 0.3.0 → 0.4.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/README.md +360 -70
  2. package/docs/anchoring.md +58 -42
  3. package/docs/troubleshooting.md +69 -27
  4. package/expo-plugin/hostDependencyWarnings.d.ts +21 -0
  5. package/expo-plugin/hostDependencyWarnings.d.ts.map +1 -0
  6. package/expo-plugin/hostDependencyWarnings.js +101 -0
  7. package/expo-plugin/hostDependencyWarnings.js.map +1 -0
  8. package/expo-plugin/withUserflow.d.ts.map +1 -1
  9. package/expo-plugin/withUserflow.js +16 -0
  10. package/expo-plugin/withUserflow.js.map +1 -1
  11. package/lib/commonjs/anchors/AnchorRegistry.js +7 -0
  12. package/lib/commonjs/anchors/AnchorRegistry.js.map +1 -1
  13. package/lib/commonjs/anchors/elementConditionEvaluator.js +189 -55
  14. package/lib/commonjs/anchors/elementConditionEvaluator.js.map +1 -1
  15. package/lib/commonjs/anchors/elementTapMonitor.js +92 -0
  16. package/lib/commonjs/anchors/elementTapMonitor.js.map +1 -0
  17. package/lib/commonjs/anchors/elementTargetMatch.js +85 -0
  18. package/lib/commonjs/anchors/elementTargetMatch.js.map +1 -0
  19. package/lib/commonjs/anchors/fiber/findAnchorFiber.js +64 -39
  20. package/lib/commonjs/anchors/fiber/findAnchorFiber.js.map +1 -1
  21. package/lib/commonjs/anchors/fiber/touchTargetFiber.js +105 -0
  22. package/lib/commonjs/anchors/fiber/touchTargetFiber.js.map +1 -0
  23. package/lib/commonjs/anchors/resolveAnchorHost.js +2 -1
  24. package/lib/commonjs/anchors/resolveAnchorHost.js.map +1 -1
  25. package/lib/commonjs/anchors/resolveAutoAnchorHost.js +4 -2
  26. package/lib/commonjs/anchors/resolveAutoAnchorHost.js.map +1 -1
  27. package/lib/commonjs/anchors/resolveElementTargets.js +158 -0
  28. package/lib/commonjs/anchors/resolveElementTargets.js.map +1 -0
  29. package/lib/commonjs/anchors/targetPressMonitor.js +9 -3
  30. package/lib/commonjs/anchors/targetPressMonitor.js.map +1 -1
  31. package/lib/commonjs/anchors/useUserflowAnchor.js +1 -0
  32. package/lib/commonjs/anchors/useUserflowAnchor.js.map +1 -1
  33. package/lib/commonjs/anonymousId.js +16 -7
  34. package/lib/commonjs/anonymousId.js.map +1 -1
  35. package/lib/commonjs/authoring/capturePickerScreenshot.js +9 -1
  36. package/lib/commonjs/authoring/capturePickerScreenshot.js.map +1 -1
  37. package/lib/commonjs/evalJs/getWebView.js +5 -13
  38. package/lib/commonjs/evalJs/getWebView.js.map +1 -1
  39. package/lib/commonjs/hostAppVersion.js +6 -1
  40. package/lib/commonjs/hostAppVersion.js.map +1 -1
  41. package/lib/commonjs/index.js +5 -0
  42. package/lib/commonjs/index.js.map +1 -1
  43. package/lib/commonjs/installCheck.js +183 -0
  44. package/lib/commonjs/installCheck.js.map +1 -0
  45. package/lib/commonjs/nativeModules.js +44 -0
  46. package/lib/commonjs/nativeModules.js.map +1 -0
  47. package/lib/commonjs/network.js +20 -7
  48. package/lib/commonjs/network.js.map +1 -1
  49. package/lib/commonjs/pairing/deviceId.js +14 -11
  50. package/lib/commonjs/pairing/deviceId.js.map +1 -1
  51. package/lib/commonjs/pairing/tokenStorage.js +17 -4
  52. package/lib/commonjs/pairing/tokenStorage.js.map +1 -1
  53. package/lib/commonjs/runtime/TargetPressBridge.js +12 -1
  54. package/lib/commonjs/runtime/TargetPressBridge.js.map +1 -1
  55. package/lib/commonjs/runtime/UserflowProvider.js +6 -3
  56. package/lib/commonjs/runtime/UserflowProvider.js.map +1 -1
  57. package/lib/commonjs/storage/asyncStorage.js +67 -0
  58. package/lib/commonjs/storage/asyncStorage.js.map +1 -0
  59. package/lib/commonjs/surfaces/BannerSurface.js +3 -1
  60. package/lib/commonjs/surfaces/BannerSurface.js.map +1 -1
  61. package/lib/commonjs/surfaces/safeArea.js +74 -28
  62. package/lib/commonjs/surfaces/safeArea.js.map +1 -1
  63. package/lib/commonjs/version.js +1 -1
  64. package/lib/module/anchors/AnchorRegistry.js +7 -0
  65. package/lib/module/anchors/AnchorRegistry.js.map +1 -1
  66. package/lib/module/anchors/elementConditionEvaluator.js +189 -55
  67. package/lib/module/anchors/elementConditionEvaluator.js.map +1 -1
  68. package/lib/module/anchors/elementTapMonitor.js +87 -0
  69. package/lib/module/anchors/elementTapMonitor.js.map +1 -0
  70. package/lib/module/anchors/elementTargetMatch.js +78 -0
  71. package/lib/module/anchors/elementTargetMatch.js.map +1 -0
  72. package/lib/module/anchors/fiber/findAnchorFiber.js +62 -39
  73. package/lib/module/anchors/fiber/findAnchorFiber.js.map +1 -1
  74. package/lib/module/anchors/fiber/touchTargetFiber.js +100 -0
  75. package/lib/module/anchors/fiber/touchTargetFiber.js.map +1 -0
  76. package/lib/module/anchors/resolveAnchorHost.js +2 -1
  77. package/lib/module/anchors/resolveAnchorHost.js.map +1 -1
  78. package/lib/module/anchors/resolveAutoAnchorHost.js +3 -3
  79. package/lib/module/anchors/resolveAutoAnchorHost.js.map +1 -1
  80. package/lib/module/anchors/resolveElementTargets.js +152 -0
  81. package/lib/module/anchors/resolveElementTargets.js.map +1 -0
  82. package/lib/module/anchors/targetPressMonitor.js +8 -3
  83. package/lib/module/anchors/targetPressMonitor.js.map +1 -1
  84. package/lib/module/anchors/useUserflowAnchor.js +1 -0
  85. package/lib/module/anchors/useUserflowAnchor.js.map +1 -1
  86. package/lib/module/anonymousId.js +15 -5
  87. package/lib/module/anonymousId.js.map +1 -1
  88. package/lib/module/authoring/capturePickerScreenshot.js +9 -1
  89. package/lib/module/authoring/capturePickerScreenshot.js.map +1 -1
  90. package/lib/module/evalJs/getWebView.js +5 -13
  91. package/lib/module/evalJs/getWebView.js.map +1 -1
  92. package/lib/module/hostAppVersion.js +6 -1
  93. package/lib/module/hostAppVersion.js.map +1 -1
  94. package/lib/module/index.js +5 -0
  95. package/lib/module/index.js.map +1 -1
  96. package/lib/module/installCheck.js +169 -0
  97. package/lib/module/installCheck.js.map +1 -0
  98. package/lib/module/nativeModules.js +40 -0
  99. package/lib/module/nativeModules.js.map +1 -0
  100. package/lib/module/network.js +20 -7
  101. package/lib/module/network.js.map +1 -1
  102. package/lib/module/pairing/deviceId.js +14 -10
  103. package/lib/module/pairing/deviceId.js.map +1 -1
  104. package/lib/module/pairing/tokenStorage.js +17 -4
  105. package/lib/module/pairing/tokenStorage.js.map +1 -1
  106. package/lib/module/runtime/TargetPressBridge.js +12 -1
  107. package/lib/module/runtime/TargetPressBridge.js.map +1 -1
  108. package/lib/module/runtime/UserflowProvider.js +7 -4
  109. package/lib/module/runtime/UserflowProvider.js.map +1 -1
  110. package/lib/module/storage/asyncStorage.js +61 -0
  111. package/lib/module/storage/asyncStorage.js.map +1 -0
  112. package/lib/module/surfaces/BannerSurface.js +3 -1
  113. package/lib/module/surfaces/BannerSurface.js.map +1 -1
  114. package/lib/module/surfaces/safeArea.js +70 -28
  115. package/lib/module/surfaces/safeArea.js.map +1 -1
  116. package/lib/module/version.js +1 -1
  117. package/lib/typescript/commonjs/src/anchors/AnchorRegistry.d.ts +7 -0
  118. package/lib/typescript/commonjs/src/anchors/AnchorRegistry.d.ts.map +1 -1
  119. package/lib/typescript/commonjs/src/anchors/elementConditionEvaluator.d.ts +12 -16
  120. package/lib/typescript/commonjs/src/anchors/elementConditionEvaluator.d.ts.map +1 -1
  121. package/lib/typescript/commonjs/src/anchors/elementTapMonitor.d.ts +36 -0
  122. package/lib/typescript/commonjs/src/anchors/elementTapMonitor.d.ts.map +1 -0
  123. package/lib/typescript/commonjs/src/anchors/elementTargetMatch.d.ts +20 -0
  124. package/lib/typescript/commonjs/src/anchors/elementTargetMatch.d.ts.map +1 -0
  125. package/lib/typescript/commonjs/src/anchors/fiber/findAnchorFiber.d.ts +17 -5
  126. package/lib/typescript/commonjs/src/anchors/fiber/findAnchorFiber.d.ts.map +1 -1
  127. package/lib/typescript/commonjs/src/anchors/fiber/touchTargetFiber.d.ts +24 -0
  128. package/lib/typescript/commonjs/src/anchors/fiber/touchTargetFiber.d.ts.map +1 -0
  129. package/lib/typescript/commonjs/src/anchors/resolveAnchorHost.d.ts +2 -1
  130. package/lib/typescript/commonjs/src/anchors/resolveAnchorHost.d.ts.map +1 -1
  131. package/lib/typescript/commonjs/src/anchors/resolveAutoAnchorHost.d.ts +10 -1
  132. package/lib/typescript/commonjs/src/anchors/resolveAutoAnchorHost.d.ts.map +1 -1
  133. package/lib/typescript/commonjs/src/anchors/resolveElementTargets.d.ts +39 -0
  134. package/lib/typescript/commonjs/src/anchors/resolveElementTargets.d.ts.map +1 -0
  135. package/lib/typescript/commonjs/src/anchors/targetPressMonitor.d.ts +2 -0
  136. package/lib/typescript/commonjs/src/anchors/targetPressMonitor.d.ts.map +1 -1
  137. package/lib/typescript/commonjs/src/anchors/useUserflowAnchor.d.ts.map +1 -1
  138. package/lib/typescript/commonjs/src/anonymousId.d.ts +2 -0
  139. package/lib/typescript/commonjs/src/anonymousId.d.ts.map +1 -1
  140. package/lib/typescript/commonjs/src/authoring/capturePickerScreenshot.d.ts.map +1 -1
  141. package/lib/typescript/commonjs/src/evalJs/getWebView.d.ts +2 -1
  142. package/lib/typescript/commonjs/src/evalJs/getWebView.d.ts.map +1 -1
  143. package/lib/typescript/commonjs/src/hostAppVersion.d.ts +1 -1
  144. package/lib/typescript/commonjs/src/hostAppVersion.d.ts.map +1 -1
  145. package/lib/typescript/commonjs/src/index.d.ts.map +1 -1
  146. package/lib/typescript/commonjs/src/installCheck.d.ts +48 -0
  147. package/lib/typescript/commonjs/src/installCheck.d.ts.map +1 -0
  148. package/lib/typescript/commonjs/src/nativeModules.d.ts +13 -0
  149. package/lib/typescript/commonjs/src/nativeModules.d.ts.map +1 -0
  150. package/lib/typescript/commonjs/src/network.d.ts.map +1 -1
  151. package/lib/typescript/commonjs/src/pairing/deviceId.d.ts.map +1 -1
  152. package/lib/typescript/commonjs/src/pairing/tokenStorage.d.ts.map +1 -1
  153. package/lib/typescript/commonjs/src/runtime/TargetPressBridge.d.ts +2 -1
  154. package/lib/typescript/commonjs/src/runtime/TargetPressBridge.d.ts.map +1 -1
  155. package/lib/typescript/commonjs/src/runtime/UserflowProvider.d.ts.map +1 -1
  156. package/lib/typescript/commonjs/src/storage/asyncStorage.d.ts +15 -0
  157. package/lib/typescript/commonjs/src/storage/asyncStorage.d.ts.map +1 -0
  158. package/lib/typescript/commonjs/src/surfaces/BannerSurface.d.ts.map +1 -1
  159. package/lib/typescript/commonjs/src/surfaces/safeArea.d.ts +6 -2
  160. package/lib/typescript/commonjs/src/surfaces/safeArea.d.ts.map +1 -1
  161. package/lib/typescript/commonjs/src/version.d.ts +1 -1
  162. package/lib/typescript/module/src/anchors/AnchorRegistry.d.ts +7 -0
  163. package/lib/typescript/module/src/anchors/AnchorRegistry.d.ts.map +1 -1
  164. package/lib/typescript/module/src/anchors/elementConditionEvaluator.d.ts +12 -16
  165. package/lib/typescript/module/src/anchors/elementConditionEvaluator.d.ts.map +1 -1
  166. package/lib/typescript/module/src/anchors/elementTapMonitor.d.ts +36 -0
  167. package/lib/typescript/module/src/anchors/elementTapMonitor.d.ts.map +1 -0
  168. package/lib/typescript/module/src/anchors/elementTargetMatch.d.ts +20 -0
  169. package/lib/typescript/module/src/anchors/elementTargetMatch.d.ts.map +1 -0
  170. package/lib/typescript/module/src/anchors/fiber/findAnchorFiber.d.ts +17 -5
  171. package/lib/typescript/module/src/anchors/fiber/findAnchorFiber.d.ts.map +1 -1
  172. package/lib/typescript/module/src/anchors/fiber/touchTargetFiber.d.ts +24 -0
  173. package/lib/typescript/module/src/anchors/fiber/touchTargetFiber.d.ts.map +1 -0
  174. package/lib/typescript/module/src/anchors/resolveAnchorHost.d.ts +2 -1
  175. package/lib/typescript/module/src/anchors/resolveAnchorHost.d.ts.map +1 -1
  176. package/lib/typescript/module/src/anchors/resolveAutoAnchorHost.d.ts +10 -1
  177. package/lib/typescript/module/src/anchors/resolveAutoAnchorHost.d.ts.map +1 -1
  178. package/lib/typescript/module/src/anchors/resolveElementTargets.d.ts +39 -0
  179. package/lib/typescript/module/src/anchors/resolveElementTargets.d.ts.map +1 -0
  180. package/lib/typescript/module/src/anchors/targetPressMonitor.d.ts +2 -0
  181. package/lib/typescript/module/src/anchors/targetPressMonitor.d.ts.map +1 -1
  182. package/lib/typescript/module/src/anchors/useUserflowAnchor.d.ts.map +1 -1
  183. package/lib/typescript/module/src/anonymousId.d.ts +2 -0
  184. package/lib/typescript/module/src/anonymousId.d.ts.map +1 -1
  185. package/lib/typescript/module/src/authoring/capturePickerScreenshot.d.ts.map +1 -1
  186. package/lib/typescript/module/src/evalJs/getWebView.d.ts +2 -1
  187. package/lib/typescript/module/src/evalJs/getWebView.d.ts.map +1 -1
  188. package/lib/typescript/module/src/hostAppVersion.d.ts +1 -1
  189. package/lib/typescript/module/src/hostAppVersion.d.ts.map +1 -1
  190. package/lib/typescript/module/src/index.d.ts.map +1 -1
  191. package/lib/typescript/module/src/installCheck.d.ts +48 -0
  192. package/lib/typescript/module/src/installCheck.d.ts.map +1 -0
  193. package/lib/typescript/module/src/nativeModules.d.ts +13 -0
  194. package/lib/typescript/module/src/nativeModules.d.ts.map +1 -0
  195. package/lib/typescript/module/src/network.d.ts.map +1 -1
  196. package/lib/typescript/module/src/pairing/deviceId.d.ts.map +1 -1
  197. package/lib/typescript/module/src/pairing/tokenStorage.d.ts.map +1 -1
  198. package/lib/typescript/module/src/runtime/TargetPressBridge.d.ts +2 -1
  199. package/lib/typescript/module/src/runtime/TargetPressBridge.d.ts.map +1 -1
  200. package/lib/typescript/module/src/runtime/UserflowProvider.d.ts.map +1 -1
  201. package/lib/typescript/module/src/storage/asyncStorage.d.ts +15 -0
  202. package/lib/typescript/module/src/storage/asyncStorage.d.ts.map +1 -0
  203. package/lib/typescript/module/src/surfaces/BannerSurface.d.ts.map +1 -1
  204. package/lib/typescript/module/src/surfaces/safeArea.d.ts +6 -2
  205. package/lib/typescript/module/src/surfaces/safeArea.d.ts.map +1 -1
  206. package/lib/typescript/module/src/version.d.ts +1 -1
  207. package/package.json +25 -8
  208. package/src/anchors/AnchorRegistry.ts +12 -0
  209. package/src/anchors/elementConditionEvaluator.ts +235 -70
  210. package/src/anchors/elementTapMonitor.ts +95 -0
  211. package/src/anchors/elementTargetMatch.ts +90 -0
  212. package/src/anchors/fiber/findAnchorFiber.ts +66 -35
  213. package/src/anchors/fiber/touchTargetFiber.ts +125 -0
  214. package/src/anchors/resolveAnchorHost.ts +2 -1
  215. package/src/anchors/resolveAutoAnchorHost.ts +3 -3
  216. package/src/anchors/resolveElementTargets.ts +165 -0
  217. package/src/anchors/targetPressMonitor.ts +12 -3
  218. package/src/anchors/useUserflowAnchor.ts +1 -0
  219. package/src/anonymousId.ts +19 -8
  220. package/src/authoring/capturePickerScreenshot.ts +10 -1
  221. package/src/evalJs/getWebView.ts +6 -13
  222. package/src/hostAppVersion.ts +7 -1
  223. package/src/index.ts +10 -0
  224. package/src/installCheck.ts +225 -0
  225. package/src/nativeModules.ts +48 -0
  226. package/src/network.ts +27 -11
  227. package/src/pairing/deviceId.ts +14 -11
  228. package/src/pairing/tokenStorage.ts +23 -7
  229. package/src/runtime/TargetPressBridge.tsx +17 -1
  230. package/src/runtime/UserflowProvider.tsx +11 -4
  231. package/src/storage/asyncStorage.ts +88 -0
  232. package/src/surfaces/BannerSurface.tsx +7 -5
  233. package/src/surfaces/safeArea.ts +85 -40
  234. package/src/version.ts +1 -1
  235. package/vendor/core/dist/constants.d.ts +2 -0
  236. package/vendor/core/dist/constants.d.ts.map +1 -1
  237. package/vendor/core/dist/constants.js +2 -0
  238. package/vendor/core/dist/constants.js.map +1 -1
  239. package/vendor/core/dist/engine/ClientConditionEngine.d.ts +20 -1
  240. package/vendor/core/dist/engine/ClientConditionEngine.d.ts.map +1 -1
  241. package/vendor/core/dist/engine/ClientConditionEngine.js +13 -10
  242. package/vendor/core/dist/engine/ClientConditionEngine.js.map +1 -1
  243. package/vendor/core/dist/engine/UserflowCore.d.ts.map +1 -1
  244. package/vendor/core/dist/engine/UserflowCore.js +21 -2
  245. package/vendor/core/dist/engine/UserflowCore.js.map +1 -1
  246. package/vendor/core/dist/index.d.ts +1 -1
  247. package/vendor/core/dist/index.d.ts.map +1 -1
  248. package/vendor/core/dist/index.js.map +1 -1
  249. package/vendor/core/dist/version.d.ts +1 -1
  250. package/vendor/core/dist/version.js +1 -1
  251. package/vendor/core/package.json +1 -1
  252. package/vendor/protocol/package.json +1 -1
  253. package/docs/webview-custom-banner-poc.md +0 -64
package/docs/anchoring.md CHANGED
@@ -6,9 +6,9 @@ host app.
6
6
  **This matters more than tooltip placement alone.** The same resolver powers:
7
7
 
8
8
  1. Tooltip target resolution (`TooltipSurface`)
9
- 2. `ELEMENT` client conditions with `PRESENT` / `NOT_PRESENT` — so a missing or
10
- misspelled anchor can mean a gated **flow never starts at all**, not merely a
11
- misplaced tooltip
9
+ 2. `ELEMENT` client conditions (`PRESENT` / `NOT_PRESENT` / `CLICK` /
10
+ `NOT_CLICK`) — so a missing or misspelled anchor can mean a gated **flow
11
+ never starts at all**, not merely a misplaced tooltip
12
12
 
13
13
  ## Preferred: tag with `testID`
14
14
 
@@ -23,15 +23,16 @@ return trimmed.startsWith('#') ? trimmed.slice(1) : trimmed;
23
23
  Then looks up a measurable host, in order:
24
24
 
25
25
  1. **`useUserflowAnchor` registry** (explicit override)
26
- 2. Fiber-tree scan for a matching **`testID`**
27
- 3. Else matching **`nativeID`**
28
- 4. Else matching **`accessibilityLabel`**
26
+ 2. Fiber-tree scan for a matching **`userflowId`**
27
+ 3. Else matching **`testID`**
28
+ 4. Else matching **`nativeID`**
29
+ 5. Else matching **`accessibilityLabel`**
29
30
 
30
- | Dashboard `selector.css` | Resolved id | Host code |
31
- | ------------------------ | ------------------ | --------------------------------------- |
32
- | `#invite-teammates` | `invite-teammates` | `<Pressable testID="invite-teammates">` |
33
- | `invite-teammates` | `invite-teammates` | `<Pressable testID="invite-teammates">` |
34
- | ` #x ` | `x` | `<View testID="x">` |
31
+ | Dashboard `selector.css` | Resolved id | Host code |
32
+ | ------------------------ | ------------------ | ------------------------------------------- |
33
+ | `#invite-teammates` | `invite-teammates` | `<Pressable userflowId="invite-teammates">` |
34
+ | `invite-teammates` | `invite-teammates` | `<Pressable testID="invite-teammates">` |
35
+ | ` #x ` | `x` | `<View nativeID="x">` |
35
36
 
36
37
  Only a plain id (with optional leading `#`) is supported. Compound CSS
37
38
  (`.class`, `[attr]`, `div > button`) is **not** parsed — the trimmed string
@@ -49,7 +50,10 @@ function InviteButton() {
49
50
  }
50
51
  ```
51
52
 
52
- No SDK import is required on the target view. Prefer **MANUAL** selectors in the
53
+ No SDK import is required on the target view. `userflowId` is the strongest
54
+ fiber tier, then `testID`, then `nativeID`. React Native's own prop types do
55
+ not include `userflowId` yet, so a TypeScript host may need a module
56
+ augmentation until the SDK ships one. Prefer **MANUAL** selectors in the
53
57
  builder for mobile when you control the host code.
54
58
 
55
59
  ### AUTO (codeless) selectors
@@ -58,9 +62,9 @@ builder for mobile when you control the host code.
58
62
  instead of a CSS id. Play-time resolution (`resolveAutoAnchorHost`):
59
63
 
60
64
  1. **Exact-id fast path** — if the fingerprint has a real `userflowId`, `testID`,
61
- or non-`uf_` `nativeID`, reuse the MANUAL resolver (`resolveAnchorHost`).
62
- This works even under Babel `stampOnly: true` (no auto-registry
63
- population).
65
+ or non-`uf_` `nativeID`, reuse the MANUAL resolver (`resolveAnchorHost` for
66
+ tooltips, `resolveElementTargets` for conditions). This works even under
67
+ Babel `stampOnly: true` (no auto-registry population).
64
68
  A zero-size measure invalidates that id in the fiber cache, same as MANUAL.
65
69
  2. **Scored match** — rank live `autoAnchorRegistry` instances on **visible**
66
70
  navigator screens (covered stack screens are skipped, same rule as the fiber
@@ -69,11 +73,13 @@ instead of a CSS id. Play-time resolution (`resolveAutoAnchorHost`):
69
73
  scroll the target into view. Babel full mode (the default) is what
70
74
  registers those instances.
71
75
 
72
- Fail-closed mapping for ELEMENT conditions:
76
+ Fail-closed mapping for ELEMENT conditions. An exact id that matches more than
77
+ one host counts as found (any of them), which is web parity and differs from
78
+ tooltip resolution. A scored match that is not unique stays unknown.
73
79
 
74
80
  | Resolution | `PRESENT` / `NOT_PRESENT` |
75
81
  | ------------------------ | -------------------------------------------- |
76
- | `found` | true / false |
82
+ | `found` | true / false, after a non-zero measure |
77
83
  | `absent` | false / true |
78
84
  | `ambiguous` or `unknown` | unknown (`null`) — gated flow does not start |
79
85
 
@@ -156,20 +162,24 @@ reading nothing.
156
162
 
157
163
  ### Prop priority
158
164
 
159
- When resolving via the fiber scan, the highest matching tier wins so a `testID`
160
- hit is never made ambiguous by an unrelated `accessibilityLabel` elsewhere on
161
- the screen:
165
+ When resolving via the fiber scan, the highest matching tier wins so a
166
+ `userflowId` or `testID` hit is never made ambiguous by an unrelated
167
+ `accessibilityLabel` elsewhere on the screen:
162
168
 
163
- 1. `testID`
164
- 2. `nativeID`
165
- 3. `accessibilityLabel`
169
+ 1. `userflowId`
170
+ 2. `testID`
171
+ 3. `nativeID`
172
+ 4. `accessibilityLabel`
166
173
 
167
- ### Duplicate ids fail closed
174
+ ### Duplicate ids
168
175
 
169
- Multiple mounts of the same id are allowed, but `TooltipSurface` treats an
170
- **ambiguous** id as **missing** — it never picks one arbitrarily. Nested
171
- duplicates on a single root-to-leaf chain (e.g. `Pressable` forwarding `testID`
172
- to its inner `View`) collapse to one host. Prefer unique ids per screen.
176
+ Multiple mounts of the same id are allowed. Nested duplicates on a single
177
+ root-to-leaf chain (e.g. `Pressable` forwarding `testID` to its inner `View`)
178
+ collapse to one host.
179
+
180
+ `TooltipSurface` treats a remaining **ambiguous** id as **missing** — it never
181
+ picks one arbitrarily. ELEMENT `PRESENT` / `CLICK` conditions follow the web
182
+ SDK instead: any of the matches counts. Prefer unique ids per screen anyway.
173
183
 
174
184
  ### Only visible screens are scanned
175
185
 
@@ -328,8 +338,10 @@ rect** via a pass-through bridge around app content (`TargetPressBridge` in
328
338
  - Empty `actions`, blocked targets, missing/fallback UI, and scrolls that exceed
329
339
  the slop do not fire.
330
340
 
331
- ELEMENT condition `CLICK` / `MOUSEDOWN` gating is separate and still unsupported
332
- — see [client-conditions.md](client-conditions.md) / [troubleshooting.md](troubleshooting.md).
341
+ ELEMENT `CLICK` / `NOT_CLICK` auto-start conditions use the same bridge
342
+ (`elementTapMonitor`) and do not steal the press either. `MOUSEDOWN` and
343
+ `DISABLED` conditions are still unsupported — see
344
+ [client-conditions.md](client-conditions.md) / [troubleshooting.md](troubleshooting.md).
333
345
 
334
346
  ## Missing-target behavior
335
347
 
@@ -352,18 +364,22 @@ missing.
352
364
 
353
365
  ## ELEMENT client conditions
354
366
 
355
- For `PRESENT` / `NOT_PRESENT` on a MANUAL selector, the evaluator resolves the
356
- same id through `resolveAnchorHost` (registry + fiber scan). A found host means
357
- the anchor is uniquely resolvable on a **visible** navigator screen — covered
358
- stack screens count as absent. Pixel visibility inside a scroll view is not
359
- checked. Ambiguous ids report unknown (`null`) so gated flows stay blocked.
360
-
361
- `AUTO` selectors go through `resolveAutoAnchorHost`. A confident hit or a
362
- genuine contradiction (`absent`) produces a boolean; weak evidence (`unknown`)
363
- and ambiguous explicit ids stay unknown so a gated flow never starts just
364
- because the auto-anchor registry is empty. Hosts on a covered navigator screen
365
- count as absent, matching MANUAL. Unsupported states (`CLICK`, `DISABLED`, …)
366
- stay unknown — see [troubleshooting.md](troubleshooting.md).
367
+ `PRESENT` / `NOT_PRESENT` / `CLICK` / `NOT_CLICK` resolve through
368
+ `resolveElementTargets` (registry + fiber scan, including `userflowId`).
369
+ Duplicate ids count as a hit. Covered stack screens count as absent. A measured
370
+ 0×0 host counts as absent; opacity and scroll clipping are not checked.
371
+
372
+ `CLICK` reports false until the user taps the host or a descendant, then stays
373
+ true until the server untracks the condition. `NOT_CLICK` starts true and
374
+ latches false on that tap. A disabled host does not count.
375
+
376
+ `AUTO` selectors use the same exact-id lookup when the fingerprint carries a
377
+ `userflowId`, `testID`, or real `nativeID`, and otherwise go through
378
+ `resolveAutoAnchorHost`. A confident hit or a genuine contradiction (`absent`)
379
+ produces a boolean; weak evidence (`unknown`) and ambiguous scored matches stay
380
+ unknown so a gated flow never starts just because the auto-anchor registry is
381
+ empty. `DISABLED` and `MOUSEDOWN` stay unknown — see
382
+ [troubleshooting.md](troubleshooting.md).
367
383
 
368
384
  ## How the fiber scan works (brief)
369
385
 
@@ -3,25 +3,57 @@
3
3
  Symptom → cause for common `@userflow-tech/react-native` integration failures.
4
4
  Messages are quoted exactly so you can search logs for them.
5
5
 
6
+ ## Install
7
+
8
+ | Symptom / log message | Likely cause | Fix |
9
+ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
10
+ | `404` from `npm install` or `npm view @userflow-tech/react-native` | The npm token is missing, or the npm user or org is not on the read-only `@userflow-tech` team. npm returns 404 for a private package the caller cannot see. | Ask Userflow to add the npm user or org to the read-only team, then create a granular read-only token limited to `@userflow-tech`. |
11
+ | Yarn 2+ still 404s with a valid `.npmrc` | Yarn 2 and later ignore `.npmrc`. | Set `npmScopes.userflow-tech.npmRegistryServer` and `npmAuthToken` in `.yarnrc.yml`. |
12
+ | EAS or CI install 404s while local install works | `NPM_TOKEN` is not available to that environment. | Add `NPM_TOKEN` as an EAS secret or CI secret. The `.npmrc` line `//registry.npmjs.org/:_authToken=${NPM_TOKEN}` reads it at install time. |
13
+ | `expo doctor` reports `react-native-view-shot` | The app pins `^5.0.0` and Expo SDK 54's expected version is 4.0.3. | Keep the pin. Add `"react-native-view-shot"` to `expo.install.exclude`. |
14
+ | `Unable to resolve module` for an optional peer (`netinfo`, `expo-secure-store`, `expo-router`, safe-area, navigation) | A custom Metro config does not extend `getDefaultConfig`, so `allowOptionalDependencies` is off. | Extend `getDefaultConfig` from `expo/metro-config` or `@react-native/metro-config`. |
15
+ | `ERESOLVE` while installing `@userflow-tech/react-native` | The app already has a version outside a peer range: view-shot 4.0.3 (what unpinned `npx expo install` installs on Expo SDK 54), NetInfo 9.x, safe-area-context 3.x, WebView 13.6.x or 14.x, or React Native older than 0.76. | Move that package into the range in the package README. For view-shot, npm prints `Found: react-native-view-shot@4.0.3` and `peer react-native-view-shot@"^5.0.0" from @userflow-tech/react-native`. Install the SDK and `react-native-view-shot@^5.0.0` in one command, then add `"react-native-view-shot"` to `expo.install.exclude` on Expo SDK 54. Do not retry with `--force` or `--legacy-peer-deps`; that leaves 4.0.3 installed. Raise React Native to 0.76 or later when that is the conflict. |
16
+ | Yarn 1 or `npm install --legacy-peer-deps` succeeded, but `react-native-webview` or `react-native-view-shot` is not installed | Those installs do not fetch peers. WebView and view-shot are required peers, not dependencies. | Install `react-native-webview` and `react-native-view-shot@^5.0.0` in the app, then rebuild native. |
17
+ | Banners, flow cards, or Builder bars draw under the status bar, notch, or home indicator. Development logs `[Userflow] react-native-safe-area-context is not installed, so banners, flow cards, and Builder bars draw under the status bar and home indicator. Install it (npx expo install react-native-safe-area-context) and wrap the app in <SafeAreaProvider>.` | `react-native-safe-area-context` is not installed, so insets are zero. | Install the package and wrap the tree in `<SafeAreaProvider>`. |
18
+ | `Uncaught Error` / `NativeModule.RNCNetInfo is null` as soon as `Userflow.init` runs | On SDK 0.3.1 and earlier, NetInfo's JavaScript was loaded while its native module was not in the binary. Debug builds show a red screen. Dismissing it leaves the app running; a release build can crash. | Link `@react-native-community/netinfo` and rebuild, or remove it. Current versions skip NetInfo when `RNCNetInfo` is not registered and log one dev warning instead. |
19
+ | `[@userflow-tech/react-native] schemeId "…" looks like an environment id. Pass the scheme_id value that starts with userflow- (an opaque id from the dashboard), not the environment UUID.` | The config plugin received the environment UUID. | Pass the `scheme_id` (`userflow-…`) from the dashboard. |
20
+ | `No schemeId was passed, so the plugin left the native config unchanged. Builder preview and pairing links will not open this app. Pass the environment scheme_id (userflow-...) from the Userflow dashboard as the plugin schemeId.` | `expo prebuild` ran the plugin without `schemeId`. | Add `{ "schemeId": "userflow-…" }` and rebuild native. |
21
+ | react-native-view-shot is not a direct dependency. Builder element selection needs >=5.0.0. On Expo SDK 54, an unpinned `npx expo install react-native-view-shot` resolves 4.0.3. Pin ^5.0.0. If expo doctor reports a version mismatch, add "react-native-view-shot" to expo.install.exclude. | Prebuild did not find view-shot in the app `package.json`. | `npx expo install react-native-view-shot@^5.0.0` and rebuild. |
22
+ | `react-native-safe-area-context is not listed in the app package.json. Expo SDK 53 does not autolink native modules that the app only receives indirectly. Without the native module, banners, flow cards, and Builder bars draw under the status bar and home indicator. Install it in the app (npx expo install react-native-safe-area-context) and wrap the app in <SafeAreaProvider>.` | Expo SDK older than 54, and safe-area-context is not a direct dependency, so its native module is not autolinked. | `npx expo install react-native-safe-area-context` and wrap the tree in `<SafeAreaProvider>`. |
23
+ | `[Userflow] react-native-view-shot@4.0.3 is older than 5.0.0, so Builder element selection may not get a screenshot.` The installed version is filled in. The warning also says not to retry with `--force` or `--legacy-peer-deps`. | view-shot 4.x is installed, usually because an `ERESOLVE` was retried with `--force` or `--legacy-peer-deps`, or Expo SDK 54's default 4.0.3 was left in place. | Install `react-native-view-shot@^5.0.0` in the same command as the SDK and rebuild. On Expo SDK 54, add `"react-native-view-shot"` to `expo.install.exclude`. |
24
+ | `react-native-view-shot@4.0.3 is older than 5.0.0. Expo SDK 54's default is 4.0.3, which does not work with this SDK. Pin ^5.0.0 and add "react-native-view-shot" to expo.install.exclude if expo doctor complains.` | The app has view-shot 4.x. | Pin `^5.0.0` and rebuild. |
25
+ | `@react-native-async-storage/async-storage is not listed in the app package.json. Expo SDK 53 does not autolink native modules that the app only receives indirectly. Install it in the app (npx expo install @react-native-async-storage/async-storage) and rebuild.` | Expo SDK older than 54, and AsyncStorage is only a transitive dependency. The WebView line is the same shape with `react-native-webview`. | Install that package in the app and rebuild. |
26
+ | `[Userflow] Native setup is incomplete. Flows may not run until you fix the following, then rebuild the app (a Metro reload is not enough):` | Dev-only check on the first `Userflow.init`. Following lines name each missing native module. A missing safe-area package is a separate warning, because flows still run. | Install the named packages and rebuild. The footer is `See node_modules/@userflow-tech/react-native/docs/troubleshooting.md.` |
27
+ | `- @react-native-async-storage/async-storage is not linked. Anonymous users and Builder pairing will not persist. Add it to the app package.json (npx expo install @react-native-async-storage/async-storage), run pod install on iOS, and rebuild.` | AsyncStorage's native module is not in this binary. | Add it to the app `package.json`, run `pod install` on iOS, and rebuild. |
28
+ | `- react-native-view-shot is not linked, so Builder element selection gets no screenshot. Install react-native-view-shot@^5.0.0 and rebuild. On Expo SDK 54, pin ^5.0.0; an unpinned npx expo install resolves 4.0.3.` | `RNViewShot` is not registered. | Install `react-native-view-shot@^5.0.0` and rebuild. |
29
+ | `- react-native-webview is not linked. Evaluate JavaScript and WebView banners will not run. Install it (npx expo install react-native-webview) and rebuild.` | The WebView native module is not registered. | Install `react-native-webview` and rebuild. |
30
+ | `- react-native-device-info is not linked, so app_version and app_build are not sent. npm install react-native-device-info, then rebuild.` | Bare React Native, and `RNDeviceInfo` is not registered. Expo apps that have `expo-constants` do not log this line. | `npm install react-native-device-info` and rebuild. |
31
+ | `[Userflow] This app is running in Expo Go, which cannot load the SDK native modules. Builder preview links will not open the app. Use a development build (npx expo run:ios / npx expo run:android).` | The app is the Expo Go store client. | Use a development build. |
32
+ | `[Userflow] UserflowProvider is not inside a <SafeAreaProvider>, so flow cards use the device's initial safe-area insets. Wrap your app in <SafeAreaProvider> from react-native-safe-area-context.` | `UserflowProvider` has no `SafeAreaProvider` ancestor. The app does not crash. Cards use `initialWindowMetrics`, or zero insets when those are unavailable. | Wrap the tree in `SafeAreaProvider`. |
33
+ | `Userflow.identifyAnonymous() needs @react-native-async-storage/async-storage, which is not linked in this native build. Add it to your app's package.json, run pod install, and rebuild.` | `identifyAnonymous()` ran without a linked AsyncStorage native module. | Install and rebuild, then call it again. |
34
+ | `clientToken is an environment secret key (esk_...). That key must never ship in the app. Pass the client token (ct_...) from Settings → Environments instead.` | `init` was given an `esk_` secret key. | Pass the `ct_…` client token. |
35
+ | `For EU-hosted environments pass serverEndpoint: 'https://e.eu.userflow.com'.` | The default US host rejected the token with `invalid_client_token`. This sentence is appended to that error. It is omitted when `serverEndpoint` was set explicitly. | For an EU environment, pass `serverEndpoint: 'https://e.eu.userflow.com'`. Pairing stays on `https://e.userflow.com`. |
36
+ | `[Userflow] Userflow.init() already ran with different options. The new clientToken, serverEndpoint, and pairingEndpoint are ignored because init runs once per process. Userflow.reset() does not apply new credentials. Restart the app to change them.` | A later `init` passed a different token or endpoint while a previous `init` is in flight or has succeeded. | Restart the app after a successful init. `reset()` clears the user and does not apply new credentials. If the previous `init` rejected, call `init` again with the corrected token or endpoint. |
37
+
6
38
  ## Init / identify / group
7
39
 
8
- | Symptom / log message | Likely cause | Fix |
9
- | --------------------------------------------------------------------------------------- | ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
10
- | `Call Userflow.init() before identify()` | `identify` / `identifyAnonymous` before `init()` resolved | `await Userflow.init(...)` first |
11
- | `Call Userflow.init() before group()` | `group` before init | Same |
12
- | `Call Userflow.identify() before group()` | `group` before any identify | Call `identify` or `identifyAnonymous` first |
13
- | `Call Userflow.init() before updateUser()` / `updateGroup()` | `updateUser` / `updateGroup` before init | `await Userflow.init(...)` first |
14
- | `Call Userflow.identify() before updateUser()` | `updateUser` before any identify | Call `identify` or `identifyAnonymous` first |
15
- | `Call Userflow.group() before updateGroup()` | `updateGroup` or a group-scoped button attribute before `group()` | Call `Userflow.group(...)` first |
16
- | `Missing clientToken` | Empty / whitespace token | Pass the `ct_...` value from the dashboard |
17
- | `… invalid_client_token: Invalid Userflow.js Token: …` | Wrong token, wrong region, or deactivated env | Copy the token from the matching environment; EU tokens may need an EU `serverEndpoint` |
18
- | `… user_signature_required: …` | Env requires identity verification; no `signature` | Compute HMAC on your backend — [identity-verification.md](identity-verification.md) |
19
- | `… incorrect_user_signature: …` | Signature does not match HMAC-SHA256(secret, userId) | Sign the **same** id string; use `esk_...`, not `ct_...` |
20
- | `… group_signature_required` / `incorrect_group_signature` | Same rules for `group()` | Sign the group id with the env secret key |
21
- | `Client message rate limit exceeded (100/min)` | Too many client messages in a 60s window | Each accepted screen uses two slots (`UpdateClientContext` + `screen_viewed`); slow down navigation or wait for the window to refill |
22
- | `Userflow.identifyAnonymous() is not supported when persistent storage is unavailable.` | AsyncStorage threw at runtime | Ensure `@react-native-async-storage/async-storage` is installed and linked |
23
- | Module resolution failure for AsyncStorage | Autolinking missed the SDK dependency | `npx expo install @react-native-async-storage/async-storage` |
24
- | Second `init()` seems to ignore new options | `init()` is idempotent | Expected; use a fresh process or `reset()` carefully |
40
+ | Symptom / log message | Likely cause | Fix |
41
+ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
42
+ | `Call Userflow.init() before identify()` | `identify` / `identifyAnonymous` before `init()` resolved | `await Userflow.init(...)` first |
43
+ | `Call Userflow.init() before group()` | `group` before init | Same |
44
+ | `Call Userflow.identify() before group()` | `group` before any identify | Call `identify` or `identifyAnonymous` first |
45
+ | `Call Userflow.init() before updateUser()` / `updateGroup()` | `updateUser` / `updateGroup` before init | `await Userflow.init(...)` first |
46
+ | `Call Userflow.identify() before updateUser()` | `updateUser` before any identify | Call `identify` or `identifyAnonymous` first |
47
+ | `Call Userflow.group() before updateGroup()` | `updateGroup` or a group-scoped button attribute before `group()` | Call `Userflow.group(...)` first |
48
+ | `Missing clientToken` | Empty / whitespace token | Pass the `ct_...` value from the dashboard |
49
+ | `… invalid_client_token: Invalid Userflow.js Token: …` | Wrong token, wrong region, or deactivated env | Copy the token from the matching environment. When the default US host returns this, the message also says `For EU-hosted environments pass serverEndpoint: 'https://e.eu.userflow.com'.` |
50
+ | `… user_signature_required: …` | Env requires identity verification; no `signature` | Compute HMAC on your backend — [identity-verification.md](identity-verification.md) |
51
+ | `… incorrect_user_signature: …` | Signature does not match HMAC-SHA256(secret, userId) | Sign the **same** id string; use `esk_...`, not `ct_...` |
52
+ | `… group_signature_required` / `incorrect_group_signature` | Same rules for `group()` | Sign the group id with the env secret key |
53
+ | `Client message rate limit exceeded (100/min)` | Too many client messages in a 60s window | Each accepted screen uses two slots (`UpdateClientContext` + `screen_viewed`); slow down navigation or wait for the window to refill |
54
+ | `Userflow.identifyAnonymous() is not supported when persistent storage is unavailable.` | AsyncStorage threw while reading or writing the anonymous id | Ensure `@react-native-async-storage/async-storage` is installed and linked |
55
+ | `Userflow.identifyAnonymous() needs @react-native-async-storage/async-storage, which is not linked in this native build. Add it to your app's package.json, run pod install, and rebuild.` | The native module is not in this binary | Add it to the app `package.json`, run `pod install`, and rebuild |
56
+ | Second `init()` seems to ignore new options | A previous `init` is in flight or has succeeded. A rejected `init` can be retried. | Development logs `[Userflow] Userflow.init() already ran with different options. The new clientToken, serverEndpoint, and pairingEndpoint are ignored because init runs once per process. Userflow.reset() does not apply new credentials. Restart the app to change them.` |
25
57
 
26
58
  ## Flow never appeared
27
59
 
@@ -37,29 +69,30 @@ Look for warnings such as:
37
69
 
38
70
  ```text
39
71
  [Userflow] ELEMENT condition … uses an AUTO (codeless) selector that could not be resolved; …
40
- [Userflow] ELEMENT condition … uses unsupported elementState "CLICK" …
72
+ [Userflow] ELEMENT condition … uses unsupported elementState "DISABLED" …
41
73
  ```
42
74
 
43
75
  Or a core warning that a condition type has no evaluator (`INPUT_VALUE`,
44
- `FILLED_IN_INPUT`, …).
76
+ `FILLED_IN_INPUT`, …). `PRESENT`, `NOT_PRESENT`, `CLICK`, and `NOT_CLICK` are
77
+ evaluated. `DISABLED`, `NOT_DISABLED`, and `MOUSEDOWN` are not.
45
78
 
46
- **Workaround:** author the start condition with a **MANUAL** selector and
47
- `PRESENT` / `NOT_PRESENT`, and tag the target with matching `testID="…"` (or
48
- `useUserflowAnchor('…')`). See [anchoring.md](anchoring.md).
79
+ **Workaround:** author the start condition with a **MANUAL** selector and one of
80
+ the four supported states, and tag the target with matching `userflowId`,
81
+ `testID`, or `nativeID` (or `useUserflowAnchor('…')`). See [anchoring.md](anchoring.md).
49
82
 
50
83
  ### 2. Anchor / tooltip placement
51
84
 
52
85
  | Symptom | Likely cause |
53
86
  | ------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
54
- | “Looking for target…” then “Target not found” | Wrong id vs dashboard `#css`, no matching `testID`/`nativeID`/`accessibilityLabel` or `useUserflowAnchor`, or zero-size measure |
55
- | Tooltip never attaches despite a visible element | **Duplicate** id on disjoint views (ambiguous → fail closed) |
87
+ | “Looking for target…” then “Target not found” | Wrong id vs dashboard `#css`, no matching `userflowId`/`testID`/`nativeID`/`accessibilityLabel` or `useUserflowAnchor`, or zero-size measure |
88
+ | Tooltip never attaches despite a visible element | **Duplicate** id on disjoint views (tooltips fail closed; element conditions still treat any match as present) |
56
89
  | Off-screen target not scrolled into view | Parent `ScrollView` not registered with `useUserflowScrollContainer` |
57
90
  | “To the left/right of target” renders above/below | No room beside the target for even the card's own padding — it shrinks first and flips only as a last resort. Draft/dev logs `… could not be drawn beside the target` |
58
91
  | Side-placed tooltip looks unusually narrow | Expected: a side card takes the room left beside the target and grows taller. Move the target inward, or pick above/below, if you want it wider |
59
92
  | Flow vanished after a few seconds | Theme `tooltipMissingBehavior: END` after tolerance |
60
93
  | Centered card with step content, no notch | Theme `tooltipMissingBehavior: BUBBLE` after missing tolerance |
61
94
 
62
- Id matching: dashboard `#invite-teammates` ↔ `testID="invite-teammates"` (or `useUserflowAnchor('invite-teammates')`).
95
+ Id matching: dashboard `#invite-teammates` ↔ `userflowId="invite-teammates"`, then `testID`, then `nativeID` (or `useUserflowAnchor('invite-teammates')`).
63
96
 
64
97
  ### 3. Screen / provider
65
98
 
@@ -105,12 +138,21 @@ Full setup: [deep-linking.md](deep-linking.md). Pairing is available in all buil
105
138
  | Duplicate React / RN instance crashes when linking local packages | Force singletons in Metro — monorepo `docs/metro.md` |
106
139
  | Preview / pairing scheme not registered | Add the `@userflow-tech/react-native` plugin with `schemeId`, then rebuild native |
107
140
 
141
+ ## Jest
142
+
143
+ | Symptom | Likely cause | Fix |
144
+ | ------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- |
145
+ | Snapshots gain `nativeID="uf_…"`, `collapsable={false}`, `__ufid`, or `__ufManual` props, and keep changing after unrelated JSX edits | The Babel plugin runs under Jest, because `babel-jest` reads `babel.config.js`. Its ids depend on file path, component name, sibling order, and static labels. | Skip the plugin when `api.env('test')` is true. See the README section "Babel plugin and snapshot tests". |
146
+ | `Caching has already been configured with .never or .forever()` after adding `api.env('test')` | `babel.config.js` still calls `api.cache(true)` before `api.env`. | Remove `api.cache(true)`. `api.env` already caches per environment. |
147
+ | Component tests load the SDK after enabling the Babel plugin | Full mode imports `@userflow-tech/react-native` into every stamped file. | Mock the SDK in the Jest setup file, or skip the plugin in tests. |
148
+
108
149
  ## Still stuck?
109
150
 
110
151
  1. Confirm `await Userflow.init` → `await Userflow.identify` → `UserflowProvider`.
111
152
  2. Search logs for `[Userflow]` and the exact strings in the tables above.
112
- 3. Verify the published flow’s start conditions use MANUAL + PRESENT/NOT_PRESENT
113
- if they depend on an on-device element.
153
+ 3. Verify the published flow’s start conditions use a supported element state
154
+ (`PRESENT`, `NOT_PRESENT`, `CLICK`, `NOT_CLICK`) if they depend on an
155
+ on-device element.
114
156
  4. Confirm the anchor id in code matches the builder selector after stripping `#`.
115
157
  5. For builder Preview: confirm the **Preview mode** top bar is visible before you
116
158
  click Preview in the dashboard.
@@ -0,0 +1,21 @@
1
+ /** Printed from the iOS and Android prebuild steps when `schemeId` is omitted. */
2
+ export declare const MISSING_SCHEME_WARNING = "No schemeId was passed, so the plugin left the native config unchanged. Builder preview and pairing links will not open this app. Pass the environment scheme_id (userflow-...) from the Userflow dashboard as the plugin schemeId.";
3
+ export interface HostDependencyWarning {
4
+ property: string;
5
+ message: string;
6
+ }
7
+ /**
8
+ * Prebuild checks that do not change the native config.
9
+ *
10
+ * `react-native-view-shot` must be at least 5. Expo SDK 54's unpinned install
11
+ * resolves 4.0.3. Expo SDK 53 and older only autolink native modules listed in
12
+ * the app's own package.json, so AsyncStorage, WebView, and safe-area-context
13
+ * have to be direct dependencies there. Expo SDK 54 and later autolink
14
+ * safe-area-context when Expo Router or React Navigation brought it in, so
15
+ * prebuild does not warn about it on those SDKs. `Userflow.init` warns when
16
+ * the package itself cannot be loaded.
17
+ */
18
+ export declare function hostDependencyWarnings(projectRoot: string | undefined, sdkVersion: string | null | undefined): HostDependencyWarning[];
19
+ /** Called from inside the iOS and Android config-plugin steps, so it runs at prebuild. */
20
+ export declare function applyPrebuildWarnings(config: object, platform: 'ios' | 'android', schemeId: string | null): void;
21
+ //# sourceMappingURL=hostDependencyWarnings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hostDependencyWarnings.d.ts","sourceRoot":"","sources":["../plugin/hostDependencyWarnings.ts"],"names":[],"mappings":"AAKA,kFAAkF;AAClF,eAAO,MAAM,sBAAsB,wOACoM,CAAC;AAExO,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB;AAcD;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CACpC,WAAW,EAAE,MAAM,GAAG,SAAS,EAC/B,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GACpC,qBAAqB,EAAE,CA+CzB;AAED,0FAA0F;AAC1F,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,KAAK,GAAG,SAAS,EAC3B,QAAQ,EAAE,MAAM,GAAG,IAAI,GACtB,IAAI,CAaN"}
@@ -0,0 +1,101 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MISSING_SCHEME_WARNING = void 0;
4
+ exports.hostDependencyWarnings = hostDependencyWarnings;
5
+ exports.applyPrebuildWarnings = applyPrebuildWarnings;
6
+ const node_fs_1 = require("node:fs");
7
+ const node_path_1 = require("node:path");
8
+ const config_plugins_1 = require("@expo/config-plugins");
9
+ /** Printed from the iOS and Android prebuild steps when `schemeId` is omitted. */
10
+ exports.MISSING_SCHEME_WARNING = 'No schemeId was passed, so the plugin left the native config unchanged. Builder preview and pairing links will not open this app. Pass the environment scheme_id (userflow-...) from the Userflow dashboard as the plugin schemeId.';
11
+ const VIEW_SHOT = 'react-native-view-shot';
12
+ const SAFE_AREA = 'react-native-safe-area-context';
13
+ const TRANSITIVE_NATIVE_MODULES = [
14
+ '@react-native-async-storage/async-storage',
15
+ 'react-native-webview',
16
+ ];
17
+ /**
18
+ * Prebuild checks that do not change the native config.
19
+ *
20
+ * `react-native-view-shot` must be at least 5. Expo SDK 54's unpinned install
21
+ * resolves 4.0.3. Expo SDK 53 and older only autolink native modules listed in
22
+ * the app's own package.json, so AsyncStorage, WebView, and safe-area-context
23
+ * have to be direct dependencies there. Expo SDK 54 and later autolink
24
+ * safe-area-context when Expo Router or React Navigation brought it in, so
25
+ * prebuild does not warn about it on those SDKs. `Userflow.init` warns when
26
+ * the package itself cannot be loaded.
27
+ */
28
+ function hostDependencyWarnings(projectRoot, sdkVersion) {
29
+ if (!projectRoot) {
30
+ return [];
31
+ }
32
+ const dependencies = readDirectDependencies(projectRoot);
33
+ if (!dependencies) {
34
+ return [];
35
+ }
36
+ const warnings = [];
37
+ const viewShot = dependencies[VIEW_SHOT];
38
+ if (!viewShot) {
39
+ warnings.push({
40
+ property: VIEW_SHOT,
41
+ message: 'react-native-view-shot is not a direct dependency. Builder element selection needs >=5.0.0. On Expo SDK 54, an unpinned `npx expo install react-native-view-shot` resolves 4.0.3. Pin ^5.0.0. If expo doctor reports a version mismatch, add "react-native-view-shot" to expo.install.exclude.',
42
+ });
43
+ }
44
+ else {
45
+ const major = leadingMajor(viewShot);
46
+ if (major != null && major < 5) {
47
+ warnings.push({
48
+ property: VIEW_SHOT,
49
+ message: `react-native-view-shot@${viewShot} is older than 5.0.0. Expo SDK 54's default is 4.0.3, which does not work with this SDK. Pin ^5.0.0 and add "react-native-view-shot" to expo.install.exclude if expo doctor complains.`,
50
+ });
51
+ }
52
+ }
53
+ const sdkMajor = leadingMajor(sdkVersion ?? '');
54
+ if (sdkMajor != null && sdkMajor < 54) {
55
+ if (!dependencies[SAFE_AREA]) {
56
+ warnings.push({
57
+ property: SAFE_AREA,
58
+ message: `react-native-safe-area-context is not listed in the app package.json. Expo SDK ${sdkMajor} does not autolink native modules that the app only receives indirectly. Without the native module, banners, flow cards, and Builder bars draw under the status bar and home indicator. Install it in the app (npx expo install react-native-safe-area-context) and wrap the app in <SafeAreaProvider>.`,
59
+ });
60
+ }
61
+ for (const name of TRANSITIVE_NATIVE_MODULES) {
62
+ if (!dependencies[name]) {
63
+ warnings.push({
64
+ property: name,
65
+ message: `${name} is not listed in the app package.json. Expo SDK ${sdkMajor} does not autolink native modules that the app only receives indirectly. Install it in the app (npx expo install ${name}) and rebuild.`,
66
+ });
67
+ }
68
+ }
69
+ }
70
+ return warnings;
71
+ }
72
+ /** Called from inside the iOS and Android config-plugin steps, so it runs at prebuild. */
73
+ function applyPrebuildWarnings(config, platform, schemeId) {
74
+ const source = config;
75
+ const add = platform === 'ios' ? config_plugins_1.WarningAggregator.addWarningIOS : config_plugins_1.WarningAggregator.addWarningAndroid;
76
+ if (!schemeId) {
77
+ add('schemeId', exports.MISSING_SCHEME_WARNING);
78
+ }
79
+ for (const warning of hostDependencyWarnings(source._internal?.projectRoot, source.sdkVersion)) {
80
+ add(warning.property, warning.message);
81
+ }
82
+ }
83
+ function readDirectDependencies(projectRoot) {
84
+ try {
85
+ const raw = (0, node_fs_1.readFileSync)((0, node_path_1.join)(projectRoot, 'package.json'), 'utf8');
86
+ const pkg = JSON.parse(raw);
87
+ return { ...pkg.dependencies, ...pkg.devDependencies };
88
+ }
89
+ catch {
90
+ return null;
91
+ }
92
+ }
93
+ /** First integer in a version or range (`^5.0.0` → 5, `54.0.0` → 54). */
94
+ function leadingMajor(specifier) {
95
+ const match = specifier.match(/\d+/);
96
+ if (!match) {
97
+ return null;
98
+ }
99
+ return Number(match[0]);
100
+ }
101
+ //# sourceMappingURL=hostDependencyWarnings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hostDependencyWarnings.js","sourceRoot":"","sources":["../plugin/hostDependencyWarnings.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"withUserflow.d.ts","sourceRoot":"","sources":["../plugin/withUserflow.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,YAAY,EAClB,MAAM,sBAAsB,CAAC;AAsC9B,MAAM,WAAW,yBAAyB;IACxC;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,sEAAsE;IACtE,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AA4ED,QAAA,MAAM,MAAM,gDAAmE,CAAC;AAEhF,eAAe,MAAM,CAAC"}
1
+ {"version":3,"file":"withUserflow.d.ts","sourceRoot":"","sources":["../plugin/withUserflow.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,YAAY,EAClB,MAAM,sBAAsB,CAAC;AA2C9B,MAAM,WAAW,yBAAyB;IACxC;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,sEAAsE;IACtE,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AA2FD,QAAA,MAAM,MAAM,gDAAmE,CAAC;AAEhF,eAAe,MAAM,CAAC"}
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const config_plugins_1 = require("@expo/config-plugins");
4
+ const hostDependencyWarnings_1 = require("./hostDependencyWarnings");
4
5
  /**
5
6
  * Expo config plugin shipped inside `@userflow-tech/react-native`.
6
7
  *
@@ -35,6 +36,8 @@ const USERFLOW_SCHEME_PREFIX = 'userflow-';
35
36
  * one or more alphanumeric segments joined by single hyphens.
36
37
  */
37
38
  const USERFLOW_SCHEME = /^userflow-[a-z0-9]+(?:-[a-z0-9]+)*$/;
39
+ /** Environment ids are UUIDs. The plugin needs `scheme_id`, which is not that UUID. */
40
+ const ENVIRONMENT_UUID = /^(?:userflow-)?[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
38
41
  function normalizeUrlScheme(urlScheme) {
39
42
  if (urlScheme == null)
40
43
  return null;
@@ -46,6 +49,9 @@ function normalizeUrlScheme(urlScheme) {
46
49
  .replace(/:$/, '');
47
50
  if (!trimmed)
48
51
  return null;
52
+ if (ENVIRONMENT_UUID.test(trimmed)) {
53
+ throw new Error(`[${PACKAGE_NAME}] schemeId "${trimmed}" looks like an environment id. Pass the scheme_id value that starts with userflow- (an opaque id from the dashboard), not the environment UUID.`);
54
+ }
49
55
  if (trimmed.includes('://') || trimmed.includes('/') || trimmed.includes(':')) {
50
56
  throw new Error(`[${PACKAGE_NAME}] urlScheme must be a bare scheme (e.g. "userflow-v7twv2fw2ja2jaco7kesvowmem"), got "${urlScheme}"`);
51
57
  }
@@ -61,6 +67,7 @@ function normalizeUrlScheme(urlScheme) {
61
67
  }
62
68
  const withUserflowUrlSchemeIos = (config, urlScheme) => {
63
69
  return (0, config_plugins_1.withInfoPlist)(config, (config) => {
70
+ (0, hostDependencyWarnings_1.applyPrebuildWarnings)(config, 'ios', urlScheme);
64
71
  if (!config_plugins_1.IOSConfig.Scheme.hasScheme(urlScheme, config.modResults)) {
65
72
  config.modResults = config_plugins_1.IOSConfig.Scheme.appendScheme(urlScheme, config.modResults);
66
73
  }
@@ -69,6 +76,7 @@ const withUserflowUrlSchemeIos = (config, urlScheme) => {
69
76
  };
70
77
  const withUserflowUrlSchemeAndroid = (config, urlScheme) => {
71
78
  return (0, config_plugins_1.withAndroidManifest)(config, (config) => {
79
+ (0, hostDependencyWarnings_1.applyPrebuildWarnings)(config, 'android', urlScheme);
72
80
  const mainActivity = config_plugins_1.AndroidConfig.Manifest.getMainActivityOrThrow(config.modResults);
73
81
  const intentFilters = mainActivity['intent-filter'] ?? [];
74
82
  const alreadyRegistered = intentFilters.some((filter) => {
@@ -92,6 +100,14 @@ const withUserflowUrlSchemeAndroid = (config, urlScheme) => {
92
100
  const withUserflow = (config, options = {}) => {
93
101
  const urlScheme = normalizeUrlScheme(options?.urlScheme ?? options?.schemeId);
94
102
  if (!urlScheme) {
103
+ config = (0, config_plugins_1.withInfoPlist)(config, (mod) => {
104
+ (0, hostDependencyWarnings_1.applyPrebuildWarnings)(mod, 'ios', null);
105
+ return mod;
106
+ });
107
+ config = (0, config_plugins_1.withAndroidManifest)(config, (mod) => {
108
+ (0, hostDependencyWarnings_1.applyPrebuildWarnings)(mod, 'android', null);
109
+ return mod;
110
+ });
95
111
  return config;
96
112
  }
97
113
  config = withUserflowUrlSchemeIos(config, urlScheme);
@@ -1 +1 @@
1
- {"version":3,"file":"withUserflow.js","sourceRoot":"","sources":["../plugin/withUserflow.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"withUserflow.js","sourceRoot":"","sources":["../plugin/withUserflow.ts"],"names":[],"mappings":"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"}