@userflow-tech/react-native 0.4.5 → 0.6.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 (502) hide show
  1. package/README.md +31 -2
  2. package/docs/anchoring.md +6 -1
  3. package/docs/custom-fonts.md +36 -0
  4. package/docs/troubleshooting.md +33 -6
  5. package/lib/commonjs/anchors/AutoAnchorRegistry.js +144 -34
  6. package/lib/commonjs/anchors/AutoAnchorRegistry.js.map +1 -1
  7. package/lib/commonjs/anchors/animationFrame.js +29 -1
  8. package/lib/commonjs/anchors/animationFrame.js.map +1 -1
  9. package/lib/commonjs/anchors/appActive.js +61 -0
  10. package/lib/commonjs/anchors/appActive.js.map +1 -0
  11. package/lib/commonjs/anchors/elementConditionEvaluator.js +25 -8
  12. package/lib/commonjs/anchors/elementConditionEvaluator.js.map +1 -1
  13. package/lib/commonjs/anchors/elementTapMonitor.js +67 -12
  14. package/lib/commonjs/anchors/elementTapMonitor.js.map +1 -1
  15. package/lib/commonjs/anchors/elementTargetMatch.js +33 -7
  16. package/lib/commonjs/anchors/elementTargetMatch.js.map +1 -1
  17. package/lib/commonjs/anchors/fiber/FiberScanRootStore.js +8 -0
  18. package/lib/commonjs/anchors/fiber/FiberScanRootStore.js.map +1 -1
  19. package/lib/commonjs/anchors/fiber/detectAppFontFamily.js +341 -0
  20. package/lib/commonjs/anchors/fiber/detectAppFontFamily.js.map +1 -0
  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/fiber/visibleScreens.js +6 -0
  28. package/lib/commonjs/anchors/fiber/visibleScreens.js.map +1 -1
  29. package/lib/commonjs/anchors/fiberAnchorCache.js +20 -0
  30. package/lib/commonjs/anchors/fiberAnchorCache.js.map +1 -1
  31. package/lib/commonjs/anchors/gestureHandlerHandoff.js +304 -0
  32. package/lib/commonjs/anchors/gestureHandlerHandoff.js.map +1 -0
  33. package/lib/commonjs/anchors/resolveAnchorHost.js +6 -0
  34. package/lib/commonjs/anchors/resolveAnchorHost.js.map +1 -1
  35. package/lib/commonjs/anchors/resolveAutoAnchorHost.js +11 -6
  36. package/lib/commonjs/anchors/resolveAutoAnchorHost.js.map +1 -1
  37. package/lib/commonjs/anchors/resolveElementTargets.js +63 -8
  38. package/lib/commonjs/anchors/resolveElementTargets.js.map +1 -1
  39. package/lib/commonjs/anchors/semanticMatcher.js +43 -21
  40. package/lib/commonjs/anchors/semanticMatcher.js.map +1 -1
  41. package/lib/commonjs/anchors/tapSlop.js +16 -0
  42. package/lib/commonjs/anchors/tapSlop.js.map +1 -0
  43. package/lib/commonjs/anchors/targetPressMonitor.js +66 -12
  44. package/lib/commonjs/anchors/targetPressMonitor.js.map +1 -1
  45. package/lib/commonjs/authoring/fingerprintFromInstance.js +5 -9
  46. package/lib/commonjs/authoring/fingerprintFromInstance.js.map +1 -1
  47. package/lib/commonjs/content/BannerStepButton.js +2 -1
  48. package/lib/commonjs/content/BannerStepButton.js.map +1 -1
  49. package/lib/commonjs/content/RichContentRenderer.js +20 -14
  50. package/lib/commonjs/content/RichContentRenderer.js.map +1 -1
  51. package/lib/commonjs/content/StepButton.js +2 -1
  52. package/lib/commonjs/content/StepButton.js.map +1 -1
  53. package/lib/commonjs/content/openSafeUrl.js +3 -1
  54. package/lib/commonjs/content/openSafeUrl.js.map +1 -1
  55. package/lib/commonjs/content/resolveContentFontFamily.js +96 -0
  56. package/lib/commonjs/content/resolveContentFontFamily.js.map +1 -0
  57. package/lib/commonjs/expo-router/useUserflowExpoRouter.js +6 -0
  58. package/lib/commonjs/expo-router/useUserflowExpoRouter.js.map +1 -1
  59. package/lib/commonjs/index.js +21 -5
  60. package/lib/commonjs/index.js.map +1 -1
  61. package/lib/commonjs/navigation/navigateUrlUtils.js +105 -0
  62. package/lib/commonjs/navigation/navigateUrlUtils.js.map +1 -0
  63. package/lib/commonjs/navigation/openExternalNavigateUrl.js +14 -0
  64. package/lib/commonjs/navigation/openExternalNavigateUrl.js.map +1 -0
  65. package/lib/commonjs/navigation/openFlowNavigateUrl.js +47 -41
  66. package/lib/commonjs/navigation/openFlowNavigateUrl.js.map +1 -1
  67. package/lib/commonjs/pairing/PairingController.js +3 -1
  68. package/lib/commonjs/pairing/PairingController.js.map +1 -1
  69. package/lib/commonjs/runtime/BannerHost.js +38 -29
  70. package/lib/commonjs/runtime/BannerHost.js.map +1 -1
  71. package/lib/commonjs/runtime/TargetPressBridge.js +55 -7
  72. package/lib/commonjs/runtime/TargetPressBridge.js.map +1 -1
  73. package/lib/commonjs/runtime/UserflowOverlay.js +5 -11
  74. package/lib/commonjs/runtime/UserflowOverlay.js.map +1 -1
  75. package/lib/commonjs/runtime/UserflowProvider.js +66 -40
  76. package/lib/commonjs/runtime/UserflowProvider.js.map +1 -1
  77. package/lib/commonjs/runtime/bannerEngine.js +8 -2
  78. package/lib/commonjs/runtime/bannerEngine.js.map +1 -1
  79. package/lib/commonjs/runtime/bannerFlowSpacer.js +71 -0
  80. package/lib/commonjs/runtime/bannerFlowSpacer.js.map +1 -0
  81. package/lib/commonjs/runtime/flowEngine.js +11 -0
  82. package/lib/commonjs/runtime/flowEngine.js.map +1 -1
  83. package/lib/commonjs/runtime/previewStart.js +39 -0
  84. package/lib/commonjs/runtime/previewStart.js.map +1 -0
  85. package/lib/commonjs/runtime/pushBannerLayoutContext.js +101 -0
  86. package/lib/commonjs/runtime/pushBannerLayoutContext.js.map +1 -0
  87. package/lib/commonjs/screenTracker.js +12 -0
  88. package/lib/commonjs/screenTracker.js.map +1 -1
  89. package/lib/commonjs/surfaces/BannerBar.js +79 -61
  90. package/lib/commonjs/surfaces/BannerBar.js.map +1 -1
  91. package/lib/commonjs/surfaces/BannerSurface.js +28 -6
  92. package/lib/commonjs/surfaces/BannerSurface.js.map +1 -1
  93. package/lib/commonjs/surfaces/ProgressBar.js +2 -1
  94. package/lib/commonjs/surfaces/ProgressBar.js.map +1 -1
  95. package/lib/commonjs/surfaces/TooltipSurface.js +48 -41
  96. package/lib/commonjs/surfaces/TooltipSurface.js.map +1 -1
  97. package/lib/commonjs/surfaces/bannerBarLayout.js +77 -10
  98. package/lib/commonjs/surfaces/bannerBarLayout.js.map +1 -1
  99. package/lib/commonjs/surfaces/bannerWebView/BannerWebViewBar.js +114 -63
  100. package/lib/commonjs/surfaces/bannerWebView/BannerWebViewBar.js.map +1 -1
  101. package/lib/commonjs/surfaces/bannerWebView/bannerNeedsWebView.js +3 -33
  102. package/lib/commonjs/surfaces/bannerWebView/bannerNeedsWebView.js.map +1 -1
  103. package/lib/commonjs/surfaces/bannerWebView/bannerThemeStyles.js +2 -1
  104. package/lib/commonjs/surfaces/bannerWebView/bannerThemeStyles.js.map +1 -1
  105. package/lib/commonjs/surfaces/bannerWebView/bannerWebViewHeight.js +33 -0
  106. package/lib/commonjs/surfaces/bannerWebView/bannerWebViewHeight.js.map +1 -0
  107. package/lib/commonjs/surfaces/bannerWebView/buildCustomBannerHtml.js +104 -23
  108. package/lib/commonjs/surfaces/bannerWebView/buildCustomBannerHtml.js.map +1 -1
  109. package/lib/commonjs/surfaces/hostAccessibilityTrap.js +28 -0
  110. package/lib/commonjs/surfaces/hostAccessibilityTrap.js.map +1 -0
  111. package/lib/commonjs/surfaces/resolveBannerTheme.js +6 -3
  112. package/lib/commonjs/surfaces/resolveBannerTheme.js.map +1 -1
  113. package/lib/commonjs/surfaces/tooltip/TooltipBubble.js +3 -2
  114. package/lib/commonjs/surfaces/tooltip/TooltipBubble.js.map +1 -1
  115. package/lib/commonjs/surfaces/tooltip/targetSearchSchedule.js +134 -0
  116. package/lib/commonjs/surfaces/tooltip/targetSearchSchedule.js.map +1 -0
  117. package/lib/commonjs/version.js +1 -1
  118. package/lib/module/anchors/AutoAnchorRegistry.js +145 -35
  119. package/lib/module/anchors/AutoAnchorRegistry.js.map +1 -1
  120. package/lib/module/anchors/animationFrame.js +29 -2
  121. package/lib/module/anchors/animationFrame.js.map +1 -1
  122. package/lib/module/anchors/appActive.js +57 -0
  123. package/lib/module/anchors/appActive.js.map +1 -0
  124. package/lib/module/anchors/elementConditionEvaluator.js +26 -9
  125. package/lib/module/anchors/elementConditionEvaluator.js.map +1 -1
  126. package/lib/module/anchors/elementTapMonitor.js +67 -12
  127. package/lib/module/anchors/elementTapMonitor.js.map +1 -1
  128. package/lib/module/anchors/elementTargetMatch.js +32 -7
  129. package/lib/module/anchors/elementTargetMatch.js.map +1 -1
  130. package/lib/module/anchors/fiber/FiberScanRootStore.js +8 -0
  131. package/lib/module/anchors/fiber/FiberScanRootStore.js.map +1 -1
  132. package/lib/module/anchors/fiber/detectAppFontFamily.js +330 -0
  133. package/lib/module/anchors/fiber/detectAppFontFamily.js.map +1 -0
  134. package/lib/module/anchors/fiber/fiberInternals.js +65 -0
  135. package/lib/module/anchors/fiber/fiberInternals.js.map +1 -1
  136. package/lib/module/anchors/fiber/indexHostFibers.js +4 -3
  137. package/lib/module/anchors/fiber/indexHostFibers.js.map +1 -1
  138. package/lib/module/anchors/fiber/resolveFiberPath.js +30 -15
  139. package/lib/module/anchors/fiber/resolveFiberPath.js.map +1 -1
  140. package/lib/module/anchors/fiber/visibleScreens.js +5 -0
  141. package/lib/module/anchors/fiber/visibleScreens.js.map +1 -1
  142. package/lib/module/anchors/fiberAnchorCache.js +19 -0
  143. package/lib/module/anchors/fiberAnchorCache.js.map +1 -1
  144. package/lib/module/anchors/gestureHandlerHandoff.js +298 -0
  145. package/lib/module/anchors/gestureHandlerHandoff.js.map +1 -0
  146. package/lib/module/anchors/resolveAnchorHost.js +1 -0
  147. package/lib/module/anchors/resolveAnchorHost.js.map +1 -1
  148. package/lib/module/anchors/resolveAutoAnchorHost.js +11 -6
  149. package/lib/module/anchors/resolveAutoAnchorHost.js.map +1 -1
  150. package/lib/module/anchors/resolveElementTargets.js +63 -8
  151. package/lib/module/anchors/resolveElementTargets.js.map +1 -1
  152. package/lib/module/anchors/semanticMatcher.js +43 -21
  153. package/lib/module/anchors/semanticMatcher.js.map +1 -1
  154. package/lib/module/anchors/tapSlop.js +11 -0
  155. package/lib/module/anchors/tapSlop.js.map +1 -0
  156. package/lib/module/anchors/targetPressMonitor.js +53 -8
  157. package/lib/module/anchors/targetPressMonitor.js.map +1 -1
  158. package/lib/module/authoring/fingerprintFromInstance.js +6 -10
  159. package/lib/module/authoring/fingerprintFromInstance.js.map +1 -1
  160. package/lib/module/content/BannerStepButton.js +2 -1
  161. package/lib/module/content/BannerStepButton.js.map +1 -1
  162. package/lib/module/content/RichContentRenderer.js +20 -14
  163. package/lib/module/content/RichContentRenderer.js.map +1 -1
  164. package/lib/module/content/StepButton.js +2 -1
  165. package/lib/module/content/StepButton.js.map +1 -1
  166. package/lib/module/content/openSafeUrl.js +3 -1
  167. package/lib/module/content/openSafeUrl.js.map +1 -1
  168. package/lib/module/content/resolveContentFontFamily.js +89 -0
  169. package/lib/module/content/resolveContentFontFamily.js.map +1 -0
  170. package/lib/module/expo-router/useUserflowExpoRouter.js +7 -1
  171. package/lib/module/expo-router/useUserflowExpoRouter.js.map +1 -1
  172. package/lib/module/index.js +24 -7
  173. package/lib/module/index.js.map +1 -1
  174. package/lib/module/navigation/navigateUrlUtils.js +94 -0
  175. package/lib/module/navigation/navigateUrlUtils.js.map +1 -0
  176. package/lib/module/navigation/openExternalNavigateUrl.js +11 -0
  177. package/lib/module/navigation/openExternalNavigateUrl.js.map +1 -0
  178. package/lib/module/navigation/openFlowNavigateUrl.js +22 -36
  179. package/lib/module/navigation/openFlowNavigateUrl.js.map +1 -1
  180. package/lib/module/pairing/PairingController.js +3 -1
  181. package/lib/module/pairing/PairingController.js.map +1 -1
  182. package/lib/module/runtime/BannerHost.js +38 -29
  183. package/lib/module/runtime/BannerHost.js.map +1 -1
  184. package/lib/module/runtime/TargetPressBridge.js +56 -8
  185. package/lib/module/runtime/TargetPressBridge.js.map +1 -1
  186. package/lib/module/runtime/UserflowOverlay.js +5 -11
  187. package/lib/module/runtime/UserflowOverlay.js.map +1 -1
  188. package/lib/module/runtime/UserflowProvider.js +66 -40
  189. package/lib/module/runtime/UserflowProvider.js.map +1 -1
  190. package/lib/module/runtime/bannerEngine.js +7 -2
  191. package/lib/module/runtime/bannerEngine.js.map +1 -1
  192. package/lib/module/runtime/bannerFlowSpacer.js +65 -0
  193. package/lib/module/runtime/bannerFlowSpacer.js.map +1 -0
  194. package/lib/module/runtime/flowEngine.js +11 -0
  195. package/lib/module/runtime/flowEngine.js.map +1 -1
  196. package/lib/module/runtime/previewStart.js +35 -0
  197. package/lib/module/runtime/previewStart.js.map +1 -0
  198. package/lib/module/runtime/pushBannerLayoutContext.js +94 -0
  199. package/lib/module/runtime/pushBannerLayoutContext.js.map +1 -0
  200. package/lib/module/screenTracker.js +11 -0
  201. package/lib/module/screenTracker.js.map +1 -1
  202. package/lib/module/surfaces/BannerBar.js +80 -62
  203. package/lib/module/surfaces/BannerBar.js.map +1 -1
  204. package/lib/module/surfaces/BannerSurface.js +28 -6
  205. package/lib/module/surfaces/BannerSurface.js.map +1 -1
  206. package/lib/module/surfaces/ProgressBar.js +2 -1
  207. package/lib/module/surfaces/ProgressBar.js.map +1 -1
  208. package/lib/module/surfaces/TooltipSurface.js +49 -42
  209. package/lib/module/surfaces/TooltipSurface.js.map +1 -1
  210. package/lib/module/surfaces/bannerBarLayout.js +72 -11
  211. package/lib/module/surfaces/bannerBarLayout.js.map +1 -1
  212. package/lib/module/surfaces/bannerWebView/BannerWebViewBar.js +115 -64
  213. package/lib/module/surfaces/bannerWebView/BannerWebViewBar.js.map +1 -1
  214. package/lib/module/surfaces/bannerWebView/bannerNeedsWebView.js +3 -31
  215. package/lib/module/surfaces/bannerWebView/bannerNeedsWebView.js.map +1 -1
  216. package/lib/module/surfaces/bannerWebView/bannerThemeStyles.js +2 -1
  217. package/lib/module/surfaces/bannerWebView/bannerThemeStyles.js.map +1 -1
  218. package/lib/module/surfaces/bannerWebView/bannerWebViewHeight.js +29 -0
  219. package/lib/module/surfaces/bannerWebView/bannerWebViewHeight.js.map +1 -0
  220. package/lib/module/surfaces/bannerWebView/buildCustomBannerHtml.js +104 -23
  221. package/lib/module/surfaces/bannerWebView/buildCustomBannerHtml.js.map +1 -1
  222. package/lib/module/surfaces/hostAccessibilityTrap.js +24 -0
  223. package/lib/module/surfaces/hostAccessibilityTrap.js.map +1 -0
  224. package/lib/module/surfaces/resolveBannerTheme.js +6 -3
  225. package/lib/module/surfaces/resolveBannerTheme.js.map +1 -1
  226. package/lib/module/surfaces/tooltip/TooltipBubble.js +3 -2
  227. package/lib/module/surfaces/tooltip/TooltipBubble.js.map +1 -1
  228. package/lib/module/surfaces/tooltip/targetSearchSchedule.js +128 -0
  229. package/lib/module/surfaces/tooltip/targetSearchSchedule.js.map +1 -0
  230. package/lib/module/version.js +1 -1
  231. package/lib/typescript/commonjs/src/anchors/AutoAnchorRegistry.d.ts +36 -2
  232. package/lib/typescript/commonjs/src/anchors/AutoAnchorRegistry.d.ts.map +1 -1
  233. package/lib/typescript/commonjs/src/anchors/animationFrame.d.ts +0 -4
  234. package/lib/typescript/commonjs/src/anchors/animationFrame.d.ts.map +1 -1
  235. package/lib/typescript/commonjs/src/anchors/appActive.d.ts +8 -0
  236. package/lib/typescript/commonjs/src/anchors/appActive.d.ts.map +1 -0
  237. package/lib/typescript/commonjs/src/anchors/elementTapMonitor.d.ts +17 -0
  238. package/lib/typescript/commonjs/src/anchors/elementTapMonitor.d.ts.map +1 -1
  239. package/lib/typescript/commonjs/src/anchors/elementTargetMatch.d.ts +7 -0
  240. package/lib/typescript/commonjs/src/anchors/elementTargetMatch.d.ts.map +1 -1
  241. package/lib/typescript/commonjs/src/anchors/fiber/FiberScanRootStore.d.ts +5 -0
  242. package/lib/typescript/commonjs/src/anchors/fiber/FiberScanRootStore.d.ts.map +1 -1
  243. package/lib/typescript/commonjs/src/anchors/fiber/detectAppFontFamily.d.ts +30 -0
  244. package/lib/typescript/commonjs/src/anchors/fiber/detectAppFontFamily.d.ts.map +1 -0
  245. package/lib/typescript/commonjs/src/anchors/fiber/fiberInternals.d.ts +7 -0
  246. package/lib/typescript/commonjs/src/anchors/fiber/fiberInternals.d.ts.map +1 -1
  247. package/lib/typescript/commonjs/src/anchors/fiber/indexHostFibers.d.ts +3 -2
  248. package/lib/typescript/commonjs/src/anchors/fiber/indexHostFibers.d.ts.map +1 -1
  249. package/lib/typescript/commonjs/src/anchors/fiber/resolveFiberPath.d.ts +3 -0
  250. package/lib/typescript/commonjs/src/anchors/fiber/resolveFiberPath.d.ts.map +1 -1
  251. package/lib/typescript/commonjs/src/anchors/fiber/visibleScreens.d.ts +2 -0
  252. package/lib/typescript/commonjs/src/anchors/fiber/visibleScreens.d.ts.map +1 -1
  253. package/lib/typescript/commonjs/src/anchors/fiberAnchorCache.d.ts +5 -0
  254. package/lib/typescript/commonjs/src/anchors/fiberAnchorCache.d.ts.map +1 -1
  255. package/lib/typescript/commonjs/src/anchors/gestureHandlerHandoff.d.ts +70 -0
  256. package/lib/typescript/commonjs/src/anchors/gestureHandlerHandoff.d.ts.map +1 -0
  257. package/lib/typescript/commonjs/src/anchors/resolveAnchorHost.d.ts +1 -0
  258. package/lib/typescript/commonjs/src/anchors/resolveAnchorHost.d.ts.map +1 -1
  259. package/lib/typescript/commonjs/src/anchors/resolveAutoAnchorHost.d.ts +11 -4
  260. package/lib/typescript/commonjs/src/anchors/resolveAutoAnchorHost.d.ts.map +1 -1
  261. package/lib/typescript/commonjs/src/anchors/resolveElementTargets.d.ts.map +1 -1
  262. package/lib/typescript/commonjs/src/anchors/semanticMatcher.d.ts +2 -0
  263. package/lib/typescript/commonjs/src/anchors/semanticMatcher.d.ts.map +1 -1
  264. package/lib/typescript/commonjs/src/anchors/tapSlop.d.ts +9 -0
  265. package/lib/typescript/commonjs/src/anchors/tapSlop.d.ts.map +1 -0
  266. package/lib/typescript/commonjs/src/anchors/targetPressMonitor.d.ts +13 -8
  267. package/lib/typescript/commonjs/src/anchors/targetPressMonitor.d.ts.map +1 -1
  268. package/lib/typescript/commonjs/src/authoring/fingerprintFromInstance.d.ts.map +1 -1
  269. package/lib/typescript/commonjs/src/content/BannerStepButton.d.ts.map +1 -1
  270. package/lib/typescript/commonjs/src/content/RichContentRenderer.d.ts.map +1 -1
  271. package/lib/typescript/commonjs/src/content/StepButton.d.ts.map +1 -1
  272. package/lib/typescript/commonjs/src/content/openSafeUrl.d.ts.map +1 -1
  273. package/lib/typescript/commonjs/src/content/resolveContentFontFamily.d.ts +35 -0
  274. package/lib/typescript/commonjs/src/content/resolveContentFontFamily.d.ts.map +1 -0
  275. package/lib/typescript/commonjs/src/expo-router/useUserflowExpoRouter.d.ts.map +1 -1
  276. package/lib/typescript/commonjs/src/index.d.ts +6 -5
  277. package/lib/typescript/commonjs/src/index.d.ts.map +1 -1
  278. package/lib/typescript/commonjs/src/navigation/navigateUrlUtils.d.ts +15 -0
  279. package/lib/typescript/commonjs/src/navigation/navigateUrlUtils.d.ts.map +1 -0
  280. package/lib/typescript/commonjs/src/navigation/openExternalNavigateUrl.d.ts +3 -0
  281. package/lib/typescript/commonjs/src/navigation/openExternalNavigateUrl.d.ts.map +1 -0
  282. package/lib/typescript/commonjs/src/navigation/openFlowNavigateUrl.d.ts +2 -5
  283. package/lib/typescript/commonjs/src/navigation/openFlowNavigateUrl.d.ts.map +1 -1
  284. package/lib/typescript/commonjs/src/pairing/PairingController.d.ts +6 -0
  285. package/lib/typescript/commonjs/src/pairing/PairingController.d.ts.map +1 -1
  286. package/lib/typescript/commonjs/src/runtime/BannerHost.d.ts.map +1 -1
  287. package/lib/typescript/commonjs/src/runtime/TargetPressBridge.d.ts +3 -0
  288. package/lib/typescript/commonjs/src/runtime/TargetPressBridge.d.ts.map +1 -1
  289. package/lib/typescript/commonjs/src/runtime/UserflowOverlay.d.ts.map +1 -1
  290. package/lib/typescript/commonjs/src/runtime/UserflowProvider.d.ts.map +1 -1
  291. package/lib/typescript/commonjs/src/runtime/bannerEngine.d.ts +5 -1
  292. package/lib/typescript/commonjs/src/runtime/bannerEngine.d.ts.map +1 -1
  293. package/lib/typescript/commonjs/src/runtime/bannerFlowSpacer.d.ts +15 -0
  294. package/lib/typescript/commonjs/src/runtime/bannerFlowSpacer.d.ts.map +1 -0
  295. package/lib/typescript/commonjs/src/runtime/flowEngine.d.ts.map +1 -1
  296. package/lib/typescript/commonjs/src/runtime/previewStart.d.ts +13 -0
  297. package/lib/typescript/commonjs/src/runtime/previewStart.d.ts.map +1 -0
  298. package/lib/typescript/commonjs/src/runtime/pushBannerLayoutContext.d.ts +22 -0
  299. package/lib/typescript/commonjs/src/runtime/pushBannerLayoutContext.d.ts.map +1 -0
  300. package/lib/typescript/commonjs/src/screenTracker.d.ts +6 -0
  301. package/lib/typescript/commonjs/src/screenTracker.d.ts.map +1 -1
  302. package/lib/typescript/commonjs/src/surfaces/BannerBar.d.ts +3 -1
  303. package/lib/typescript/commonjs/src/surfaces/BannerBar.d.ts.map +1 -1
  304. package/lib/typescript/commonjs/src/surfaces/BannerSurface.d.ts +6 -5
  305. package/lib/typescript/commonjs/src/surfaces/BannerSurface.d.ts.map +1 -1
  306. package/lib/typescript/commonjs/src/surfaces/ProgressBar.d.ts.map +1 -1
  307. package/lib/typescript/commonjs/src/surfaces/TooltipSurface.d.ts +1 -1
  308. package/lib/typescript/commonjs/src/surfaces/TooltipSurface.d.ts.map +1 -1
  309. package/lib/typescript/commonjs/src/surfaces/bannerBarLayout.d.ts +17 -0
  310. package/lib/typescript/commonjs/src/surfaces/bannerBarLayout.d.ts.map +1 -1
  311. package/lib/typescript/commonjs/src/surfaces/bannerWebView/BannerWebViewBar.d.ts +3 -1
  312. package/lib/typescript/commonjs/src/surfaces/bannerWebView/BannerWebViewBar.d.ts.map +1 -1
  313. package/lib/typescript/commonjs/src/surfaces/bannerWebView/bannerNeedsWebView.d.ts +3 -12
  314. package/lib/typescript/commonjs/src/surfaces/bannerWebView/bannerNeedsWebView.d.ts.map +1 -1
  315. package/lib/typescript/commonjs/src/surfaces/bannerWebView/bannerThemeStyles.d.ts.map +1 -1
  316. package/lib/typescript/commonjs/src/surfaces/bannerWebView/bannerWebViewHeight.d.ts +13 -0
  317. package/lib/typescript/commonjs/src/surfaces/bannerWebView/bannerWebViewHeight.d.ts.map +1 -0
  318. package/lib/typescript/commonjs/src/surfaces/bannerWebView/buildCustomBannerHtml.d.ts.map +1 -1
  319. package/lib/typescript/commonjs/src/surfaces/hostAccessibilityTrap.d.ts +14 -0
  320. package/lib/typescript/commonjs/src/surfaces/hostAccessibilityTrap.d.ts.map +1 -0
  321. package/lib/typescript/commonjs/src/surfaces/resolveBannerTheme.d.ts +4 -1
  322. package/lib/typescript/commonjs/src/surfaces/resolveBannerTheme.d.ts.map +1 -1
  323. package/lib/typescript/commonjs/src/surfaces/tooltip/TooltipBubble.d.ts +7 -1
  324. package/lib/typescript/commonjs/src/surfaces/tooltip/TooltipBubble.d.ts.map +1 -1
  325. package/lib/typescript/commonjs/src/surfaces/tooltip/targetSearchSchedule.d.ts +60 -0
  326. package/lib/typescript/commonjs/src/surfaces/tooltip/targetSearchSchedule.d.ts.map +1 -0
  327. package/lib/typescript/commonjs/src/version.d.ts +1 -1
  328. package/lib/typescript/module/src/anchors/AutoAnchorRegistry.d.ts +36 -2
  329. package/lib/typescript/module/src/anchors/AutoAnchorRegistry.d.ts.map +1 -1
  330. package/lib/typescript/module/src/anchors/animationFrame.d.ts +0 -4
  331. package/lib/typescript/module/src/anchors/animationFrame.d.ts.map +1 -1
  332. package/lib/typescript/module/src/anchors/appActive.d.ts +8 -0
  333. package/lib/typescript/module/src/anchors/appActive.d.ts.map +1 -0
  334. package/lib/typescript/module/src/anchors/elementTapMonitor.d.ts +17 -0
  335. package/lib/typescript/module/src/anchors/elementTapMonitor.d.ts.map +1 -1
  336. package/lib/typescript/module/src/anchors/elementTargetMatch.d.ts +7 -0
  337. package/lib/typescript/module/src/anchors/elementTargetMatch.d.ts.map +1 -1
  338. package/lib/typescript/module/src/anchors/fiber/FiberScanRootStore.d.ts +5 -0
  339. package/lib/typescript/module/src/anchors/fiber/FiberScanRootStore.d.ts.map +1 -1
  340. package/lib/typescript/module/src/anchors/fiber/detectAppFontFamily.d.ts +30 -0
  341. package/lib/typescript/module/src/anchors/fiber/detectAppFontFamily.d.ts.map +1 -0
  342. package/lib/typescript/module/src/anchors/fiber/fiberInternals.d.ts +7 -0
  343. package/lib/typescript/module/src/anchors/fiber/fiberInternals.d.ts.map +1 -1
  344. package/lib/typescript/module/src/anchors/fiber/indexHostFibers.d.ts +3 -2
  345. package/lib/typescript/module/src/anchors/fiber/indexHostFibers.d.ts.map +1 -1
  346. package/lib/typescript/module/src/anchors/fiber/resolveFiberPath.d.ts +3 -0
  347. package/lib/typescript/module/src/anchors/fiber/resolveFiberPath.d.ts.map +1 -1
  348. package/lib/typescript/module/src/anchors/fiber/visibleScreens.d.ts +2 -0
  349. package/lib/typescript/module/src/anchors/fiber/visibleScreens.d.ts.map +1 -1
  350. package/lib/typescript/module/src/anchors/fiberAnchorCache.d.ts +5 -0
  351. package/lib/typescript/module/src/anchors/fiberAnchorCache.d.ts.map +1 -1
  352. package/lib/typescript/module/src/anchors/gestureHandlerHandoff.d.ts +70 -0
  353. package/lib/typescript/module/src/anchors/gestureHandlerHandoff.d.ts.map +1 -0
  354. package/lib/typescript/module/src/anchors/resolveAnchorHost.d.ts +1 -0
  355. package/lib/typescript/module/src/anchors/resolveAnchorHost.d.ts.map +1 -1
  356. package/lib/typescript/module/src/anchors/resolveAutoAnchorHost.d.ts +11 -4
  357. package/lib/typescript/module/src/anchors/resolveAutoAnchorHost.d.ts.map +1 -1
  358. package/lib/typescript/module/src/anchors/resolveElementTargets.d.ts.map +1 -1
  359. package/lib/typescript/module/src/anchors/semanticMatcher.d.ts +2 -0
  360. package/lib/typescript/module/src/anchors/semanticMatcher.d.ts.map +1 -1
  361. package/lib/typescript/module/src/anchors/tapSlop.d.ts +9 -0
  362. package/lib/typescript/module/src/anchors/tapSlop.d.ts.map +1 -0
  363. package/lib/typescript/module/src/anchors/targetPressMonitor.d.ts +13 -8
  364. package/lib/typescript/module/src/anchors/targetPressMonitor.d.ts.map +1 -1
  365. package/lib/typescript/module/src/authoring/fingerprintFromInstance.d.ts.map +1 -1
  366. package/lib/typescript/module/src/content/BannerStepButton.d.ts.map +1 -1
  367. package/lib/typescript/module/src/content/RichContentRenderer.d.ts.map +1 -1
  368. package/lib/typescript/module/src/content/StepButton.d.ts.map +1 -1
  369. package/lib/typescript/module/src/content/openSafeUrl.d.ts.map +1 -1
  370. package/lib/typescript/module/src/content/resolveContentFontFamily.d.ts +35 -0
  371. package/lib/typescript/module/src/content/resolveContentFontFamily.d.ts.map +1 -0
  372. package/lib/typescript/module/src/expo-router/useUserflowExpoRouter.d.ts.map +1 -1
  373. package/lib/typescript/module/src/index.d.ts +6 -5
  374. package/lib/typescript/module/src/index.d.ts.map +1 -1
  375. package/lib/typescript/module/src/navigation/navigateUrlUtils.d.ts +15 -0
  376. package/lib/typescript/module/src/navigation/navigateUrlUtils.d.ts.map +1 -0
  377. package/lib/typescript/module/src/navigation/openExternalNavigateUrl.d.ts +3 -0
  378. package/lib/typescript/module/src/navigation/openExternalNavigateUrl.d.ts.map +1 -0
  379. package/lib/typescript/module/src/navigation/openFlowNavigateUrl.d.ts +2 -5
  380. package/lib/typescript/module/src/navigation/openFlowNavigateUrl.d.ts.map +1 -1
  381. package/lib/typescript/module/src/pairing/PairingController.d.ts +6 -0
  382. package/lib/typescript/module/src/pairing/PairingController.d.ts.map +1 -1
  383. package/lib/typescript/module/src/runtime/BannerHost.d.ts.map +1 -1
  384. package/lib/typescript/module/src/runtime/TargetPressBridge.d.ts +3 -0
  385. package/lib/typescript/module/src/runtime/TargetPressBridge.d.ts.map +1 -1
  386. package/lib/typescript/module/src/runtime/UserflowOverlay.d.ts.map +1 -1
  387. package/lib/typescript/module/src/runtime/UserflowProvider.d.ts.map +1 -1
  388. package/lib/typescript/module/src/runtime/bannerEngine.d.ts +5 -1
  389. package/lib/typescript/module/src/runtime/bannerEngine.d.ts.map +1 -1
  390. package/lib/typescript/module/src/runtime/bannerFlowSpacer.d.ts +15 -0
  391. package/lib/typescript/module/src/runtime/bannerFlowSpacer.d.ts.map +1 -0
  392. package/lib/typescript/module/src/runtime/flowEngine.d.ts.map +1 -1
  393. package/lib/typescript/module/src/runtime/previewStart.d.ts +13 -0
  394. package/lib/typescript/module/src/runtime/previewStart.d.ts.map +1 -0
  395. package/lib/typescript/module/src/runtime/pushBannerLayoutContext.d.ts +22 -0
  396. package/lib/typescript/module/src/runtime/pushBannerLayoutContext.d.ts.map +1 -0
  397. package/lib/typescript/module/src/screenTracker.d.ts +6 -0
  398. package/lib/typescript/module/src/screenTracker.d.ts.map +1 -1
  399. package/lib/typescript/module/src/surfaces/BannerBar.d.ts +3 -1
  400. package/lib/typescript/module/src/surfaces/BannerBar.d.ts.map +1 -1
  401. package/lib/typescript/module/src/surfaces/BannerSurface.d.ts +6 -5
  402. package/lib/typescript/module/src/surfaces/BannerSurface.d.ts.map +1 -1
  403. package/lib/typescript/module/src/surfaces/ProgressBar.d.ts.map +1 -1
  404. package/lib/typescript/module/src/surfaces/TooltipSurface.d.ts +1 -1
  405. package/lib/typescript/module/src/surfaces/TooltipSurface.d.ts.map +1 -1
  406. package/lib/typescript/module/src/surfaces/bannerBarLayout.d.ts +17 -0
  407. package/lib/typescript/module/src/surfaces/bannerBarLayout.d.ts.map +1 -1
  408. package/lib/typescript/module/src/surfaces/bannerWebView/BannerWebViewBar.d.ts +3 -1
  409. package/lib/typescript/module/src/surfaces/bannerWebView/BannerWebViewBar.d.ts.map +1 -1
  410. package/lib/typescript/module/src/surfaces/bannerWebView/bannerNeedsWebView.d.ts +3 -12
  411. package/lib/typescript/module/src/surfaces/bannerWebView/bannerNeedsWebView.d.ts.map +1 -1
  412. package/lib/typescript/module/src/surfaces/bannerWebView/bannerThemeStyles.d.ts.map +1 -1
  413. package/lib/typescript/module/src/surfaces/bannerWebView/bannerWebViewHeight.d.ts +13 -0
  414. package/lib/typescript/module/src/surfaces/bannerWebView/bannerWebViewHeight.d.ts.map +1 -0
  415. package/lib/typescript/module/src/surfaces/bannerWebView/buildCustomBannerHtml.d.ts.map +1 -1
  416. package/lib/typescript/module/src/surfaces/hostAccessibilityTrap.d.ts +14 -0
  417. package/lib/typescript/module/src/surfaces/hostAccessibilityTrap.d.ts.map +1 -0
  418. package/lib/typescript/module/src/surfaces/resolveBannerTheme.d.ts +4 -1
  419. package/lib/typescript/module/src/surfaces/resolveBannerTheme.d.ts.map +1 -1
  420. package/lib/typescript/module/src/surfaces/tooltip/TooltipBubble.d.ts +7 -1
  421. package/lib/typescript/module/src/surfaces/tooltip/TooltipBubble.d.ts.map +1 -1
  422. package/lib/typescript/module/src/surfaces/tooltip/targetSearchSchedule.d.ts +60 -0
  423. package/lib/typescript/module/src/surfaces/tooltip/targetSearchSchedule.d.ts.map +1 -0
  424. package/lib/typescript/module/src/version.d.ts +1 -1
  425. package/package.json +1 -1
  426. package/src/anchors/AutoAnchorRegistry.ts +166 -35
  427. package/src/anchors/animationFrame.ts +31 -1
  428. package/src/anchors/appActive.ts +63 -0
  429. package/src/anchors/elementConditionEvaluator.ts +29 -12
  430. package/src/anchors/elementTapMonitor.ts +68 -10
  431. package/src/anchors/elementTargetMatch.ts +34 -7
  432. package/src/anchors/fiber/FiberScanRootStore.ts +8 -0
  433. package/src/anchors/fiber/detectAppFontFamily.ts +400 -0
  434. package/src/anchors/fiber/fiberInternals.ts +68 -0
  435. package/src/anchors/fiber/indexHostFibers.ts +8 -3
  436. package/src/anchors/fiber/resolveFiberPath.ts +25 -16
  437. package/src/anchors/fiber/visibleScreens.ts +5 -0
  438. package/src/anchors/fiberAnchorCache.ts +19 -0
  439. package/src/anchors/gestureHandlerHandoff.ts +356 -0
  440. package/src/anchors/resolveAnchorHost.ts +2 -0
  441. package/src/anchors/resolveAutoAnchorHost.ts +18 -8
  442. package/src/anchors/resolveElementTargets.ts +64 -7
  443. package/src/anchors/semanticMatcher.ts +48 -27
  444. package/src/anchors/tapSlop.ts +18 -0
  445. package/src/anchors/targetPressMonitor.ts +56 -19
  446. package/src/authoring/fingerprintFromInstance.ts +4 -5
  447. package/src/content/BannerStepButton.tsx +2 -1
  448. package/src/content/RichContentRenderer.tsx +19 -13
  449. package/src/content/StepButton.tsx +2 -1
  450. package/src/content/openSafeUrl.ts +3 -1
  451. package/src/content/resolveContentFontFamily.ts +119 -0
  452. package/src/expo-router/useUserflowExpoRouter.ts +10 -1
  453. package/src/index.ts +22 -9
  454. package/src/navigation/navigateUrlUtils.ts +100 -0
  455. package/src/navigation/openExternalNavigateUrl.ts +9 -0
  456. package/src/navigation/openFlowNavigateUrl.ts +36 -36
  457. package/src/pairing/PairingController.ts +9 -1
  458. package/src/runtime/BannerHost.tsx +41 -23
  459. package/src/runtime/TargetPressBridge.tsx +66 -9
  460. package/src/runtime/UserflowOverlay.tsx +7 -9
  461. package/src/runtime/UserflowProvider.tsx +56 -32
  462. package/src/runtime/bannerEngine.ts +10 -2
  463. package/src/runtime/bannerFlowSpacer.tsx +70 -0
  464. package/src/runtime/flowEngine.ts +11 -0
  465. package/src/runtime/previewStart.ts +49 -0
  466. package/src/runtime/pushBannerLayoutContext.tsx +126 -0
  467. package/src/screenTracker.ts +11 -0
  468. package/src/surfaces/BannerBar.tsx +93 -55
  469. package/src/surfaces/BannerSurface.tsx +61 -9
  470. package/src/surfaces/ProgressBar.tsx +2 -1
  471. package/src/surfaces/TooltipSurface.tsx +78 -53
  472. package/src/surfaces/bannerBarLayout.ts +80 -7
  473. package/src/surfaces/bannerWebView/BannerWebViewBar.tsx +151 -57
  474. package/src/surfaces/bannerWebView/bannerNeedsWebView.ts +4 -36
  475. package/src/surfaces/bannerWebView/bannerThemeStyles.ts +2 -1
  476. package/src/surfaces/bannerWebView/bannerWebViewHeight.ts +32 -0
  477. package/src/surfaces/bannerWebView/buildCustomBannerHtml.ts +111 -23
  478. package/src/surfaces/hostAccessibilityTrap.ts +25 -0
  479. package/src/surfaces/resolveBannerTheme.ts +14 -3
  480. package/src/surfaces/tooltip/TooltipBubble.tsx +8 -1
  481. package/src/surfaces/tooltip/targetSearchSchedule.ts +140 -0
  482. package/src/version.ts +1 -1
  483. package/vendor/core/dist/engine/BannerSessionEngine.d.ts +29 -2
  484. package/vendor/core/dist/engine/BannerSessionEngine.d.ts.map +1 -1
  485. package/vendor/core/dist/engine/BannerSessionEngine.js +87 -6
  486. package/vendor/core/dist/engine/BannerSessionEngine.js.map +1 -1
  487. package/vendor/core/dist/engine/ClientConditionEngine.d.ts.map +1 -1
  488. package/vendor/core/dist/engine/ClientConditionEngine.js +30 -7
  489. package/vendor/core/dist/engine/ClientConditionEngine.js.map +1 -1
  490. package/vendor/core/dist/engine/PairingEngine.d.ts +6 -1
  491. package/vendor/core/dist/engine/PairingEngine.d.ts.map +1 -1
  492. package/vendor/core/dist/engine/PairingEngine.js +23 -3
  493. package/vendor/core/dist/engine/PairingEngine.js.map +1 -1
  494. package/vendor/core/dist/engine/handleActions.d.ts.map +1 -1
  495. package/vendor/core/dist/engine/handleActions.js +67 -2
  496. package/vendor/core/dist/engine/handleActions.js.map +1 -1
  497. package/vendor/core/dist/version.d.ts +1 -1
  498. package/vendor/core/dist/version.js +1 -1
  499. package/vendor/core/package.json +1 -1
  500. package/vendor/protocol/dist/flows.d.ts +2 -0
  501. package/vendor/protocol/dist/flows.d.ts.map +1 -1
  502. package/vendor/protocol/package.json +1 -1
