@userflow-tech/react-native 0.4.4 → 0.5.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 (431) hide show
  1. package/README.md +124 -34
  2. package/docs/anchoring.md +6 -1
  3. package/docs/deep-linking.md +26 -0
  4. package/docs/troubleshooting.md +50 -23
  5. package/expo-plugin/hostDependencyWarnings.d.ts +6 -4
  6. package/expo-plugin/hostDependencyWarnings.d.ts.map +1 -1
  7. package/expo-plugin/hostDependencyWarnings.js +8 -6
  8. package/expo-plugin/hostDependencyWarnings.js.map +1 -1
  9. package/lib/commonjs/anchors/AutoAnchorRegistry.js +144 -34
  10. package/lib/commonjs/anchors/AutoAnchorRegistry.js.map +1 -1
  11. package/lib/commonjs/anchors/animationFrame.js +29 -1
  12. package/lib/commonjs/anchors/animationFrame.js.map +1 -1
  13. package/lib/commonjs/anchors/appActive.js +61 -0
  14. package/lib/commonjs/anchors/appActive.js.map +1 -0
  15. package/lib/commonjs/anchors/elementConditionEvaluator.js +25 -8
  16. package/lib/commonjs/anchors/elementConditionEvaluator.js.map +1 -1
  17. package/lib/commonjs/anchors/elementTapMonitor.js +67 -12
  18. package/lib/commonjs/anchors/elementTapMonitor.js.map +1 -1
  19. package/lib/commonjs/anchors/elementTargetMatch.js +33 -7
  20. package/lib/commonjs/anchors/elementTargetMatch.js.map +1 -1
  21. package/lib/commonjs/anchors/fiber/fiberInternals.js +66 -0
  22. package/lib/commonjs/anchors/fiber/fiberInternals.js.map +1 -1
  23. package/lib/commonjs/anchors/fiber/indexHostFibers.js +4 -3
  24. package/lib/commonjs/anchors/fiber/indexHostFibers.js.map +1 -1
  25. package/lib/commonjs/anchors/fiber/resolveFiberPath.js +30 -15
  26. package/lib/commonjs/anchors/fiber/resolveFiberPath.js.map +1 -1
  27. package/lib/commonjs/anchors/fiberAnchorCache.js +20 -0
  28. package/lib/commonjs/anchors/fiberAnchorCache.js.map +1 -1
  29. package/lib/commonjs/anchors/gestureHandlerHandoff.js +304 -0
  30. package/lib/commonjs/anchors/gestureHandlerHandoff.js.map +1 -0
  31. package/lib/commonjs/anchors/resolveAnchorHost.js +6 -0
  32. package/lib/commonjs/anchors/resolveAnchorHost.js.map +1 -1
  33. package/lib/commonjs/anchors/resolveAutoAnchorHost.js +11 -6
  34. package/lib/commonjs/anchors/resolveAutoAnchorHost.js.map +1 -1
  35. package/lib/commonjs/anchors/resolveElementTargets.js +63 -8
  36. package/lib/commonjs/anchors/resolveElementTargets.js.map +1 -1
  37. package/lib/commonjs/anchors/semanticMatcher.js +43 -21
  38. package/lib/commonjs/anchors/semanticMatcher.js.map +1 -1
  39. package/lib/commonjs/anchors/tapSlop.js +16 -0
  40. package/lib/commonjs/anchors/tapSlop.js.map +1 -0
  41. package/lib/commonjs/anchors/targetPressMonitor.js +66 -12
  42. package/lib/commonjs/anchors/targetPressMonitor.js.map +1 -1
  43. package/lib/commonjs/authoring/fingerprintFromInstance.js +5 -9
  44. package/lib/commonjs/authoring/fingerprintFromInstance.js.map +1 -1
  45. package/lib/commonjs/content/RichContentRenderer.js +3 -3
  46. package/lib/commonjs/content/RichContentRenderer.js.map +1 -1
  47. package/lib/commonjs/content/openSafeUrl.js +3 -1
  48. package/lib/commonjs/content/openSafeUrl.js.map +1 -1
  49. package/lib/commonjs/expo-router/useUserflowExpoRouter.js +6 -0
  50. package/lib/commonjs/expo-router/useUserflowExpoRouter.js.map +1 -1
  51. package/lib/commonjs/index.js +19 -5
  52. package/lib/commonjs/index.js.map +1 -1
  53. package/lib/commonjs/installCheck.js +2 -2
  54. package/lib/commonjs/installCheck.js.map +1 -1
  55. package/lib/commonjs/navigation/navigateUrlUtils.js +105 -0
  56. package/lib/commonjs/navigation/navigateUrlUtils.js.map +1 -0
  57. package/lib/commonjs/navigation/openExternalNavigateUrl.js +14 -0
  58. package/lib/commonjs/navigation/openExternalNavigateUrl.js.map +1 -0
  59. package/lib/commonjs/navigation/openFlowNavigateUrl.js +47 -41
  60. package/lib/commonjs/navigation/openFlowNavigateUrl.js.map +1 -1
  61. package/lib/commonjs/pairing/PairingController.js +3 -1
  62. package/lib/commonjs/pairing/PairingController.js.map +1 -1
  63. package/lib/commonjs/runtime/BannerHost.js +38 -29
  64. package/lib/commonjs/runtime/BannerHost.js.map +1 -1
  65. package/lib/commonjs/runtime/TargetPressBridge.js +55 -7
  66. package/lib/commonjs/runtime/TargetPressBridge.js.map +1 -1
  67. package/lib/commonjs/runtime/UserflowOverlay.js +5 -11
  68. package/lib/commonjs/runtime/UserflowOverlay.js.map +1 -1
  69. package/lib/commonjs/runtime/UserflowProvider.js +66 -40
  70. package/lib/commonjs/runtime/UserflowProvider.js.map +1 -1
  71. package/lib/commonjs/runtime/bannerEngine.js +8 -2
  72. package/lib/commonjs/runtime/bannerEngine.js.map +1 -1
  73. package/lib/commonjs/runtime/bannerFlowSpacer.js +71 -0
  74. package/lib/commonjs/runtime/bannerFlowSpacer.js.map +1 -0
  75. package/lib/commonjs/runtime/flowEngine.js +11 -0
  76. package/lib/commonjs/runtime/flowEngine.js.map +1 -1
  77. package/lib/commonjs/runtime/previewStart.js +39 -0
  78. package/lib/commonjs/runtime/previewStart.js.map +1 -0
  79. package/lib/commonjs/runtime/pushBannerLayoutContext.js +98 -0
  80. package/lib/commonjs/runtime/pushBannerLayoutContext.js.map +1 -0
  81. package/lib/commonjs/screenTracker.js +12 -0
  82. package/lib/commonjs/screenTracker.js.map +1 -1
  83. package/lib/commonjs/surfaces/BannerBar.js +79 -61
  84. package/lib/commonjs/surfaces/BannerBar.js.map +1 -1
  85. package/lib/commonjs/surfaces/BannerSurface.js +26 -0
  86. package/lib/commonjs/surfaces/BannerSurface.js.map +1 -1
  87. package/lib/commonjs/surfaces/TooltipSurface.js +43 -41
  88. package/lib/commonjs/surfaces/TooltipSurface.js.map +1 -1
  89. package/lib/commonjs/surfaces/bannerBarLayout.js +77 -10
  90. package/lib/commonjs/surfaces/bannerBarLayout.js.map +1 -1
  91. package/lib/commonjs/surfaces/bannerWebView/BannerWebViewBar.js +112 -63
  92. package/lib/commonjs/surfaces/bannerWebView/BannerWebViewBar.js.map +1 -1
  93. package/lib/commonjs/surfaces/bannerWebView/buildCustomBannerHtml.js +59 -11
  94. package/lib/commonjs/surfaces/bannerWebView/buildCustomBannerHtml.js.map +1 -1
  95. package/lib/commonjs/surfaces/hostAccessibilityTrap.js +28 -0
  96. package/lib/commonjs/surfaces/hostAccessibilityTrap.js.map +1 -0
  97. package/lib/commonjs/surfaces/resolveBannerTheme.js +6 -3
  98. package/lib/commonjs/surfaces/resolveBannerTheme.js.map +1 -1
  99. package/lib/commonjs/surfaces/tooltip/TooltipBubble.js +3 -2
  100. package/lib/commonjs/surfaces/tooltip/TooltipBubble.js.map +1 -1
  101. package/lib/commonjs/surfaces/tooltip/targetSearchSchedule.js +134 -0
  102. package/lib/commonjs/surfaces/tooltip/targetSearchSchedule.js.map +1 -0
  103. package/lib/commonjs/version.js +1 -1
  104. package/lib/module/anchors/AutoAnchorRegistry.js +145 -35
  105. package/lib/module/anchors/AutoAnchorRegistry.js.map +1 -1
  106. package/lib/module/anchors/animationFrame.js +29 -2
  107. package/lib/module/anchors/animationFrame.js.map +1 -1
  108. package/lib/module/anchors/appActive.js +57 -0
  109. package/lib/module/anchors/appActive.js.map +1 -0
  110. package/lib/module/anchors/elementConditionEvaluator.js +26 -9
  111. package/lib/module/anchors/elementConditionEvaluator.js.map +1 -1
  112. package/lib/module/anchors/elementTapMonitor.js +67 -12
  113. package/lib/module/anchors/elementTapMonitor.js.map +1 -1
  114. package/lib/module/anchors/elementTargetMatch.js +32 -7
  115. package/lib/module/anchors/elementTargetMatch.js.map +1 -1
  116. package/lib/module/anchors/fiber/fiberInternals.js +65 -0
  117. package/lib/module/anchors/fiber/fiberInternals.js.map +1 -1
  118. package/lib/module/anchors/fiber/indexHostFibers.js +4 -3
  119. package/lib/module/anchors/fiber/indexHostFibers.js.map +1 -1
  120. package/lib/module/anchors/fiber/resolveFiberPath.js +30 -15
  121. package/lib/module/anchors/fiber/resolveFiberPath.js.map +1 -1
  122. package/lib/module/anchors/fiberAnchorCache.js +19 -0
  123. package/lib/module/anchors/fiberAnchorCache.js.map +1 -1
  124. package/lib/module/anchors/gestureHandlerHandoff.js +298 -0
  125. package/lib/module/anchors/gestureHandlerHandoff.js.map +1 -0
  126. package/lib/module/anchors/resolveAnchorHost.js +1 -0
  127. package/lib/module/anchors/resolveAnchorHost.js.map +1 -1
  128. package/lib/module/anchors/resolveAutoAnchorHost.js +11 -6
  129. package/lib/module/anchors/resolveAutoAnchorHost.js.map +1 -1
  130. package/lib/module/anchors/resolveElementTargets.js +63 -8
  131. package/lib/module/anchors/resolveElementTargets.js.map +1 -1
  132. package/lib/module/anchors/semanticMatcher.js +43 -21
  133. package/lib/module/anchors/semanticMatcher.js.map +1 -1
  134. package/lib/module/anchors/tapSlop.js +11 -0
  135. package/lib/module/anchors/tapSlop.js.map +1 -0
  136. package/lib/module/anchors/targetPressMonitor.js +53 -8
  137. package/lib/module/anchors/targetPressMonitor.js.map +1 -1
  138. package/lib/module/authoring/fingerprintFromInstance.js +6 -10
  139. package/lib/module/authoring/fingerprintFromInstance.js.map +1 -1
  140. package/lib/module/content/RichContentRenderer.js +3 -3
  141. package/lib/module/content/RichContentRenderer.js.map +1 -1
  142. package/lib/module/content/openSafeUrl.js +3 -1
  143. package/lib/module/content/openSafeUrl.js.map +1 -1
  144. package/lib/module/expo-router/useUserflowExpoRouter.js +7 -1
  145. package/lib/module/expo-router/useUserflowExpoRouter.js.map +1 -1
  146. package/lib/module/index.js +22 -7
  147. package/lib/module/index.js.map +1 -1
  148. package/lib/module/installCheck.js +2 -2
  149. package/lib/module/installCheck.js.map +1 -1
  150. package/lib/module/navigation/navigateUrlUtils.js +94 -0
  151. package/lib/module/navigation/navigateUrlUtils.js.map +1 -0
  152. package/lib/module/navigation/openExternalNavigateUrl.js +11 -0
  153. package/lib/module/navigation/openExternalNavigateUrl.js.map +1 -0
  154. package/lib/module/navigation/openFlowNavigateUrl.js +22 -36
  155. package/lib/module/navigation/openFlowNavigateUrl.js.map +1 -1
  156. package/lib/module/pairing/PairingController.js +3 -1
  157. package/lib/module/pairing/PairingController.js.map +1 -1
  158. package/lib/module/runtime/BannerHost.js +38 -29
  159. package/lib/module/runtime/BannerHost.js.map +1 -1
  160. package/lib/module/runtime/TargetPressBridge.js +56 -8
  161. package/lib/module/runtime/TargetPressBridge.js.map +1 -1
  162. package/lib/module/runtime/UserflowOverlay.js +5 -11
  163. package/lib/module/runtime/UserflowOverlay.js.map +1 -1
  164. package/lib/module/runtime/UserflowProvider.js +66 -40
  165. package/lib/module/runtime/UserflowProvider.js.map +1 -1
  166. package/lib/module/runtime/bannerEngine.js +7 -2
  167. package/lib/module/runtime/bannerEngine.js.map +1 -1
  168. package/lib/module/runtime/bannerFlowSpacer.js +65 -0
  169. package/lib/module/runtime/bannerFlowSpacer.js.map +1 -0
  170. package/lib/module/runtime/flowEngine.js +11 -0
  171. package/lib/module/runtime/flowEngine.js.map +1 -1
  172. package/lib/module/runtime/previewStart.js +35 -0
  173. package/lib/module/runtime/previewStart.js.map +1 -0
  174. package/lib/module/runtime/pushBannerLayoutContext.js +91 -0
  175. package/lib/module/runtime/pushBannerLayoutContext.js.map +1 -0
  176. package/lib/module/screenTracker.js +11 -0
  177. package/lib/module/screenTracker.js.map +1 -1
  178. package/lib/module/surfaces/BannerBar.js +80 -62
  179. package/lib/module/surfaces/BannerBar.js.map +1 -1
  180. package/lib/module/surfaces/BannerSurface.js +26 -0
  181. package/lib/module/surfaces/BannerSurface.js.map +1 -1
  182. package/lib/module/surfaces/TooltipSurface.js +44 -42
  183. package/lib/module/surfaces/TooltipSurface.js.map +1 -1
  184. package/lib/module/surfaces/bannerBarLayout.js +72 -11
  185. package/lib/module/surfaces/bannerBarLayout.js.map +1 -1
  186. package/lib/module/surfaces/bannerWebView/BannerWebViewBar.js +113 -64
  187. package/lib/module/surfaces/bannerWebView/BannerWebViewBar.js.map +1 -1
  188. package/lib/module/surfaces/bannerWebView/buildCustomBannerHtml.js +59 -11
  189. package/lib/module/surfaces/bannerWebView/buildCustomBannerHtml.js.map +1 -1
  190. package/lib/module/surfaces/hostAccessibilityTrap.js +24 -0
  191. package/lib/module/surfaces/hostAccessibilityTrap.js.map +1 -0
  192. package/lib/module/surfaces/resolveBannerTheme.js +6 -3
  193. package/lib/module/surfaces/resolveBannerTheme.js.map +1 -1
  194. package/lib/module/surfaces/tooltip/TooltipBubble.js +3 -2
  195. package/lib/module/surfaces/tooltip/TooltipBubble.js.map +1 -1
  196. package/lib/module/surfaces/tooltip/targetSearchSchedule.js +128 -0
  197. package/lib/module/surfaces/tooltip/targetSearchSchedule.js.map +1 -0
  198. package/lib/module/version.js +1 -1
  199. package/lib/typescript/commonjs/src/anchors/AutoAnchorRegistry.d.ts +36 -2
  200. package/lib/typescript/commonjs/src/anchors/AutoAnchorRegistry.d.ts.map +1 -1
  201. package/lib/typescript/commonjs/src/anchors/animationFrame.d.ts +0 -4
  202. package/lib/typescript/commonjs/src/anchors/animationFrame.d.ts.map +1 -1
  203. package/lib/typescript/commonjs/src/anchors/appActive.d.ts +8 -0
  204. package/lib/typescript/commonjs/src/anchors/appActive.d.ts.map +1 -0
  205. package/lib/typescript/commonjs/src/anchors/elementTapMonitor.d.ts +17 -0
  206. package/lib/typescript/commonjs/src/anchors/elementTapMonitor.d.ts.map +1 -1
  207. package/lib/typescript/commonjs/src/anchors/elementTargetMatch.d.ts +7 -0
  208. package/lib/typescript/commonjs/src/anchors/elementTargetMatch.d.ts.map +1 -1
  209. package/lib/typescript/commonjs/src/anchors/fiber/fiberInternals.d.ts +7 -0
  210. package/lib/typescript/commonjs/src/anchors/fiber/fiberInternals.d.ts.map +1 -1
  211. package/lib/typescript/commonjs/src/anchors/fiber/indexHostFibers.d.ts +3 -2
  212. package/lib/typescript/commonjs/src/anchors/fiber/indexHostFibers.d.ts.map +1 -1
  213. package/lib/typescript/commonjs/src/anchors/fiber/resolveFiberPath.d.ts +3 -0
  214. package/lib/typescript/commonjs/src/anchors/fiber/resolveFiberPath.d.ts.map +1 -1
  215. package/lib/typescript/commonjs/src/anchors/fiberAnchorCache.d.ts +5 -0
  216. package/lib/typescript/commonjs/src/anchors/fiberAnchorCache.d.ts.map +1 -1
  217. package/lib/typescript/commonjs/src/anchors/gestureHandlerHandoff.d.ts +70 -0
  218. package/lib/typescript/commonjs/src/anchors/gestureHandlerHandoff.d.ts.map +1 -0
  219. package/lib/typescript/commonjs/src/anchors/resolveAnchorHost.d.ts +1 -0
  220. package/lib/typescript/commonjs/src/anchors/resolveAnchorHost.d.ts.map +1 -1
  221. package/lib/typescript/commonjs/src/anchors/resolveAutoAnchorHost.d.ts +11 -4
  222. package/lib/typescript/commonjs/src/anchors/resolveAutoAnchorHost.d.ts.map +1 -1
  223. package/lib/typescript/commonjs/src/anchors/resolveElementTargets.d.ts.map +1 -1
  224. package/lib/typescript/commonjs/src/anchors/semanticMatcher.d.ts +2 -0
  225. package/lib/typescript/commonjs/src/anchors/semanticMatcher.d.ts.map +1 -1
  226. package/lib/typescript/commonjs/src/anchors/tapSlop.d.ts +9 -0
  227. package/lib/typescript/commonjs/src/anchors/tapSlop.d.ts.map +1 -0
  228. package/lib/typescript/commonjs/src/anchors/targetPressMonitor.d.ts +13 -8
  229. package/lib/typescript/commonjs/src/anchors/targetPressMonitor.d.ts.map +1 -1
  230. package/lib/typescript/commonjs/src/authoring/fingerprintFromInstance.d.ts.map +1 -1
  231. package/lib/typescript/commonjs/src/content/RichContentRenderer.d.ts.map +1 -1
  232. package/lib/typescript/commonjs/src/content/openSafeUrl.d.ts.map +1 -1
  233. package/lib/typescript/commonjs/src/expo-router/useUserflowExpoRouter.d.ts.map +1 -1
  234. package/lib/typescript/commonjs/src/index.d.ts +6 -5
  235. package/lib/typescript/commonjs/src/index.d.ts.map +1 -1
  236. package/lib/typescript/commonjs/src/installCheck.d.ts +1 -1
  237. package/lib/typescript/commonjs/src/installCheck.d.ts.map +1 -1
  238. package/lib/typescript/commonjs/src/navigation/navigateUrlUtils.d.ts +15 -0
  239. package/lib/typescript/commonjs/src/navigation/navigateUrlUtils.d.ts.map +1 -0
  240. package/lib/typescript/commonjs/src/navigation/openExternalNavigateUrl.d.ts +3 -0
  241. package/lib/typescript/commonjs/src/navigation/openExternalNavigateUrl.d.ts.map +1 -0
  242. package/lib/typescript/commonjs/src/navigation/openFlowNavigateUrl.d.ts +2 -5
  243. package/lib/typescript/commonjs/src/navigation/openFlowNavigateUrl.d.ts.map +1 -1
  244. package/lib/typescript/commonjs/src/pairing/PairingController.d.ts +6 -0
  245. package/lib/typescript/commonjs/src/pairing/PairingController.d.ts.map +1 -1
  246. package/lib/typescript/commonjs/src/runtime/BannerHost.d.ts.map +1 -1
  247. package/lib/typescript/commonjs/src/runtime/TargetPressBridge.d.ts +3 -0
  248. package/lib/typescript/commonjs/src/runtime/TargetPressBridge.d.ts.map +1 -1
  249. package/lib/typescript/commonjs/src/runtime/UserflowOverlay.d.ts.map +1 -1
  250. package/lib/typescript/commonjs/src/runtime/UserflowProvider.d.ts.map +1 -1
  251. package/lib/typescript/commonjs/src/runtime/bannerEngine.d.ts +5 -1
  252. package/lib/typescript/commonjs/src/runtime/bannerEngine.d.ts.map +1 -1
  253. package/lib/typescript/commonjs/src/runtime/bannerFlowSpacer.d.ts +15 -0
  254. package/lib/typescript/commonjs/src/runtime/bannerFlowSpacer.d.ts.map +1 -0
  255. package/lib/typescript/commonjs/src/runtime/flowEngine.d.ts.map +1 -1
  256. package/lib/typescript/commonjs/src/runtime/previewStart.d.ts +13 -0
  257. package/lib/typescript/commonjs/src/runtime/previewStart.d.ts.map +1 -0
  258. package/lib/typescript/commonjs/src/runtime/pushBannerLayoutContext.d.ts +17 -0
  259. package/lib/typescript/commonjs/src/runtime/pushBannerLayoutContext.d.ts.map +1 -0
  260. package/lib/typescript/commonjs/src/screenTracker.d.ts +6 -0
  261. package/lib/typescript/commonjs/src/screenTracker.d.ts.map +1 -1
  262. package/lib/typescript/commonjs/src/surfaces/BannerBar.d.ts +3 -1
  263. package/lib/typescript/commonjs/src/surfaces/BannerBar.d.ts.map +1 -1
  264. package/lib/typescript/commonjs/src/surfaces/BannerSurface.d.ts +5 -1
  265. package/lib/typescript/commonjs/src/surfaces/BannerSurface.d.ts.map +1 -1
  266. package/lib/typescript/commonjs/src/surfaces/TooltipSurface.d.ts +1 -1
  267. package/lib/typescript/commonjs/src/surfaces/TooltipSurface.d.ts.map +1 -1
  268. package/lib/typescript/commonjs/src/surfaces/bannerBarLayout.d.ts +17 -0
  269. package/lib/typescript/commonjs/src/surfaces/bannerBarLayout.d.ts.map +1 -1
  270. package/lib/typescript/commonjs/src/surfaces/bannerWebView/BannerWebViewBar.d.ts +3 -1
  271. package/lib/typescript/commonjs/src/surfaces/bannerWebView/BannerWebViewBar.d.ts.map +1 -1
  272. package/lib/typescript/commonjs/src/surfaces/bannerWebView/buildCustomBannerHtml.d.ts.map +1 -1
  273. package/lib/typescript/commonjs/src/surfaces/hostAccessibilityTrap.d.ts +14 -0
  274. package/lib/typescript/commonjs/src/surfaces/hostAccessibilityTrap.d.ts.map +1 -0
  275. package/lib/typescript/commonjs/src/surfaces/resolveBannerTheme.d.ts +4 -1
  276. package/lib/typescript/commonjs/src/surfaces/resolveBannerTheme.d.ts.map +1 -1
  277. package/lib/typescript/commonjs/src/surfaces/tooltip/TooltipBubble.d.ts +7 -1
  278. package/lib/typescript/commonjs/src/surfaces/tooltip/TooltipBubble.d.ts.map +1 -1
  279. package/lib/typescript/commonjs/src/surfaces/tooltip/targetSearchSchedule.d.ts +60 -0
  280. package/lib/typescript/commonjs/src/surfaces/tooltip/targetSearchSchedule.d.ts.map +1 -0
  281. package/lib/typescript/commonjs/src/version.d.ts +1 -1
  282. package/lib/typescript/module/src/anchors/AutoAnchorRegistry.d.ts +36 -2
  283. package/lib/typescript/module/src/anchors/AutoAnchorRegistry.d.ts.map +1 -1
  284. package/lib/typescript/module/src/anchors/animationFrame.d.ts +0 -4
  285. package/lib/typescript/module/src/anchors/animationFrame.d.ts.map +1 -1
  286. package/lib/typescript/module/src/anchors/appActive.d.ts +8 -0
  287. package/lib/typescript/module/src/anchors/appActive.d.ts.map +1 -0
  288. package/lib/typescript/module/src/anchors/elementTapMonitor.d.ts +17 -0
  289. package/lib/typescript/module/src/anchors/elementTapMonitor.d.ts.map +1 -1
  290. package/lib/typescript/module/src/anchors/elementTargetMatch.d.ts +7 -0
  291. package/lib/typescript/module/src/anchors/elementTargetMatch.d.ts.map +1 -1
  292. package/lib/typescript/module/src/anchors/fiber/fiberInternals.d.ts +7 -0
  293. package/lib/typescript/module/src/anchors/fiber/fiberInternals.d.ts.map +1 -1
  294. package/lib/typescript/module/src/anchors/fiber/indexHostFibers.d.ts +3 -2
  295. package/lib/typescript/module/src/anchors/fiber/indexHostFibers.d.ts.map +1 -1
  296. package/lib/typescript/module/src/anchors/fiber/resolveFiberPath.d.ts +3 -0
  297. package/lib/typescript/module/src/anchors/fiber/resolveFiberPath.d.ts.map +1 -1
  298. package/lib/typescript/module/src/anchors/fiberAnchorCache.d.ts +5 -0
  299. package/lib/typescript/module/src/anchors/fiberAnchorCache.d.ts.map +1 -1
  300. package/lib/typescript/module/src/anchors/gestureHandlerHandoff.d.ts +70 -0
  301. package/lib/typescript/module/src/anchors/gestureHandlerHandoff.d.ts.map +1 -0
  302. package/lib/typescript/module/src/anchors/resolveAnchorHost.d.ts +1 -0
  303. package/lib/typescript/module/src/anchors/resolveAnchorHost.d.ts.map +1 -1
  304. package/lib/typescript/module/src/anchors/resolveAutoAnchorHost.d.ts +11 -4
  305. package/lib/typescript/module/src/anchors/resolveAutoAnchorHost.d.ts.map +1 -1
  306. package/lib/typescript/module/src/anchors/resolveElementTargets.d.ts.map +1 -1
  307. package/lib/typescript/module/src/anchors/semanticMatcher.d.ts +2 -0
  308. package/lib/typescript/module/src/anchors/semanticMatcher.d.ts.map +1 -1
  309. package/lib/typescript/module/src/anchors/tapSlop.d.ts +9 -0
  310. package/lib/typescript/module/src/anchors/tapSlop.d.ts.map +1 -0
  311. package/lib/typescript/module/src/anchors/targetPressMonitor.d.ts +13 -8
  312. package/lib/typescript/module/src/anchors/targetPressMonitor.d.ts.map +1 -1
  313. package/lib/typescript/module/src/authoring/fingerprintFromInstance.d.ts.map +1 -1
  314. package/lib/typescript/module/src/content/RichContentRenderer.d.ts.map +1 -1
  315. package/lib/typescript/module/src/content/openSafeUrl.d.ts.map +1 -1
  316. package/lib/typescript/module/src/expo-router/useUserflowExpoRouter.d.ts.map +1 -1
  317. package/lib/typescript/module/src/index.d.ts +6 -5
  318. package/lib/typescript/module/src/index.d.ts.map +1 -1
  319. package/lib/typescript/module/src/installCheck.d.ts +1 -1
  320. package/lib/typescript/module/src/installCheck.d.ts.map +1 -1
  321. package/lib/typescript/module/src/navigation/navigateUrlUtils.d.ts +15 -0
  322. package/lib/typescript/module/src/navigation/navigateUrlUtils.d.ts.map +1 -0
  323. package/lib/typescript/module/src/navigation/openExternalNavigateUrl.d.ts +3 -0
  324. package/lib/typescript/module/src/navigation/openExternalNavigateUrl.d.ts.map +1 -0
  325. package/lib/typescript/module/src/navigation/openFlowNavigateUrl.d.ts +2 -5
  326. package/lib/typescript/module/src/navigation/openFlowNavigateUrl.d.ts.map +1 -1
  327. package/lib/typescript/module/src/pairing/PairingController.d.ts +6 -0
  328. package/lib/typescript/module/src/pairing/PairingController.d.ts.map +1 -1
  329. package/lib/typescript/module/src/runtime/BannerHost.d.ts.map +1 -1
  330. package/lib/typescript/module/src/runtime/TargetPressBridge.d.ts +3 -0
  331. package/lib/typescript/module/src/runtime/TargetPressBridge.d.ts.map +1 -1
  332. package/lib/typescript/module/src/runtime/UserflowOverlay.d.ts.map +1 -1
  333. package/lib/typescript/module/src/runtime/UserflowProvider.d.ts.map +1 -1
  334. package/lib/typescript/module/src/runtime/bannerEngine.d.ts +5 -1
  335. package/lib/typescript/module/src/runtime/bannerEngine.d.ts.map +1 -1
  336. package/lib/typescript/module/src/runtime/bannerFlowSpacer.d.ts +15 -0
  337. package/lib/typescript/module/src/runtime/bannerFlowSpacer.d.ts.map +1 -0
  338. package/lib/typescript/module/src/runtime/flowEngine.d.ts.map +1 -1
  339. package/lib/typescript/module/src/runtime/previewStart.d.ts +13 -0
  340. package/lib/typescript/module/src/runtime/previewStart.d.ts.map +1 -0
  341. package/lib/typescript/module/src/runtime/pushBannerLayoutContext.d.ts +17 -0
  342. package/lib/typescript/module/src/runtime/pushBannerLayoutContext.d.ts.map +1 -0
  343. package/lib/typescript/module/src/screenTracker.d.ts +6 -0
  344. package/lib/typescript/module/src/screenTracker.d.ts.map +1 -1
  345. package/lib/typescript/module/src/surfaces/BannerBar.d.ts +3 -1
  346. package/lib/typescript/module/src/surfaces/BannerBar.d.ts.map +1 -1
  347. package/lib/typescript/module/src/surfaces/BannerSurface.d.ts +5 -1
  348. package/lib/typescript/module/src/surfaces/BannerSurface.d.ts.map +1 -1
  349. package/lib/typescript/module/src/surfaces/TooltipSurface.d.ts +1 -1
  350. package/lib/typescript/module/src/surfaces/TooltipSurface.d.ts.map +1 -1
  351. package/lib/typescript/module/src/surfaces/bannerBarLayout.d.ts +17 -0
  352. package/lib/typescript/module/src/surfaces/bannerBarLayout.d.ts.map +1 -1
  353. package/lib/typescript/module/src/surfaces/bannerWebView/BannerWebViewBar.d.ts +3 -1
  354. package/lib/typescript/module/src/surfaces/bannerWebView/BannerWebViewBar.d.ts.map +1 -1
  355. package/lib/typescript/module/src/surfaces/bannerWebView/buildCustomBannerHtml.d.ts.map +1 -1
  356. package/lib/typescript/module/src/surfaces/hostAccessibilityTrap.d.ts +14 -0
  357. package/lib/typescript/module/src/surfaces/hostAccessibilityTrap.d.ts.map +1 -0
  358. package/lib/typescript/module/src/surfaces/resolveBannerTheme.d.ts +4 -1
  359. package/lib/typescript/module/src/surfaces/resolveBannerTheme.d.ts.map +1 -1
  360. package/lib/typescript/module/src/surfaces/tooltip/TooltipBubble.d.ts +7 -1
  361. package/lib/typescript/module/src/surfaces/tooltip/TooltipBubble.d.ts.map +1 -1
  362. package/lib/typescript/module/src/surfaces/tooltip/targetSearchSchedule.d.ts +60 -0
  363. package/lib/typescript/module/src/surfaces/tooltip/targetSearchSchedule.d.ts.map +1 -0
  364. package/lib/typescript/module/src/version.d.ts +1 -1
  365. package/package.json +1 -1
  366. package/src/anchors/AutoAnchorRegistry.ts +166 -35
  367. package/src/anchors/animationFrame.ts +31 -1
  368. package/src/anchors/appActive.ts +63 -0
  369. package/src/anchors/elementConditionEvaluator.ts +29 -12
  370. package/src/anchors/elementTapMonitor.ts +68 -10
  371. package/src/anchors/elementTargetMatch.ts +34 -7
  372. package/src/anchors/fiber/fiberInternals.ts +68 -0
  373. package/src/anchors/fiber/indexHostFibers.ts +8 -3
  374. package/src/anchors/fiber/resolveFiberPath.ts +25 -16
  375. package/src/anchors/fiberAnchorCache.ts +19 -0
  376. package/src/anchors/gestureHandlerHandoff.ts +356 -0
  377. package/src/anchors/resolveAnchorHost.ts +2 -0
  378. package/src/anchors/resolveAutoAnchorHost.ts +18 -8
  379. package/src/anchors/resolveElementTargets.ts +64 -7
  380. package/src/anchors/semanticMatcher.ts +48 -27
  381. package/src/anchors/tapSlop.ts +18 -0
  382. package/src/anchors/targetPressMonitor.ts +56 -19
  383. package/src/authoring/fingerprintFromInstance.ts +4 -5
  384. package/src/content/RichContentRenderer.tsx +4 -3
  385. package/src/content/openSafeUrl.ts +3 -1
  386. package/src/expo-router/useUserflowExpoRouter.ts +10 -1
  387. package/src/index.ts +20 -9
  388. package/src/installCheck.ts +4 -4
  389. package/src/navigation/navigateUrlUtils.ts +100 -0
  390. package/src/navigation/openExternalNavigateUrl.ts +9 -0
  391. package/src/navigation/openFlowNavigateUrl.ts +36 -36
  392. package/src/pairing/PairingController.ts +9 -1
  393. package/src/runtime/BannerHost.tsx +41 -23
  394. package/src/runtime/TargetPressBridge.tsx +66 -9
  395. package/src/runtime/UserflowOverlay.tsx +7 -9
  396. package/src/runtime/UserflowProvider.tsx +56 -32
  397. package/src/runtime/bannerEngine.ts +10 -2
  398. package/src/runtime/bannerFlowSpacer.tsx +70 -0
  399. package/src/runtime/flowEngine.ts +11 -0
  400. package/src/runtime/previewStart.ts +49 -0
  401. package/src/runtime/pushBannerLayoutContext.tsx +121 -0
  402. package/src/screenTracker.ts +11 -0
  403. package/src/surfaces/BannerBar.tsx +93 -55
  404. package/src/surfaces/BannerSurface.tsx +59 -3
  405. package/src/surfaces/TooltipSurface.tsx +63 -51
  406. package/src/surfaces/bannerBarLayout.ts +80 -7
  407. package/src/surfaces/bannerWebView/BannerWebViewBar.tsx +149 -57
  408. package/src/surfaces/bannerWebView/buildCustomBannerHtml.ts +63 -11
  409. package/src/surfaces/hostAccessibilityTrap.ts +25 -0
  410. package/src/surfaces/resolveBannerTheme.ts +14 -3
  411. package/src/surfaces/tooltip/TooltipBubble.tsx +8 -1
  412. package/src/surfaces/tooltip/targetSearchSchedule.ts +140 -0
  413. package/src/version.ts +1 -1
  414. package/vendor/core/dist/engine/BannerSessionEngine.d.ts +29 -2
  415. package/vendor/core/dist/engine/BannerSessionEngine.d.ts.map +1 -1
  416. package/vendor/core/dist/engine/BannerSessionEngine.js +87 -6
  417. package/vendor/core/dist/engine/BannerSessionEngine.js.map +1 -1
  418. package/vendor/core/dist/engine/ClientConditionEngine.d.ts.map +1 -1
  419. package/vendor/core/dist/engine/ClientConditionEngine.js +30 -7
  420. package/vendor/core/dist/engine/ClientConditionEngine.js.map +1 -1
  421. package/vendor/core/dist/engine/PairingEngine.d.ts +6 -1
  422. package/vendor/core/dist/engine/PairingEngine.d.ts.map +1 -1
  423. package/vendor/core/dist/engine/PairingEngine.js +23 -3
  424. package/vendor/core/dist/engine/PairingEngine.js.map +1 -1
  425. package/vendor/core/dist/engine/handleActions.d.ts.map +1 -1
  426. package/vendor/core/dist/engine/handleActions.js +67 -2
  427. package/vendor/core/dist/engine/handleActions.js.map +1 -1
  428. package/vendor/core/dist/version.d.ts +1 -1
  429. package/vendor/core/dist/version.js +1 -1
  430. package/vendor/core/package.json +1 -1
  431. package/vendor/protocol/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"resolveBannerTheme.d.ts","sourceRoot":"","sources":["../../../../../src/surfaces/resolveBannerTheme.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAE7D,yGAAyG;AACzG,eAAO,MAAM,+BAA+B,YAAY,CAAC;AACzD,eAAO,MAAM,+BAA+B,YAAY,CAAC;AAOzD,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,CAEzE;AAED,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,CAEzE"}
