@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
package/src/screenTracker.ts
CHANGED
|
@@ -24,6 +24,17 @@ function locationKey(location: ClientLocationUpdate): string {
|
|
|
24
24
|
return 'path' in location ? `path:${location.path}` : `screen:${location.screen}`;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
/**
|
|
28
|
+
* The screen id stored on an AUTO envelope (`path` for Expo Router, `screen`
|
|
29
|
+
* otherwise). Missing or blank locations are `'unknown'`, the same sentinel
|
|
30
|
+
* the element picker writes when it has not seen a screen yet.
|
|
31
|
+
*/
|
|
32
|
+
export function screenIdFromLocation(location: ClientLocationUpdate | null | undefined): string {
|
|
33
|
+
if (!location) return 'unknown';
|
|
34
|
+
const id = 'path' in location ? location.path : location.screen;
|
|
35
|
+
return id || 'unknown';
|
|
36
|
+
}
|
|
37
|
+
|
|
27
38
|
/** Event attributes for `screen_viewed`, or `null` when the location has no identity. */
|
|
28
39
|
export function screenViewedAttributes(
|
|
29
40
|
location: ClientLocationUpdate,
|
|
@@ -11,14 +11,18 @@ import { Animated, Pressable, StyleSheet, Text, View } from 'react-native';
|
|
|
11
11
|
import { BannerStepButton } from '../content/BannerStepButton';
|
|
12
12
|
import { RichContentRenderer } from '../content/RichContentRenderer';
|
|
13
13
|
import { mixThemeColors } from '../content/themeColor';
|
|
14
|
+
import { usePushBannerHostInsetRegistration } from '../runtime/pushBannerLayoutContext';
|
|
14
15
|
|
|
15
16
|
import {
|
|
16
17
|
BANNER_CLOSE_SLOT_SIZE,
|
|
17
18
|
BANNER_ROOT_PADDING,
|
|
19
|
+
bannerBarRootStyle,
|
|
18
20
|
bannerFrameStyle,
|
|
19
21
|
bannerInnerStyle,
|
|
22
|
+
bannerPushLayoutChrome,
|
|
20
23
|
resolveBannerBarBorderRadius,
|
|
21
24
|
} from './bannerBarLayout';
|
|
25
|
+
import { useUserflowSafeAreaInsets } from './safeArea';
|
|
22
26
|
import {
|
|
23
27
|
BANNER_BUTTON_GAP,
|
|
24
28
|
BANNER_CLOSE_BORDER_RADIUS,
|
|
@@ -28,6 +32,8 @@ import { resolveBannerBackgroundColor, resolveBannerForegroundColor } from './re
|
|
|
28
32
|
|
|
29
33
|
export interface BannerBarProps {
|
|
30
34
|
session: BannerSessionFragment;
|
|
35
|
+
pushLayoutEdge?: 'top' | 'bottom' | null;
|
|
36
|
+
overlaySafeEdge?: 'top' | 'bottom' | null;
|
|
31
37
|
onActions: (actions: FlowActionFragment[]) => void;
|
|
32
38
|
onDismiss: (endReason: EndFlowReasonInput) => void;
|
|
33
39
|
}
|
|
@@ -38,6 +44,8 @@ export interface BannerBarProps {
|
|
|
38
44
|
*/
|
|
39
45
|
export function BannerBar({
|
|
40
46
|
session,
|
|
47
|
+
pushLayoutEdge = null,
|
|
48
|
+
overlaySafeEdge = null,
|
|
41
49
|
onActions,
|
|
42
50
|
onDismiss,
|
|
43
51
|
}: BannerBarProps): React.ReactElement | null {
|
|
@@ -50,10 +58,20 @@ export function BannerBar({
|
|
|
50
58
|
[theme, backgroundColor, foregroundColor],
|
|
51
59
|
);
|
|
52
60
|
const lookupAttribute = React.useMemo(() => genSessionDataLookup(session.data), [session.data]);
|
|
53
|
-
const
|
|
61
|
+
const insets = useUserflowSafeAreaInsets();
|
|
62
|
+
const overlay = banner?.overlay !== false;
|
|
63
|
+
const hostInsetEdge = !overlay && pushLayoutEdge ? pushLayoutEdge : null;
|
|
64
|
+
const safeAreaEdge = hostInsetEdge ?? overlaySafeEdge ?? null;
|
|
65
|
+
const onPushChromeLayout = usePushBannerHostInsetRegistration(
|
|
66
|
+
hostInsetEdge,
|
|
67
|
+
session.id,
|
|
68
|
+
hostInsetEdge != null,
|
|
69
|
+
);
|
|
70
|
+
const fadeIn = banner?.animate === true && hostInsetEdge == null;
|
|
71
|
+
const opacity = React.useRef(new Animated.Value(fadeIn ? 0 : 1)).current;
|
|
54
72
|
|
|
55
73
|
React.useEffect(() => {
|
|
56
|
-
if (!
|
|
74
|
+
if (!fadeIn) {
|
|
57
75
|
opacity.setValue(1);
|
|
58
76
|
return;
|
|
59
77
|
}
|
|
@@ -67,73 +85,93 @@ export function BannerBar({
|
|
|
67
85
|
return () => {
|
|
68
86
|
animation.stop();
|
|
69
87
|
};
|
|
70
|
-
}, [
|
|
88
|
+
}, [fadeIn, opacity, session.id]);
|
|
71
89
|
|
|
72
90
|
if (!banner) return null;
|
|
73
91
|
|
|
74
|
-
const overlay = banner.overlay !== false;
|
|
75
92
|
const frameStyle = bannerFrameStyle(banner);
|
|
93
|
+
const rootStyle = bannerBarRootStyle(banner);
|
|
76
94
|
const innerStyle = bannerInnerStyle(banner);
|
|
77
95
|
const closePressedBackground = mixThemeColors(backgroundColor, foregroundColor, 0.12);
|
|
78
96
|
const overlayEdge = banner.embedMode === BannerEmbedMode.BODY_LAST ? 'bottom' : 'top';
|
|
79
97
|
const barRadius = resolveBannerBarBorderRadius(banner);
|
|
98
|
+
const insetChrome = safeAreaEdge
|
|
99
|
+
? bannerPushLayoutChrome(safeAreaEdge, insets, backgroundColor)
|
|
100
|
+
: null;
|
|
101
|
+
const insetChromeOutsideFade = insetChrome != null && fadeIn;
|
|
80
102
|
|
|
81
|
-
|
|
82
|
-
<View
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
103
|
+
const bar = (
|
|
104
|
+
<View
|
|
105
|
+
testID="userflow-banner"
|
|
106
|
+
style={[
|
|
107
|
+
styles.root,
|
|
108
|
+
rootStyle,
|
|
109
|
+
{ backgroundColor },
|
|
110
|
+
barRadius != null ? { borderRadius: barRadius, overflow: 'hidden' as const } : null,
|
|
111
|
+
]}
|
|
112
|
+
>
|
|
113
|
+
<View style={styles.startSpacer} />
|
|
114
|
+
<View style={innerStyle}>
|
|
115
|
+
<View style={styles.content}>
|
|
116
|
+
<RichContentRenderer
|
|
117
|
+
content={banner.content}
|
|
118
|
+
buttons={[]}
|
|
119
|
+
theme={bannerTheme}
|
|
120
|
+
sessionData={session.data}
|
|
121
|
+
lookupAttribute={lookupAttribute}
|
|
122
|
+
onActions={onActions}
|
|
123
|
+
/>
|
|
124
|
+
</View>
|
|
125
|
+
{banner.buttons.length > 0 ? (
|
|
126
|
+
<View style={styles.buttons}>
|
|
127
|
+
{banner.buttons.map((button) => (
|
|
128
|
+
<BannerStepButton
|
|
129
|
+
key={button.id}
|
|
130
|
+
button={button}
|
|
98
131
|
theme={bannerTheme}
|
|
99
132
|
sessionData={session.data}
|
|
100
|
-
lookupAttribute={lookupAttribute}
|
|
101
133
|
onActions={onActions}
|
|
102
134
|
/>
|
|
103
|
-
|
|
104
|
-
{banner.buttons.length > 0 ? (
|
|
105
|
-
<View style={styles.buttons}>
|
|
106
|
-
{banner.buttons.map((button) => (
|
|
107
|
-
<BannerStepButton
|
|
108
|
-
key={button.id}
|
|
109
|
-
button={button}
|
|
110
|
-
theme={bannerTheme}
|
|
111
|
-
sessionData={session.data}
|
|
112
|
-
onActions={onActions}
|
|
113
|
-
/>
|
|
114
|
-
))}
|
|
115
|
-
</View>
|
|
116
|
-
) : null}
|
|
135
|
+
))}
|
|
117
136
|
</View>
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
</
|
|
136
|
-
|
|
137
|
+
) : null}
|
|
138
|
+
</View>
|
|
139
|
+
{session.version.closeDisabled ? (
|
|
140
|
+
<View style={styles.startSpacer} />
|
|
141
|
+
) : (
|
|
142
|
+
<Pressable
|
|
143
|
+
testID="userflow-banner-dismiss"
|
|
144
|
+
accessibilityRole="button"
|
|
145
|
+
accessibilityLabel="Dismiss"
|
|
146
|
+
hitSlop={8}
|
|
147
|
+
onPress={() => onDismiss(EndFlowReasonInput.USER_CLOSED)}
|
|
148
|
+
style={({ pressed }) => [
|
|
149
|
+
styles.close,
|
|
150
|
+
pressed ? { backgroundColor: closePressedBackground } : null,
|
|
151
|
+
]}
|
|
152
|
+
>
|
|
153
|
+
<Text style={[styles.dismissIcon, { color: foregroundColor }]}>×</Text>
|
|
154
|
+
</Pressable>
|
|
155
|
+
)}
|
|
156
|
+
</View>
|
|
157
|
+
);
|
|
158
|
+
|
|
159
|
+
const animatedBar = (
|
|
160
|
+
<Animated.View
|
|
161
|
+
onLayout={hostInsetEdge ? onPushChromeLayout : undefined}
|
|
162
|
+
style={[
|
|
163
|
+
{ opacity },
|
|
164
|
+
overlay ? bannerOverlayShadowStyle(overlayEdge) : null,
|
|
165
|
+
insetChromeOutsideFade ? null : insetChrome,
|
|
166
|
+
]}
|
|
167
|
+
>
|
|
168
|
+
{bar}
|
|
169
|
+
</Animated.View>
|
|
170
|
+
);
|
|
171
|
+
|
|
172
|
+
return (
|
|
173
|
+
<View testID="userflow-banner-frame" style={frameStyle}>
|
|
174
|
+
{insetChromeOutsideFade ? <View style={insetChrome}>{animatedBar}</View> : animatedBar}
|
|
137
175
|
</View>
|
|
138
176
|
);
|
|
139
177
|
}
|
|
@@ -15,6 +15,10 @@ import { bannerNeedsWebView } from './bannerWebView/bannerNeedsWebView';
|
|
|
15
15
|
|
|
16
16
|
export interface BannerSurfaceProps {
|
|
17
17
|
session: BannerSessionFragment;
|
|
18
|
+
/** When set, the banner pushes host layout and fills the safe-area inset on this edge. */
|
|
19
|
+
pushLayoutEdge?: 'top' | 'bottom' | null;
|
|
20
|
+
/** Overlay host edge — paints safe-area padding without pushing layout. */
|
|
21
|
+
overlaySafeEdge?: 'top' | 'bottom' | null;
|
|
18
22
|
onActions: (actions: FlowActionFragment[]) => void | Promise<void>;
|
|
19
23
|
onDismiss: (endReason: EndFlowReasonInput) => void;
|
|
20
24
|
}
|
|
@@ -27,6 +31,8 @@ let warnedMissingWebView = false;
|
|
|
27
31
|
*/
|
|
28
32
|
export function BannerSurface({
|
|
29
33
|
session,
|
|
34
|
+
pushLayoutEdge = null,
|
|
35
|
+
overlaySafeEdge = null,
|
|
30
36
|
onActions,
|
|
31
37
|
onDismiss,
|
|
32
38
|
}: BannerSurfaceProps): React.ReactElement | null {
|
|
@@ -35,6 +41,34 @@ export function BannerSurface({
|
|
|
35
41
|
const needsWebView = banner != null && bannerNeedsWebView(banner, theme);
|
|
36
42
|
const webView = needsWebView ? getEvalJsWebView() : null;
|
|
37
43
|
|
|
44
|
+
React.useEffect(() => {
|
|
45
|
+
if (!banner || !__DEV__) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
// eslint-disable-next-line no-console -- intentional development diagnostic
|
|
49
|
+
console.log('[Userflow] banner shown', {
|
|
50
|
+
flowId: session.flow.id,
|
|
51
|
+
flowName: session.flow.name,
|
|
52
|
+
bannerSessionId: session.id,
|
|
53
|
+
versionId: session.version.id,
|
|
54
|
+
embedMode: banner.embedMode,
|
|
55
|
+
overlay: banner.overlay !== false,
|
|
56
|
+
webView: needsWebView,
|
|
57
|
+
pushLayoutEdge: pushLayoutEdge ?? null,
|
|
58
|
+
overlaySafeEdge: overlaySafeEdge ?? null,
|
|
59
|
+
hostAsOverlay: banner.overlay !== false || needsWebView,
|
|
60
|
+
});
|
|
61
|
+
}, [
|
|
62
|
+
banner,
|
|
63
|
+
needsWebView,
|
|
64
|
+
overlaySafeEdge,
|
|
65
|
+
pushLayoutEdge,
|
|
66
|
+
session.flow.id,
|
|
67
|
+
session.flow.name,
|
|
68
|
+
session.id,
|
|
69
|
+
session.version.id,
|
|
70
|
+
]);
|
|
71
|
+
|
|
38
72
|
React.useLayoutEffect(() => {
|
|
39
73
|
if (!needsWebView || !webView) {
|
|
40
74
|
return;
|
|
@@ -69,13 +103,35 @@ export function BannerSurface({
|
|
|
69
103
|
);
|
|
70
104
|
}
|
|
71
105
|
}
|
|
72
|
-
return
|
|
106
|
+
return (
|
|
107
|
+
<BannerBar
|
|
108
|
+
session={session}
|
|
109
|
+
pushLayoutEdge={pushLayoutEdge}
|
|
110
|
+
overlaySafeEdge={overlaySafeEdge}
|
|
111
|
+
onActions={onActions}
|
|
112
|
+
onDismiss={onDismiss}
|
|
113
|
+
/>
|
|
114
|
+
);
|
|
73
115
|
}
|
|
74
116
|
return (
|
|
75
|
-
<BannerWebViewBar
|
|
117
|
+
<BannerWebViewBar
|
|
118
|
+
session={session}
|
|
119
|
+
pushLayoutEdge={pushLayoutEdge}
|
|
120
|
+
overlaySafeEdge={overlaySafeEdge}
|
|
121
|
+
onActions={onActions}
|
|
122
|
+
onDismiss={dismissWebViewBanner}
|
|
123
|
+
/>
|
|
76
124
|
);
|
|
77
125
|
}
|
|
78
|
-
return
|
|
126
|
+
return (
|
|
127
|
+
<BannerBar
|
|
128
|
+
session={session}
|
|
129
|
+
pushLayoutEdge={pushLayoutEdge}
|
|
130
|
+
overlaySafeEdge={overlaySafeEdge}
|
|
131
|
+
onActions={onActions}
|
|
132
|
+
onDismiss={onDismiss}
|
|
133
|
+
/>
|
|
134
|
+
);
|
|
79
135
|
}
|
|
80
136
|
|
|
81
137
|
/** @internal */
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import type { FlowSessionEngine } from '@userflow-tech/core';
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
import {
|
|
3
|
+
decodeMobileAutoData,
|
|
4
|
+
type EndFlowReasonInput,
|
|
5
|
+
type FlowSessionFragment,
|
|
6
|
+
type FlowStepFragment,
|
|
7
|
+
type ThemeFragment,
|
|
7
8
|
} from '@userflow-tech/protocol';
|
|
8
9
|
import * as React from 'react';
|
|
9
10
|
import {
|
|
@@ -20,6 +21,7 @@ import {
|
|
|
20
21
|
import { anchorRegistry } from '../anchors/AnchorRegistry';
|
|
21
22
|
import { autoAnchorRegistry } from '../anchors/AutoAnchorRegistry';
|
|
22
23
|
import { addAnimationFrameCallback, removeAnimationFrameCallback } from '../anchors/animationFrame';
|
|
24
|
+
import { isAppActive, subscribeAppActive } from '../anchors/appActive';
|
|
23
25
|
import { fiberScanRoot } from '../anchors/fiber/FiberScanRoot';
|
|
24
26
|
import type { AnyFiber } from '../anchors/fiber/fiberInternals';
|
|
25
27
|
import { clipToScrollViewports } from '../anchors/fiber/visibleRect';
|
|
@@ -27,6 +29,7 @@ import {
|
|
|
27
29
|
clearFiberAnchorCache,
|
|
28
30
|
invalidateFiberAnchor,
|
|
29
31
|
resolveAnchorHost,
|
|
32
|
+
subscribeAnchorScreenChange,
|
|
30
33
|
} from '../anchors/resolveAnchorHost';
|
|
31
34
|
import { resolveAutoAnchorHost } from '../anchors/resolveAutoAnchorHost';
|
|
32
35
|
import { resolveManualAnchorId } from '../anchors/resolveManualAnchorId';
|
|
@@ -42,6 +45,7 @@ import { MADE_WITH_USERFLOW_GAP, MadeWithUserflow } from './MadeWithUserflow';
|
|
|
42
45
|
import { ProgressBar } from './ProgressBar';
|
|
43
46
|
import { ABSOLUTE_FILL } from './absoluteFill';
|
|
44
47
|
import { useCardTransitionPhase } from './cardTransition';
|
|
48
|
+
import { stepTrapsHostAccessibility } from './hostAccessibilityTrap';
|
|
45
49
|
import { parseBackdropOpacity } from './parseBackdropOpacity';
|
|
46
50
|
import { resolveStepProgress } from './progress';
|
|
47
51
|
import { resolveCloseButtonColor } from './resolveCloseButtonColor';
|
|
@@ -77,6 +81,7 @@ import {
|
|
|
77
81
|
tooltipSideGap,
|
|
78
82
|
tooltipVerticalGap,
|
|
79
83
|
} from './tooltip/resolveSideCardWidth';
|
|
84
|
+
import { TargetSearchSchedule } from './tooltip/targetSearchSchedule';
|
|
80
85
|
|
|
81
86
|
export interface TooltipSurfaceProps {
|
|
82
87
|
engine: FlowSessionEngine;
|
|
@@ -94,10 +99,6 @@ export interface TooltipSurfaceProps {
|
|
|
94
99
|
|
|
95
100
|
type MissingMode = 'waiting' | 'reported';
|
|
96
101
|
|
|
97
|
-
/** Interval for re-resolving a missing / remounted anchor (not for live measure). */
|
|
98
|
-
const RESOLVE_MS = 250;
|
|
99
|
-
/** Slower resolve poll after FLAG/ERROR report so a late-mounting target can recover. */
|
|
100
|
-
const RESOLVE_SLOW_MS = 1000;
|
|
101
102
|
/**
|
|
102
103
|
* One-frame delay before the first resolve after a step/reset so dialog
|
|
103
104
|
* teardown cannot arm the missing-target timer with a 0-size measure.
|
|
@@ -162,6 +163,11 @@ export function TooltipSurface({
|
|
|
162
163
|
const selector = currentStep.selector;
|
|
163
164
|
const isAuto = (selector?.type as string | null) === 'AUTO';
|
|
164
165
|
const autoData = selector?.autoData ?? null;
|
|
166
|
+
// Decoded once per step rather than on every search.
|
|
167
|
+
const decodedAutoData = React.useMemo(
|
|
168
|
+
() => (isAuto ? decodeMobileAutoData(autoData) : null),
|
|
169
|
+
[isAuto, autoData],
|
|
170
|
+
);
|
|
165
171
|
const anchorId = isAuto ? null : resolveManualAnchorId(selector?.css);
|
|
166
172
|
const targetKey = isAuto ? `auto:${autoData ?? ''}` : (anchorId ?? '');
|
|
167
173
|
const highlight = currentStep.backdrop ? resolveHighlightChrome(theme, backdropPadding) : null;
|
|
@@ -191,7 +197,6 @@ export function TooltipSurface({
|
|
|
191
197
|
desiredPlacement ?? 'BELOW',
|
|
192
198
|
);
|
|
193
199
|
const [missingMode, setMissingMode] = React.useState<MissingMode>('waiting');
|
|
194
|
-
const [registryTick, setRegistryTick] = React.useState(0);
|
|
195
200
|
/** True after at least one *failed* measure for the current step/anchor. */
|
|
196
201
|
const [measureAttempted, setMeasureAttempted] = React.useState(false);
|
|
197
202
|
/**
|
|
@@ -272,18 +277,6 @@ export function TooltipSurface({
|
|
|
272
277
|
};
|
|
273
278
|
}, []);
|
|
274
279
|
|
|
275
|
-
React.useEffect(() => {
|
|
276
|
-
const bump = () => setRegistryTick((n) => n + 1);
|
|
277
|
-
const unsubRegistry = anchorRegistry.subscribe(bump);
|
|
278
|
-
const unsubAuto = autoAnchorRegistry.subscribe(bump);
|
|
279
|
-
const unsubScan = fiberScanRoot.subscribe(bump);
|
|
280
|
-
return () => {
|
|
281
|
-
unsubRegistry();
|
|
282
|
-
unsubAuto();
|
|
283
|
-
unsubScan();
|
|
284
|
-
};
|
|
285
|
-
}, []);
|
|
286
|
-
|
|
287
280
|
React.useEffect(() => {
|
|
288
281
|
reportedRef.current = false;
|
|
289
282
|
scrollAttemptsRef.current = 0;
|
|
@@ -426,14 +419,14 @@ export function TooltipSurface({
|
|
|
426
419
|
);
|
|
427
420
|
|
|
428
421
|
/**
|
|
429
|
-
* Resolve the anchor host (registry / fiber scan).
|
|
430
|
-
*
|
|
422
|
+
* Resolve the anchor host (registry / fiber scan). Driven by
|
|
423
|
+
* {@link TargetSearchSchedule} — intentionally NOT on every animation frame.
|
|
431
424
|
*/
|
|
432
425
|
const resolveTarget = React.useCallback(() => {
|
|
433
426
|
if (!mountedRef.current) return;
|
|
434
427
|
|
|
435
428
|
const resolution = isAuto
|
|
436
|
-
? resolveAutoAnchorHost(
|
|
429
|
+
? resolveAutoAnchorHost(decodedAutoData)
|
|
437
430
|
: anchorId
|
|
438
431
|
? resolveAnchorHost(anchorId)
|
|
439
432
|
: null;
|
|
@@ -474,7 +467,7 @@ export function TooltipSurface({
|
|
|
474
467
|
maybeScrollIntoView(rect);
|
|
475
468
|
applyTarget(rect);
|
|
476
469
|
});
|
|
477
|
-
}, [anchorId, applyTarget,
|
|
470
|
+
}, [anchorId, applyTarget, decodedAutoData, dropHost, isAuto, maybeScrollIntoView]);
|
|
478
471
|
|
|
479
472
|
/**
|
|
480
473
|
* Live re-measure of an already-resolved host. Driven by the shared rAF hub
|
|
@@ -509,45 +502,60 @@ export function TooltipSurface({
|
|
|
509
502
|
});
|
|
510
503
|
}, [applyTarget, dropHost, maybeScrollIntoView]);
|
|
511
504
|
|
|
505
|
+
const resolveTargetRef = React.useRef(resolveTarget);
|
|
506
|
+
resolveTargetRef.current = resolveTarget;
|
|
507
|
+
const searchRef = React.useRef<TargetSearchSchedule | null>(null);
|
|
508
|
+
const searchAllowsRecovery =
|
|
509
|
+
behavior === 'FLAG' || behavior === 'ERROR' || (behavior === 'END' && session.draftMode);
|
|
510
|
+
const searchStopped = missingMode === 'reported' && !searchAllowsRecovery;
|
|
511
|
+
|
|
512
|
+
// Target search: steady poll while anchored, backoff while missing, nothing
|
|
513
|
+
// while the app is in the background. Live measurement is on rAF. A new step
|
|
514
|
+
// or target restarts it right away; a same-step restart (`resetNonce`) goes
|
|
515
|
+
// through `resolveArmed`, after the first-resolve delay.
|
|
512
516
|
React.useEffect(() => {
|
|
513
|
-
if (!resolveArmed)
|
|
514
|
-
resolveTarget();
|
|
515
|
-
}, [resolveTarget, registryTick, resolveArmed]);
|
|
516
|
-
|
|
517
|
-
// Resolve poll: recover missing / remounted anchors. Live measurement is on rAF.
|
|
518
|
-
React.useEffect(() => {
|
|
519
|
-
if (!resolveArmed) {
|
|
517
|
+
if (!resolveArmed || searchStopped) {
|
|
520
518
|
return;
|
|
521
519
|
}
|
|
522
|
-
const
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
520
|
+
const search = new TargetSearchSchedule(() => resolveTargetRef.current());
|
|
521
|
+
searchRef.current = search;
|
|
522
|
+
search.setMode(targetRef.current ? 'anchored' : 'missing');
|
|
523
|
+
|
|
524
|
+
const trigger = () => search.trigger();
|
|
525
|
+
const unsubscribers = [
|
|
526
|
+
anchorRegistry.subscribe(trigger),
|
|
527
|
+
autoAnchorRegistry.subscribe(trigger),
|
|
528
|
+
fiberScanRoot.subscribe(trigger),
|
|
529
|
+
subscribeAnchorScreenChange(() => search.rearm()),
|
|
530
|
+
subscribeAppActive((active) => (active ? search.resume() : search.pause())),
|
|
531
|
+
];
|
|
532
|
+
if (!isAppActive()) search.pause();
|
|
533
|
+
search.runNow();
|
|
534
|
+
|
|
535
|
+
const dimSub = Dimensions.addEventListener('change', () => search.runNow());
|
|
534
536
|
const onKeyboardShow = (event: { endCoordinates?: { height?: number } }) => {
|
|
535
537
|
setKeyboardBottomInset(Math.max(0, event.endCoordinates?.height ?? 0));
|
|
536
|
-
|
|
538
|
+
search.runNow();
|
|
537
539
|
};
|
|
538
540
|
const onKeyboardHide = () => {
|
|
539
541
|
setKeyboardBottomInset(0);
|
|
540
|
-
|
|
542
|
+
search.runNow();
|
|
541
543
|
};
|
|
542
544
|
const kbShow = Keyboard.addListener('keyboardDidShow', onKeyboardShow);
|
|
543
545
|
const kbHide = Keyboard.addListener('keyboardDidHide', onKeyboardHide);
|
|
544
546
|
return () => {
|
|
545
|
-
|
|
547
|
+
for (const unsubscribe of unsubscribers) unsubscribe();
|
|
546
548
|
dimSub.remove();
|
|
547
549
|
kbShow.remove();
|
|
548
550
|
kbHide.remove();
|
|
551
|
+
search.dispose();
|
|
552
|
+
if (searchRef.current === search) searchRef.current = null;
|
|
549
553
|
};
|
|
550
|
-
}, [
|
|
554
|
+
}, [resolveArmed, searchStopped, currentStep.id, targetKey]);
|
|
555
|
+
|
|
556
|
+
React.useEffect(() => {
|
|
557
|
+
searchRef.current?.setMode(target ? 'anchored' : 'missing');
|
|
558
|
+
}, [target]);
|
|
551
559
|
|
|
552
560
|
// rAF tracking while a host is resolved (and we are not paused after report).
|
|
553
561
|
React.useEffect(() => {
|
|
@@ -864,6 +872,9 @@ export function TooltipSurface({
|
|
|
864
872
|
|
|
865
873
|
const showBranding = session.flow.company.flowBranding;
|
|
866
874
|
const contentPadding = chrome.contentPadding;
|
|
875
|
+
// Modal only while the host is trapped too. Otherwise VoiceOver would skip
|
|
876
|
+
// the host app, including the target this step asks the user to press.
|
|
877
|
+
const cardIsModal = stepTrapsHostAccessibility(currentStep);
|
|
867
878
|
|
|
868
879
|
// Still pending the first measure attempt — only the blocker shows.
|
|
869
880
|
if (isMissing && missingMode === 'waiting' && !measureAttempted) {
|
|
@@ -877,7 +888,7 @@ export function TooltipSurface({
|
|
|
877
888
|
<View style={[styles.center, centerPaddingStyle]} pointerEvents="box-none">
|
|
878
889
|
<CardFade
|
|
879
890
|
testID="userflow-tooltip-waiting"
|
|
880
|
-
accessibilityViewIsModal
|
|
891
|
+
accessibilityViewIsModal={cardIsModal}
|
|
881
892
|
pointerEvents="auto"
|
|
882
893
|
style={[
|
|
883
894
|
chrome.shadowStyle,
|
|
@@ -990,7 +1001,7 @@ export function TooltipSurface({
|
|
|
990
1001
|
<View style={[styles.center, centerPaddingStyle]} pointerEvents="box-none">
|
|
991
1002
|
<CardFade
|
|
992
1003
|
testID="userflow-tooltip-card"
|
|
993
|
-
accessibilityViewIsModal
|
|
1004
|
+
accessibilityViewIsModal={cardIsModal}
|
|
994
1005
|
pointerEvents="auto"
|
|
995
1006
|
onLayout={onCardLayout}
|
|
996
1007
|
style={[
|
|
@@ -1032,6 +1043,7 @@ export function TooltipSurface({
|
|
|
1032
1043
|
onLayout={onCardLayout}
|
|
1033
1044
|
maxHeight={layout.maxCardHeight}
|
|
1034
1045
|
showNotch={layout.showNotch}
|
|
1046
|
+
accessibilityViewIsModal={cardIsModal}
|
|
1035
1047
|
style={{
|
|
1036
1048
|
position: 'absolute',
|
|
1037
1049
|
left: layout.cardPosition.x,
|
|
@@ -3,10 +3,12 @@ import { BannerContentLayout } from '@userflow-tech/protocol';
|
|
|
3
3
|
import type { ViewStyle } from 'react-native';
|
|
4
4
|
|
|
5
5
|
import {
|
|
6
|
+
BANNER_CLOSE_SLOT_SIZE,
|
|
6
7
|
BANNER_INNER_COLUMN_GAP,
|
|
7
8
|
BANNER_INNER_MARGIN_HORIZONTAL,
|
|
8
9
|
BANNER_INNER_ROW_GAP,
|
|
9
10
|
BANNER_OVERLAY_SCREEN_INSET_HORIZONTAL,
|
|
11
|
+
BANNER_ROOT_PADDING,
|
|
10
12
|
} from './bannerBarTokens';
|
|
11
13
|
import type { EdgeInsets } from './safeArea';
|
|
12
14
|
|
|
@@ -16,13 +18,50 @@ function optionalMargin(value: number | null | undefined): number | undefined {
|
|
|
16
18
|
return value == null ? undefined : value;
|
|
17
19
|
}
|
|
18
20
|
|
|
21
|
+
/** Fixed horizontal chrome inside the embed width (padding, close/spacer slots, inner margins). */
|
|
22
|
+
export function bannerHorizontalChromeWidth(): number {
|
|
23
|
+
return BANNER_ROOT_PADDING * 2 + BANNER_CLOSE_SLOT_SIZE * 2 + BANNER_INNER_MARGIN_HORIZONTAL * 2;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** Outer bar cap — max embed width only (max content width limits the inner row on web). */
|
|
27
|
+
export function resolveBannerFrameMaxWidth(banner: BannerFragment): number | null {
|
|
28
|
+
return banner.maxWidth;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function bannerHasMaxContentWidth(banner: BannerFragment): boolean {
|
|
32
|
+
return banner.maxContentWidth != null;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Cap for the native inner row and WebView HTML `.userflowjs-banner-inner` only.
|
|
37
|
+
* Returns null when max content width is unset. May be 0 when embed width is narrower than chrome.
|
|
38
|
+
*/
|
|
39
|
+
export function resolveBannerInnerMaxWidth(banner: BannerFragment): number | null {
|
|
40
|
+
if (!bannerHasMaxContentWidth(banner)) {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
let cap = banner.maxContentWidth!;
|
|
44
|
+
if (banner.maxWidth != null) {
|
|
45
|
+
const embedInnerCap = Math.max(0, banner.maxWidth - bannerHorizontalChromeWidth());
|
|
46
|
+
cap = Math.min(cap, embedInnerCap);
|
|
47
|
+
}
|
|
48
|
+
return cap;
|
|
49
|
+
}
|
|
50
|
+
|
|
19
51
|
/** Outer frame: max embed width and builder outer margin (web `userflowjs-banner-frame`). */
|
|
20
52
|
export function bannerFrameStyle(banner: BannerFragment): ViewStyle {
|
|
21
|
-
const
|
|
53
|
+
const frameMaxWidth = resolveBannerFrameMaxWidth(banner);
|
|
54
|
+
const hasFrameCap = frameMaxWidth != null;
|
|
22
55
|
|
|
23
56
|
return {
|
|
24
|
-
alignSelf:
|
|
25
|
-
...(
|
|
57
|
+
alignSelf: hasFrameCap ? 'center' : 'stretch',
|
|
58
|
+
...(hasFrameCap
|
|
59
|
+
? {
|
|
60
|
+
maxWidth: frameMaxWidth!,
|
|
61
|
+
width: '100%' as const,
|
|
62
|
+
overflow: 'hidden' as const,
|
|
63
|
+
}
|
|
64
|
+
: null),
|
|
26
65
|
marginTop: optionalMargin(banner.marginTop),
|
|
27
66
|
marginRight: optionalMargin(banner.marginRight),
|
|
28
67
|
marginBottom: optionalMargin(banner.marginBottom),
|
|
@@ -56,12 +95,45 @@ export function bannerInnerJustifyContent(
|
|
|
56
95
|
}
|
|
57
96
|
}
|
|
58
97
|
|
|
98
|
+
/**
|
|
99
|
+
* Push-layout chrome: safe-area pad + bar background on the same node as the
|
|
100
|
+
* fade so an animated banner does not leave a visible status-bar strip at opacity 0.
|
|
101
|
+
*/
|
|
102
|
+
export function bannerPushLayoutChrome(
|
|
103
|
+
edge: 'top' | 'bottom',
|
|
104
|
+
insets: EdgeInsets,
|
|
105
|
+
backgroundColor: string,
|
|
106
|
+
): ViewStyle {
|
|
107
|
+
return {
|
|
108
|
+
backgroundColor,
|
|
109
|
+
paddingTop: edge === 'top' ? insets.top : 0,
|
|
110
|
+
paddingBottom: edge === 'bottom' ? insets.bottom : 0,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/** Matches web `.userflowjs-banner-inner { flex(1000000) }` vs start-spacer `flex(1)`. */
|
|
115
|
+
const BANNER_INNER_FLEX_GROW = 1_000_000;
|
|
116
|
+
|
|
117
|
+
/** Painted bar (`userflow-banner`) — fill the frame so max embed width clips chrome, not just margins. */
|
|
118
|
+
export function bannerBarRootStyle(banner: BannerFragment): ViewStyle {
|
|
119
|
+
if (resolveBannerFrameMaxWidth(banner) == null) {
|
|
120
|
+
return {};
|
|
121
|
+
}
|
|
122
|
+
return {
|
|
123
|
+
width: '100%',
|
|
124
|
+
maxWidth: '100%',
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
59
128
|
export function bannerInnerStyle(banner: BannerFragment): ViewStyle {
|
|
60
|
-
const hasMaxContentWidth = banner
|
|
129
|
+
const hasMaxContentWidth = bannerHasMaxContentWidth(banner);
|
|
130
|
+
const innerMaxWidth = resolveBannerInnerMaxWidth(banner);
|
|
61
131
|
return {
|
|
62
|
-
|
|
132
|
+
// Web `.userflowjs-banner-inner { flex(1000000) }` — grow with shrink so text wraps and close stays visible.
|
|
133
|
+
flexGrow: BANNER_INNER_FLEX_GROW,
|
|
63
134
|
flexShrink: 1,
|
|
64
|
-
flexBasis: 0
|
|
135
|
+
// `auto` avoids the old `flexBasis: 0` + inner `width: 100%` sliver; `minWidth: 0` lets shrink wrap text.
|
|
136
|
+
flexBasis: hasMaxContentWidth ? ('auto' as const) : 0,
|
|
65
137
|
flexDirection: 'row',
|
|
66
138
|
flexWrap: 'wrap',
|
|
67
139
|
alignItems: 'center',
|
|
@@ -69,6 +141,7 @@ export function bannerInnerStyle(banner: BannerFragment): ViewStyle {
|
|
|
69
141
|
rowGap: BANNER_INNER_ROW_GAP,
|
|
70
142
|
marginHorizontal: BANNER_INNER_MARGIN_HORIZONTAL,
|
|
71
143
|
justifyContent: bannerInnerJustifyContent(banner.contentLayout),
|
|
72
|
-
|
|
144
|
+
minWidth: hasMaxContentWidth ? 0 : undefined,
|
|
145
|
+
...(innerMaxWidth != null && innerMaxWidth > 0 ? { maxWidth: innerMaxWidth } : null),
|
|
73
146
|
};
|
|
74
147
|
}
|