@userflow-tech/react-native 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (204) hide show
  1. package/README.md +41 -33
  2. package/docs/troubleshooting.md +38 -38
  3. package/expo-plugin/hostDependencyWarnings.d.ts +5 -5
  4. package/expo-plugin/hostDependencyWarnings.js +7 -7
  5. package/expo-plugin/hostDependencyWarnings.js.map +1 -1
  6. package/lib/commonjs/anchors/AnchorRegistry.js +5 -0
  7. package/lib/commonjs/anchors/AnchorRegistry.js.map +1 -1
  8. package/lib/commonjs/anchors/ScrollContainerRegistry.js +8 -0
  9. package/lib/commonjs/anchors/ScrollContainerRegistry.js.map +1 -1
  10. package/lib/commonjs/anchors/fiber/presentedModal.js +215 -0
  11. package/lib/commonjs/anchors/fiber/presentedModal.js.map +1 -0
  12. package/lib/commonjs/anchors/fiber/touchTargetFiber.js +1 -0
  13. package/lib/commonjs/anchors/fiber/touchTargetFiber.js.map +1 -1
  14. package/lib/commonjs/anchors/fiber/visibleRect.js +12 -3
  15. package/lib/commonjs/anchors/fiber/visibleRect.js.map +1 -1
  16. package/lib/commonjs/anchors/useUserflowAnchor.js.map +1 -1
  17. package/lib/commonjs/anchors/useUserflowScrollContainer.js.map +1 -1
  18. package/lib/commonjs/authoring/ElementPickerOverlay.js +197 -138
  19. package/lib/commonjs/authoring/ElementPickerOverlay.js.map +1 -1
  20. package/lib/commonjs/authoring/hitTest.js +67 -10
  21. package/lib/commonjs/authoring/hitTest.js.map +1 -1
  22. package/lib/commonjs/authoring/hostAtPoint.js +45 -21
  23. package/lib/commonjs/authoring/hostAtPoint.js.map +1 -1
  24. package/lib/commonjs/content/RichContentRenderer.js +19 -7
  25. package/lib/commonjs/content/RichContentRenderer.js.map +1 -1
  26. package/lib/commonjs/deepLinking.js.map +1 -1
  27. package/lib/commonjs/deviceContext.js +39 -19
  28. package/lib/commonjs/deviceContext.js.map +1 -1
  29. package/lib/commonjs/index.js +11 -5
  30. package/lib/commonjs/index.js.map +1 -1
  31. package/lib/commonjs/installCheck.js +3 -3
  32. package/lib/commonjs/installCheck.js.map +1 -1
  33. package/lib/commonjs/lifecycle.js +2 -0
  34. package/lib/commonjs/lifecycle.js.map +1 -1
  35. package/lib/commonjs/pairing/PairingController.js.map +1 -1
  36. package/lib/commonjs/runtime/UserflowOverlay.js +17 -13
  37. package/lib/commonjs/runtime/UserflowOverlay.js.map +1 -1
  38. package/lib/commonjs/runtime/WindowOverlayHost.js +83 -0
  39. package/lib/commonjs/runtime/WindowOverlayHost.js.map +1 -0
  40. package/lib/commonjs/runtime/userflowCore.js +9 -2
  41. package/lib/commonjs/runtime/userflowCore.js.map +1 -1
  42. package/lib/commonjs/surfaces/TooltipSurface.js +109 -51
  43. package/lib/commonjs/surfaces/TooltipSurface.js.map +1 -1
  44. package/lib/commonjs/surfaces/tooltip/TooltipHighlight.js +6 -6
  45. package/lib/commonjs/surfaces/tooltip/TooltipHighlight.js.map +1 -1
  46. package/lib/commonjs/surfaces/tooltip/targetOrigin.js +74 -0
  47. package/lib/commonjs/surfaces/tooltip/targetOrigin.js.map +1 -0
  48. package/lib/commonjs/version.js +1 -1
  49. package/lib/module/anchors/AnchorRegistry.js +5 -0
  50. package/lib/module/anchors/AnchorRegistry.js.map +1 -1
  51. package/lib/module/anchors/ScrollContainerRegistry.js +8 -0
  52. package/lib/module/anchors/ScrollContainerRegistry.js.map +1 -1
  53. package/lib/module/anchors/fiber/presentedModal.js +206 -0
  54. package/lib/module/anchors/fiber/presentedModal.js.map +1 -0
  55. package/lib/module/anchors/fiber/touchTargetFiber.js +1 -0
  56. package/lib/module/anchors/fiber/touchTargetFiber.js.map +1 -1
  57. package/lib/module/anchors/fiber/visibleRect.js +12 -3
  58. package/lib/module/anchors/fiber/visibleRect.js.map +1 -1
  59. package/lib/module/anchors/useUserflowAnchor.js.map +1 -1
  60. package/lib/module/anchors/useUserflowScrollContainer.js.map +1 -1
  61. package/lib/module/authoring/ElementPickerOverlay.js +199 -140
  62. package/lib/module/authoring/ElementPickerOverlay.js.map +1 -1
  63. package/lib/module/authoring/hitTest.js +67 -11
  64. package/lib/module/authoring/hitTest.js.map +1 -1
  65. package/lib/module/authoring/hostAtPoint.js +45 -21
  66. package/lib/module/authoring/hostAtPoint.js.map +1 -1
  67. package/lib/module/content/RichContentRenderer.js +19 -7
  68. package/lib/module/content/RichContentRenderer.js.map +1 -1
  69. package/lib/module/deepLinking.js.map +1 -1
  70. package/lib/module/deviceContext.js +38 -17
  71. package/lib/module/deviceContext.js.map +1 -1
  72. package/lib/module/index.js +11 -5
  73. package/lib/module/index.js.map +1 -1
  74. package/lib/module/installCheck.js +3 -3
  75. package/lib/module/installCheck.js.map +1 -1
  76. package/lib/module/lifecycle.js +2 -0
  77. package/lib/module/lifecycle.js.map +1 -1
  78. package/lib/module/pairing/PairingController.js.map +1 -1
  79. package/lib/module/runtime/UserflowOverlay.js +18 -14
  80. package/lib/module/runtime/UserflowOverlay.js.map +1 -1
  81. package/lib/module/runtime/WindowOverlayHost.js +76 -0
  82. package/lib/module/runtime/WindowOverlayHost.js.map +1 -0
  83. package/lib/module/runtime/userflowCore.js +9 -2
  84. package/lib/module/runtime/userflowCore.js.map +1 -1
  85. package/lib/module/surfaces/TooltipSurface.js +109 -51
  86. package/lib/module/surfaces/TooltipSurface.js.map +1 -1
  87. package/lib/module/surfaces/tooltip/TooltipHighlight.js +6 -6
  88. package/lib/module/surfaces/tooltip/TooltipHighlight.js.map +1 -1
  89. package/lib/module/surfaces/tooltip/targetOrigin.js +67 -0
  90. package/lib/module/surfaces/tooltip/targetOrigin.js.map +1 -0
  91. package/lib/module/version.js +1 -1
  92. package/lib/typescript/commonjs/src/anchors/AnchorRegistry.d.ts +7 -0
  93. package/lib/typescript/commonjs/src/anchors/AnchorRegistry.d.ts.map +1 -1
  94. package/lib/typescript/commonjs/src/anchors/ScrollContainerRegistry.d.ts +11 -2
  95. package/lib/typescript/commonjs/src/anchors/ScrollContainerRegistry.d.ts.map +1 -1
  96. package/lib/typescript/commonjs/src/anchors/fiber/presentedModal.d.ts +45 -0
  97. package/lib/typescript/commonjs/src/anchors/fiber/presentedModal.d.ts.map +1 -0
  98. package/lib/typescript/commonjs/src/anchors/fiber/visibleRect.d.ts +5 -2
  99. package/lib/typescript/commonjs/src/anchors/fiber/visibleRect.d.ts.map +1 -1
  100. package/lib/typescript/commonjs/src/anchors/useUserflowAnchor.d.ts +2 -2
  101. package/lib/typescript/commonjs/src/anchors/useUserflowAnchor.d.ts.map +1 -1
  102. package/lib/typescript/commonjs/src/anchors/useUserflowScrollContainer.d.ts +3 -2
  103. package/lib/typescript/commonjs/src/anchors/useUserflowScrollContainer.d.ts.map +1 -1
  104. package/lib/typescript/commonjs/src/authoring/ElementPickerOverlay.d.ts +4 -0
  105. package/lib/typescript/commonjs/src/authoring/ElementPickerOverlay.d.ts.map +1 -1
  106. package/lib/typescript/commonjs/src/authoring/hitTest.d.ts +25 -2
  107. package/lib/typescript/commonjs/src/authoring/hitTest.d.ts.map +1 -1
  108. package/lib/typescript/commonjs/src/authoring/hostAtPoint.d.ts +6 -1
  109. package/lib/typescript/commonjs/src/authoring/hostAtPoint.d.ts.map +1 -1
  110. package/lib/typescript/commonjs/src/deepLinking.d.ts +1 -1
  111. package/lib/typescript/commonjs/src/deepLinking.d.ts.map +1 -1
  112. package/lib/typescript/commonjs/src/deviceContext.d.ts +14 -5
  113. package/lib/typescript/commonjs/src/deviceContext.d.ts.map +1 -1
  114. package/lib/typescript/commonjs/src/index.d.ts +11 -5
  115. package/lib/typescript/commonjs/src/index.d.ts.map +1 -1
  116. package/lib/typescript/commonjs/src/installCheck.d.ts +2 -2
  117. package/lib/typescript/commonjs/src/installCheck.d.ts.map +1 -1
  118. package/lib/typescript/commonjs/src/lifecycle.d.ts +1 -0
  119. package/lib/typescript/commonjs/src/lifecycle.d.ts.map +1 -1
  120. package/lib/typescript/commonjs/src/pairing/PairingController.d.ts +1 -1
  121. package/lib/typescript/commonjs/src/pairing/PairingController.d.ts.map +1 -1
  122. package/lib/typescript/commonjs/src/runtime/UserflowOverlay.d.ts.map +1 -1
  123. package/lib/typescript/commonjs/src/runtime/WindowOverlayHost.d.ts +34 -0
  124. package/lib/typescript/commonjs/src/runtime/WindowOverlayHost.d.ts.map +1 -0
  125. package/lib/typescript/commonjs/src/runtime/userflowCore.d.ts.map +1 -1
  126. package/lib/typescript/commonjs/src/surfaces/TooltipSurface.d.ts.map +1 -1
  127. package/lib/typescript/commonjs/src/surfaces/tooltip/targetOrigin.d.ts +26 -0
  128. package/lib/typescript/commonjs/src/surfaces/tooltip/targetOrigin.d.ts.map +1 -0
  129. package/lib/typescript/commonjs/src/version.d.ts +1 -1
  130. package/lib/typescript/module/src/anchors/AnchorRegistry.d.ts +7 -0
  131. package/lib/typescript/module/src/anchors/AnchorRegistry.d.ts.map +1 -1
  132. package/lib/typescript/module/src/anchors/ScrollContainerRegistry.d.ts +11 -2
  133. package/lib/typescript/module/src/anchors/ScrollContainerRegistry.d.ts.map +1 -1
  134. package/lib/typescript/module/src/anchors/fiber/presentedModal.d.ts +45 -0
  135. package/lib/typescript/module/src/anchors/fiber/presentedModal.d.ts.map +1 -0
  136. package/lib/typescript/module/src/anchors/fiber/visibleRect.d.ts +5 -2
  137. package/lib/typescript/module/src/anchors/fiber/visibleRect.d.ts.map +1 -1
  138. package/lib/typescript/module/src/anchors/useUserflowAnchor.d.ts +2 -2
  139. package/lib/typescript/module/src/anchors/useUserflowAnchor.d.ts.map +1 -1
  140. package/lib/typescript/module/src/anchors/useUserflowScrollContainer.d.ts +3 -2
  141. package/lib/typescript/module/src/anchors/useUserflowScrollContainer.d.ts.map +1 -1
  142. package/lib/typescript/module/src/authoring/ElementPickerOverlay.d.ts +4 -0
  143. package/lib/typescript/module/src/authoring/ElementPickerOverlay.d.ts.map +1 -1
  144. package/lib/typescript/module/src/authoring/hitTest.d.ts +25 -2
  145. package/lib/typescript/module/src/authoring/hitTest.d.ts.map +1 -1
  146. package/lib/typescript/module/src/authoring/hostAtPoint.d.ts +6 -1
  147. package/lib/typescript/module/src/authoring/hostAtPoint.d.ts.map +1 -1
  148. package/lib/typescript/module/src/deepLinking.d.ts +1 -1
  149. package/lib/typescript/module/src/deepLinking.d.ts.map +1 -1
  150. package/lib/typescript/module/src/deviceContext.d.ts +14 -5
  151. package/lib/typescript/module/src/deviceContext.d.ts.map +1 -1
  152. package/lib/typescript/module/src/index.d.ts +11 -5
  153. package/lib/typescript/module/src/index.d.ts.map +1 -1
  154. package/lib/typescript/module/src/installCheck.d.ts +2 -2
  155. package/lib/typescript/module/src/installCheck.d.ts.map +1 -1
  156. package/lib/typescript/module/src/lifecycle.d.ts +1 -0
  157. package/lib/typescript/module/src/lifecycle.d.ts.map +1 -1
  158. package/lib/typescript/module/src/pairing/PairingController.d.ts +1 -1
  159. package/lib/typescript/module/src/pairing/PairingController.d.ts.map +1 -1
  160. package/lib/typescript/module/src/runtime/UserflowOverlay.d.ts.map +1 -1
  161. package/lib/typescript/module/src/runtime/WindowOverlayHost.d.ts +34 -0
  162. package/lib/typescript/module/src/runtime/WindowOverlayHost.d.ts.map +1 -0
  163. package/lib/typescript/module/src/runtime/userflowCore.d.ts.map +1 -1
  164. package/lib/typescript/module/src/surfaces/TooltipSurface.d.ts.map +1 -1
  165. package/lib/typescript/module/src/surfaces/tooltip/targetOrigin.d.ts +26 -0
  166. package/lib/typescript/module/src/surfaces/tooltip/targetOrigin.d.ts.map +1 -0
  167. package/lib/typescript/module/src/version.d.ts +1 -1
  168. package/package.json +5 -4
  169. package/src/anchors/AnchorRegistry.ts +8 -0
  170. package/src/anchors/ScrollContainerRegistry.ts +15 -3
  171. package/src/anchors/fiber/presentedModal.ts +203 -0
  172. package/src/anchors/fiber/touchTargetFiber.ts +2 -1
  173. package/src/anchors/fiber/visibleRect.ts +12 -3
  174. package/src/anchors/useUserflowAnchor.ts +4 -5
  175. package/src/anchors/useUserflowScrollContainer.ts +5 -4
  176. package/src/authoring/ElementPickerOverlay.tsx +242 -166
  177. package/src/authoring/hitTest.ts +88 -13
  178. package/src/authoring/hostAtPoint.ts +67 -21
  179. package/src/content/RichContentRenderer.tsx +11 -9
  180. package/src/deepLinking.ts +2 -1
  181. package/src/deviceContext.ts +50 -14
  182. package/src/index.ts +11 -5
  183. package/src/installCheck.ts +3 -3
  184. package/src/lifecycle.ts +2 -1
  185. package/src/pairing/PairingController.ts +2 -1
  186. package/src/runtime/UserflowOverlay.tsx +29 -21
  187. package/src/runtime/WindowOverlayHost.tsx +95 -0
  188. package/src/runtime/userflowCore.ts +8 -2
  189. package/src/surfaces/TooltipSurface.tsx +103 -45
  190. package/src/surfaces/tooltip/TooltipHighlight.tsx +3 -5
  191. package/src/surfaces/tooltip/targetOrigin.ts +74 -0
  192. package/src/version.ts +1 -1
  193. package/vendor/core/dist/engine/UserflowCore.d.ts +7 -0
  194. package/vendor/core/dist/engine/UserflowCore.d.ts.map +1 -1
  195. package/vendor/core/dist/engine/UserflowCore.js +3 -2
  196. package/vendor/core/dist/engine/UserflowCore.js.map +1 -1
  197. package/vendor/core/dist/transport/phoenix.d.ts +12 -2
  198. package/vendor/core/dist/transport/phoenix.d.ts.map +1 -1
  199. package/vendor/core/dist/transport/phoenix.js +7 -6
  200. package/vendor/core/dist/transport/phoenix.js.map +1 -1
  201. package/vendor/core/dist/version.d.ts +1 -1
  202. package/vendor/core/dist/version.js +1 -1
  203. package/vendor/core/package.json +1 -1
  204. package/vendor/protocol/package.json +1 -1