1
+ {"version":3,"file":"resolveBannerTheme.d.ts","sourceRoot":"","sources":["../../../../../src/surfaces/resolveBannerTheme.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAE7D;;;GAGG;AACH,eAAO,MAAM,+BAA+B,YAAY,CAAC;AACzD,eAAO,MAAM,+BAA+B,YAAY,CAAC;AAOzD,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,CAMzE;AAED,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,CAMzE"}
@@ -15,6 +15,12 @@ export interface TooltipBubbleProps {
15
15
  * target. Defaults to true so isolated chrome tests keep the diamond.
16
16
  */
17
17
  showNotch?: boolean;
18
+ /**
19
+ * iOS: confine VoiceOver to this card. VoiceOver then skips the host app,
20
+ * including the target, so set it only while the host is hidden from
21
+ * accessibility anyway. Defaults to false.
22
+ */
23
+ accessibilityViewIsModal?: boolean;
18
24
  }
19
25
  /**
20
26
  * Tooltip chrome shell: diamond notch + card fill sharing one shadow family.
@@ -34,5 +40,5 @@ export interface TooltipBubbleProps {
34
40
  * iOS gets `shadow*` on the notch (`elevation` is inert there); Android gets
35
41
  * `elevation`, which is the only shadow it honors on a rotated view.
36
42
  */
37
- export declare function TooltipBubble({ chrome, notchPosition, style, onLayout, children, maxHeight, showNotch: showNotchProp, }: TooltipBubbleProps): React.ReactElement;
43
+ export declare function TooltipBubble({ chrome, notchPosition, style, onLayout, children, maxHeight, showNotch: showNotchProp, accessibilityViewIsModal, }: TooltipBubbleProps): React.ReactElement;
38
44
  //# sourceMappingURL=TooltipBubble.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"TooltipBubble.d.ts","sourceRoot":"","sources":["../../../../../../src/surfaces/tooltip/TooltipBubble.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAIL,KAAK,iBAAiB,EACtB,KAAK,SAAS,EACd,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AAItB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAGnD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAE9D,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,YAAY,CAAC;IACrB,aAAa,EAAE,aAAa,CAAC;IAC7B,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,CAAC;IAC9C,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,4FAA4F;IAC5F,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,aAAa,CAAC,EAC5B,MAAM,EACN,aAAa,EACb,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,SAAS,EAAE,aAAoB,GAChC,EAAE,kBAAkB,GAAG,KAAK,CAAC,YAAY,CAgIzC"}
1
+ {"version":3,"file":"TooltipBubble.d.ts","sourceRoot":"","sources":["../../../../../../src/surfaces/tooltip/TooltipBubble.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAIL,KAAK,iBAAiB,EACtB,KAAK,SAAS,EACd,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AAItB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAGnD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAE9D,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,YAAY,CAAC;IACrB,aAAa,EAAE,aAAa,CAAC;IAC7B,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,CAAC;IAC9C,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,4FAA4F;IAC5F,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;;OAIG;IACH,wBAAwB,CAAC,EAAE,OAAO,CAAC;CACpC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,aAAa,CAAC,EAC5B,MAAM,EACN,aAAa,EACb,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,SAAS,EAAE,aAAoB,EAC/B,wBAAgC,GACjC,EAAE,kBAAkB,GAAG,KAAK,CAAC,YAAY,CAgIzC"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * When TooltipSurface looks for its target.
3
+ *
4
+ * - Anchored: a steady poll, so a covered or remounted host is noticed quickly.
5
+ * Each search is a cache hit for the resolved host.
6
+ * - Missing: exponential backoff. A miss walks the tree and scores registered
7
+ * hosts, so a target on another screen must not cost a full search every
8
+ * second for as long as the flow stays open.
9
+ * - Registry churn (list rows mounting while the user scrolls) pulls the next
10
+ * missing search forward, never closer than {@link MISSING_TRIGGER_GAP_MS}
11
+ * to the previous one.
12
+ * - A screen change or a return to the foreground starts the backoff over.
13
+ * - Nothing runs while paused (app not active).
14
+ */
15
+ /** Poll while the target is anchored. */
16
+ export declare const ANCHORED_POLL_MS = 250;
17
+ /** First retry after a miss; doubles per consecutive miss. */
18
+ export declare const MISSING_BACKOFF_BASE_MS = 250;
19
+ /** Ceiling for the missing-target backoff. */
20
+ export declare const MISSING_BACKOFF_MAX_MS = 4000;
21
+ /** Closest a registry change can pull a missing search to the previous one. */
22
+ export declare const MISSING_TRIGGER_GAP_MS = 500;
23
+ export type TargetSearchMode = 'anchored' | 'missing';
24
+ export interface TargetSearchClock {
25
+ now(): number;
26
+ setTimeout(handler: () => void, ms: number): ReturnType<typeof setTimeout>;
27
+ clearTimeout(handle: ReturnType<typeof setTimeout>): void;
28
+ }
29
+ /** Delay before the next search after `misses` consecutive missing searches. */
30
+ export declare function missingBackoffDelay(misses: number): number;
31
+ export declare class TargetSearchSchedule {
32
+ private readonly search;
33
+ private readonly clock;
34
+ private mode;
35
+ /** Searches run since the target was last anchored (or the backoff restarted). */
36
+ private misses;
37
+ private lastRunAt;
38
+ private handle;
39
+ private dueAt;
40
+ private paused;
41
+ private disposed;
42
+ constructor(search: () => void, clock?: TargetSearchClock);
43
+ /** Search now and schedule the next one. No-op while paused. */
44
+ runNow(): void;
45
+ /** The target was found or lost. Starts the matching cadence from now. */
46
+ setMode(mode: TargetSearchMode): void;
47
+ /** Something the target may depend on changed (a registry mount / unmount). */
48
+ trigger(): void;
49
+ /** Restart the backoff and search now (screen change, foreground). */
50
+ rearm(): void;
51
+ /** Stop searching until {@link resume}. */
52
+ pause(): void;
53
+ /** Leave the paused state and search right away. */
54
+ resume(): void;
55
+ dispose(): void;
56
+ private nextDelay;
57
+ private scheduleIn;
58
+ private cancel;
59
+ }
60
+ //# sourceMappingURL=targetSearchSchedule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"targetSearchSchedule.d.ts","sourceRoot":"","sources":["../../../../../../src/surfaces/tooltip/targetSearchSchedule.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,yCAAyC;AACzC,eAAO,MAAM,gBAAgB,MAAM,CAAC;AACpC,8DAA8D;AAC9D,eAAO,MAAM,uBAAuB,MAAM,CAAC;AAC3C,8CAA8C;AAC9C,eAAO,MAAM,sBAAsB,OAAO,CAAC;AAC3C,+EAA+E;AAC/E,eAAO,MAAM,sBAAsB,MAAM,CAAC;AAE1C,MAAM,MAAM,gBAAgB,GAAG,UAAU,GAAG,SAAS,CAAC;AAEtD,MAAM,WAAW,iBAAiB;IAChC,GAAG,IAAI,MAAM,CAAC;IACd,UAAU,CAAC,OAAO,EAAE,MAAM,IAAI,EAAE,EAAE,EAAE,MAAM,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;IAC3E,YAAY,CAAC,MAAM,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,GAAG,IAAI,CAAC;CAC3D;AAQD,gFAAgF;AAChF,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAG1D;AAED,qBAAa,oBAAoB;IAW7B,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,KAAK;IAXxB,OAAO,CAAC,IAAI,CAA+B;IAC3C,kFAAkF;IAClF,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,SAAS,CAA4B;IAC7C,OAAO,CAAC,MAAM,CAA8C;IAC5D,OAAO,CAAC,KAAK,CAA4B;IACzC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,QAAQ,CAAS;gBAGN,MAAM,EAAE,MAAM,IAAI,EAClB,KAAK,GAAE,iBAAgC;IAG1D,gEAAgE;IAChE,MAAM,IAAI,IAAI;IAcd,0EAA0E;IAC1E,OAAO,CAAC,IAAI,EAAE,gBAAgB,GAAG,IAAI;IAQrC,+EAA+E;IAC/E,OAAO,IAAI,IAAI;IAQf,sEAAsE;IACtE,KAAK,IAAI,IAAI;IAMb,2CAA2C;IAC3C,KAAK,IAAI,IAAI;IAMb,oDAAoD;IACpD,MAAM,IAAI,IAAI;IAMd,OAAO,IAAI,IAAI;IAKf,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,UAAU;IAUlB,OAAO,CAAC,MAAM;CAOf"}
@@ -1,3 +1,3 @@
1
1
  /** Generated by scripts/write-version.mjs — do not edit. */
2
- export declare const SDK_VERSION = "0.4.4";
2
+ export declare const SDK_VERSION = "0.5.0";
3
3
  //# sourceMappingURL=version.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@userflow-tech/react-native",
3
- "version": "0.4.4",
3
+ "version": "0.5.0",
4
4
  "description": "Userflow SDK for React Native — onboarding flows, tooltips, and modals.",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "main": "./lib/commonjs/index.js",
@@ -1,7 +1,11 @@
1
1
  import type { SemanticRole, SemanticSegment, SiblingDescriptor } from '@userflow-tech/protocol';
2
2
  import type { MutableRefObject, RefObject } from 'react';
3
3
 
4
- import { getLiveHostProps, type AnyFiber } from './fiber/fiberInternals';
4
+ import {
5
+ createCurrentFiberResolver,
6
+ getLiveHostProps,
7
+ type AnyFiber,
8
+ } from './fiber/fiberInternals';
5
9
  import {
6
10
  createLazyHostFiberIndex,
7
11
  lookupHostFiber,
@@ -134,10 +138,20 @@ function contentSignature(inst: AutoAnchorInstance): string | undefined {
134
138
  }
135
139
 
136
140
  interface LiveContentCache {
141
+ /** The fiber of the pair that was committed when read. */
137
142
  fiber: AnyFiber;
138
- /** Props object identity — React replaces it on every render. */
143
+ /** That fiber's props object. */
139
144
  props: Record<string, unknown> | undefined;
140
- childText: string;
145
+ /** Undefined when the host shows no readable text (the hint stays). */
146
+ childText: string | undefined;
147
+ }
148
+
149
+ /** Twin evidence for one registry group, computed once per settle. */
150
+ interface TwinGroup {
151
+ /** More than one member and none carries a manual id. */
152
+ unlabelled: boolean;
153
+ /** How many members show each content signature. */
154
+ signatures: Map<string, number>;
141
155
  }
142
156
 
143
157
  export class AutoAnchorRegistry {
@@ -148,6 +162,22 @@ export class AutoAnchorRegistry {
148
162
  private readonly liveContent = new Map<string, LiveContentCache>();
149
163
  private readonly listeners = new Set<AutoAnchorListener>();
150
164
  private notifyScheduled = false;
165
+ /** Settled {@link AutoAnchorInstance.ambiguous} verdicts by instance id. */
166
+ private readonly ambiguity = new Map<string, boolean>();
167
+ /**
168
+ * Groups whose verdicts are out of date: `r:` registry key, `t:` template
169
+ * path, `m:` manual id. Mounting a list or reading changed row labels marks
170
+ * a group once; it is settled once, on the next read of a verdict, instead
171
+ * of being recomputed for every member that changed.
172
+ */
173
+ private readonly staleGroups = new Set<string>();
174
+ /**
175
+ * Set instead of {@link staleGroups} once that outgrows the registry: with
176
+ * no flow or element condition reading verdicts, marks from list mounts
177
+ * would otherwise pile up for the whole session.
178
+ */
179
+ private allStale = false;
180
+ private settling = false;
151
181
 
152
182
  registerInstance(input: RegisterInstanceInput): { instanceId: string; dispose: () => void } {
153
183
  const instanceId = mintInstanceId();
@@ -200,6 +230,7 @@ export class AutoAnchorRegistry {
200
230
  childInstanceIds: [],
201
231
  ambiguous: false,
202
232
  };
233
+ this.defineAmbiguity(instance);
203
234
 
204
235
  this.instances.set(instanceId, instance);
205
236
  this.addIndex(this.byRegistryKey, input.registryKey, instanceId);
@@ -213,7 +244,7 @@ export class AutoAnchorRegistry {
213
244
  if (parent) parent.childInstanceIds.push(instanceId);
214
245
  }
215
246
 
216
- this.recomputeAmbiguity(input.registryKey, templatePath, manualId);
247
+ this.markStale(instance);
217
248
  this.notify();
218
249
 
219
250
  return {
@@ -272,7 +303,7 @@ export class AutoAnchorRegistry {
272
303
  else delete inst.manualId;
273
304
  }
274
305
  this.refreshManualIndexes(inst, prevIds);
275
- this.recomputeAmbiguity(inst.registryKey, inst.templatePath, inst.manualId);
306
+ this.markStale(inst, prevIds.manualId, prevIds.userflowId, prevIds.testID);
276
307
  this.notify();
277
308
  }
278
309
 
@@ -339,25 +370,32 @@ export class AutoAnchorRegistry {
339
370
  *
340
371
  * Direct fiber pointers are preferred; the scan-root index is built lazily
341
372
  * and only if some instance cannot reach its fiber that way (Paper release
342
- * builds, mainly), then reused for the rest of the pass.
373
+ * builds, mainly), then reused for the rest of the pass. Finding which fiber
374
+ * of each pair is committed walks to the root; the pass shares one walk per
375
+ * ancestor across every instance.
343
376
  *
344
377
  * Silent — does not notify listeners.
345
378
  */
346
379
  refreshLiveContent(instances?: AutoAnchorInstance[]): void {
347
380
  const list = instances ?? this.allInstances();
348
381
  const getIndex = createLazyHostFiberIndex();
382
+ const resolveCurrent = createCurrentFiberResolver();
349
383
  const seen = new Set<string>();
350
384
  for (const inst of list) {
351
385
  if (seen.has(inst.instanceId)) continue;
352
386
  seen.add(inst.instanceId);
353
- this.refreshOneLiveContent(inst, getIndex);
387
+ this.refreshOneLiveContent(inst, getIndex, resolveCurrent);
354
388
  }
355
389
  }
356
390
 
357
- private refreshOneLiveContent(inst: AutoAnchorInstance, getIndex: () => HostFiberIndex): void {
391
+ private refreshOneLiveContent(
392
+ inst: AutoAnchorInstance,
393
+ getIndex: () => HostFiberIndex,
394
+ resolveCurrent: (fiber: AnyFiber) => AnyFiber,
395
+ ): void {
358
396
  let fiber: AnyFiber | null = null;
359
397
  try {
360
- fiber = lookupHostFiber(getIndex, inst.ref.current);
398
+ fiber = lookupHostFiber(getIndex, inst.ref.current, resolveCurrent);
361
399
  } catch {
362
400
  fiber = null;
363
401
  }
@@ -370,12 +408,17 @@ export class AutoAnchorRegistry {
370
408
  props = undefined;
371
409
  }
372
410
 
411
+ // Same committed fiber and same props object means nothing was committed
412
+ // here since the last read, so the subtree walk would return what we
413
+ // already have. A commit that re-renders this host or anything inside it
414
+ // makes the other fiber of the pair current, even when the host keeps its
415
+ // props object. Both only change at commit, unlike Fabric's
416
+ // `canonical.currentProps`, which is written during render and stays the
417
+ // same object when only a child changed. Matters because resolution polls
418
+ // this for every registered instance.
373
419
  const cached = this.liveContent.get(inst.instanceId);
374
- // Same fiber and same props object means no re-render since the last read,
375
- // so the subtree walk would return what we already have. Matters because
376
- // resolution polls this for every registered instance.
377
420
  if (cached && cached.fiber === fiber && props !== undefined && cached.props === props) {
378
- inst.childText = cached.childText;
421
+ if (cached.childText !== undefined) inst.childText = cached.childText;
379
422
  return;
380
423
  }
381
424
 
@@ -391,17 +434,14 @@ export class AutoAnchorRegistry {
391
434
  live = undefined;
392
435
  }
393
436
 
394
- if (live) {
395
- const changed = inst.childText !== live;
437
+ // A host with no readable text is cached too, so it is not walked again
438
+ // until it re-renders; its build-time hint stays.
439
+ this.liveContent.set(inst.instanceId, { fiber, props, childText: live });
440
+ if (live && inst.childText !== live) {
396
441
  inst.childText = live;
397
- this.liveContent.set(inst.instanceId, { fiber, props, childText: live });
398
442
  // Text is what separates helper-rendered twins, so the group's ambiguity
399
443
  // verdict is only trustworthy once it has been read.
400
- if (changed) this.recomputeAmbiguity(inst.registryKey, inst.templatePath, inst.manualId);
401
- return;
402
- }
403
- if (cached && cached.fiber !== fiber) {
404
- this.liveContent.delete(inst.instanceId);
444
+ this.markStale(inst);
405
445
  }
406
446
  }
407
447
 
@@ -421,7 +461,7 @@ export class AutoAnchorRegistry {
421
461
  inst.manualId = liveTestID;
422
462
  }
423
463
  this.refreshManualIndexes(inst, prev);
424
- this.recomputeAmbiguity(inst.registryKey, inst.templatePath, inst.manualId);
464
+ this.markStale(inst, prev.manualId, prev.userflowId, prev.testID);
425
465
  }
426
466
 
427
467
  subscribe(listener: AutoAnchorListener): () => void {
@@ -462,6 +502,9 @@ export class AutoAnchorRegistry {
462
502
  this.byManualId.clear();
463
503
  this.byTemplatePath.clear();
464
504
  this.liveContent.clear();
505
+ this.ambiguity.clear();
506
+ this.staleGroups.clear();
507
+ this.allStale = false;
465
508
  this.notifyScheduled = false;
466
509
  nextInstanceSeq = 1;
467
510
  }
@@ -483,13 +526,14 @@ export class AutoAnchorRegistry {
483
526
 
484
527
  this.instances.delete(instanceId);
485
528
  this.liveContent.delete(instanceId);
529
+ this.ambiguity.delete(instanceId);
486
530
  this.removeIndex(this.byRegistryKey, inst.registryKey, instanceId);
487
531
  this.removeIndex(this.byTemplatePath, inst.templatePath, instanceId);
488
532
  if (inst.manualId) this.removeIndex(this.byManualId, inst.manualId, instanceId);
489
533
  if (inst.userflowId) this.removeIndex(this.byManualId, inst.userflowId, instanceId);
490
534
  if (inst.testID) this.removeIndex(this.byManualId, inst.testID, instanceId);
491
535
 
492
- this.recomputeAmbiguity(inst.registryKey, inst.templatePath, inst.manualId);
536
+ this.markStale(inst);
493
537
  this.notify();
494
538
  }
495
539
 
@@ -533,29 +577,116 @@ export class AutoAnchorRegistry {
533
577
  return false;
534
578
  }
535
579
 
580
+ /**
581
+ * Back {@link AutoAnchorInstance.ambiguous} with a verdict that is settled on
582
+ * read, so callers holding an instance always see the current value.
583
+ */
584
+ private defineAmbiguity(inst: AutoAnchorInstance): void {
585
+ const id = inst.instanceId;
586
+ Object.defineProperty(inst, 'ambiguous', {
587
+ configurable: true,
588
+ enumerable: true,
589
+ get: () => {
590
+ this.settleAmbiguity();
591
+ return this.ambiguity.get(id) ?? false;
592
+ },
593
+ set: (value: boolean) => {
594
+ this.ambiguity.set(id, value);
595
+ },
596
+ });
597
+ }
598
+
599
+ /** Every group `inst` belongs to, plus ids it was indexed under before a change. */
600
+ private markStale(inst: AutoAnchorInstance, ...previousIds: Array<string | undefined>): void {
601
+ if (this.allStale) return;
602
+ this.staleGroups.add(`r:${inst.registryKey}`);
603
+ this.staleGroups.add(`t:${inst.templatePath}`);
604
+ for (const id of [inst.manualId, inst.userflowId, inst.testID, ...previousIds]) {
605
+ if (id) this.staleGroups.add(`m:${id}`);
606
+ }
607
+ // Settling every instance is linear in the registry, so past this size
608
+ // tracking groups no longer saves work.
609
+ if (this.staleGroups.size > this.instances.size) {
610
+ this.allStale = true;
611
+ this.staleGroups.clear();
612
+ }
613
+ }
614
+
615
+ private groupIds(groupKey: string): Set<string> | undefined {
616
+ const value = groupKey.slice(2);
617
+ if (groupKey.startsWith('r:')) return this.byRegistryKey.get(value);
618
+ if (groupKey.startsWith('t:')) return this.byTemplatePath.get(value);
619
+ return this.byManualId.get(value);
620
+ }
621
+
536
622
  /**
537
623
  * Instances sharing a template path are only twins while they look alike.
538
624
  * Four rows from one `field()` helper are indistinguishable at register time
539
625
  * and separate once their labels are read, so ambiguity is decided on
540
626
  * content, not on the shared path alone. An instance stays ambiguous when it
541
627
  * carries no content of its own, or when a peer carries the same content.
628
+ * An instance with a manual id is ambiguous only when another shares the id.
629
+ *
630
+ * Each stale group is settled once, in time linear in its size: recomputing
631
+ * a whole group for every member that changed made a list whose labels all
632
+ * changed cost the cube of its length.
542
633
  */
543
- private recomputeAmbiguity(registryKey: string, templatePath: string, manualId?: string): void {
544
- const mark = (list: AutoAnchorInstance[]) => {
545
- for (const i of list) {
546
- i.ambiguous =
547
- this.isTwinWithin(i, list) ||
548
- (i.manualId ? this.getInstancesByManualId(i.manualId).length > 1 : false);
634
+ private settleAmbiguity(): void {
635
+ if ((this.staleGroups.size === 0 && !this.allStale) || this.settling) return;
636
+ this.settling = true;
637
+ try {
638
+ const affected = new Set<string>(this.allStale ? this.instances.keys() : []);
639
+ for (const groupKey of this.staleGroups) {
640
+ const ids = this.groupIds(groupKey);
641
+ if (ids) for (const id of ids) affected.add(id);
549
642
  }
550
- };
551
- mark(this.getInstancesByRegistryKey(registryKey));
552
- mark(this.getInstancesByTemplatePath(templatePath));
553
- if (manualId) {
554
- const list = this.getInstancesByManualId(manualId);
555
- for (const i of list) i.ambiguous = list.length > 1;
643
+ this.staleGroups.clear();
644
+ this.allStale = false;
645
+
646
+ const twinGroups = new Map<string, TwinGroup>();
647
+ for (const id of affected) {
648
+ const inst = this.instances.get(id);
649
+ if (!inst) continue;
650
+ this.ambiguity.set(id, this.computeAmbiguous(inst, twinGroups));
651
+ }
652
+ } finally {
653
+ this.settling = false;
556
654
  }
557
655
  }
558
656
 
657
+ private computeAmbiguous(inst: AutoAnchorInstance, twinGroups: Map<string, TwinGroup>): boolean {
658
+ if (inst.manualId) return (this.byManualId.get(inst.manualId)?.size ?? 0) > 1;
659
+ return (
660
+ this.isTwinInGroup(inst, `r:${inst.registryKey}`, twinGroups) ||
661
+ this.isTwinInGroup(inst, `t:${inst.templatePath}`, twinGroups)
662
+ );
663
+ }
664
+
665
+ /** {@link isTwinWithin} against a whole registry group, with the group's evidence memoized. */
666
+ private isTwinInGroup(
667
+ inst: AutoAnchorInstance,
668
+ groupKey: string,
669
+ twinGroups: Map<string, TwinGroup>,
670
+ ): boolean {
671
+ let group = twinGroups.get(groupKey);
672
+ if (!group) {
673
+ const members = this.idsToInstances(this.groupIds(groupKey));
674
+ const signatures = new Map<string, number>();
675
+ for (const member of members) {
676
+ const sig = contentSignature(member);
677
+ if (sig) signatures.set(sig, (signatures.get(sig) ?? 0) + 1);
678
+ }
679
+ group = {
680
+ unlabelled: members.length > 1 && members.every((member) => !member.manualId),
681
+ signatures,
682
+ };
683
+ twinGroups.set(groupKey, group);
684
+ }
685
+ if (!group.unlabelled) return false;
686
+ const sig = contentSignature(inst);
687
+ return !sig || (group.signatures.get(sig) ?? 0) > 1;
688
+ }
689
+
559
690
  private addIndex(map: Map<string, Set<string>>, key: string, instanceId: string): void {
560
691
  let set = map.get(key);
561
692
  if (!set) {
@@ -1,13 +1,21 @@
1
1
  /**
2
2
  * Shared requestAnimationFrame hub so multiple surfaces never stack loops.
3
3
  * Mirrors web userflowjs `util/animation-frame.tsx`.
4
+ *
5
+ * Paused while the app is not active. In bridgeless React Native,
6
+ * `requestAnimationFrame` is a 0 ms timer, and once the app is backgrounded
7
+ * iOS fires timers from an NSTimer instead of the display link, so a loop that
8
+ * kept going would spin as fast as the JS thread allows.
4
9
  */
10
+ import { isAppActive, subscribeAppActive } from './appActive';
5
11
 
6
12
  type Callback = () => void;
7
13
 
8
14
  const callbacks: Callback[] = [];
9
15
  let rafHandle: number | ReturnType<typeof setTimeout> | null = null;
10
16
  let active = false;
17
+ let appActive = true;
18
+ let unsubscribeAppActive: (() => void) | null = null;
11
19
 
12
20
  /**
13
21
  * `callback` runs on every animation frame. Starts the shared loop when the
@@ -18,6 +26,7 @@ export function addAnimationFrameCallback(callback: Callback): void {
18
26
  callbacks.push(callback);
19
27
  if (callbacks.length === 1) {
20
28
  active = true;
29
+ watchAppState();
21
30
  requestNext();
22
31
  }
23
32
  }
@@ -33,6 +42,7 @@ export function removeAnimationFrameCallback(callback: Callback): void {
33
42
  if (callbacks.length === 0) {
34
43
  active = false;
35
44
  cancelPending();
45
+ unwatchAppState();
36
46
  }
37
47
  }
38
48
 
@@ -41,6 +51,7 @@ export function resetAnimationFrameForTests(): void {
41
51
  callbacks.length = 0;
42
52
  active = false;
43
53
  cancelPending();
54
+ unwatchAppState();
44
55
  }
45
56
 
46
57
  /** Test helper — number of active subscribers. */
@@ -62,8 +73,27 @@ function onAnimationFrame(): void {
62
73
  requestNext();
63
74
  }
64
75
 
76
+ function watchAppState(): void {
77
+ if (unsubscribeAppActive) return;
78
+ appActive = isAppActive();
79
+ unsubscribeAppActive = subscribeAppActive((next) => {
80
+ appActive = next;
81
+ if (!next) {
82
+ cancelPending();
83
+ } else if (rafHandle == null) {
84
+ requestNext();
85
+ }
86
+ });
87
+ }
88
+
89
+ function unwatchAppState(): void {
90
+ unsubscribeAppActive?.();
91
+ unsubscribeAppActive = null;
92
+ appActive = true;
93
+ }
94
+
65
95
  function requestNext(): void {
66
- if (!active) return;
96
+ if (!active || !appActive) return;
67
97
  const raf =
68
98
  typeof globalThis.requestAnimationFrame === 'function'
69
99
  ? globalThis.requestAnimationFrame.bind(globalThis)
@@ -0,0 +1,63 @@
1
+ import { AppState } from 'react-native';
2
+
3
+ /**
4
+ * Foreground signal for the anchoring loops (animation-frame tracking and the
5
+ * tooltip target search).
6
+ *
7
+ * Anything other than `background` / `inactive` counts as active, including
8
+ * `unknown` before the first native report. Hosts or test doubles without
9
+ * `AppState` always read as active and never notify.
10
+ */
11
+
12
+ type AppStateLike = {
13
+ currentState?: unknown;
14
+ addEventListener?: (
15
+ type: 'change',
16
+ handler: (state: unknown) => void,
17
+ ) => { remove: () => void } | undefined;
18
+ };
19
+
20
+ function appState(): AppStateLike | null {
21
+ const candidate = AppState as AppStateLike | undefined;
22
+ return candidate && typeof candidate === 'object' ? candidate : null;
23
+ }
24
+
25
+ function isActiveState(state: unknown): boolean {
26
+ return state !== 'background' && state !== 'inactive';
27
+ }
28
+
29
+ /** Whether the app is in the foreground right now. */
30
+ export function isAppActive(): boolean {
31
+ try {
32
+ return isActiveState(appState()?.currentState);
33
+ } catch {
34
+ return true;
35
+ }
36
+ }
37
+
38
+ /**
39
+ * `listener(active)` runs when the app moves between foreground and anything
40
+ * else. Repeated reports of the same side are dropped. Returns an unsubscribe.
41
+ */
42
+ export function subscribeAppActive(listener: (active: boolean) => void): () => void {
43
+ const state = appState();
44
+ if (!state || typeof state.addEventListener !== 'function') return () => {};
45
+ let active = isAppActive();
46
+ try {
47
+ const subscription = state.addEventListener('change', (next) => {
48
+ const nextActive = isActiveState(next);
49
+ if (nextActive === active) return;
50
+ active = nextActive;
51
+ listener(nextActive);
52
+ });
53
+ return () => {
54
+ try {
55
+ subscription?.remove();
56
+ } catch {
57
+ // Teardown is best-effort.
58
+ }
59
+ };
60
+ } catch {
61
+ return () => {};
62
+ }
63
+ }
@@ -7,7 +7,7 @@ import { decodeMobileAutoData, type FlowConditionFragment } from '@userflow-tech
7
7
 
8
8
  import { anchorChangeTicker } from './anchorChangeTicker';
9
9
  import { elementTapMonitor } from './elementTapMonitor';
10
- import { fiberIsUnder, tapPathDisabled } from './elementTargetMatch';
10
+ import { fiberBearingAnchorId, fiberIsUnder, tapPathDisabled } from './elementTargetMatch';
11
11
  import {
12
12
  resolveElementTargets,
13
13
  tapMayHitSelector,
@@ -188,22 +188,39 @@ function trackClick(
188
188
  const subscription = {
189
189
  unsubscribe: (): void => {},
190
190
  };
191
+ const latch = (): void => {
192
+ latched = true;
193
+ report(valueWhenOccurred, { immediate: true });
194
+ subscription.unsubscribe();
195
+ stopWatchingResolution();
196
+ };
197
+
191
198
  subscription.unsubscribe = elementTapMonitor.subscribe((tap) => {
192
199
  if (latched) return;
193
200
  if (!tapMayHitSelector(condition.selector, tap)) return;
194
- const resolution = resolveElementTargets(condition.selector);
195
- if (resolution.status !== 'found') return;
196
201
 
197
- const matched = resolution.targets.find(
198
- (target) => target.fiber != null && fiberIsUnder(tap.targetFiber, target.fiber),
199
- );
200
- if (!matched?.fiber) return;
201
- if (tapPathDisabled(tap.targetFiber, matched.fiber)) return;
202
+ const resolution = resolveElementTargets(condition.selector);
203
+ if (resolution.status === 'found') {
204
+ const matched = resolution.targets.find(
205
+ (target) => target.fiber != null && fiberIsUnder(tap.targetFiber, target.fiber),
206
+ );
207
+ if (!matched?.fiber) return;
208
+ if (tapPathDisabled(tap.targetFiber, matched.fiber)) return;
209
+ latch();
210
+ return;
211
+ }
202
212
 
203
- latched = true;
204
- report(valueWhenOccurred, { immediate: true });
205
- subscription.unsubscribe();
206
- stopWatchingResolution();
213
+ // The press may already have navigated away, so the live scan is absent.
214
+ // The fiber captured at touch start still carries the manual id. This is
215
+ // only the fallback: a target that is still on screen keeps the registry
216
+ // and prop-tier precedence of the live scan.
217
+ if (resolution.status !== 'absent') return;
218
+ if ((condition.selector?.type as string | null) === 'AUTO') return;
219
+ const anchorId = resolveManualAnchorId(condition.selector?.css);
220
+ const capturedHost = anchorId ? fiberBearingAnchorId(tap.targetFiber, anchorId) : null;
221
+ if (!capturedHost) return;
222
+ if (tapPathDisabled(tap.targetFiber, capturedHost)) return;
223
+ latch();
207
224
  });
208
225
 
209
226
  return () => {