@userflow-tech/react-native 0.4.5 → 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.
- package/README.md +7 -2
- package/docs/anchoring.md +6 -1
- package/docs/troubleshooting.md +26 -0
- package/lib/commonjs/anchors/AutoAnchorRegistry.js +144 -34
- package/lib/commonjs/anchors/AutoAnchorRegistry.js.map +1 -1
- package/lib/commonjs/anchors/animationFrame.js +29 -1
- package/lib/commonjs/anchors/animationFrame.js.map +1 -1
- package/lib/commonjs/anchors/appActive.js +61 -0
- package/lib/commonjs/anchors/appActive.js.map +1 -0
- package/lib/commonjs/anchors/elementConditionEvaluator.js +25 -8
- package/lib/commonjs/anchors/elementConditionEvaluator.js.map +1 -1
- package/lib/commonjs/anchors/elementTapMonitor.js +67 -12
- package/lib/commonjs/anchors/elementTapMonitor.js.map +1 -1
- package/lib/commonjs/anchors/elementTargetMatch.js +33 -7
- package/lib/commonjs/anchors/elementTargetMatch.js.map +1 -1
- package/lib/commonjs/anchors/fiber/fiberInternals.js +66 -0
- package/lib/commonjs/anchors/fiber/fiberInternals.js.map +1 -1
- package/lib/commonjs/anchors/fiber/indexHostFibers.js +4 -3
- package/lib/commonjs/anchors/fiber/indexHostFibers.js.map +1 -1
- package/lib/commonjs/anchors/fiber/resolveFiberPath.js +30 -15
- package/lib/commonjs/anchors/fiber/resolveFiberPath.js.map +1 -1
- package/lib/commonjs/anchors/fiberAnchorCache.js +20 -0
- package/lib/commonjs/anchors/fiberAnchorCache.js.map +1 -1
- package/lib/commonjs/anchors/gestureHandlerHandoff.js +304 -0
- package/lib/commonjs/anchors/gestureHandlerHandoff.js.map +1 -0
- package/lib/commonjs/anchors/resolveAnchorHost.js +6 -0
- package/lib/commonjs/anchors/resolveAnchorHost.js.map +1 -1
- package/lib/commonjs/anchors/resolveAutoAnchorHost.js +11 -6
- package/lib/commonjs/anchors/resolveAutoAnchorHost.js.map +1 -1
- package/lib/commonjs/anchors/resolveElementTargets.js +63 -8
- package/lib/commonjs/anchors/resolveElementTargets.js.map +1 -1
- package/lib/commonjs/anchors/semanticMatcher.js +43 -21
- package/lib/commonjs/anchors/semanticMatcher.js.map +1 -1
- package/lib/commonjs/anchors/tapSlop.js +16 -0
- package/lib/commonjs/anchors/tapSlop.js.map +1 -0
- package/lib/commonjs/anchors/targetPressMonitor.js +66 -12
- package/lib/commonjs/anchors/targetPressMonitor.js.map +1 -1
- package/lib/commonjs/authoring/fingerprintFromInstance.js +5 -9
- package/lib/commonjs/authoring/fingerprintFromInstance.js.map +1 -1
- package/lib/commonjs/content/RichContentRenderer.js +3 -3
- package/lib/commonjs/content/RichContentRenderer.js.map +1 -1
- package/lib/commonjs/content/openSafeUrl.js +3 -1
- package/lib/commonjs/content/openSafeUrl.js.map +1 -1
- package/lib/commonjs/expo-router/useUserflowExpoRouter.js +6 -0
- package/lib/commonjs/expo-router/useUserflowExpoRouter.js.map +1 -1
- package/lib/commonjs/index.js +19 -5
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/navigation/navigateUrlUtils.js +105 -0
- package/lib/commonjs/navigation/navigateUrlUtils.js.map +1 -0
- package/lib/commonjs/navigation/openExternalNavigateUrl.js +14 -0
- package/lib/commonjs/navigation/openExternalNavigateUrl.js.map +1 -0
- package/lib/commonjs/navigation/openFlowNavigateUrl.js +47 -41
- package/lib/commonjs/navigation/openFlowNavigateUrl.js.map +1 -1
- package/lib/commonjs/pairing/PairingController.js +3 -1
- package/lib/commonjs/pairing/PairingController.js.map +1 -1
- package/lib/commonjs/runtime/BannerHost.js +38 -29
- package/lib/commonjs/runtime/BannerHost.js.map +1 -1
- package/lib/commonjs/runtime/TargetPressBridge.js +55 -7
- package/lib/commonjs/runtime/TargetPressBridge.js.map +1 -1
- package/lib/commonjs/runtime/UserflowOverlay.js +5 -11
- package/lib/commonjs/runtime/UserflowOverlay.js.map +1 -1
- package/lib/commonjs/runtime/UserflowProvider.js +66 -40
- package/lib/commonjs/runtime/UserflowProvider.js.map +1 -1
- package/lib/commonjs/runtime/bannerEngine.js +8 -2
- package/lib/commonjs/runtime/bannerEngine.js.map +1 -1
- package/lib/commonjs/runtime/bannerFlowSpacer.js +71 -0
- package/lib/commonjs/runtime/bannerFlowSpacer.js.map +1 -0
- package/lib/commonjs/runtime/flowEngine.js +11 -0
- package/lib/commonjs/runtime/flowEngine.js.map +1 -1
- package/lib/commonjs/runtime/previewStart.js +39 -0
- package/lib/commonjs/runtime/previewStart.js.map +1 -0
- package/lib/commonjs/runtime/pushBannerLayoutContext.js +98 -0
- package/lib/commonjs/runtime/pushBannerLayoutContext.js.map +1 -0
- package/lib/commonjs/screenTracker.js +12 -0
- package/lib/commonjs/screenTracker.js.map +1 -1
- package/lib/commonjs/surfaces/BannerBar.js +79 -61
- package/lib/commonjs/surfaces/BannerBar.js.map +1 -1
- package/lib/commonjs/surfaces/BannerSurface.js +26 -0
- package/lib/commonjs/surfaces/BannerSurface.js.map +1 -1
- package/lib/commonjs/surfaces/TooltipSurface.js +43 -41
- package/lib/commonjs/surfaces/TooltipSurface.js.map +1 -1
- package/lib/commonjs/surfaces/bannerBarLayout.js +77 -10
- package/lib/commonjs/surfaces/bannerBarLayout.js.map +1 -1
- package/lib/commonjs/surfaces/bannerWebView/BannerWebViewBar.js +112 -63
- package/lib/commonjs/surfaces/bannerWebView/BannerWebViewBar.js.map +1 -1
- package/lib/commonjs/surfaces/bannerWebView/buildCustomBannerHtml.js +59 -11
- package/lib/commonjs/surfaces/bannerWebView/buildCustomBannerHtml.js.map +1 -1
- package/lib/commonjs/surfaces/hostAccessibilityTrap.js +28 -0
- package/lib/commonjs/surfaces/hostAccessibilityTrap.js.map +1 -0
- package/lib/commonjs/surfaces/resolveBannerTheme.js +6 -3
- package/lib/commonjs/surfaces/resolveBannerTheme.js.map +1 -1
- package/lib/commonjs/surfaces/tooltip/TooltipBubble.js +3 -2
- package/lib/commonjs/surfaces/tooltip/TooltipBubble.js.map +1 -1
- package/lib/commonjs/surfaces/tooltip/targetSearchSchedule.js +134 -0
- package/lib/commonjs/surfaces/tooltip/targetSearchSchedule.js.map +1 -0
- package/lib/commonjs/version.js +1 -1
- package/lib/module/anchors/AutoAnchorRegistry.js +145 -35
- package/lib/module/anchors/AutoAnchorRegistry.js.map +1 -1
- package/lib/module/anchors/animationFrame.js +29 -2
- package/lib/module/anchors/animationFrame.js.map +1 -1
- package/lib/module/anchors/appActive.js +57 -0
- package/lib/module/anchors/appActive.js.map +1 -0
- package/lib/module/anchors/elementConditionEvaluator.js +26 -9
- package/lib/module/anchors/elementConditionEvaluator.js.map +1 -1
- package/lib/module/anchors/elementTapMonitor.js +67 -12
- package/lib/module/anchors/elementTapMonitor.js.map +1 -1
- package/lib/module/anchors/elementTargetMatch.js +32 -7
- package/lib/module/anchors/elementTargetMatch.js.map +1 -1
- package/lib/module/anchors/fiber/fiberInternals.js +65 -0
- package/lib/module/anchors/fiber/fiberInternals.js.map +1 -1
- package/lib/module/anchors/fiber/indexHostFibers.js +4 -3
- package/lib/module/anchors/fiber/indexHostFibers.js.map +1 -1
- package/lib/module/anchors/fiber/resolveFiberPath.js +30 -15
- package/lib/module/anchors/fiber/resolveFiberPath.js.map +1 -1
- package/lib/module/anchors/fiberAnchorCache.js +19 -0
- package/lib/module/anchors/fiberAnchorCache.js.map +1 -1
- package/lib/module/anchors/gestureHandlerHandoff.js +298 -0
- package/lib/module/anchors/gestureHandlerHandoff.js.map +1 -0
- package/lib/module/anchors/resolveAnchorHost.js +1 -0
- package/lib/module/anchors/resolveAnchorHost.js.map +1 -1
- package/lib/module/anchors/resolveAutoAnchorHost.js +11 -6
- package/lib/module/anchors/resolveAutoAnchorHost.js.map +1 -1
- package/lib/module/anchors/resolveElementTargets.js +63 -8
- package/lib/module/anchors/resolveElementTargets.js.map +1 -1
- package/lib/module/anchors/semanticMatcher.js +43 -21
- package/lib/module/anchors/semanticMatcher.js.map +1 -1
- package/lib/module/anchors/tapSlop.js +11 -0
- package/lib/module/anchors/tapSlop.js.map +1 -0
- package/lib/module/anchors/targetPressMonitor.js +53 -8
- package/lib/module/anchors/targetPressMonitor.js.map +1 -1
- package/lib/module/authoring/fingerprintFromInstance.js +6 -10
- package/lib/module/authoring/fingerprintFromInstance.js.map +1 -1
- package/lib/module/content/RichContentRenderer.js +3 -3
- package/lib/module/content/RichContentRenderer.js.map +1 -1
- package/lib/module/content/openSafeUrl.js +3 -1
- package/lib/module/content/openSafeUrl.js.map +1 -1
- package/lib/module/expo-router/useUserflowExpoRouter.js +7 -1
- package/lib/module/expo-router/useUserflowExpoRouter.js.map +1 -1
- package/lib/module/index.js +22 -7
- package/lib/module/index.js.map +1 -1
- package/lib/module/navigation/navigateUrlUtils.js +94 -0
- package/lib/module/navigation/navigateUrlUtils.js.map +1 -0
- package/lib/module/navigation/openExternalNavigateUrl.js +11 -0
- package/lib/module/navigation/openExternalNavigateUrl.js.map +1 -0
- package/lib/module/navigation/openFlowNavigateUrl.js +22 -36
- package/lib/module/navigation/openFlowNavigateUrl.js.map +1 -1
- package/lib/module/pairing/PairingController.js +3 -1
- package/lib/module/pairing/PairingController.js.map +1 -1
- package/lib/module/runtime/BannerHost.js +38 -29
- package/lib/module/runtime/BannerHost.js.map +1 -1
- package/lib/module/runtime/TargetPressBridge.js +56 -8
- package/lib/module/runtime/TargetPressBridge.js.map +1 -1
- package/lib/module/runtime/UserflowOverlay.js +5 -11
- package/lib/module/runtime/UserflowOverlay.js.map +1 -1
- package/lib/module/runtime/UserflowProvider.js +66 -40
- package/lib/module/runtime/UserflowProvider.js.map +1 -1
- package/lib/module/runtime/bannerEngine.js +7 -2
- package/lib/module/runtime/bannerEngine.js.map +1 -1
- package/lib/module/runtime/bannerFlowSpacer.js +65 -0
- package/lib/module/runtime/bannerFlowSpacer.js.map +1 -0
- package/lib/module/runtime/flowEngine.js +11 -0
- package/lib/module/runtime/flowEngine.js.map +1 -1
- package/lib/module/runtime/previewStart.js +35 -0
- package/lib/module/runtime/previewStart.js.map +1 -0
- package/lib/module/runtime/pushBannerLayoutContext.js +91 -0
- package/lib/module/runtime/pushBannerLayoutContext.js.map +1 -0
- package/lib/module/screenTracker.js +11 -0
- package/lib/module/screenTracker.js.map +1 -1
- package/lib/module/surfaces/BannerBar.js +80 -62
- package/lib/module/surfaces/BannerBar.js.map +1 -1
- package/lib/module/surfaces/BannerSurface.js +26 -0
- package/lib/module/surfaces/BannerSurface.js.map +1 -1
- package/lib/module/surfaces/TooltipSurface.js +44 -42
- package/lib/module/surfaces/TooltipSurface.js.map +1 -1
- package/lib/module/surfaces/bannerBarLayout.js +72 -11
- package/lib/module/surfaces/bannerBarLayout.js.map +1 -1
- package/lib/module/surfaces/bannerWebView/BannerWebViewBar.js +113 -64
- package/lib/module/surfaces/bannerWebView/BannerWebViewBar.js.map +1 -1
- package/lib/module/surfaces/bannerWebView/buildCustomBannerHtml.js +59 -11
- package/lib/module/surfaces/bannerWebView/buildCustomBannerHtml.js.map +1 -1
- package/lib/module/surfaces/hostAccessibilityTrap.js +24 -0
- package/lib/module/surfaces/hostAccessibilityTrap.js.map +1 -0
- package/lib/module/surfaces/resolveBannerTheme.js +6 -3
- package/lib/module/surfaces/resolveBannerTheme.js.map +1 -1
- package/lib/module/surfaces/tooltip/TooltipBubble.js +3 -2
- package/lib/module/surfaces/tooltip/TooltipBubble.js.map +1 -1
- package/lib/module/surfaces/tooltip/targetSearchSchedule.js +128 -0
- package/lib/module/surfaces/tooltip/targetSearchSchedule.js.map +1 -0
- package/lib/module/version.js +1 -1
- package/lib/typescript/commonjs/src/anchors/AutoAnchorRegistry.d.ts +36 -2
- package/lib/typescript/commonjs/src/anchors/AutoAnchorRegistry.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/anchors/animationFrame.d.ts +0 -4
- package/lib/typescript/commonjs/src/anchors/animationFrame.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/anchors/appActive.d.ts +8 -0
- package/lib/typescript/commonjs/src/anchors/appActive.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/anchors/elementTapMonitor.d.ts +17 -0
- package/lib/typescript/commonjs/src/anchors/elementTapMonitor.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/anchors/elementTargetMatch.d.ts +7 -0
- package/lib/typescript/commonjs/src/anchors/elementTargetMatch.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/anchors/fiber/fiberInternals.d.ts +7 -0
- package/lib/typescript/commonjs/src/anchors/fiber/fiberInternals.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/anchors/fiber/indexHostFibers.d.ts +3 -2
- package/lib/typescript/commonjs/src/anchors/fiber/indexHostFibers.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/anchors/fiber/resolveFiberPath.d.ts +3 -0
- package/lib/typescript/commonjs/src/anchors/fiber/resolveFiberPath.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/anchors/fiberAnchorCache.d.ts +5 -0
- package/lib/typescript/commonjs/src/anchors/fiberAnchorCache.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/anchors/gestureHandlerHandoff.d.ts +70 -0
- package/lib/typescript/commonjs/src/anchors/gestureHandlerHandoff.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/anchors/resolveAnchorHost.d.ts +1 -0
- package/lib/typescript/commonjs/src/anchors/resolveAnchorHost.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/anchors/resolveAutoAnchorHost.d.ts +11 -4
- package/lib/typescript/commonjs/src/anchors/resolveAutoAnchorHost.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/anchors/resolveElementTargets.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/anchors/semanticMatcher.d.ts +2 -0
- package/lib/typescript/commonjs/src/anchors/semanticMatcher.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/anchors/tapSlop.d.ts +9 -0
- package/lib/typescript/commonjs/src/anchors/tapSlop.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/anchors/targetPressMonitor.d.ts +13 -8
- package/lib/typescript/commonjs/src/anchors/targetPressMonitor.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/authoring/fingerprintFromInstance.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/content/RichContentRenderer.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/content/openSafeUrl.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/expo-router/useUserflowExpoRouter.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/index.d.ts +6 -5
- package/lib/typescript/commonjs/src/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/navigation/navigateUrlUtils.d.ts +15 -0
- package/lib/typescript/commonjs/src/navigation/navigateUrlUtils.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/navigation/openExternalNavigateUrl.d.ts +3 -0
- package/lib/typescript/commonjs/src/navigation/openExternalNavigateUrl.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/navigation/openFlowNavigateUrl.d.ts +2 -5
- package/lib/typescript/commonjs/src/navigation/openFlowNavigateUrl.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/pairing/PairingController.d.ts +6 -0
- package/lib/typescript/commonjs/src/pairing/PairingController.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/runtime/BannerHost.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/runtime/TargetPressBridge.d.ts +3 -0
- package/lib/typescript/commonjs/src/runtime/TargetPressBridge.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/runtime/UserflowOverlay.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/runtime/UserflowProvider.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/runtime/bannerEngine.d.ts +5 -1
- package/lib/typescript/commonjs/src/runtime/bannerEngine.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/runtime/bannerFlowSpacer.d.ts +15 -0
- package/lib/typescript/commonjs/src/runtime/bannerFlowSpacer.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/runtime/flowEngine.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/runtime/previewStart.d.ts +13 -0
- package/lib/typescript/commonjs/src/runtime/previewStart.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/runtime/pushBannerLayoutContext.d.ts +17 -0
- package/lib/typescript/commonjs/src/runtime/pushBannerLayoutContext.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/screenTracker.d.ts +6 -0
- package/lib/typescript/commonjs/src/screenTracker.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/surfaces/BannerBar.d.ts +3 -1
- package/lib/typescript/commonjs/src/surfaces/BannerBar.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/surfaces/BannerSurface.d.ts +5 -1
- package/lib/typescript/commonjs/src/surfaces/BannerSurface.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/surfaces/TooltipSurface.d.ts +1 -1
- package/lib/typescript/commonjs/src/surfaces/TooltipSurface.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/surfaces/bannerBarLayout.d.ts +17 -0
- package/lib/typescript/commonjs/src/surfaces/bannerBarLayout.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/surfaces/bannerWebView/BannerWebViewBar.d.ts +3 -1
- package/lib/typescript/commonjs/src/surfaces/bannerWebView/BannerWebViewBar.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/surfaces/bannerWebView/buildCustomBannerHtml.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/surfaces/hostAccessibilityTrap.d.ts +14 -0
- package/lib/typescript/commonjs/src/surfaces/hostAccessibilityTrap.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/surfaces/resolveBannerTheme.d.ts +4 -1
- package/lib/typescript/commonjs/src/surfaces/resolveBannerTheme.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/surfaces/tooltip/TooltipBubble.d.ts +7 -1
- package/lib/typescript/commonjs/src/surfaces/tooltip/TooltipBubble.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/surfaces/tooltip/targetSearchSchedule.d.ts +60 -0
- package/lib/typescript/commonjs/src/surfaces/tooltip/targetSearchSchedule.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/version.d.ts +1 -1
- package/lib/typescript/module/src/anchors/AutoAnchorRegistry.d.ts +36 -2
- package/lib/typescript/module/src/anchors/AutoAnchorRegistry.d.ts.map +1 -1
- package/lib/typescript/module/src/anchors/animationFrame.d.ts +0 -4
- package/lib/typescript/module/src/anchors/animationFrame.d.ts.map +1 -1
- package/lib/typescript/module/src/anchors/appActive.d.ts +8 -0
- package/lib/typescript/module/src/anchors/appActive.d.ts.map +1 -0
- package/lib/typescript/module/src/anchors/elementTapMonitor.d.ts +17 -0
- package/lib/typescript/module/src/anchors/elementTapMonitor.d.ts.map +1 -1
- package/lib/typescript/module/src/anchors/elementTargetMatch.d.ts +7 -0
- package/lib/typescript/module/src/anchors/elementTargetMatch.d.ts.map +1 -1
- package/lib/typescript/module/src/anchors/fiber/fiberInternals.d.ts +7 -0
- package/lib/typescript/module/src/anchors/fiber/fiberInternals.d.ts.map +1 -1
- package/lib/typescript/module/src/anchors/fiber/indexHostFibers.d.ts +3 -2
- package/lib/typescript/module/src/anchors/fiber/indexHostFibers.d.ts.map +1 -1
- package/lib/typescript/module/src/anchors/fiber/resolveFiberPath.d.ts +3 -0
- package/lib/typescript/module/src/anchors/fiber/resolveFiberPath.d.ts.map +1 -1
- package/lib/typescript/module/src/anchors/fiberAnchorCache.d.ts +5 -0
- package/lib/typescript/module/src/anchors/fiberAnchorCache.d.ts.map +1 -1
- package/lib/typescript/module/src/anchors/gestureHandlerHandoff.d.ts +70 -0
- package/lib/typescript/module/src/anchors/gestureHandlerHandoff.d.ts.map +1 -0
- package/lib/typescript/module/src/anchors/resolveAnchorHost.d.ts +1 -0
- package/lib/typescript/module/src/anchors/resolveAnchorHost.d.ts.map +1 -1
- package/lib/typescript/module/src/anchors/resolveAutoAnchorHost.d.ts +11 -4
- package/lib/typescript/module/src/anchors/resolveAutoAnchorHost.d.ts.map +1 -1
- package/lib/typescript/module/src/anchors/resolveElementTargets.d.ts.map +1 -1
- package/lib/typescript/module/src/anchors/semanticMatcher.d.ts +2 -0
- package/lib/typescript/module/src/anchors/semanticMatcher.d.ts.map +1 -1
- package/lib/typescript/module/src/anchors/tapSlop.d.ts +9 -0
- package/lib/typescript/module/src/anchors/tapSlop.d.ts.map +1 -0
- package/lib/typescript/module/src/anchors/targetPressMonitor.d.ts +13 -8
- package/lib/typescript/module/src/anchors/targetPressMonitor.d.ts.map +1 -1
- package/lib/typescript/module/src/authoring/fingerprintFromInstance.d.ts.map +1 -1
- package/lib/typescript/module/src/content/RichContentRenderer.d.ts.map +1 -1
- package/lib/typescript/module/src/content/openSafeUrl.d.ts.map +1 -1
- package/lib/typescript/module/src/expo-router/useUserflowExpoRouter.d.ts.map +1 -1
- package/lib/typescript/module/src/index.d.ts +6 -5
- package/lib/typescript/module/src/index.d.ts.map +1 -1
- package/lib/typescript/module/src/navigation/navigateUrlUtils.d.ts +15 -0
- package/lib/typescript/module/src/navigation/navigateUrlUtils.d.ts.map +1 -0
- package/lib/typescript/module/src/navigation/openExternalNavigateUrl.d.ts +3 -0
- package/lib/typescript/module/src/navigation/openExternalNavigateUrl.d.ts.map +1 -0
- package/lib/typescript/module/src/navigation/openFlowNavigateUrl.d.ts +2 -5
- package/lib/typescript/module/src/navigation/openFlowNavigateUrl.d.ts.map +1 -1
- package/lib/typescript/module/src/pairing/PairingController.d.ts +6 -0
- package/lib/typescript/module/src/pairing/PairingController.d.ts.map +1 -1
- package/lib/typescript/module/src/runtime/BannerHost.d.ts.map +1 -1
- package/lib/typescript/module/src/runtime/TargetPressBridge.d.ts +3 -0
- package/lib/typescript/module/src/runtime/TargetPressBridge.d.ts.map +1 -1
- package/lib/typescript/module/src/runtime/UserflowOverlay.d.ts.map +1 -1
- package/lib/typescript/module/src/runtime/UserflowProvider.d.ts.map +1 -1
- package/lib/typescript/module/src/runtime/bannerEngine.d.ts +5 -1
- package/lib/typescript/module/src/runtime/bannerEngine.d.ts.map +1 -1
- package/lib/typescript/module/src/runtime/bannerFlowSpacer.d.ts +15 -0
- package/lib/typescript/module/src/runtime/bannerFlowSpacer.d.ts.map +1 -0
- package/lib/typescript/module/src/runtime/flowEngine.d.ts.map +1 -1
- package/lib/typescript/module/src/runtime/previewStart.d.ts +13 -0
- package/lib/typescript/module/src/runtime/previewStart.d.ts.map +1 -0
- package/lib/typescript/module/src/runtime/pushBannerLayoutContext.d.ts +17 -0
- package/lib/typescript/module/src/runtime/pushBannerLayoutContext.d.ts.map +1 -0
- package/lib/typescript/module/src/screenTracker.d.ts +6 -0
- package/lib/typescript/module/src/screenTracker.d.ts.map +1 -1
- package/lib/typescript/module/src/surfaces/BannerBar.d.ts +3 -1
- package/lib/typescript/module/src/surfaces/BannerBar.d.ts.map +1 -1
- package/lib/typescript/module/src/surfaces/BannerSurface.d.ts +5 -1
- package/lib/typescript/module/src/surfaces/BannerSurface.d.ts.map +1 -1
- package/lib/typescript/module/src/surfaces/TooltipSurface.d.ts +1 -1
- package/lib/typescript/module/src/surfaces/TooltipSurface.d.ts.map +1 -1
- package/lib/typescript/module/src/surfaces/bannerBarLayout.d.ts +17 -0
- package/lib/typescript/module/src/surfaces/bannerBarLayout.d.ts.map +1 -1
- package/lib/typescript/module/src/surfaces/bannerWebView/BannerWebViewBar.d.ts +3 -1
- package/lib/typescript/module/src/surfaces/bannerWebView/BannerWebViewBar.d.ts.map +1 -1
- package/lib/typescript/module/src/surfaces/bannerWebView/buildCustomBannerHtml.d.ts.map +1 -1
- package/lib/typescript/module/src/surfaces/hostAccessibilityTrap.d.ts +14 -0
- package/lib/typescript/module/src/surfaces/hostAccessibilityTrap.d.ts.map +1 -0
- package/lib/typescript/module/src/surfaces/resolveBannerTheme.d.ts +4 -1
- package/lib/typescript/module/src/surfaces/resolveBannerTheme.d.ts.map +1 -1
- package/lib/typescript/module/src/surfaces/tooltip/TooltipBubble.d.ts +7 -1
- package/lib/typescript/module/src/surfaces/tooltip/TooltipBubble.d.ts.map +1 -1
- package/lib/typescript/module/src/surfaces/tooltip/targetSearchSchedule.d.ts +60 -0
- package/lib/typescript/module/src/surfaces/tooltip/targetSearchSchedule.d.ts.map +1 -0
- package/lib/typescript/module/src/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/anchors/AutoAnchorRegistry.ts +166 -35
- package/src/anchors/animationFrame.ts +31 -1
- package/src/anchors/appActive.ts +63 -0
- package/src/anchors/elementConditionEvaluator.ts +29 -12
- package/src/anchors/elementTapMonitor.ts +68 -10
- package/src/anchors/elementTargetMatch.ts +34 -7
- package/src/anchors/fiber/fiberInternals.ts +68 -0
- package/src/anchors/fiber/indexHostFibers.ts +8 -3
- package/src/anchors/fiber/resolveFiberPath.ts +25 -16
- package/src/anchors/fiberAnchorCache.ts +19 -0
- package/src/anchors/gestureHandlerHandoff.ts +356 -0
- package/src/anchors/resolveAnchorHost.ts +2 -0
- package/src/anchors/resolveAutoAnchorHost.ts +18 -8
- package/src/anchors/resolveElementTargets.ts +64 -7
- package/src/anchors/semanticMatcher.ts +48 -27
- package/src/anchors/tapSlop.ts +18 -0
- package/src/anchors/targetPressMonitor.ts +56 -19
- package/src/authoring/fingerprintFromInstance.ts +4 -5
- package/src/content/RichContentRenderer.tsx +4 -3
- package/src/content/openSafeUrl.ts +3 -1
- package/src/expo-router/useUserflowExpoRouter.ts +10 -1
- package/src/index.ts +20 -9
- package/src/navigation/navigateUrlUtils.ts +100 -0
- package/src/navigation/openExternalNavigateUrl.ts +9 -0
- package/src/navigation/openFlowNavigateUrl.ts +36 -36
- package/src/pairing/PairingController.ts +9 -1
- package/src/runtime/BannerHost.tsx +41 -23
- package/src/runtime/TargetPressBridge.tsx +66 -9
- package/src/runtime/UserflowOverlay.tsx +7 -9
- package/src/runtime/UserflowProvider.tsx +56 -32
- package/src/runtime/bannerEngine.ts +10 -2
- package/src/runtime/bannerFlowSpacer.tsx +70 -0
- package/src/runtime/flowEngine.ts +11 -0
- package/src/runtime/previewStart.ts +49 -0
- package/src/runtime/pushBannerLayoutContext.tsx +121 -0
- package/src/screenTracker.ts +11 -0
- package/src/surfaces/BannerBar.tsx +93 -55
- package/src/surfaces/BannerSurface.tsx +59 -3
- package/src/surfaces/TooltipSurface.tsx +63 -51
- package/src/surfaces/bannerBarLayout.ts +80 -7
- package/src/surfaces/bannerWebView/BannerWebViewBar.tsx +149 -57
- package/src/surfaces/bannerWebView/buildCustomBannerHtml.ts +63 -11
- package/src/surfaces/hostAccessibilityTrap.ts +25 -0
- package/src/surfaces/resolveBannerTheme.ts +14 -3
- package/src/surfaces/tooltip/TooltipBubble.tsx +8 -1
- package/src/surfaces/tooltip/targetSearchSchedule.ts +140 -0
- package/src/version.ts +1 -1
- package/vendor/core/dist/engine/BannerSessionEngine.d.ts +29 -2
- package/vendor/core/dist/engine/BannerSessionEngine.d.ts.map +1 -1
- package/vendor/core/dist/engine/BannerSessionEngine.js +87 -6
- package/vendor/core/dist/engine/BannerSessionEngine.js.map +1 -1
- package/vendor/core/dist/engine/ClientConditionEngine.d.ts.map +1 -1
- package/vendor/core/dist/engine/ClientConditionEngine.js +30 -7
- package/vendor/core/dist/engine/ClientConditionEngine.js.map +1 -1
- package/vendor/core/dist/engine/PairingEngine.d.ts +6 -1
- package/vendor/core/dist/engine/PairingEngine.d.ts.map +1 -1
- package/vendor/core/dist/engine/PairingEngine.js +23 -3
- package/vendor/core/dist/engine/PairingEngine.js.map +1 -1
- package/vendor/core/dist/engine/handleActions.d.ts.map +1 -1
- package/vendor/core/dist/engine/handleActions.js +67 -2
- package/vendor/core/dist/engine/handleActions.js.map +1 -1
- package/vendor/core/dist/version.d.ts +1 -1
- package/vendor/core/dist/version.js +1 -1
- package/vendor/core/package.json +1 -1
- package/vendor/protocol/package.json +1 -1
|
@@ -9,7 +9,7 @@ import type { AutoAnchorInstance } from './AutoAnchorRegistry';
|
|
|
9
9
|
import type { AnyFiber } from './fiber/fiberInternals';
|
|
10
10
|
import { fiberFromPublicInstance } from './fiber/fiberInternals';
|
|
11
11
|
import { createFiberMeasureInWindow } from './fiber/measureHostFiber';
|
|
12
|
-
import { resolveFiberPath } from './fiber/resolveFiberPath';
|
|
12
|
+
import { resolveFiberPath, type FiberPathMissReason } from './fiber/resolveFiberPath';
|
|
13
13
|
import { createVisibleInstanceFilter } from './isInstanceOnVisibleScreen';
|
|
14
14
|
import { resolveAnchorHost } from './resolveAnchorHost';
|
|
15
15
|
import { matchFingerprint, type MatchResult } from './semanticMatcher';
|
|
@@ -28,7 +28,15 @@ export type AutoAnchorResolution =
|
|
|
28
28
|
}
|
|
29
29
|
| { status: 'ambiguous'; match?: MatchResult }
|
|
30
30
|
| { status: 'absent'; match?: MatchResult }
|
|
31
|
-
| {
|
|
31
|
+
| {
|
|
32
|
+
status: 'unknown';
|
|
33
|
+
match?: MatchResult;
|
|
34
|
+
/**
|
|
35
|
+
* Set when a fiber path did not resolve. Element conditions treat
|
|
36
|
+
* `no-match` as absent and `no-root` / `empty` as unknown.
|
|
37
|
+
*/
|
|
38
|
+
fiberMiss?: FiberPathMissReason;
|
|
39
|
+
};
|
|
32
40
|
|
|
33
41
|
type MeasureInWindowCallback = (x: number, y: number, width: number, height: number) => void;
|
|
34
42
|
|
|
@@ -121,7 +129,8 @@ export function resolveScoredAutoAnchor(fp: MobileFingerprint): AutoAnchorResolu
|
|
|
121
129
|
if (visible.instance) return mapMatch(visible);
|
|
122
130
|
|
|
123
131
|
if (visible.reason === 'no-candidates') {
|
|
124
|
-
|
|
132
|
+
// Nothing can commit between the two matches, so the first read stands.
|
|
133
|
+
const any = matchFingerprint(fp, { liveContentFresh: true });
|
|
125
134
|
if (any.instance) return { status: 'absent', match: any };
|
|
126
135
|
if (any.reason === 'all-contradicted') return mapMatch(any);
|
|
127
136
|
}
|
|
@@ -136,10 +145,11 @@ export function resolveScoredAutoAnchor(fp: MobileFingerprint): AutoAnchorResolu
|
|
|
136
145
|
* carries a real `testID` / `userflowId` / non-`uf_` `nativeID` still resolves
|
|
137
146
|
* under Babel `stampOnly: true` (no auto-registry population).
|
|
138
147
|
*
|
|
139
|
-
* Scored matches run over `autoAnchorRegistry
|
|
140
|
-
*
|
|
141
|
-
*
|
|
142
|
-
* are skipped the same way the fiber scan
|
|
148
|
+
* Scored matches run over `autoAnchorRegistry`. A covered screen and a
|
|
149
|
+
* contradicted fingerprint are `absent`. Weak, missing, or tied evidence stays
|
|
150
|
+
* `unknown` here; element conditions decide which of those count as absent.
|
|
151
|
+
* Hosts on a covered navigator screen are skipped the same way the fiber scan
|
|
152
|
+
* skips them.
|
|
143
153
|
*/
|
|
144
154
|
export function resolveAutoAnchorHost(
|
|
145
155
|
autoData: string | MobileAutoData | null | undefined,
|
|
@@ -159,7 +169,7 @@ export function resolveAutoAnchorHost(
|
|
|
159
169
|
};
|
|
160
170
|
}
|
|
161
171
|
if (fiberHit.status === 'ambiguous') return { status: 'ambiguous' };
|
|
162
|
-
return { status: 'unknown' };
|
|
172
|
+
return { status: 'unknown', fiberMiss: fiberHit.reason };
|
|
163
173
|
}
|
|
164
174
|
|
|
165
175
|
const exactId = exactIdFromFingerprint(fp);
|
|
@@ -6,9 +6,16 @@
|
|
|
6
6
|
* `testID`, then a real `nativeID`) use that same multi-host lookup, and fall
|
|
7
7
|
* through to scoring only when nothing matched.
|
|
8
8
|
*/
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
decodeMobileAutoData,
|
|
11
|
+
type FlowSelectorFragment,
|
|
12
|
+
type MobileAutoData,
|
|
13
|
+
} from '@userflow-tech/protocol';
|
|
14
|
+
|
|
15
|
+
import { screenIdFromLocation, getCurrentScreenLocation } from '../screenTracker';
|
|
10
16
|
|
|
11
17
|
import { type AnchorHost, anchorRegistry } from './AnchorRegistry';
|
|
18
|
+
import { autoAnchorRegistry } from './AutoAnchorRegistry';
|
|
12
19
|
import type { ElementTap } from './elementTapMonitor';
|
|
13
20
|
import { anchorIdsAboveTap } from './elementTargetMatch';
|
|
14
21
|
import { fiberScanRoot } from './fiber/FiberScanRoot';
|
|
@@ -85,21 +92,38 @@ function resolveAutoTargets(autoData: string | null): ElementTargetResolution {
|
|
|
85
92
|
if (!decoded || !fingerprint) return { status: 'unknown' };
|
|
86
93
|
|
|
87
94
|
if (decoded.resolver === 'fiber' && decoded.fiberPath) {
|
|
88
|
-
return
|
|
95
|
+
return conditionVerdict(resolveAutoAnchorHost(decoded), decoded);
|
|
89
96
|
}
|
|
90
97
|
|
|
91
98
|
const exactId = exactIdFromFingerprint(fingerprint);
|
|
99
|
+
let exactIdAbsent = false;
|
|
92
100
|
if (exactId) {
|
|
93
101
|
const manual = resolveManualTargets(exactId);
|
|
94
102
|
if (manual.status === 'found') return manual;
|
|
103
|
+
// "Absent" before a scan root exists only means we have not looked yet.
|
|
104
|
+
exactIdAbsent = fiberScanRoot.getFiber() != null;
|
|
95
105
|
}
|
|
96
106
|
|
|
97
107
|
// The exact id already missed above, so go straight to scoring rather than
|
|
98
108
|
// letting resolveAutoAnchorHost scan for it again.
|
|
99
|
-
return
|
|
109
|
+
return conditionVerdict(resolveScoredAutoAnchor(fingerprint), decoded, exactIdAbsent);
|
|
100
110
|
}
|
|
101
111
|
|
|
102
|
-
|
|
112
|
+
/**
|
|
113
|
+
* Turn an AUTO resolution into the value an element condition can report.
|
|
114
|
+
*
|
|
115
|
+
* A miss (nothing scored, or an exact id that a scan did not find) is absent,
|
|
116
|
+
* matching web. A tie stays unknown on the screen where the element was picked,
|
|
117
|
+
* because the target may be one of the look-alikes, and is absent on any other
|
|
118
|
+
* screen. An empty registry with no exact id, a missing scan root, and a
|
|
119
|
+
* missing fingerprint stay unknown so `stampOnly` cannot open a "not present"
|
|
120
|
+
* gate.
|
|
121
|
+
*/
|
|
122
|
+
function conditionVerdict(
|
|
123
|
+
resolution: AutoAnchorResolution,
|
|
124
|
+
decoded: MobileAutoData,
|
|
125
|
+
exactIdAbsent = false,
|
|
126
|
+
): ElementTargetResolution {
|
|
103
127
|
if (resolution.status === 'found') {
|
|
104
128
|
// Scored matches only try the direct ref pointer, which Paper release
|
|
105
129
|
// builds null out. Without the index fallback a tap could never match.
|
|
@@ -112,12 +136,45 @@ function fromAutoResolution(resolution: AutoAnchorResolution): ElementTargetReso
|
|
|
112
136
|
};
|
|
113
137
|
}
|
|
114
138
|
if (resolution.status === 'absent') return { status: 'absent' };
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
139
|
+
|
|
140
|
+
if (resolution.status === 'unknown') {
|
|
141
|
+
if (resolution.fiberMiss === 'no-root' || resolution.fiberMiss === 'empty') {
|
|
142
|
+
return { status: 'unknown' };
|
|
143
|
+
}
|
|
144
|
+
if (resolution.fiberMiss === 'no-match') return { status: 'absent' };
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const reason = resolution.match?.reason;
|
|
148
|
+
const tie =
|
|
149
|
+
resolution.status === 'ambiguous' ||
|
|
150
|
+
reason === 'not-unique' ||
|
|
151
|
+
reason === 'ambiguous-explicit-id';
|
|
152
|
+
if (tie) {
|
|
153
|
+
if (offPickedScreen(decoded.screenId)) return { status: 'absent' };
|
|
154
|
+
// A real tie is not a broken selector, so it does not warn. A weak
|
|
155
|
+
// not-unique miss still does, matching the previous unknown report.
|
|
156
|
+
return reason === 'not-unique' ? { status: 'unknown' } : { status: 'unknown', silent: true };
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if (reason === 'below-threshold') return { status: 'absent' };
|
|
160
|
+
|
|
161
|
+
if (reason === 'no-candidates') {
|
|
162
|
+
const nothingToMatch = autoAnchorRegistry.allInstances().length === 0 && !exactIdAbsent;
|
|
163
|
+
if (nothingToMatch) return { status: 'unknown' };
|
|
164
|
+
return { status: 'absent' };
|
|
165
|
+
}
|
|
166
|
+
|
|
118
167
|
return { status: 'unknown' };
|
|
119
168
|
}
|
|
120
169
|
|
|
170
|
+
/** True when the picked screen is known and the app is on a different one. */
|
|
171
|
+
function offPickedScreen(pickedScreenId: string | undefined): boolean {
|
|
172
|
+
if (!pickedScreenId || pickedScreenId === 'unknown') return false;
|
|
173
|
+
const current = screenIdFromLocation(getCurrentScreenLocation());
|
|
174
|
+
if (current === 'unknown') return false;
|
|
175
|
+
return current !== pickedScreenId;
|
|
176
|
+
}
|
|
177
|
+
|
|
121
178
|
function resolveManualTargets(id: string): ElementTargetResolution {
|
|
122
179
|
const registered = anchorRegistry.getAll(id);
|
|
123
180
|
if (registered.length > 0) {
|
|
@@ -190,18 +190,21 @@ function intrinsicNonTextAgrees(fp: MobileFingerprint, inst: AutoAnchorInstance)
|
|
|
190
190
|
);
|
|
191
191
|
}
|
|
192
192
|
|
|
193
|
+
/**
|
|
194
|
+
* An id or kind conflict, or a childText disagreement no text-independent
|
|
195
|
+
* identity (authoritative id, matching icon/image) vouches for.
|
|
196
|
+
*/
|
|
197
|
+
function isContradicted(fp: MobileFingerprint, inst: AutoAnchorInstance): boolean {
|
|
198
|
+
if (contradictsStrong(fp, inst)) return true;
|
|
199
|
+
return childTextDisagrees(fp, inst) && !idAgrees(fp, inst) && !intrinsicNonTextAgrees(fp, inst);
|
|
200
|
+
}
|
|
201
|
+
|
|
193
202
|
function scoreInstance(
|
|
194
203
|
fp: MobileFingerprint,
|
|
195
204
|
inst: AutoAnchorInstance,
|
|
196
205
|
ambiguous: boolean,
|
|
197
206
|
): number {
|
|
198
|
-
if (
|
|
199
|
-
|
|
200
|
-
// A childText disagreement is disqualifying unless a text-independent identity
|
|
201
|
-
// vouches for the element (authoritative id, or matching icon/image).
|
|
202
|
-
if (childTextDisagrees(fp, inst) && !idAgrees(fp, inst) && !intrinsicNonTextAgrees(fp, inst)) {
|
|
203
|
-
return -Infinity;
|
|
204
|
-
}
|
|
207
|
+
if (isContradicted(fp, inst)) return -Infinity;
|
|
205
208
|
|
|
206
209
|
let score = 0;
|
|
207
210
|
|
|
@@ -231,11 +234,14 @@ function scoreInstance(
|
|
|
231
234
|
|
|
232
235
|
score += scoreAncestors(fp.ancestors ?? [], inst.ancestors ?? []);
|
|
233
236
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
237
|
+
// The window scans the registry, so skip it when there is nothing to compare.
|
|
238
|
+
if (fp.previousSiblings?.length || fp.nextSiblings?.length) {
|
|
239
|
+
const window = autoAnchorRegistry.siblingWindow(inst.instanceId, 2);
|
|
240
|
+
score += scoreSiblingWindow(fp.previousSiblings ?? [], window.previous);
|
|
241
|
+
// Score next siblings once. The POC added a reversed pass *and* a direct pass,
|
|
242
|
+
// which double-counted the next window.
|
|
243
|
+
score += scoreSiblingWindow(fp.nextSiblings ?? [], window.next);
|
|
244
|
+
}
|
|
239
245
|
|
|
240
246
|
if (ambiguous && !inst.manualId) score -= 40;
|
|
241
247
|
|
|
@@ -246,6 +252,8 @@ type InstanceFilter = (inst: AutoAnchorInstance) => boolean;
|
|
|
246
252
|
|
|
247
253
|
interface MatchOptions {
|
|
248
254
|
instanceFilter?: InstanceFilter;
|
|
255
|
+
/** The caller refreshed live content earlier in this same synchronous call. */
|
|
256
|
+
liveContentFresh?: boolean;
|
|
249
257
|
}
|
|
250
258
|
|
|
251
259
|
/** Each instance's visibility is computed once per match. */
|
|
@@ -260,10 +268,7 @@ function memoizeFilter(filter: InstanceFilter): InstanceFilter {
|
|
|
260
268
|
};
|
|
261
269
|
}
|
|
262
270
|
|
|
263
|
-
function candidatePool(
|
|
264
|
-
fp: MobileFingerprint,
|
|
265
|
-
instanceFilter?: InstanceFilter,
|
|
266
|
-
): AutoAnchorInstance[] {
|
|
271
|
+
function candidatePool(fp: MobileFingerprint): AutoAnchorInstance[] {
|
|
267
272
|
// Explicit ids are authoritative: a miss is no-candidates, not a full-registry search.
|
|
268
273
|
let pool: AutoAnchorInstance[];
|
|
269
274
|
if (fp.manualId) {
|
|
@@ -286,29 +291,45 @@ function candidatePool(
|
|
|
286
291
|
if (filtered.length > 0) pool = filtered;
|
|
287
292
|
}
|
|
288
293
|
}
|
|
289
|
-
return
|
|
294
|
+
return pool;
|
|
290
295
|
}
|
|
291
296
|
|
|
292
297
|
function miss(reason: MatchMissReason, score = 0, secondScore = 0): MatchResult {
|
|
293
298
|
return { instance: null, score, secondScore, reason };
|
|
294
299
|
}
|
|
295
300
|
|
|
296
|
-
function matchFingerprintCore(
|
|
301
|
+
function matchFingerprintCore(
|
|
302
|
+
fp: MobileFingerprint,
|
|
303
|
+
instanceFilter?: InstanceFilter,
|
|
304
|
+
liveContentFresh = false,
|
|
305
|
+
): MatchResult {
|
|
297
306
|
// Live text / testID must be applied *before* pooling. A shared Babel helper
|
|
298
307
|
// (`const field = () => <TextInput testID={id} />`) reuses one auto-anchor
|
|
299
308
|
// callback, so the runtime bag is last-writer-wins until we read the host.
|
|
309
|
+
// An unchanged host is a fiber and props-identity check after one shared
|
|
310
|
+
// ancestor walk per pass, so refreshing every instance stays cheap; the
|
|
311
|
+
// per-instance screen walk is what is not, and it only runs for the pool
|
|
312
|
+
// below.
|
|
313
|
+
const all = autoAnchorRegistry.allInstances();
|
|
314
|
+
if (all.length > 0 && !liveContentFresh) {
|
|
315
|
+
autoAnchorRegistry.refreshLiveContent(all);
|
|
316
|
+
}
|
|
317
|
+
|
|
300
318
|
// A filter's verdict is memoized so covered-screen checks run once per instance.
|
|
301
319
|
const filter = instanceFilter ? memoizeFilter(instanceFilter) : undefined;
|
|
302
|
-
const
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
320
|
+
const candidates = candidatePool(fp);
|
|
321
|
+
// A contradiction does not depend on visibility, so settle it before the
|
|
322
|
+
// covered-screen check. Visibility of contradicted instances only matters to
|
|
323
|
+
// tell `all-contradicted` from `no-candidates` when nothing else is left.
|
|
324
|
+
const viable: AutoAnchorInstance[] = [];
|
|
325
|
+
const contradicted: AutoAnchorInstance[] = [];
|
|
326
|
+
for (const inst of candidates) {
|
|
327
|
+
(isContradicted(fp, inst) ? contradicted : viable).push(inst);
|
|
307
328
|
}
|
|
308
|
-
|
|
309
|
-
const pool = candidatePool(fp, filter);
|
|
329
|
+
const pool = filter ? viable.filter(filter) : viable;
|
|
310
330
|
if (pool.length === 0) {
|
|
311
|
-
|
|
331
|
+
const anyContradictedCandidate = filter ? contradicted.some(filter) : contradicted.length > 0;
|
|
332
|
+
return miss(anyContradictedCandidate ? 'all-contradicted' : 'no-candidates');
|
|
312
333
|
}
|
|
313
334
|
|
|
314
335
|
// Visibility can clear a registry-wide ambiguous flag (a covered twin) but
|
|
@@ -367,7 +388,7 @@ function matchFingerprintCore(fp: MobileFingerprint, instanceFilter?: InstanceFi
|
|
|
367
388
|
* can flag weak (`structural`) targets.
|
|
368
389
|
*/
|
|
369
390
|
export function matchFingerprint(fp: MobileFingerprint, opts?: MatchOptions): MatchResult {
|
|
370
|
-
const result = matchFingerprintCore(fp, opts?.instanceFilter);
|
|
391
|
+
const result = matchFingerprintCore(fp, opts?.instanceFilter, opts?.liveContentFresh);
|
|
371
392
|
if (fp.identityStrength) result.identityStrength = fp.identityStrength;
|
|
372
393
|
return result;
|
|
373
394
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/** Max finger travel (px) between start and end to count as a tap, not a scroll. */
|
|
2
|
+
export const TARGET_PRESS_TAP_SLOP = 10;
|
|
3
|
+
|
|
4
|
+
export interface TouchPoint {
|
|
5
|
+
pageX: number;
|
|
6
|
+
pageY: number;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/** True when the finger moved no more than `slop` between start and end. */
|
|
10
|
+
export function withinTapSlop(
|
|
11
|
+
start: TouchPoint,
|
|
12
|
+
end: TouchPoint,
|
|
13
|
+
slop: number = TARGET_PRESS_TAP_SLOP,
|
|
14
|
+
): boolean {
|
|
15
|
+
const dx = end.pageX - start.pageX;
|
|
16
|
+
const dy = end.pageY - start.pageY;
|
|
17
|
+
return dx * dx + dy * dy <= slop * slop;
|
|
18
|
+
}
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
import { gestureHandlerHandoff } from './gestureHandlerHandoff';
|
|
2
|
+
import { TARGET_PRESS_TAP_SLOP, type TouchPoint, withinTapSlop } from './tapSlop';
|
|
3
|
+
|
|
4
|
+
export { TARGET_PRESS_TAP_SLOP, type TouchPoint, withinTapSlop };
|
|
5
|
+
|
|
1
6
|
/**
|
|
2
7
|
* Active tooltip target-press subscription.
|
|
3
8
|
*
|
|
@@ -19,29 +24,10 @@ export interface TargetPressSubscription {
|
|
|
19
24
|
onPress: () => void;
|
|
20
25
|
}
|
|
21
26
|
|
|
22
|
-
/** Max finger travel (px) between start and end to count as a tap, not a scroll. */
|
|
23
|
-
export const TARGET_PRESS_TAP_SLOP = 10;
|
|
24
|
-
|
|
25
27
|
export function pointInRect(x: number, y: number, rect: TargetPressRect): boolean {
|
|
26
28
|
return x >= rect.x && x <= rect.x + rect.width && y >= rect.y && y <= rect.y + rect.height;
|
|
27
29
|
}
|
|
28
30
|
|
|
29
|
-
export interface TouchPoint {
|
|
30
|
-
pageX: number;
|
|
31
|
-
pageY: number;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/** True when the finger moved no more than `slop` between start and end. */
|
|
35
|
-
export function withinTapSlop(
|
|
36
|
-
start: TouchPoint,
|
|
37
|
-
end: TouchPoint,
|
|
38
|
-
slop: number = TARGET_PRESS_TAP_SLOP,
|
|
39
|
-
): boolean {
|
|
40
|
-
const dx = end.pageX - start.pageX;
|
|
41
|
-
const dy = end.pageY - start.pageY;
|
|
42
|
-
return dx * dx + dy * dy <= slop * slop;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
31
|
/**
|
|
46
32
|
* True when start and end both land in `rect` and movement stays within tap
|
|
47
33
|
* slop — mirrors a DOM click on the target without claiming the responder.
|
|
@@ -70,14 +56,25 @@ export type TouchIdentifier = number | string;
|
|
|
70
56
|
export class TargetPressMonitor {
|
|
71
57
|
private subscription: TargetPressSubscription | null = null;
|
|
72
58
|
private touchStarts = new Map<TouchIdentifier, TouchPoint>();
|
|
59
|
+
private handoffStops = new Map<TouchIdentifier, () => void>();
|
|
73
60
|
|
|
74
61
|
set(subscription: TargetPressSubscription | null): void {
|
|
75
62
|
this.subscription = subscription;
|
|
76
63
|
if (!subscription) {
|
|
77
64
|
this.touchStarts.clear();
|
|
65
|
+
this.dropHandoffs();
|
|
78
66
|
}
|
|
79
67
|
}
|
|
80
68
|
|
|
69
|
+
/** Fingers with a recorded start that have not ended, cancelled, or been handed off. */
|
|
70
|
+
inProgressIdentifiers(): TouchIdentifier[] {
|
|
71
|
+
return [...this.touchStarts.keys()];
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
hasTouch(identifier: TouchIdentifier): boolean {
|
|
75
|
+
return this.touchStarts.has(identifier);
|
|
76
|
+
}
|
|
77
|
+
|
|
81
78
|
clear(): void {
|
|
82
79
|
this.set(null);
|
|
83
80
|
}
|
|
@@ -113,6 +110,38 @@ export class TargetPressMonitor {
|
|
|
113
110
|
}
|
|
114
111
|
}
|
|
115
112
|
|
|
113
|
+
/**
|
|
114
|
+
* Gesture-handler cancelled this finger. Press if that handler later ends as
|
|
115
|
+
* a tap and the start (and the end, when the payload has one) is inside the
|
|
116
|
+
* current target rect.
|
|
117
|
+
*/
|
|
118
|
+
handOffTouch(identifier: TouchIdentifier, handlerTags: readonly number[]): void {
|
|
119
|
+
const start = this.touchStarts.get(identifier);
|
|
120
|
+
if (!start) return;
|
|
121
|
+
this.touchStarts.delete(identifier);
|
|
122
|
+
this.handoffStops.get(identifier)?.();
|
|
123
|
+
if (!this.subscription || handlerTags.length === 0) return;
|
|
124
|
+
const stop = gestureHandlerHandoff.track({
|
|
125
|
+
identifier,
|
|
126
|
+
pageX: start.pageX,
|
|
127
|
+
pageY: start.pageY,
|
|
128
|
+
handlerTags,
|
|
129
|
+
onResolve: (end) => {
|
|
130
|
+
const sub = this.subscription;
|
|
131
|
+
if (!sub) return;
|
|
132
|
+
const rect = sub.getRect();
|
|
133
|
+
if (!rect || rect.width <= 0 || rect.height <= 0) return;
|
|
134
|
+
if (!pointInRect(start.pageX, start.pageY, rect)) return;
|
|
135
|
+
if (end && !pointInRect(end.pageX, end.pageY, rect)) return;
|
|
136
|
+
sub.onPress();
|
|
137
|
+
},
|
|
138
|
+
});
|
|
139
|
+
this.handoffStops.set(identifier, () => {
|
|
140
|
+
stop();
|
|
141
|
+
this.handoffStops.delete(identifier);
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
|
|
116
145
|
/**
|
|
117
146
|
* Drop in-progress gesture(s). With `identifier`, cancels that finger only;
|
|
118
147
|
* otherwise clears all (e.g. blanket `onTouchCancel`).
|
|
@@ -120,15 +149,23 @@ export class TargetPressMonitor {
|
|
|
120
149
|
cancelTouch(identifier?: TouchIdentifier): void {
|
|
121
150
|
if (identifier == null) {
|
|
122
151
|
this.touchStarts.clear();
|
|
152
|
+
this.dropHandoffs();
|
|
123
153
|
return;
|
|
124
154
|
}
|
|
125
155
|
this.touchStarts.delete(identifier);
|
|
156
|
+
this.handoffStops.get(identifier)?.();
|
|
126
157
|
}
|
|
127
158
|
|
|
128
159
|
/** Test helper. */
|
|
129
160
|
resetForTests(): void {
|
|
130
161
|
this.subscription = null;
|
|
131
162
|
this.touchStarts.clear();
|
|
163
|
+
this.dropHandoffs();
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
private dropHandoffs(): void {
|
|
167
|
+
for (const stop of this.handoffStops.values()) stop();
|
|
168
|
+
this.handoffStops.clear();
|
|
132
169
|
}
|
|
133
170
|
}
|
|
134
171
|
|
|
@@ -16,7 +16,7 @@ import { fibersMatch, resolveFiberPath } from '../anchors/fiber/resolveFiberPath
|
|
|
16
16
|
import { createVisibleInstanceFilter } from '../anchors/isInstanceOnVisibleScreen';
|
|
17
17
|
import * as semanticMatcher from '../anchors/semanticMatcher';
|
|
18
18
|
import type { MatchMissReason } from '../anchors/semanticMatcher';
|
|
19
|
-
import { getCurrentScreenLocation } from '../screenTracker';
|
|
19
|
+
import { getCurrentScreenLocation, screenIdFromLocation } from '../screenTracker';
|
|
20
20
|
|
|
21
21
|
import type { PickTarget } from './hitTest';
|
|
22
22
|
|
|
@@ -35,10 +35,9 @@ function deriveIdentityStrength(inst: AutoAnchorInstance): IdentityStrength {
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
function screenFromLocation(): { screenId: string; screenName?: string } {
|
|
38
|
-
const
|
|
39
|
-
if (
|
|
40
|
-
|
|
41
|
-
return { screenId: location.screen, screenName: location.screen };
|
|
38
|
+
const screenId = screenIdFromLocation(getCurrentScreenLocation());
|
|
39
|
+
if (screenId === 'unknown') return { screenId };
|
|
40
|
+
return { screenId, screenName: screenId };
|
|
42
41
|
}
|
|
43
42
|
|
|
44
43
|
function deviceMetadata(): DeviceMetadata | undefined {
|
|
@@ -8,6 +8,8 @@ import * as React from 'react';
|
|
|
8
8
|
import type { TextStyle, ViewStyle } from 'react-native';
|
|
9
9
|
import { Image, Platform, Pressable, ScrollView, StyleSheet, Text, View } from 'react-native';
|
|
10
10
|
|
|
11
|
+
import { openFlowNavigateUrl } from '../navigation/openFlowNavigateUrl';
|
|
12
|
+
|
|
11
13
|
import { StepButton } from './StepButton';
|
|
12
14
|
import {
|
|
13
15
|
deserializeRichContentDoc,
|
|
@@ -17,7 +19,6 @@ import {
|
|
|
17
19
|
} from './deserialize';
|
|
18
20
|
import { resolveImageFrame } from './imageLayout';
|
|
19
21
|
import { migrateFlowBlocksIntoContent } from './migrateFlowBlocks';
|
|
20
|
-
import { openSafeUrl } from './openSafeUrl';
|
|
21
22
|
import {
|
|
22
23
|
ROOT_CONTENT_GAP,
|
|
23
24
|
WEB_CODE_BG_ALPHA,
|
|
@@ -401,7 +402,7 @@ function RenderedLink({
|
|
|
401
402
|
accessibilityRole="link"
|
|
402
403
|
accessibilityHint={href || undefined}
|
|
403
404
|
onPress={() => {
|
|
404
|
-
void
|
|
405
|
+
void openFlowNavigateUrl(href);
|
|
405
406
|
}}
|
|
406
407
|
>
|
|
407
408
|
<InlineChildren
|
|
@@ -480,7 +481,7 @@ function RenderedImage({
|
|
|
480
481
|
accessibilityRole="link"
|
|
481
482
|
accessibilityLabel="Image link"
|
|
482
483
|
onPress={() => {
|
|
483
|
-
void
|
|
484
|
+
void openFlowNavigateUrl(href);
|
|
484
485
|
}}
|
|
485
486
|
>
|
|
486
487
|
{framed}
|
|
@@ -15,7 +15,9 @@ export function isSafeUrl(url: string | null | undefined): boolean {
|
|
|
15
15
|
const parsed = new URL(trimmed);
|
|
16
16
|
return ALLOWED_PROTOCOLS.has(parsed.protocol);
|
|
17
17
|
} catch {
|
|
18
|
-
|
|
18
|
+
// Hermes / older runtimes can lack a full URL implementation; still allow
|
|
19
|
+
// obvious http(s) strings so NAVIGATE does not fall through to Expo Router.
|
|
20
|
+
return /^https?:\/\//i.test(trimmed);
|
|
19
21
|
}
|
|
20
22
|
}
|
|
21
23
|
|
|
@@ -6,7 +6,11 @@ import {
|
|
|
6
6
|
readNavigationPresentation,
|
|
7
7
|
subscribeNavigationState,
|
|
8
8
|
} from '../navigation/isOverlayPresentation';
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
mustNotUseExpoRouterPush,
|
|
11
|
+
shouldOpenExternalNavigateUrl,
|
|
12
|
+
} from '../navigation/navigateUrlUtils';
|
|
13
|
+
import { openFlowNavigateUrl, setExpoRouterNavigator } from '../navigation/openFlowNavigateUrl';
|
|
10
14
|
import { handleScreenChange } from '../screenTracker';
|
|
11
15
|
|
|
12
16
|
/**
|
|
@@ -73,6 +77,11 @@ export function useUserflowExpoRouter(): void {
|
|
|
73
77
|
useEffect(() => {
|
|
74
78
|
setExpoRouterNavigator({
|
|
75
79
|
push: (href) => {
|
|
80
|
+
const trimmed = String(href).trim();
|
|
81
|
+
if (mustNotUseExpoRouterPush(trimmed) || shouldOpenExternalNavigateUrl(trimmed)) {
|
|
82
|
+
void openFlowNavigateUrl(trimmed);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
76
85
|
router.push(href as never);
|
|
77
86
|
},
|
|
78
87
|
});
|
package/src/index.ts
CHANGED
|
@@ -80,13 +80,13 @@ import {
|
|
|
80
80
|
attachFlowSessionEngine,
|
|
81
81
|
cancelPendingDraftEnd,
|
|
82
82
|
clearFlowSessionEngineLocalSession,
|
|
83
|
-
endDraftFlowSession,
|
|
84
83
|
endEvalJsFlowSession,
|
|
85
84
|
getFlowSessionEngine,
|
|
86
85
|
hasActiveFlowSession,
|
|
87
86
|
resetFlowSessionEngine,
|
|
88
87
|
} from './runtime/flowEngine';
|
|
89
88
|
import { isolateAsync, isolateSync } from './runtime/isolateCall';
|
|
89
|
+
import { endDraftPreviewSessions, prepareForBuilderPreviewStart } from './runtime/previewStart';
|
|
90
90
|
import { getUserflowCore } from './runtime/userflowCore';
|
|
91
91
|
import {
|
|
92
92
|
disableScreenTracking,
|
|
@@ -100,7 +100,9 @@ import {
|
|
|
100
100
|
} from './screenTracker';
|
|
101
101
|
import { setSurfaceInteractionBlocking as setSurfaceInteractionBlockingConfig } from './surfaces/surfaceInteractionConfig';
|
|
102
102
|
|
|
103
|
-
|
|
103
|
+
import { SDK_VERSION } from './version';
|
|
104
|
+
|
|
105
|
+
export { SDK_VERSION };
|
|
104
106
|
export type { DeviceContext, DeviceOs, DeviceType, SdkPlatform } from './deviceContext';
|
|
105
107
|
export type { HostAppVersion, HostAppVersionSource } from './hostAppVersion';
|
|
106
108
|
export { EmbedBannerPlaceholder } from './runtime/EmbedBannerPlaceholder';
|
|
@@ -141,8 +143,8 @@ export type {
|
|
|
141
143
|
/** Configuration passed to {@link Userflow.init}. */
|
|
142
144
|
export type UserflowInitConfig = UserflowInitOptions & {
|
|
143
145
|
/**
|
|
144
|
-
* Optional host handler for flow NAVIGATE actions. When set, wins
|
|
145
|
-
* React Navigation / Expo Router / Linking.
|
|
146
|
+
* Optional host handler for flow and banner NAVIGATE actions. When set, wins
|
|
147
|
+
* over React Navigation / Expo Router / Linking.
|
|
146
148
|
*/
|
|
147
149
|
onNavigate?: FlowNavigateHandler;
|
|
148
150
|
/**
|
|
@@ -297,6 +299,10 @@ export const Userflow = {
|
|
|
297
299
|
...(config.appBuild !== undefined ? { appBuild: config.appBuild } : {}),
|
|
298
300
|
});
|
|
299
301
|
warnIfInstallIncomplete();
|
|
302
|
+
if (__DEV__) {
|
|
303
|
+
// eslint-disable-next-line no-console -- intentional development diagnostic
|
|
304
|
+
console.log(`[Userflow] react-native SDK ${SDK_VERSION} (source)`);
|
|
305
|
+
}
|
|
300
306
|
cacheDeviceContextAtInit();
|
|
301
307
|
setHostOnNavigate(config.onNavigate);
|
|
302
308
|
lifecycle.start();
|
|
@@ -311,6 +317,7 @@ export const Userflow = {
|
|
|
311
317
|
// the success path makes a failed init look like a broken deep link.
|
|
312
318
|
const pairing = installPairingController(core, {
|
|
313
319
|
...(config.pairingEndpoint !== undefined ? { pairingEndpoint: config.pairingEndpoint } : {}),
|
|
320
|
+
prepareForBuilderPreviewStart: () => prepareForBuilderPreviewStart(core),
|
|
314
321
|
clearLocalSession: () => {
|
|
315
322
|
clearFlowSessionEngineLocalSession();
|
|
316
323
|
core.setFlowSessionId(null);
|
|
@@ -318,7 +325,7 @@ export const Userflow = {
|
|
|
318
325
|
core.setBannerSessionId(null);
|
|
319
326
|
evalJsController.reset();
|
|
320
327
|
},
|
|
321
|
-
endDraftSession:
|
|
328
|
+
endDraftSession: endDraftPreviewSessions,
|
|
322
329
|
cancelPendingDraftEnd,
|
|
323
330
|
});
|
|
324
331
|
pairing.notifyInitStarted();
|
|
@@ -354,8 +361,8 @@ export const Userflow = {
|
|
|
354
361
|
return getPairingController(core).exitPreview();
|
|
355
362
|
},
|
|
356
363
|
/**
|
|
357
|
-
* Override or clear the host NAVIGATE handler (same as
|
|
358
|
-
* Wins over React Navigation / Expo Router / Linking
|
|
364
|
+
* Override or clear the host NAVIGATE handler for flows and banners (same as
|
|
365
|
+
* `init({ onNavigate })`). Wins over React Navigation / Expo Router / Linking.
|
|
359
366
|
*/
|
|
360
367
|
setOnNavigate(handler: FlowNavigateHandler | null | undefined): void {
|
|
361
368
|
setHostOnNavigate(handler);
|
|
@@ -372,7 +379,9 @@ export const Userflow = {
|
|
|
372
379
|
if (previousId != null && previousId !== userId) {
|
|
373
380
|
resetClientConditionEngine();
|
|
374
381
|
core.setClientConditions([]);
|
|
375
|
-
|
|
382
|
+
clearFlowSessionEngineLocalSession();
|
|
383
|
+
clearBannerSessionEngineLocalSession({ rememberDraftForPreviewEnd: false });
|
|
384
|
+
core.setFlowSessionId(null);
|
|
376
385
|
core.setBannerSessionId(null);
|
|
377
386
|
evalJsController.reset();
|
|
378
387
|
await clearAnonymousId();
|
|
@@ -391,7 +400,9 @@ export const Userflow = {
|
|
|
391
400
|
if (previousId != null && previousId !== anonymousId) {
|
|
392
401
|
resetClientConditionEngine();
|
|
393
402
|
core.setClientConditions([]);
|
|
394
|
-
|
|
403
|
+
clearFlowSessionEngineLocalSession();
|
|
404
|
+
clearBannerSessionEngineLocalSession({ rememberDraftForPreviewEnd: false });
|
|
405
|
+
core.setFlowSessionId(null);
|
|
395
406
|
core.setBannerSessionId(null);
|
|
396
407
|
evalJsController.reset();
|
|
397
408
|
armScreenViewedForNextIdentify();
|