@@ -12,6 +12,7 @@ import { stepTrapsHostAccessibility } from '../surfaces/hostAccessibilityTrap';
12
12
 
13
13
  import { BannerHost } from './BannerHost';
14
14
  import { FlowRenderer } from './FlowRenderer';
15
+ import { WindowOverlayHost } from './WindowOverlayHost';
15
16
  import { useFlowSessionState } from './useFlowSessionState';
16
17
  import { getUserflowCore } from './userflowCore';
17
18
 
@@ -86,30 +87,37 @@ export function UserflowOverlay({
86
87
  * destroy a running script. `suppressed` hides it for the pick.
87
88
  */}
88
89
  <EvalJsHost suppressed={pickerActive} />
89
- <PreviewModeBanner
90
- onConfirmingChange={setPreviewConfirming}
91
- onExit={onExitPreview}
92
- held={previewHeld}
93
- onRestart={onRestartPreview}
94
- state={pairingState}
95
- suppressed={pickerActive}
96
- />
97
90
  {/*
98
- * Unmount flow chrome for the whole pick. The session stays alive;
99
- * captureScreen would otherwise include the modal or tooltip.
100
- * Remounting reads the same session back.
91
+ * One host for all three, so they keep this paint order above native
92
+ * modal screens. The host app's trap does not reach a natively presented
93
+ * modal, so the host traps VoiceOver itself.
101
94
  */}
102
- {pickerActive ? null : (
103
- <FlowRenderer
104
- engine={engine}
105
- previewRestartGeneration={pairingState.previewRestartGeneration}
95
+ <WindowOverlayHost accessibilityModal={trapHostAccessibility}>
96
+ <PreviewModeBanner
97
+ onConfirmingChange={setPreviewConfirming}
98
+ onExit={onExitPreview}
99
+ held={previewHeld}
100
+ onRestart={onRestartPreview}
101
+ state={pairingState}
102
+ suppressed={pickerActive}
106
103
  />
107
- )}
108
- {/*
109
- * After flow chrome so BODY_FIRST / BODY_LAST overlay banners stay visible
110
- * while a tour step (modal, tooltip, condition wait) is still active.
111
- */}
112
- <BannerHost engine={bannerEngine} hidden={pickerActive} />
104
+ {/*
105
+ * Unmount flow chrome for the whole pick. The session stays alive;
106
+ * captureScreen would otherwise include the modal or tooltip.
107
+ * Remounting reads the same session back.
108
+ */}
109
+ {pickerActive ? null : (
110
+ <FlowRenderer
111
+ engine={engine}
112
+ previewRestartGeneration={pairingState.previewRestartGeneration}
113
+ />
114
+ )}
115
+ {/*
116
+ * After flow chrome so BODY_FIRST / BODY_LAST overlay banners stay visible
117
+ * while a tour step (modal, tooltip, condition wait) is still active.
118
+ */}
119
+ <BannerHost engine={bannerEngine} hidden={pickerActive} />
120
+ </WindowOverlayHost>
113
121
  <ElementPickerOverlay />
114
122
  </>
115
123
  );