@@ -0,0 +1,100 @@
1
+ const ABSOLUTE_WEB_URL = /^https?:\/\//i;
2
+
3
+ /** Hostname.tld with optional port, path, query, or hash — not an in-app screen name like `Profile`. */
4
+ const BARE_EXTERNAL_HOST =
5
+ /^[\w.-]+\.[a-z]{2,}(?::\d+)?(?:\/[^\s?#]*)?(?:\?[^\s#]*)?(?:#[^\s]*)?$/i;
6
+
7
+ function isAllowlistedWebUrl(url: string): boolean {
8
+ const trimmed = url.trim();
9
+ if (!trimmed) {
10
+ return false;
11
+ }
12
+ if (!ABSOLUTE_WEB_URL.test(trimmed) && !/^mailto:/i.test(trimmed) && !/^tel:/i.test(trimmed)) {
13
+ return false;
14
+ }
15
+ try {
16
+ const parsed = new URL(trimmed);
17
+ return (
18
+ parsed.protocol === 'http:' ||
19
+ parsed.protocol === 'https:' ||
20
+ parsed.protocol === 'mailto:' ||
21
+ parsed.protocol === 'tel:'
22
+ );
23
+ } catch {
24
+ return ABSOLUTE_WEB_URL.test(trimmed);
25
+ }
26
+ }
27
+
28
+ /** Fix common builder typos before classification (`https:/google.com`). */
29
+ export function normalizeNavigateUrlInput(url: string): string {
30
+ const trimmed = url.trim();
31
+ return trimmed.replace(/^(https?):\/(?!\/)/i, '$1://');
32
+ }
33
+
34
+ /** Prefix `https://` when the builder URL omitted the scheme (e.g. `google.com`). */
35
+ export function normalizeExternalNavigateUrl(url: string): string {
36
+ const trimmed = normalizeNavigateUrlInput(url);
37
+ if (ABSOLUTE_WEB_URL.test(trimmed)) {
38
+ return trimmed;
39
+ }
40
+ if (BARE_EXTERNAL_HOST.test(trimmed) && !trimmed.startsWith('/')) {
41
+ return `https://${trimmed}`;
42
+ }
43
+ return trimmed;
44
+ }
45
+
46
+ /** True when the URL should open outside the app (browser / mail / tel). */
47
+ export function shouldOpenExternalNavigateUrl(url: string): boolean {
48
+ const trimmed = normalizeNavigateUrlInput(url);
49
+ if (!trimmed) {
50
+ return false;
51
+ }
52
+ if (isAllowlistedWebUrl(trimmed)) {
53
+ return true;
54
+ }
55
+ if (ABSOLUTE_WEB_URL.test(trimmed)) {
56
+ return true;
57
+ }
58
+ if (/^mailto:/i.test(trimmed) || /^tel:/i.test(trimmed)) {
59
+ return true;
60
+ }
61
+ if (BARE_EXTERNAL_HOST.test(trimmed) && !trimmed.startsWith('/')) {
62
+ return true;
63
+ }
64
+ return false;
65
+ }
66
+
67
+ /** True for http(s) / mailto / tel (external). */
68
+ export function isExternalNavigateUrl(url: string): boolean {
69
+ return shouldOpenExternalNavigateUrl(url);
70
+ }
71
+
72
+ /** Path-like in-app URL: leading slash, or no scheme. */
73
+ export function isInAppNavigateUrl(url: string): boolean {
74
+ const trimmed = normalizeNavigateUrlInput(url);
75
+ if (!trimmed) return false;
76
+ if (shouldOpenExternalNavigateUrl(trimmed)) return false;
77
+ if (/^[a-z][a-z0-9+.-]*:/i.test(trimmed)) return false;
78
+ return true;
79
+ }
80
+
81
+ /** Never pass absolute / external URLs to Expo Router `push`. */
82
+ export function mustNotUseExpoRouterPush(url: string): boolean {
83
+ const trimmed = normalizeNavigateUrlInput(url);
84
+ if (!trimmed) return false;
85
+ if (shouldOpenExternalNavigateUrl(trimmed)) return true;
86
+ if (trimmed.includes('://')) return true;
87
+ return false;
88
+ }
89
+
90
+ export function normalizeInAppPath(url: string): string {
91
+ const trimmed = normalizeNavigateUrlInput(url);
92
+ if (trimmed.startsWith('/')) return trimmed;
93
+ return `/${trimmed}`;
94
+ }
95
+
96
+ export function routeNameFromPath(path: string): string {
97
+ const normalized = normalizeInAppPath(path).replace(/^\//, '');
98
+ const [first] = normalized.split(/[/?#]/);
99
+ return first || normalized;
100
+ }
@@ -0,0 +1,9 @@
1
+ import { openSafeUrl } from '../content/openSafeUrl';
2
+
3
+ import { normalizeExternalNavigateUrl } from './navigateUrlUtils';
4
+
5
+ /** Open http(s)/mailto/tel via Linking (documented SDK behavior). */
6
+ export async function openExternalNavigateUrl(url: string): Promise<void> {
7
+ const external = normalizeExternalNavigateUrl(url);
8
+ await openSafeUrl(external);
9
+ }
@@ -1,9 +1,18 @@
1
1
  import type { NavigationContainerRef, ParamListBase } from '@react-navigation/native';
2
- import { Linking } from 'react-native';
3
2
 
4
- import { isSafeUrl, openSafeUrl } from '../content/openSafeUrl';
3
+ import { isSafeUrl } from '../content/openSafeUrl';
5
4
  import { isolateAsync, isolateSync } from '../runtime/isolateCall';
6
5
 
6
+ import {
7
+ isInAppNavigateUrl,
8
+ mustNotUseExpoRouterPush,
9
+ normalizeInAppPath,
10
+ normalizeNavigateUrlInput,
11
+ routeNameFromPath,
12
+ shouldOpenExternalNavigateUrl,
13
+ } from './navigateUrlUtils';
14
+ import { openExternalNavigateUrl } from './openExternalNavigateUrl';
15
+
7
16
  export type FlowNavigateHandler = (url: string) => void | boolean | Promise<void | boolean>;
8
17
 
9
18
  export type ExpoRouterLike = {
@@ -31,38 +40,19 @@ export function setExpoRouterNavigator(router: ExpoRouterLike | null | undefined
31
40
  expoRouter = router ?? null;
32
41
  }
33
42
 
34
- /** True for http(s) / mailto / tel (external). */
35
- export function isExternalNavigateUrl(url: string): boolean {
36
- return isSafeUrl(url);
37
- }
38
-
39
- /** Path-like in-app URL: leading slash, or no scheme. */
40
- export function isInAppNavigateUrl(url: string): boolean {
41
- const trimmed = url.trim();
42
- if (!trimmed) return false;
43
- if (isExternalNavigateUrl(trimmed)) return false;
44
- if (/^[a-z][a-z0-9+.-]*:/i.test(trimmed)) return false;
45
- return true;
46
- }
47
-
48
- function normalizeInAppPath(url: string): string {
49
- const trimmed = url.trim();
50
- if (trimmed.startsWith('/')) return trimmed;
51
- return `/${trimmed}`;
52
- }
53
-
54
- function routeNameFromPath(path: string): string {
55
- const normalized = normalizeInAppPath(path).replace(/^\//, '');
56
- const [first] = normalized.split(/[/?#]/);
57
- return first || normalized;
58
- }
43
+ export {
44
+ isExternalNavigateUrl,
45
+ isInAppNavigateUrl,
46
+ normalizeExternalNavigateUrl,
47
+ shouldOpenExternalNavigateUrl,
48
+ } from './navigateUrlUtils';
59
49
 
60
50
  /**
61
51
  * Open a flow NAVIGATE url.
62
52
  *
63
53
  * Priority:
64
54
  * 1. Host `onNavigate` (custom schemes / exotic routing)
65
- * 2. External allowlisted schemes → Linking / `openSafeUrl`
55
+ * 2. External allowlisted schemes → in-app browser / Linking
66
56
  * 3. Path-like → Expo Router `push` or React Navigation `navigate`
67
57
  * 4. Fallback → Linking (best-effort)
68
58
  *
@@ -72,9 +62,18 @@ function routeNameFromPath(path: string): string {
72
62
  * `@userflow-tech/react-native/expo-router` under `UserflowProvider`.
73
63
  */
74
64
  export async function openFlowNavigateUrl(url: string): Promise<void> {
75
- const trimmed = url.trim();
65
+ const trimmed = normalizeNavigateUrlInput(url);
76
66
  if (!trimmed) return;
77
67
 
68
+ if (__DEV__) {
69
+ // eslint-disable-next-line no-console -- intentional development diagnostic
70
+ console.log('[Userflow] NAVIGATE openFlowNavigateUrl', {
71
+ url: trimmed,
72
+ external: shouldOpenExternalNavigateUrl(trimmed),
73
+ inApp: isInAppNavigateUrl(trimmed),
74
+ });
75
+ }
76
+
78
77
  if (hostOnNavigate) {
79
78
  await isolateAsync('onNavigate', async () => {
80
79
  await hostOnNavigate!(trimmed);
@@ -82,13 +81,17 @@ export async function openFlowNavigateUrl(url: string): Promise<void> {
82
81
  return;
83
82
  }
84
83
 
85
- if (isExternalNavigateUrl(trimmed)) {
86
- await openSafeUrl(trimmed);
84
+ if (shouldOpenExternalNavigateUrl(trimmed)) {
85
+ await openExternalNavigateUrl(trimmed);
87
86
  return;
88
87
  }
89
88
 
90
89
  if (isInAppNavigateUrl(trimmed)) {
91
90
  if (expoRouter) {
91
+ if (mustNotUseExpoRouterPush(trimmed)) {
92
+ await openExternalNavigateUrl(trimmed);
93
+ return;
94
+ }
92
95
  isolateSync('onNavigate', () => {
93
96
  expoRouter!.push(normalizeInAppPath(trimmed));
94
97
  });
@@ -104,11 +107,8 @@ export async function openFlowNavigateUrl(url: string): Promise<void> {
104
107
  }
105
108
  }
106
109
 
107
- // Last resort — may fail for custom schemes; hosts should set onNavigate.
108
- try {
109
- await Linking.openURL(trimmed);
110
- } catch {
111
- // Best-effort.
110
+ if (isSafeUrl(trimmed) || /^https?:\/\//i.test(trimmed)) {
111
+ await openExternalNavigateUrl(trimmed);
112
112
  }
113
113
  }
114
114
 
@@ -46,6 +46,11 @@ export interface PairingControllerOptions {
46
46
  tokenStore?: PairingTokenStore;
47
47
  /** Clear mid-flow session when exiting preview. */
48
48
  clearLocalSession?: () => void;
49
+ /**
50
+ * Runs before a Builder preview start is sent on the end-user channel.
51
+ * Defaults to {@link clearLocalSession} when omitted.
52
+ */
53
+ prepareForBuilderPreviewStart?: () => void | Promise<void>;
49
54
  /** End the previewed draft on the server when exiting preview. */
50
55
  endDraftSession?: () => Promise<void>;
51
56
  /**
@@ -84,6 +89,7 @@ export class PairingController {
84
89
  private readonly LinkingModule: NonNullable<PairingControllerOptions['LinkingModule']>;
85
90
  private readonly AppStateModule: NonNullable<PairingControllerOptions['AppStateModule']>;
86
91
  private readonly clearLocalSession: (() => void) | undefined;
92
+ private readonly prepareForBuilderPreviewStart: (() => void | Promise<void>) | undefined;
87
93
  private readonly endDraftSession: (() => Promise<void>) | undefined;
88
94
  private readonly cancelPendingDraftEnd: (() => void) | undefined;
89
95
  private readonly core: UserflowCore;
@@ -122,6 +128,7 @@ export class PairingController {
122
128
  this.LinkingModule = options.LinkingModule ?? Linking;
123
129
  this.AppStateModule = options.AppStateModule ?? AppState;
124
130
  this.clearLocalSession = options.clearLocalSession ?? undefined;
131
+ this.prepareForBuilderPreviewStart = options.prepareForBuilderPreviewStart ?? undefined;
125
132
  this.endDraftSession = options.endDraftSession ?? undefined;
126
133
  this.cancelPendingDraftEnd = options.cancelPendingDraftEnd ?? undefined;
127
134
  this.logger = options.logger ?? defaultPairingLogger;
@@ -596,7 +603,8 @@ export class PairingController {
596
603
  ...(this.pairingDeviceId !== null ? { device_id: this.pairingDeviceId } : {}),
597
604
  }),
598
605
  onBeforePreviewStart: () => {
599
- this.clearLocalSession?.();
606
+ const run = this.prepareForBuilderPreviewStart ?? this.clearLocalSession;
607
+ return run?.();
600
608
  },
601
609
  });
602
610
 
@@ -1,11 +1,10 @@
1
1
  import type { BannerSessionEngine } from '@userflow-tech/core';
2
- import type { BannerSessionFragment } from '@userflow-tech/protocol';
3
2
  import * as React from 'react';
4
3
  import { StyleSheet, View } from 'react-native';
5
4
 
6
5
  import { BannerSurface } from '../surfaces/BannerSurface';
7
6
  import { bannerOverlayHostPadding } from '../surfaces/bannerBarLayout';
8
- import { resolveBannerBackgroundColor } from '../surfaces/resolveBannerTheme';
7
+ import { bannerNeedsWebView } from '../surfaces/bannerWebView/bannerNeedsWebView';
9
8
  import { useUserflowSafeAreaInsets } from '../surfaces/safeArea';
10
9
 
11
10
  import { SdkErrorBoundary } from './SdkErrorBoundary';
@@ -50,53 +49,72 @@ export function BannerHost({
50
49
  if (edgeFilter && edge !== edgeFilter) return null;
51
50
 
52
51
  const floats = banner.overlay !== false;
53
- if ((placement === 'overlay') !== floats) return null;
52
+ const usesWebView = bannerNeedsWebView(banner);
53
+ // Custom banner WebViews paint in the overlay host (same as userflow.js). A second
54
+ // WKWebView in the flow slot often fails to load after the first banner dismisses.
55
+ const hostAsOverlay = floats || usesWebView;
56
+ if ((placement === 'overlay') !== hostAsOverlay) return null;
57
+
58
+ const pushLayoutEdge = placement === 'flow' && !hostAsOverlay ? edge : null;
59
+ // Builder overlay:true floats below the status bar. Push-layout WebViews in the overlay
60
+ // host still paint safe-area chrome (overlay:false + custom banner).
61
+ const overlaySafeEdge = hostAsOverlay && !floats ? edge : null;
62
+
63
+ const surface = (
64
+ <BannerSurface
65
+ session={session}
66
+ pushLayoutEdge={pushLayoutEdge}
67
+ overlaySafeEdge={overlaySafeEdge}
68
+ onActions={(actions) => engine.handleActions(actions)}
69
+ onDismiss={(endReason) => {
70
+ void engine.endBanner(endReason);
71
+ }}
72
+ />
73
+ );
54
74
 
55
75
  const bar = (
56
76
  <SdkErrorBoundary scope="banner" resetKey={session.id}>
57
- <BannerSurface
58
- session={session}
59
- onActions={(actions) => engine.handleActions(actions)}
60
- onDismiss={(endReason) => {
61
- void engine.endBanner(endReason);
62
- }}
63
- />
77
+ {placement === 'flow' ? (
78
+ <View testID="userflow-banner-flow" style={styles.flow}>
79
+ {surface}
80
+ </View>
81
+ ) : (
82
+ surface
83
+ )}
64
84
  </SdkErrorBoundary>
65
85
  );
66
86
 
67
87
  if (placement === 'flow') {
68
- const backgroundColor = bannerBackground(session);
69
- const safePad = edge === 'top' ? { paddingTop: insets.top } : { paddingBottom: insets.bottom };
70
- return (
71
- <View testID="userflow-banner-flow" style={[styles.flow, safePad, { backgroundColor }]}>
72
- {bar}
73
- </View>
74
- );
88
+ return bar;
75
89
  }
76
90
 
77
- const edgeStyle = edge === 'top' ? { top: insets.top } : { bottom: insets.bottom };
91
+ const edgeStyle =
92
+ edge === 'top' ? { top: floats ? insets.top : 0 } : { bottom: floats ? insets.bottom : 0 };
78
93
 
79
94
  return (
80
95
  <View
81
96
  pointerEvents="box-none"
82
97
  style={[styles.pin, edgeStyle, bannerOverlayHostPadding(insets)]}
83
98
  >
84
- {bar}
99
+ <View pointerEvents="auto" style={styles.pinInteractive}>
100
+ {bar}
101
+ </View>
85
102
  </View>
86
103
  );
87
104
  }
88
105
 
89
- function bannerBackground(session: BannerSessionFragment): string {
90
- return resolveBannerBackgroundColor(session.version.theme);
91
- }
92
-
93
106
  const styles = StyleSheet.create({
94
107
  pin: {
95
108
  position: 'absolute',
96
109
  left: 0,
97
110
  right: 0,
111
+ zIndex: 10,
112
+ elevation: 10,
98
113
  },
99
114
  flow: {
100
115
  alignSelf: 'stretch',
101
116
  },
117
+ pinInteractive: {
118
+ alignSelf: 'stretch',
119
+ },
102
120
  });
@@ -2,10 +2,12 @@ import * as React from 'react';
2
2
  import { StyleSheet, View, type GestureResponderEvent } from 'react-native';
3
3
 
4
4
  import { elementTapMonitor } from '../anchors/elementTapMonitor';
5
+ import type { AnyFiber } from '../anchors/fiber/fiberInternals';
5
6
  import { touchBelongsToEvent, touchTargetFiber } from '../anchors/fiber/touchTargetFiber';
6
- import { targetPressMonitor } from '../anchors/targetPressMonitor';
7
+ import { collectGestureHandlerTags } from '../anchors/gestureHandlerHandoff';
8
+ import { targetPressMonitor, type TouchIdentifier } from '../anchors/targetPressMonitor';
7
9
 
8
- import { changedTouchPoints, forEachChangedTouch } from './changedTouchPoints';
10
+ import { forEachChangedTouch } from './changedTouchPoints';
9
11
  import { isolateSync } from './isolateCall';
10
12
 
11
13
  export interface TargetPressBridgeProps {
@@ -25,6 +27,9 @@ export interface TargetPressBridgeProps {
25
27
  * Preview-chrome double taps are observed by `DoubleTapBridge` around the
26
28
  * whole provider tree — this bridge never sees overlay touches.
27
29
  *
30
+ * A touch that gesture-handler cancels is not dropped. The start is kept and
31
+ * counts as a tap if that handler later ends from ACTIVE.
32
+ *
28
33
  * Does not claim the gesture responder.
29
34
  */
30
35
  export function TargetPressBridge({ children }: TargetPressBridgeProps): React.ReactElement {
@@ -57,15 +62,23 @@ export function TargetPressBridge({ children }: TargetPressBridgeProps): React.R
57
62
 
58
63
  const onTouchCancel = React.useCallback((event: GestureResponderEvent) => {
59
64
  isolateSync('target-press', () => {
60
- const points = changedTouchPoints(event);
61
- if (points.length === 0) {
62
- targetPressMonitor.cancelTouch();
63
- elementTapMonitor.cancelTouch();
65
+ const changed = event.nativeEvent.changedTouches;
66
+ if (!changed || changed.length === 0) {
67
+ const identifiers = inProgressIdentifiers();
68
+ if (identifiers.length === 0) {
69
+ targetPressMonitor.cancelTouch();
70
+ elementTapMonitor.cancelTouch();
71
+ return;
72
+ }
73
+ // No per-finger target on this event; every finger shares its view.
74
+ const fallback = touchTargetFiber(event);
75
+ for (const identifier of identifiers) {
76
+ handOffCancelledTouch(event, identifier, fallback);
77
+ }
64
78
  return;
65
79
  }
66
- for (const touch of points) {
67
- targetPressMonitor.cancelTouch(touch.identifier);
68
- elementTapMonitor.cancelTouch(touch.identifier);
80
+ for (const touch of changed) {
81
+ handOffCancelledTouch(event, touch.identifier, null);
69
82
  }
70
83
  });
71
84
  }, []);
@@ -84,6 +97,50 @@ export function TargetPressBridge({ children }: TargetPressBridgeProps): React.R
84
97
  );
85
98
  }
86
99
 
100
+ /**
101
+ * A finger gesture-handler cancelled. Keep it if the touched view belongs to a
102
+ * gesture-handler control. A scroll container, or a touch with no handler, is
103
+ * dropped the way a system cancel is.
104
+ * `fallbackFiber` is used when this event names no per-finger target.
105
+ */
106
+ function handOffCancelledTouch(
107
+ event: GestureResponderEvent,
108
+ identifier: TouchIdentifier,
109
+ fallbackFiber: AnyFiber | null,
110
+ ): void {
111
+ const elementHas = elementTapMonitor.hasTouch(identifier);
112
+ const tooltipHas = targetPressMonitor.hasTouch(identifier);
113
+ if (!elementHas && !tooltipHas) {
114
+ elementTapMonitor.cancelTouch(identifier);
115
+ targetPressMonitor.cancelTouch(identifier);
116
+ return;
117
+ }
118
+ const stored = elementHas ? elementTapMonitor.startFiber(identifier) : null;
119
+ const fiber = stored ?? fallbackFiber ?? touchTargetFiber(event, identifier);
120
+ const tags = collectGestureHandlerTags(fiber);
121
+ if (tags.length === 0) {
122
+ elementTapMonitor.cancelTouch(identifier);
123
+ targetPressMonitor.cancelTouch(identifier);
124
+ return;
125
+ }
126
+ if (elementHas) elementTapMonitor.handOffTouch(identifier, tags);
127
+ if (tooltipHas) targetPressMonitor.handOffTouch(identifier, tags);
128
+ }
129
+
130
+ function inProgressIdentifiers(): TouchIdentifier[] {
131
+ const seen = new Set<TouchIdentifier>();
132
+ const identifiers: TouchIdentifier[] = [];
133
+ for (const identifier of [
134
+ ...elementTapMonitor.inProgressIdentifiers(),
135
+ ...targetPressMonitor.inProgressIdentifiers(),
136
+ ]) {
137
+ if (seen.has(identifier)) continue;
138
+ seen.add(identifier);
139
+ identifiers.push(identifier);
140
+ }
141
+ return identifiers;
142
+ }
143
+
87
144
  const styles = StyleSheet.create({
88
145
  root: {
89
146
  flex: 1,
@@ -8,6 +8,7 @@ import { PreviewModeBanner } from '../pairing/PreviewModeBanner';
8
8
  import { getPairingController } from '../pairing/pairingRuntime';
9
9
  import { usePairingState } from '../pairing/usePairingState';
10
10
  import { usePreviewBarHold } from '../pairing/usePreviewBarHold';
11
+ import { stepTrapsHostAccessibility } from '../surfaces/hostAccessibilityTrap';
11
12
 
12
13
  import { BannerHost } from './BannerHost';
13
14
  import { FlowRenderer } from './FlowRenderer';
@@ -57,14 +58,7 @@ export function UserflowOverlay({
57
58
  if (!session || !currentStep) {
58
59
  return false;
59
60
  }
60
- const appearance = String(currentStep.appearance).toUpperCase();
61
- if (appearance === 'HIDDEN') {
62
- return false;
63
- }
64
- if (appearance !== 'TOOLTIP') {
65
- return true;
66
- }
67
- return currentStep.tooltipTargetBlocked;
61
+ return stepTrapsHostAccessibility(currentStep);
68
62
  }, [pickerActive, previewConfirming, session, currentStep]);
69
63
 
70
64
  React.useLayoutEffect(() => {
@@ -105,13 +99,17 @@ export function UserflowOverlay({
105
99
  * captureScreen would otherwise include the modal or tooltip.
106
100
  * Remounting reads the same session back.
107
101
  */}
108
- <BannerHost engine={bannerEngine} hidden={pickerActive} />
109
102
  {pickerActive ? null : (
110
103
  <FlowRenderer
111
104
  engine={engine}
112
105
  previewRestartGeneration={pairingState.previewRestartGeneration}
113
106
  />
114
107
  )}
108
+ {/*
109
+ * After flow chrome so BODY_FIRST / BODY_LAST overlay banners stay visible
110
+ * while a tour step (modal, tooltip, condition wait) is still active.
111
+ */}
112
+ <BannerHost engine={bannerEngine} hidden={pickerActive} />
115
113
  <ElementPickerOverlay />
116
114
  </>
117
115
  );
@@ -15,15 +15,15 @@ import type { EdgeInsets } from '../surfaces/safeArea';
15
15
  import { SurfaceLayoutInsetsProvider } from '../surfaces/surfaceLayoutInsets';
16
16
 
17
17
  import { BannerHost } from './BannerHost';
18
+ import { BannerWebViewFlowSpacer } from './bannerFlowSpacer';
18
19
  import { SdkErrorBoundary } from './SdkErrorBoundary';
19
20
  import { TargetPressBridge } from './TargetPressBridge';
20
21
  import { UserflowOverlay } from './UserflowOverlay';
21
22
  import { getBannerSessionEngine } from './bannerEngine';
22
23
  import { BannerEngineContext } from './bannerEngineContext';
23
- import { bannerEdge } from './bannerPlacement';
24
24
  import { getFlowSessionEngine } from './flowEngine';
25
+ import { PushBannerLayoutProvider, type PushBannerLayoutEdge } from './pushBannerLayoutContext';
25
26
  import { isolateSync } from './isolateCall';
26
- import { useBannerSession } from './useBannerSession';
27
27
  import { getUserflowCore } from './userflowCore';
28
28
 
29
29
  export interface UserflowContextValue {
@@ -122,8 +122,9 @@ export function UserflowProvider({
122
122
  const onOverlayError = React.useCallback(() => {
123
123
  setTrapHostAccessibility(false);
124
124
  }, []);
125
- const bannerSession = useBannerSession(bannerEngine);
126
125
  const safeInsets = useUserflowSafeAreaInsets();
126
+ const [pushBannerLayoutEdge, setPushBannerLayoutEdge] =
127
+ React.useState<PushBannerLayoutEdge | null>(null);
127
128
  const [pickerActive, setPickerActive] = React.useState(
128
129
  () => elementPickerController.getState().active,
129
130
  );
@@ -134,15 +135,12 @@ export function UserflowProvider({
134
135
  });
135
136
  }, []);
136
137
 
137
- const banner = bannerSession?.version.banner ?? null;
138
- const flowEdge =
139
- banner && banner.overlay === false && !pickerActive ? bannerEdge(banner.embedMode) : null;
140
138
  const hostInsets: EdgeInsets | null =
141
- flowEdge === 'top' || flowEdge === 'bottom'
139
+ pushBannerLayoutEdge === 'top' || pushBannerLayoutEdge === 'bottom'
142
140
  ? {
143
141
  ...safeInsets,
144
- top: flowEdge === 'top' ? 0 : safeInsets.top,
145
- bottom: flowEdge === 'bottom' ? 0 : safeInsets.bottom,
142
+ top: pushBannerLayoutEdge === 'top' ? 0 : safeInsets.top,
143
+ bottom: pushBannerLayoutEdge === 'bottom' ? 0 : safeInsets.bottom,
146
144
  }
147
145
  : null;
148
146
 
@@ -163,31 +161,44 @@ export function UserflowProvider({
163
161
  <BannerEngineContext.Provider value={bannerEngine}>
164
162
  <UserflowContext.Provider value={contextValue}>
165
163
  <SurfaceLayoutInsetsProvider>
166
- <DoubleTapBridge>
167
- <View style={styles.root} collapsable={false} testID="userflow-root">
168
- <BannerHost engine={bannerEngine} placement="flow" edge="top" hidden={pickerActive} />
169
- <HostSafeArea insets={hostInsets}>{appContent}</HostSafeArea>
170
- <BannerHost
171
- engine={bannerEngine}
172
- placement="flow"
173
- edge="bottom"
174
- hidden={pickerActive}
175
- />
176
- <View style={styles.overlay} pointerEvents="box-none">
177
- <SdkErrorBoundary
178
- scope="overlay"
179
- resetKey={overlayResetKey}
180
- onError={onOverlayError}
181
- >
182
- <UserflowOverlay
183
- engine={engine}
184
- bannerEngine={bannerEngine}
185
- onTrapChange={onTrapChange}
164
+ <PushBannerLayoutProvider onActiveEdgeChange={setPushBannerLayoutEdge}>
165
+ <DoubleTapBridge>
166
+ <View style={styles.root} collapsable={false} testID="userflow-root">
167
+ <View style={styles.flowBannerTop}>
168
+ <BannerHost
169
+ engine={bannerEngine}
170
+ placement="flow"
171
+ edge="top"
172
+ hidden={pickerActive}
186
173
  />
187
- </SdkErrorBoundary>
174
+ <BannerWebViewFlowSpacer engine={bannerEngine} edge="top" />
175
+ </View>
176
+ <HostSafeArea insets={hostInsets}>{appContent}</HostSafeArea>
177
+ <View style={styles.flowBannerBottom}>
178
+ <BannerHost
179
+ engine={bannerEngine}
180
+ placement="flow"
181
+ edge="bottom"
182
+ hidden={pickerActive}
183
+ />
184
+ <BannerWebViewFlowSpacer engine={bannerEngine} edge="bottom" />
185
+ </View>
186
+ <View style={styles.overlay} pointerEvents="box-none">
187
+ <SdkErrorBoundary
188
+ scope="overlay"
189
+ resetKey={overlayResetKey}
190
+ onError={onOverlayError}
191
+ >
192
+ <UserflowOverlay
193
+ engine={engine}
194
+ bannerEngine={bannerEngine}
195
+ onTrapChange={onTrapChange}
196
+ />
197
+ </SdkErrorBoundary>
198
+ </View>
188
199
  </View>
189
- </View>
190
- </DoubleTapBridge>
200
+ </DoubleTapBridge>
201
+ </PushBannerLayoutProvider>
191
202
  </SurfaceLayoutInsetsProvider>
192
203
  </UserflowContext.Provider>
193
204
  </BannerEngineContext.Provider>
@@ -228,7 +239,20 @@ const styles = StyleSheet.create({
228
239
  appContent: {
229
240
  flex: 1,
230
241
  },
242
+ flowBannerTop: {
243
+ zIndex: 1,
244
+ elevation: 1,
245
+ pointerEvents: 'box-none',
246
+ },
247
+ flowBannerBottom: {
248
+ zIndex: 1,
249
+ elevation: 1,
250
+ pointerEvents: 'box-none',
251
+ },
231
252
  overlay: {
232
253
  ...ABSOLUTE_FILL,
254
+ // Above flow banner slots so WebView banners receive touches (spacers are layout-only).
255
+ zIndex: 2,
256
+ elevation: 2,
233
257
  },
234
258
  });