@userflow-tech/react-native 0.4.4 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +124 -34
- package/docs/anchoring.md +6 -1
- package/docs/deep-linking.md +26 -0
- package/docs/troubleshooting.md +50 -23
- package/expo-plugin/hostDependencyWarnings.d.ts +6 -4
- package/expo-plugin/hostDependencyWarnings.d.ts.map +1 -1
- package/expo-plugin/hostDependencyWarnings.js +8 -6
- package/expo-plugin/hostDependencyWarnings.js.map +1 -1
- 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/installCheck.js +2 -2
- package/lib/commonjs/installCheck.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/installCheck.js +2 -2
- package/lib/module/installCheck.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/installCheck.d.ts +1 -1
- package/lib/typescript/commonjs/src/installCheck.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/installCheck.d.ts +1 -1
- package/lib/typescript/module/src/installCheck.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/installCheck.ts +4 -4
- 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
|
@@ -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();
|
package/src/installCheck.ts
CHANGED
|
@@ -10,7 +10,7 @@ export const INSTALL_ASYNC_STORAGE_LINE =
|
|
|
10
10
|
'- @react-native-async-storage/async-storage is not linked. Anonymous users and Builder pairing will not persist. Add it to the app package.json (npx expo install @react-native-async-storage/async-storage), run pod install on iOS, and rebuild.';
|
|
11
11
|
|
|
12
12
|
export const INSTALL_VIEW_SHOT_LINE =
|
|
13
|
-
'- react-native-view-shot is not linked, so Builder element selection gets no screenshot. Install react-native-view-shot
|
|
13
|
+
'- react-native-view-shot is not linked, so Builder element selection gets no screenshot. Install it and rebuild. On Expo SDK 56 and 57, run npx expo install react-native-view-shot unpinned, with no expo.install.exclude entry for it. Otherwise install react-native-view-shot@^5.0.0; on Expo SDK 55 and older, an unpinned npx expo install resolves 4.0.3.';
|
|
14
14
|
|
|
15
15
|
export const INSTALL_WEBVIEW_LINE =
|
|
16
16
|
'- react-native-webview is not linked. Evaluate JavaScript and WebView banners will not run. Install it (npx expo install react-native-webview) and rebuild.';
|
|
@@ -36,9 +36,9 @@ export const INSTALL_SAFE_AREA_WARNING =
|
|
|
36
36
|
export function formatViewShotVersionWarning(version: string): string {
|
|
37
37
|
return (
|
|
38
38
|
`[Userflow] react-native-view-shot@${version} is older than 5.0.0, so Builder element selection may not get a screenshot. ` +
|
|
39
|
-
'
|
|
40
|
-
'
|
|
41
|
-
'
|
|
39
|
+
'On Expo SDK 56 and 57, run npx expo install react-native-view-shot unpinned, with no expo.install.exclude entry for it, and rebuild. ' +
|
|
40
|
+
'Otherwise install react-native-view-shot@^5.0.0 in the same command as the SDK and rebuild; on Expo SDK 55 and older, also add "react-native-view-shot" to expo.install.exclude. ' +
|
|
41
|
+
'Do not retry the install with --force or --legacy-peer-deps; that leaves this version in place.\n' +
|
|
42
42
|
INSTALL_CHECK_FOOTER
|
|
43
43
|
);
|
|
44
44
|
}
|
|
@@ -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
|
|
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
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
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 →
|
|
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
|
|
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 (
|
|
86
|
-
await
|
|
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
|
-
|
|
108
|
-
|
|
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
|
|