@@ -0,0 +1,95 @@
1
+ import * as React from 'react';
2
+ import { Platform } from 'react-native';
3
+
4
+ import { isNativeModuleLinked } from '../nativeModules';
5
+
6
+ interface FullWindowOverlayProps {
7
+ children?: React.ReactNode;
8
+ /** react-native-screens 4.x. Defaults to true, which traps VoiceOver inside the overlay. */
9
+ unstable_accessibilityContainerViewIsModal?: boolean;
10
+ }
11
+
12
+ type FullWindowOverlayComponent = React.ComponentType<FullWindowOverlayProps>;
13
+
14
+ /**
15
+ * Native module in every react-native-screens 3.x and 4.x build. Rendering
16
+ * `FullWindowOverlay` without the native half would mount an unregistered
17
+ * component, so the package is not required until this is linked.
18
+ */
19
+ const SCREENS_NATIVE_MODULE = 'RNSModule';
20
+
21
+ let cached: FullWindowOverlayComponent | null | undefined;
22
+
23
+ /** react-native-screens' `FullWindowOverlay`, or null when it cannot host chrome here. */
24
+ function getFullWindowOverlay(): FullWindowOverlayComponent | null {
25
+ if (cached !== undefined) return cached;
26
+ cached = null;
27
+
28
+ // FullWindowOverlay is iOS-only; elsewhere it renders a plain View.
29
+ if (Platform.OS !== 'ios' || typeof require !== 'function') return cached;
30
+ if (!isNativeModuleLinked(SCREENS_NATIVE_MODULE)) return cached;
31
+
32
+ try {
33
+ // Not a peer: apps that present native modals already have it, through
34
+ // Expo Router or React Navigation's native stack.
35
+ // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires -- optional package probe
36
+ const mod = require('react-native-screens') as {
37
+ FullWindowOverlay?: FullWindowOverlayComponent;
38
+ };
39
+ cached = mod?.FullWindowOverlay ?? null;
40
+ } catch {
41
+ cached = null;
42
+ }
43
+ return cached;
44
+ }
45
+
46
+ export interface WindowOverlayHostProps {
47
+ children: React.ReactNode;
48
+ /**
49
+ * Hide everything outside the host from VoiceOver, natively presented
50
+ * modals included. Defaults to false.
51
+ */
52
+ accessibilityModal?: boolean;
53
+ }
54
+
55
+ /** True when {@link WindowOverlayHost} draws above natively presented modals. */
56
+ export function hasWindowOverlayHost(): boolean {
57
+ return getFullWindowOverlay() != null;
58
+ }
59
+
60
+ /**
61
+ * Hosts SDK chrome above everything else in the app window.
62
+ *
63
+ * On iOS, react-native-screens presents `modal`, `transparentModal`,
64
+ * `formSheet` and `fullScreenModal` screens, and React Native presents
65
+ * `<Modal>`, as view controllers above the React Native root view, so chrome
66
+ * rendered in `UserflowProvider`'s overlay is drawn beneath them and never
67
+ * receives touches there. `FullWindowOverlay` moves its children into a
68
+ * container on the window itself. Measured on iOS 17.4 and 26.5 with
69
+ * react-native-screens 4.16, that container stays above sheets whether they are
70
+ * presented before or after it mounts.
71
+ *
72
+ * Each host is its own container, stacked by when it was attached rather than
73
+ * by React order, so chrome that has to keep a paint order shares one host.
74
+ *
75
+ * Touches inside the host arrive in window coordinates, as they do in the root
76
+ * view. Children render in place when the overlay is unavailable: on Android,
77
+ * and in apps without react-native-screens.
78
+ */
79
+ export function WindowOverlayHost({
80
+ children,
81
+ accessibilityModal = false,
82
+ }: WindowOverlayHostProps): React.ReactElement {
83
+ const FullWindowOverlay = getFullWindowOverlay();
84
+ if (!FullWindowOverlay) return <>{children}</>;
85
+ return (
86
+ <FullWindowOverlay unstable_accessibilityContainerViewIsModal={accessibilityModal}>
87
+ {children}
88
+ </FullWindowOverlay>
89
+ );
90
+ }
91
+
92
+ /** @internal Clears the cached `FullWindowOverlay` lookup between tests. */
93
+ export function resetWindowOverlayHostForTests(): void {
94
+ cached = undefined;
95
+ }
@@ -1,7 +1,13 @@
1
1
  import { UserflowCore } from '@userflow-tech/core';
2
2
 
3
- /** Shared {@link UserflowCore} singleton for the RN package facade + provider. */
4
- const core = new UserflowCore();
3
+ import { SDK_VERSION } from '../version';
4
+
5
+ /**
6
+ * Shared {@link UserflowCore} singleton for the RN package facade + provider.
7
+ * Joins report the published SDK version (not the internal core version) as
8
+ * `userflowClientBuild`.
9
+ */
10
+ const core = new UserflowCore({ clientBuild: `react-native-${SDK_VERSION}` });
5
11
 
6
12
  export function getUserflowCore(): UserflowCore {
7
13
  return core;
@@ -23,7 +23,8 @@ import { autoAnchorRegistry } from '../anchors/AutoAnchorRegistry';
23
23
  import { addAnimationFrameCallback, removeAnimationFrameCallback } from '../anchors/animationFrame';
24
24
  import { isAppActive, subscribeAppActive } from '../anchors/appActive';
25
25
  import { fiberScanRoot } from '../anchors/fiber/FiberScanRoot';
26
- import type { AnyFiber } from '../anchors/fiber/fiberInternals';
26
+ import { type AnyFiber, fiberFromPublicInstance } from '../anchors/fiber/fiberInternals';
27
+ import type { Point } from '../anchors/fiber/presentedModal';
27
28
  import { clipToScrollViewports } from '../anchors/fiber/visibleRect';
28
29
  import {
29
30
  clearFiberAnchorCache,
@@ -82,6 +83,7 @@ import {
82
83
  tooltipSideGap,
83
84
  tooltipVerticalGap,
84
85
  } from './tooltip/resolveSideCardWidth';
86
+ import { locateTargetOrigin, offsetRect } from './tooltip/targetOrigin';
85
87
  import { TargetSearchSchedule } from './tooltip/targetSearchSchedule';
86
88
 
87
89
  export interface TooltipSurfaceProps {
@@ -201,6 +203,12 @@ export function TooltipSurface({
201
203
  const [missingMode, setMissingMode] = React.useState<MissingMode>('waiting');
202
204
  /** True after at least one *failed* measure for the current step/anchor. */
203
205
  const [measureAttempted, setMeasureAttempted] = React.useState(false);
206
+ /**
207
+ * True while a natively presented modal hides the target, or the target is
208
+ * in a sheet that cannot be placed. The step waits without counting the
209
+ * target as missing, and draws nothing over the modal.
210
+ */
211
+ const [concealed, setConcealed] = React.useState(false);
204
212
  /**
205
213
  * False only after a same-step `resetNonce` bump (preview restart) until one
206
214
  * frame has passed, so dialog teardown cannot 0-size FLAG.
@@ -238,7 +246,15 @@ export function TooltipSurface({
238
246
  const resolveEpochRef = React.useRef(0);
239
247
  /** Latest resolved host fiber (for scroll-ancestor walk + rAF remeasure). */
240
248
  const hostFiberRef = React.useRef<AnyFiber | null>(null);
241
- /** Target rect clipped to scroll viewports, for tap detection only. */
249
+ /**
250
+ * Window position of the host's measure space, from the last resolve. Not
251
+ * zero only inside a native sheet, whose content measures and receives
252
+ * touches relative to the sheet.
253
+ */
254
+ const measureOriginRef = React.useRef<Point>({ x: 0, y: 0 });
255
+ /** `targetRef` in the host's measure space. */
256
+ const measuredRef = React.useRef<Rect | null>(null);
257
+ /** Target rect clipped to scroll viewports, for tap detection only. In measure space, as touches are. */
242
258
  const clippedPressRef = React.useRef<Rect | null>(null);
243
259
  const clipGenRef = React.useRef(0);
244
260
  const hostMeasureRef = React.useRef<
@@ -263,6 +279,8 @@ export function TooltipSurface({
263
279
  insetsRef.current = layoutInsets;
264
280
  const missingModeRef = React.useRef(missingMode);
265
281
  missingModeRef.current = missingMode;
282
+ const concealedRef = React.useRef(concealed);
283
+ concealedRef.current = concealed;
266
284
  const behaviorRef = React.useRef(behavior);
267
285
  behaviorRef.current = behavior;
268
286
  const draftModeRef = React.useRef(session.draftMode);
@@ -292,6 +310,7 @@ export function TooltipSurface({
292
310
  warnedSidePlacementStepRef.current = null;
293
311
  targetStepIdRef.current = null;
294
312
  targetRef.current = null;
313
+ measuredRef.current = null;
295
314
  // Drop the previous card's measured size and side so the next step does not
296
315
  // inherit a wrapped 115×400 LEFT into `fits(currentPlacement)`.
297
316
  const nextPlacement = desiredPlacementRef.current ?? 'BELOW';
@@ -300,6 +319,7 @@ export function TooltipSurface({
300
319
  setBubbleSize({ width: 280, height: 160 });
301
320
  setMissingMode('waiting');
302
321
  setMeasureAttempted(false);
322
+ setConcealed(false);
303
323
  setTarget(null);
304
324
  const prev = targetingIdentityRef.current;
305
325
  const sameIdentity = prev.stepId === currentStep.id && prev.targetKey === targetKey;
@@ -319,10 +339,13 @@ export function TooltipSurface({
319
339
  return () => clearTimeout(handle);
320
340
  }, [resolveArmed]);
321
341
 
322
- const applyTarget = React.useCallback((next: Rect | null) => {
342
+ /** `next` is in window coordinates; `measured` is the same rect in the host's measure space. */
343
+ const applyTarget = React.useCallback((next: Rect | null, measured: Rect | null = next) => {
323
344
  if (!mountedRef.current) return;
345
+ if (next != null) setConcealed(false);
324
346
  targetStepIdRef.current = next == null ? null : currentStepIdRef.current;
325
- if (rectsEqual(targetRef.current, next)) return;
347
+ if (rectsEqual(targetRef.current, next) && rectsEqual(measuredRef.current, measured)) return;
348
+ measuredRef.current = measured;
326
349
  if (next == null) {
327
350
  // The anchor went away (unmount / navigation), so whatever scroll position
328
351
  // the user had settled on no longer applies. Treat its next appearance as
@@ -332,15 +355,15 @@ export function TooltipSurface({
332
355
  }
333
356
  targetRef.current = next;
334
357
  setTarget(next);
335
- if (next == null) {
358
+ if (next == null || measured == null) {
336
359
  clippedPressRef.current = null;
337
360
  return;
338
361
  }
339
- clippedPressRef.current = next;
362
+ clippedPressRef.current = measured;
340
363
  const fiber = hostFiberRef.current;
341
364
  const gen = (clipGenRef.current += 1);
342
365
  if (!fiber) return;
343
- void clipToScrollViewports(fiber, next).then((clipped) => {
366
+ void clipToScrollViewports(fiber, measured).then((clipped) => {
344
367
  if (clipGenRef.current !== gen) return;
345
368
  clippedPressRef.current = clipped;
346
369
  });
@@ -364,10 +387,28 @@ export function TooltipSurface({
364
387
  hostMeasureRef.current = null;
365
388
  hostScrollIntoViewRef.current = undefined;
366
389
  fiberCacheIdRef.current = null;
390
+ setConcealed(false);
367
391
  markMeasureAttempted();
368
392
  applyTarget(null);
369
393
  }, [applyTarget, markMeasureAttempted]);
370
394
 
395
+ /**
396
+ * Forget the resolved host while a natively presented modal hides it. Unlike
397
+ * {@link dropHost} the target is not gone: the missing-target timer does not
398
+ * run, so opening a sheet mid-step cannot flag or end the flow, and the
399
+ * tooltip comes back when the sheet closes.
400
+ */
401
+ const concealHost = React.useCallback(() => {
402
+ resolveEpochRef.current += 1;
403
+ measureInFlightRef.current = false;
404
+ hostFiberRef.current = null;
405
+ hostMeasureRef.current = null;
406
+ hostScrollIntoViewRef.current = undefined;
407
+ fiberCacheIdRef.current = null;
408
+ setConcealed(true);
409
+ applyTarget(null);
410
+ }, [applyTarget]);
411
+
371
412
  const effectiveViewport = React.useCallback(() => {
372
413
  const windowSize = Dimensions.get('window');
373
414
  const scrollPadding = getScrollPadding();
@@ -386,8 +427,9 @@ export function TooltipSurface({
386
427
  );
387
428
  }, []);
388
429
 
430
+ /** `rect` is in window coordinates; `measured` is the same rect in the host's measure space. */
389
431
  const maybeScrollIntoView = React.useCallback(
390
- (rect: Rect) => {
432
+ (rect: Rect, measured: Rect) => {
391
433
  // Scrolling the app to reveal a target we are fading away from is visible.
392
434
  if (exitingRef.current) return;
393
435
  if (scrollSettledRef.current) return;
@@ -408,8 +450,9 @@ export function TooltipSurface({
408
450
  ? { scrollIntoView: hostScrollIntoViewRef.current }
409
451
  : {}),
410
452
  };
453
+ // Scroll containers are measured in the same space as the host.
411
454
  scrollAnchorIntoView({
412
- rect,
455
+ rect: measured,
413
456
  host,
414
457
  fiber: hostFiberRef.current,
415
458
  });
@@ -420,6 +463,31 @@ export function TooltipSurface({
420
463
  [effectiveViewport],
421
464
  );
422
465
 
466
+ /** Measure callback for both the resolve and the rAF remeasure of `epoch`'s host. */
467
+ const onHostMeasured = React.useCallback(
468
+ (epoch: number, x: number, y: number, width: number, height: number) => {
469
+ if (resolveEpochRef.current !== epoch) {
470
+ measureInFlightRef.current = false;
471
+ return;
472
+ }
473
+ measureInFlightRef.current = false;
474
+ if (!mountedRef.current) return;
475
+
476
+ if (width <= 0 || height <= 0) {
477
+ const cacheId = fiberCacheIdRef.current;
478
+ if (cacheId) invalidateFiberAnchor(cacheId);
479
+ dropHost();
480
+ return;
481
+ }
482
+
483
+ const measured: Rect = { x, y, width, height };
484
+ const rect = offsetRect(measured, measureOriginRef.current);
485
+ maybeScrollIntoView(rect, measured);
486
+ applyTarget(rect, measured);
487
+ },
488
+ [applyTarget, dropHost, maybeScrollIntoView],
489
+ );
490
+
423
491
  /**
424
492
  * Resolve the anchor host (registry / fiber scan). Driven by
425
493
  * {@link TargetSearchSchedule} — intentionally NOT on every animation frame.
@@ -450,26 +518,25 @@ export function TooltipSurface({
450
518
  if (measureInFlightRef.current) return;
451
519
  const epoch = resolveEpochRef.current;
452
520
  measureInFlightRef.current = true;
453
- resolution.host.measureInWindow((x, y, width, height) => {
454
- if (resolveEpochRef.current !== epoch) {
521
+ const { host } = resolution;
522
+ const placedFiber = resolution.fiber ?? fiberFromPublicInstance(host.node);
523
+ // Refreshed per resolve, not per frame: a sheet moves rarely, and the
524
+ // lookup walks the whole tree.
525
+ locateTargetOrigin(placedFiber, (origin) => {
526
+ if (resolveEpochRef.current !== epoch || !mountedRef.current) {
455
527
  measureInFlightRef.current = false;
456
528
  return;
457
529
  }
458
- measureInFlightRef.current = false;
459
- if (!mountedRef.current) return;
460
-
461
- if (width <= 0 || height <= 0) {
462
- const cacheId = fiberCacheIdRef.current;
463
- if (cacheId) invalidateFiberAnchor(cacheId);
464
- dropHost();
530
+ if (!origin) {
531
+ concealHost();
465
532
  return;
466
533
  }
467
-
468
- const rect: Rect = { x, y, width, height };
469
- maybeScrollIntoView(rect);
470
- applyTarget(rect);
534
+ measureOriginRef.current = origin;
535
+ host.measureInWindow((x, y, width, height) => {
536
+ onHostMeasured(epoch, x, y, width, height);
537
+ });
471
538
  });
472
- }, [anchorId, applyTarget, decodedAutoData, dropHost, isAuto, maybeScrollIntoView]);
539
+ }, [anchorId, concealHost, decodedAutoData, dropHost, isAuto, onHostMeasured]);
473
540
 
474
541
  /**
475
542
  * Live re-measure of an already-resolved host. Driven by the shared rAF hub
@@ -484,25 +551,9 @@ export function TooltipSurface({
484
551
  const epoch = resolveEpochRef.current;
485
552
  measureInFlightRef.current = true;
486
553
  measure((x, y, width, height) => {
487
- if (resolveEpochRef.current !== epoch) {
488
- measureInFlightRef.current = false;
489
- return;
490
- }
491
- measureInFlightRef.current = false;
492
- if (!mountedRef.current) return;
493
-
494
- if (width <= 0 || height <= 0) {
495
- const cacheId = fiberCacheIdRef.current;
496
- if (cacheId) invalidateFiberAnchor(cacheId);
497
- dropHost();
498
- return;
499
- }
500
-
501
- const rect: Rect = { x, y, width, height };
502
- maybeScrollIntoView(rect);
503
- applyTarget(rect);
554
+ onHostMeasured(epoch, x, y, width, height);
504
555
  });
505
- }, [applyTarget, dropHost, maybeScrollIntoView]);
556
+ }, [onHostMeasured]);
506
557
 
507
558
  const resolveTargetRef = React.useRef(resolveTarget);
508
559
  resolveTargetRef.current = resolveTarget;
@@ -521,7 +572,8 @@ export function TooltipSurface({
521
572
  }
522
573
  const search = new TargetSearchSchedule(() => resolveTargetRef.current());
523
574
  searchRef.current = search;
524
- search.setMode(targetRef.current ? 'anchored' : 'missing');
575
+ // A concealed target keeps the steady poll, so the tooltip is back soon after the modal closes.
576
+ search.setMode(targetRef.current || concealedRef.current ? 'anchored' : 'missing');
525
577
 
526
578
  const trigger = () => search.trigger();
527
579
  const unsubscribers = [
@@ -556,8 +608,8 @@ export function TooltipSurface({
556
608
  }, [resolveArmed, searchStopped, currentStep.id, targetKey]);
557
609
 
558
610
  React.useEffect(() => {
559
- searchRef.current?.setMode(target ? 'anchored' : 'missing');
560
- }, [target]);
611
+ searchRef.current?.setMode(target || concealed ? 'anchored' : 'missing');
612
+ }, [target, concealed]);
561
613
 
562
614
  // rAF tracking while a host is resolved (and we are not paused after report).
563
615
  React.useEffect(() => {
@@ -592,7 +644,7 @@ export function TooltipSurface({
592
644
  return;
593
645
  }
594
646
 
595
- if (!measureAttempted) {
647
+ if (!measureAttempted || concealed) {
596
648
  return;
597
649
  }
598
650
 
@@ -608,6 +660,7 @@ export function TooltipSurface({
608
660
  }, [
609
661
  target,
610
662
  measureAttempted,
663
+ concealed,
611
664
  engine,
612
665
  currentStep.id,
613
666
  theme.tooltipMissingBehavior,
@@ -872,6 +925,11 @@ export function TooltipSurface({
872
925
  return null;
873
926
  }
874
927
 
928
+ // A native modal hides the target: nothing over it, not even the blocker.
929
+ if (isMissing && concealed) {
930
+ return null;
931
+ }
932
+
875
933
  const showBranding = session.flow.company.flowBranding;
876
934
  const contentPadding = chrome.contentPadding;
877
935
  // Modal only while the host is trapped too. Otherwise VoiceOver would skip
@@ -90,16 +90,14 @@ export function buildHighlightRings(rect: HighlightRect, chrome: HighlightChrome
90
90
 
91
91
  function strokeGlow(chrome: HighlightChrome): ViewStyle {
92
92
  const blur = Math.max(chrome.radius, 6);
93
- const glow: ViewStyle = {
93
+ // Built in one literal: React Native 0.88 types ViewStyle as readonly.
94
+ return {
94
95
  shadowColor: chrome.color,
95
96
  shadowOffset: { width: 0, height: 0 },
96
97
  shadowOpacity: Math.min(0.45, chrome.opacity),
97
98
  shadowRadius: blur,
99
+ ...(Platform?.OS !== 'ios' ? { boxShadow: `0px 0px ${blur}px 0px ${chrome.glowColor}` } : null),
98
100
  };
99
- if (Platform?.OS !== 'ios') {
100
- glow.boxShadow = `0px 0px ${blur}px 0px ${chrome.glowColor}`;
101
- }
102
- return glow;
103
101
  }
104
102
 
105
103
  function ringFrame(
@@ -0,0 +1,74 @@
1
+ import { fiberScanRoot } from '../../anchors/fiber/FiberScanRootStore';
2
+ import type { AnyFiber } from '../../anchors/fiber/fiberInternals';
3
+ import {
4
+ locatePresentedModal,
5
+ measureOriginOf,
6
+ type Point,
7
+ } from '../../anchors/fiber/presentedModal';
8
+ import { getFiberAnchorScreenKey } from '../../anchors/fiberAnchorCache';
9
+ import { hasWindowOverlayHost } from '../../runtime/WindowOverlayHost';
10
+
11
+ import type { Rect } from './inferTooltipPlacement';
12
+
13
+ const ZERO: Point = { x: 0, y: 0 };
14
+
15
+ /**
16
+ * How long "nothing is presented" is trusted on the same screen. The lookup
17
+ * walks the whole fiber tree (1.4ms for 2,200 fibers in a debug build), and
18
+ * an anchored tooltip resolves four times a second. Expo Router and native
19
+ * stack modals change the screen, which skips this wait; a React Native
20
+ * `<Modal>` over the target is noticed within it.
21
+ */
22
+ export const NO_MODAL_TRUST_MS = 1000;
23
+
24
+ let noModalSince: { at: number; screenKey: string | null } | null = null;
25
+
26
+ /**
27
+ * Where a tooltip target's measured rects sit in the window. `done` gets the
28
+ * window position of `(0, 0)` in the target's measure space, or null when the
29
+ * tooltip cannot point at it: a natively presented modal covers the target,
30
+ * or the target is inside a modal that cannot be placed (see
31
+ * `presentedModal.ts`). Also null when the target has no fiber to place.
32
+ *
33
+ * Without the window host, flow chrome is drawn in the root view under any
34
+ * native modal, as before, and `done` runs synchronously with zero.
35
+ */
36
+ export function locateTargetOrigin(
37
+ fiber: AnyFiber | null,
38
+ done: (origin: Point | null) => void,
39
+ ): void {
40
+ if (!hasWindowOverlayHost()) {
41
+ done(ZERO);
42
+ return;
43
+ }
44
+ const screenKey = getFiberAnchorScreenKey();
45
+ const now = Date.now();
46
+ if (
47
+ noModalSince &&
48
+ noModalSince.screenKey === screenKey &&
49
+ now - noModalSince.at < NO_MODAL_TRUST_MS
50
+ ) {
51
+ done(ZERO);
52
+ return;
53
+ }
54
+ locatePresentedModal(fiberScanRoot.getFiber()).then(
55
+ (modal) => {
56
+ noModalSince = modal == null ? { at: now, screenKey } : null;
57
+ done(modal == null ? ZERO : fiber ? measureOriginOf(fiber, modal) : null);
58
+ },
59
+ () => {
60
+ noModalSince = null;
61
+ done(null);
62
+ },
63
+ );
64
+ }
65
+
66
+ export function offsetRect(rect: Rect, origin: Point): Rect {
67
+ if (origin.x === 0 && origin.y === 0) return rect;
68
+ return { ...rect, x: rect.x + origin.x, y: rect.y + origin.y };
69
+ }
70
+
71
+ /** @internal Forgets the cached "nothing is presented" between tests. */
72
+ export function resetTargetOriginForTests(): void {
73
+ noModalSince = null;
74
+ }
package/src/version.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  /** Generated by scripts/write-version.mjs — do not edit. */
2
- export const SDK_VERSION = '0.6.0';
2
+ export const SDK_VERSION = '0.7.0';
@@ -5,6 +5,13 @@ import type { PublicAttributes, UserflowConfig, UserflowGroupOptions, UserflowId
5
5
  export interface UserflowCoreDeps {
6
6
  validate?: ValidateCredentialsFn;
7
7
  createConnection?: CreateConnectionFn;
8
+ /**
9
+ * Reported as `userflowClientBuild` by the default Phoenix transport, on both
10
+ * the init credential probe and the end-user channel. Each default applies it
11
+ * on its own, so an injected `validate` or `createConnection` only drops it
12
+ * for that one.
13
+ */
14
+ clientBuild?: string;
8
15
  }
9
16
  export interface UpsertGroupPayload {
10
17
  groupExternalId: string;
@@ -1 +1 @@
1
- {"version":3,"file":"UserflowCore.d.ts","sourceRoot":"","sources":["../../src/engine/UserflowCore.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"UserflowCore.d.ts","sourceRoot":"","sources":["../../src/engine/UserflowCore.ts"],"names":[],"mappings":"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"}
@@ -30,12 +30,13 @@ export class UserflowCore {
30
30
  this.attributes = {};
31
31
  this.clientContext = { ...DEFAULT_CLIENT_CONTEXT };
32
32
  this.initPromise = null;
33
+ const transportOptions = deps.clientBuild !== undefined ? { clientBuild: deps.clientBuild } : {};
33
34
  this.validate =
34
35
  deps.validate ??
35
- ((clientToken, serverEndpoint) => validateCredentials(clientToken, serverEndpoint));
36
+ ((clientToken, serverEndpoint) => validateCredentials(clientToken, serverEndpoint, undefined, transportOptions));
36
37
  this.createConnection =
37
38
  deps.createConnection ??
38
- ((clientToken, serverEndpoint) => new PhoenixConnection(clientToken, serverEndpoint));
39
+ ((clientToken, serverEndpoint) => new PhoenixConnection(clientToken, serverEndpoint, undefined, transportOptions));
39
40
  }
40
41
  init(options) {
41
42
  if (this.initPromise)