@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
@@ -1 +1 @@
1
- {"version":3,"file":"PairingController.d.ts","sourceRoot":"","sources":["../../../../../src/pairing/PairingController.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"PairingController.d.ts","sourceRoot":"","sources":["../../../../../src/pairing/PairingController.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"UserflowOverlay.d.ts","sourceRoot":"","sources":["../../../../../src/runtime/UserflowOverlay.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAClF,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAgB/B,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,iBAAiB,CAAC;IAC1B,YAAY,EAAE,mBAAmB,CAAC;IAClC,6EAA6E;IAC7E,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;CACvC;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,EAC9B,MAAM,EACN,YAAY,EACZ,YAAY,GACb,EAAE,oBAAoB,GAAG,KAAK,CAAC,YAAY,CAkF3C"}
1
+ {"version":3,"file":"UserflowOverlay.d.ts","sourceRoot":"","sources":["../../../../../src/runtime/UserflowOverlay.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAClF,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAiB/B,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,iBAAiB,CAAC;IAC1B,YAAY,EAAE,mBAAmB,CAAC;IAClC,6EAA6E;IAC7E,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;CACvC;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,EAC9B,MAAM,EACN,YAAY,EACZ,YAAY,GACb,EAAE,oBAAoB,GAAG,KAAK,CAAC,YAAY,CAyF3C"}
@@ -0,0 +1,34 @@
1
+ import * as React from 'react';
2
+ export interface WindowOverlayHostProps {
3
+ children: React.ReactNode;
4
+ /**
5
+ * Hide everything outside the host from VoiceOver, natively presented
6
+ * modals included. Defaults to false.
7
+ */
8
+ accessibilityModal?: boolean;
9
+ }
10
+ /** True when {@link WindowOverlayHost} draws above natively presented modals. */
11
+ export declare function hasWindowOverlayHost(): boolean;
12
+ /**
13
+ * Hosts SDK chrome above everything else in the app window.
14
+ *
15
+ * On iOS, react-native-screens presents `modal`, `transparentModal`,
16
+ * `formSheet` and `fullScreenModal` screens, and React Native presents
17
+ * `<Modal>`, as view controllers above the React Native root view, so chrome
18
+ * rendered in `UserflowProvider`'s overlay is drawn beneath them and never
19
+ * receives touches there. `FullWindowOverlay` moves its children into a
20
+ * container on the window itself. Measured on iOS 17.4 and 26.5 with
21
+ * react-native-screens 4.16, that container stays above sheets whether they are
22
+ * presented before or after it mounts.
23
+ *
24
+ * Each host is its own container, stacked by when it was attached rather than
25
+ * by React order, so chrome that has to keep a paint order shares one host.
26
+ *
27
+ * Touches inside the host arrive in window coordinates, as they do in the root
28
+ * view. Children render in place when the overlay is unavailable: on Android,
29
+ * and in apps without react-native-screens.
30
+ */
31
+ export declare function WindowOverlayHost({ children, accessibilityModal, }: WindowOverlayHostProps): React.ReactElement;
32
+ /** @internal Clears the cached `FullWindowOverlay` lookup between tests. */
33
+ export declare function resetWindowOverlayHostForTests(): void;
34
+ //# sourceMappingURL=WindowOverlayHost.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WindowOverlayHost.d.ts","sourceRoot":"","sources":["../../../../../src/runtime/WindowOverlayHost.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AA6C/B,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B;;;OAGG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,iFAAiF;AACjF,wBAAgB,oBAAoB,IAAI,OAAO,CAE9C;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,QAAQ,EACR,kBAA0B,GAC3B,EAAE,sBAAsB,GAAG,KAAK,CAAC,YAAY,CAQ7C;AAED,4EAA4E;AAC5E,wBAAgB,8BAA8B,IAAI,IAAI,CAErD"}
@@ -1 +1 @@
1
- {"version":3,"file":"userflowCore.d.ts","sourceRoot":"","sources":["../../../../../src/runtime/userflowCore.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAKnD,wBAAgB,eAAe,IAAI,YAAY,CAE9C"}
1
+ {"version":3,"file":"userflowCore.d.ts","sourceRoot":"","sources":["../../../../../src/runtime/userflowCore.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAWnD,wBAAgB,eAAe,IAAI,YAAY,CAE9C"}
@@ -1 +1 @@
1
- {"version":3,"file":"TooltipSurface.d.ts","sourceRoot":"","sources":["../../../../../src/surfaces/TooltipSurface.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAGL,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACrB,KAAK,aAAa,EACnB,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAgC/B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AA8CxD,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,iBAAiB,CAAC;IAC1B,OAAO,EAAE,mBAAmB,CAAC;IAC7B,WAAW,EAAE,gBAAgB,CAAC;IAC9B,KAAK,EAAE,aAAa,CAAC;IACrB,eAAe,EAAE,eAAe,CAAC;IACjC;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAID;;;GAGG;AACH,eAAO,MAAM,sBAAsB,KAAK,CAAC;AAuCzC;;;GAGG;AACH,wBAAgB,cAAc,CAAC,EAC7B,MAAM,EACN,OAAO,EACP,WAAW,EACX,KAAK,EACL,eAAe,EACf,UAAc,GACf,EAAE,mBAAmB,GAAG,KAAK,CAAC,YAAY,GAAG,IAAI,CAk5BjD"}
1
+ {"version":3,"file":"TooltipSurface.d.ts","sourceRoot":"","sources":["../../../../../src/surfaces/TooltipSurface.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAGL,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACrB,KAAK,aAAa,EACnB,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAiC/B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AA+CxD,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,iBAAiB,CAAC;IAC1B,OAAO,EAAE,mBAAmB,CAAC;IAC7B,WAAW,EAAE,gBAAgB,CAAC;IAC9B,KAAK,EAAE,aAAa,CAAC;IACrB,eAAe,EAAE,eAAe,CAAC;IACjC;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAID;;;GAGG;AACH,eAAO,MAAM,sBAAsB,KAAK,CAAC;AAuCzC;;;GAGG;AACH,wBAAgB,cAAc,CAAC,EAC7B,MAAM,EACN,OAAO,EACP,WAAW,EACX,KAAK,EACL,eAAe,EACf,UAAc,GACf,EAAE,mBAAmB,GAAG,KAAK,CAAC,YAAY,GAAG,IAAI,CA08BjD"}
@@ -0,0 +1,26 @@
1
+ import type { AnyFiber } from '../../anchors/fiber/fiberInternals';
2
+ import { type Point } from '../../anchors/fiber/presentedModal';
3
+ import type { Rect } from './inferTooltipPlacement';
4
+ /**
5
+ * How long "nothing is presented" is trusted on the same screen. The lookup
6
+ * walks the whole fiber tree (1.4ms for 2,200 fibers in a debug build), and
7
+ * an anchored tooltip resolves four times a second. Expo Router and native
8
+ * stack modals change the screen, which skips this wait; a React Native
9
+ * `<Modal>` over the target is noticed within it.
10
+ */
11
+ export declare const NO_MODAL_TRUST_MS = 1000;
12
+ /**
13
+ * Where a tooltip target's measured rects sit in the window. `done` gets the
14
+ * window position of `(0, 0)` in the target's measure space, or null when the
15
+ * tooltip cannot point at it: a natively presented modal covers the target,
16
+ * or the target is inside a modal that cannot be placed (see
17
+ * `presentedModal.ts`). Also null when the target has no fiber to place.
18
+ *
19
+ * Without the window host, flow chrome is drawn in the root view under any
20
+ * native modal, as before, and `done` runs synchronously with zero.
21
+ */
22
+ export declare function locateTargetOrigin(fiber: AnyFiber | null, done: (origin: Point | null) => void): void;
23
+ export declare function offsetRect(rect: Rect, origin: Point): Rect;
24
+ /** @internal Forgets the cached "nothing is presented" between tests. */
25
+ export declare function resetTargetOriginForTests(): void;
26
+ //# sourceMappingURL=targetOrigin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"targetOrigin.d.ts","sourceRoot":"","sources":["../../../../../../src/surfaces/tooltip/targetOrigin.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oCAAoC,CAAC;AACnE,OAAO,EAGL,KAAK,KAAK,EACX,MAAM,oCAAoC,CAAC;AAI5C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,yBAAyB,CAAC;AAIpD;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,OAAO,CAAC;AAItC;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,QAAQ,GAAG,IAAI,EACtB,IAAI,EAAE,CAAC,MAAM,EAAE,KAAK,GAAG,IAAI,KAAK,IAAI,GACnC,IAAI,CAyBN;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,GAAG,IAAI,CAG1D;AAED,yEAAyE;AACzE,wBAAgB,yBAAyB,IAAI,IAAI,CAEhD"}
@@ -1,3 +1,3 @@
1
1
  /** Generated by scripts/write-version.mjs — do not edit. */
2
- export declare const SDK_VERSION = "0.6.0";
2
+ export declare const SDK_VERSION = "0.7.0";
3
3
  //# sourceMappingURL=version.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@userflow-tech/react-native",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "Userflow SDK for React Native — onboarding flows, tooltips, and modals.",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "main": "./lib/commonjs/index.js",
@@ -79,7 +79,7 @@
79
79
  "build": "node ../../scripts/write-version.mjs SDK_VERSION && bob build",
80
80
  "test": "jest",
81
81
  "lint": "eslint src",
82
- "typecheck": "tsc --noEmit",
82
+ "typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.typetests.json",
83
83
  "pretest": "node ../../scripts/write-version.mjs SDK_VERSION",
84
84
  "prepack": "node ../../scripts/prepare-sdk-pack.mjs",
85
85
  "postpack": "node ../../scripts/restore-sdk-pack.mjs",
@@ -94,8 +94,8 @@
94
94
  "react-native": ">=0.76.0",
95
95
  "react-native-device-info": ">=11.0.0 <16.0.0",
96
96
  "react-native-safe-area-context": ">=4.0.0 <6.0.0",
97
- "react-native-view-shot": "^5.0.0",
98
- "react-native-webview": ">=13.8.0 <14.0.0"
97
+ "react-native-view-shot": "^5.0.0 || ^6.0.0",
98
+ "react-native-webview": ">=13.8.0 <15.0.0"
99
99
  },
100
100
  "peerDependenciesMeta": {
101
101
  "@react-native-community/netinfo": {
@@ -133,6 +133,7 @@
133
133
  "@userflow-tech/eslint-config": "workspace:*",
134
134
  "@userflow-tech/tsconfig": "workspace:*",
135
135
  "babel-jest": "^29.7.0",
136
+ "expo-constants": "~57.0.19",
136
137
  "expo-router": "^5.1.0",
137
138
  "jest": "^29.7.0",
138
139
  "react": "19.1.0",
@@ -15,6 +15,14 @@ export interface AnchorHost {
15
15
  node?: object | null;
16
16
  }
17
17
 
18
+ /**
19
+ * The view instance an anchor ref receives. Structural rather than `View`,
20
+ * which React Native 0.88 types as a function component, not an instance.
21
+ */
22
+ export interface MeasurableNode {
23
+ measureInWindow: AnchorHost['measureInWindow'];
24
+ }
25
+
18
26
  type Listener = () => void;
19
27
 
20
28
  /**
@@ -1,7 +1,9 @@
1
- import type { NativeScrollEvent, NativeSyntheticEvent, ScrollView, View } from 'react-native';
1
+ import type { NativeScrollEvent, NativeSyntheticEvent } from 'react-native';
2
2
 
3
3
  import type { Rect } from '../surfaces/tooltip/inferTooltipPlacement';
4
4
 
5
+ import type { MeasurableNode } from './AnchorRegistry';
6
+
5
7
  /** Padding applied when scrolling a target into the visible region of a container. */
6
8
  const INTO_VIEW_PADDING = 24;
7
9
 
@@ -13,6 +15,16 @@ export interface ScrollContainerHost {
13
15
  scrollTo: (options: { x?: number; y?: number; animated?: boolean }) => void;
14
16
  }
15
17
 
18
+ /**
19
+ * The ScrollView instance a scroll container ref receives. Structural rather
20
+ * than `ScrollView`, which React Native 0.88 types as a function component.
21
+ * Older React Native types leave measureInWindow off the ScrollView instance,
22
+ * so it is not required here.
23
+ */
24
+ export interface ScrollContainerNode {
25
+ scrollTo: ScrollContainerHost['scrollTo'];
26
+ }
27
+
16
28
  type Listener = () => void;
17
29
 
18
30
  /**
@@ -90,10 +102,10 @@ export const scrollContainerRegistry = new ScrollContainerRegistry();
90
102
 
91
103
  /** Build a host from a live ScrollView + tracked content offset. */
92
104
  export function createScrollContainerHost(
93
- node: ScrollView,
105
+ node: ScrollContainerNode,
94
106
  getContentOffset: () => { x: number; y: number },
95
107
  ): ScrollContainerHost {
96
- const measurable = node as ScrollView & View;
108
+ const measurable = node as ScrollContainerNode & MeasurableNode;
97
109
  return {
98
110
  measureInWindow: (callback) => {
99
111
  measurable.measureInWindow(callback);
@@ -0,0 +1,203 @@
1
+ /**
2
+ * Where a natively presented modal sits in the window.
3
+ *
4
+ * Fabric measures and hit-tests content inside a react-native-screens modal
5
+ * screen (`RNSModalScreen`) or a React Native `<Modal>` relative to the modal,
6
+ * not the window: both shadow nodes are `RootNodeKind`, and the native side
7
+ * reports only their size. That is the window for full-screen presentations,
8
+ * but a page sheet or form sheet starts below the top of the window, so window
9
+ * points and measured rects disagree by the sheet's origin.
10
+ *
11
+ * The SDK has no native code to ask UIKit where the sheet is, so the origin is
12
+ * derived from sizes: a sheet as wide as the window is anchored to its bottom.
13
+ * Measured on iOS 17.4 and 26.5 and an iPadOS 26.5 portrait iPad: page sheets
14
+ * at 852 − 783 = 69, 874 − 812 = 62 and 1210 − 1104 = 106, a `fitToContents`
15
+ * form sheet at 852 − 424 = 428.
16
+ *
17
+ * A narrower sheet (an iPad form sheet) cannot be placed from sizes. One
18
+ * measured 580×376 on a 834×1210 window sat at y = 549, neither centered (417)
19
+ * nor bottom-anchored (834): its detent is anchored inside a taller container
20
+ * the shadow tree never sees. It gets no origin, so picks on it fail closed.
21
+ *
22
+ * Only a sheet at its full-height detent is reliably on the bottom edge. A
23
+ * shorter one is not, in two cases, and also gets no origin:
24
+ * - From iOS 26 it floats. On iOS 26.5 the `fitToContents` trade ticket
25
+ * measured 402×424 on a 402×874 window, but UIKit drew it about 8pt in from
26
+ * the sides and bottom at about 0.96 scale, so a bottom-anchored origin was
27
+ * up to 8pt off. Page sheets there stay edge to edge (origin 62, exact).
28
+ * - While the keyboard is up, a sheet that fits above the keyboard may have
29
+ * been lifted to clear it. One that is taller than the space above the
30
+ * keyboard was not: on iOS 26.5 a page sheet stayed at 62 with a 335pt
31
+ * keyboard, and on iOS 17.4 the trade ticket grew from 424 to 715 under a
32
+ * 291pt keyboard and stayed on the bottom edge (852 − 715 = 137, exact).
33
+ *
34
+ * Paper measures with UIKit, in window coordinates, so its origin is zero.
35
+ * Outside iOS the modal is measured where it sits, as before this lookup.
36
+ */
37
+ import { Dimensions, Keyboard, Platform } from 'react-native';
38
+
39
+ import type { AnyFiber } from './fiberInternals';
40
+ import { measureHostFiber } from './measureHostFiber';
41
+ import { fiberIsUnder, topmostVisibleModalHost } from './visibleRect';
42
+
43
+ export interface Point {
44
+ x: number;
45
+ y: number;
46
+ }
47
+
48
+ export interface Size {
49
+ width: number;
50
+ height: number;
51
+ }
52
+
53
+ export interface PresentedModal {
54
+ /** `RNSModalScreen`, or React Native's `ModalHostView`. */
55
+ host: AnyFiber;
56
+ /**
57
+ * Window position of `(0, 0)` in the space the modal's content is measured
58
+ * and hit-tested in. Null when the modal cannot be placed.
59
+ */
60
+ origin: Point | null;
61
+ /** The modal's size, when it was measured (iOS Fabric only). */
62
+ size: Size | null;
63
+ /** True on iOS Fabric, where that space is the modal's own rather than the window's. */
64
+ modalSpace: boolean;
65
+ }
66
+
67
+ const ZERO: Point = { x: 0, y: 0 };
68
+
69
+ const MEASURE_TIMEOUT_MS = 400;
70
+
71
+ /** Layout sizes are fractional and may miss the window size by a hair. */
72
+ const SIZE_SLACK = 1;
73
+
74
+ /**
75
+ * A sheet whose top is within this fraction of the window height is at its
76
+ * full-height detent. Measured: 69/852 (iOS 17.4), 62/874 (iOS 26.5) and
77
+ * 106/1210 (iPadOS 26.5). Medium and `fitToContents` detents start far lower.
78
+ */
79
+ const FULL_HEIGHT_SHEET_MAX_TOP = 0.15;
80
+
81
+ /** First iOS release that floats sheets shorter than full height. */
82
+ const FLOATING_SHEETS_IOS = 26;
83
+
84
+ function isFabric(): boolean {
85
+ const manager = (globalThis as { nativeFabricUIManager?: unknown }).nativeFabricUIManager;
86
+ return manager != null && typeof manager === 'object';
87
+ }
88
+
89
+ function readWindowSize(): Size | null {
90
+ try {
91
+ const { width, height } = Dimensions.get('window');
92
+ if (width > 0 && height > 0) return { width, height };
93
+ } catch {
94
+ // Tests and odd hosts.
95
+ }
96
+ return null;
97
+ }
98
+
99
+ function floatsShortSheets(): boolean {
100
+ const major = parseInt(String(Platform.Version), 10);
101
+ return Number.isFinite(major) && major >= FLOATING_SHEETS_IOS;
102
+ }
103
+
104
+ /** Window y of the keyboard's top edge, or null when it is down. Unknown counts as up at the bottom. */
105
+ function keyboardTop(windowSize: Size): number | null {
106
+ try {
107
+ if (typeof Keyboard?.isVisible !== 'function' || !Keyboard.isVisible()) return null;
108
+ const metrics = typeof Keyboard.metrics === 'function' ? Keyboard.metrics() : undefined;
109
+ return metrics && metrics.height > 0 ? metrics.screenY : windowSize.height;
110
+ } catch {
111
+ return null;
112
+ }
113
+ }
114
+
115
+ function measureSize(fiber: AnyFiber): Promise<Size | null> {
116
+ return new Promise((resolve) => {
117
+ let settled = false;
118
+ const timer = setTimeout(() => {
119
+ if (settled) return;
120
+ settled = true;
121
+ resolve(null);
122
+ }, MEASURE_TIMEOUT_MS);
123
+ try {
124
+ measureHostFiber(fiber, (_x, _y, width, height) => {
125
+ if (settled) return;
126
+ settled = true;
127
+ clearTimeout(timer);
128
+ resolve(width > 0 && height > 0 ? { width, height } : null);
129
+ });
130
+ } catch {
131
+ if (settled) return;
132
+ settled = true;
133
+ clearTimeout(timer);
134
+ resolve(null);
135
+ }
136
+ });
137
+ }
138
+
139
+ /**
140
+ * Window origin of a presented modal of `size`, bottom-anchored. Null when it
141
+ * is narrower than the window (see above) or does not fit in it, as
142
+ * mid-rotation.
143
+ */
144
+ export function modalOriginInWindow(size: Size, windowSize: Size): Point | null {
145
+ if (size.width <= 0 || size.height <= 0) return null;
146
+ if (size.width > windowSize.width + SIZE_SLACK || size.height > windowSize.height + SIZE_SLACK) {
147
+ return null;
148
+ }
149
+ if (size.width < windowSize.width - SIZE_SLACK) return null;
150
+ return { x: 0, y: Math.max(0, windowSize.height - size.height) };
151
+ }
152
+
153
+ /** {@link modalOriginInWindow}, or null when a short sheet may be off the bottom edge (see above). */
154
+ function placeModal(size: Size, windowSize: Size): Point | null {
155
+ const origin = modalOriginInWindow(size, windowSize);
156
+ if (!origin || origin.y <= windowSize.height * FULL_HEIGHT_SHEET_MAX_TOP) return origin;
157
+ if (floatsShortSheets()) return null;
158
+ const keyboard = keyboardTop(windowSize);
159
+ if (keyboard != null && size.height <= keyboard) return null;
160
+ return origin;
161
+ }
162
+
163
+ /**
164
+ * The modal drawn on top of the app and where its content space sits in the
165
+ * window, or null when nothing is presented. Look it up per tap: a
166
+ * `fitToContents` sheet resizes as its content changes.
167
+ */
168
+ export async function locatePresentedModal(root: AnyFiber | null): Promise<PresentedModal | null> {
169
+ const host = topmostVisibleModalHost(root);
170
+ if (!host) return null;
171
+ if (Platform.OS !== 'ios' || !isFabric()) {
172
+ return { host, origin: ZERO, size: null, modalSpace: false };
173
+ }
174
+ const size = await measureSize(host);
175
+ const windowSize = readWindowSize();
176
+ const origin = size && windowSize ? placeModal(size, windowSize) : null;
177
+ return { host, origin, size, modalSpace: true };
178
+ }
179
+
180
+ /** True when window point `(x, y)` is outside a placed modal, on the screen it covers. */
181
+ export function isOutsideModal(x: number, y: number, modal: PresentedModal): boolean {
182
+ const { origin, size } = modal;
183
+ if (!origin || !size) return false;
184
+ return x < origin.x || y < origin.y || x > origin.x + size.width || y > origin.y + size.height;
185
+ }
186
+
187
+ /**
188
+ * Window position of `(0, 0)` in the space `fiber` is measured in, given what
189
+ * {@link locatePresentedModal} returned. Null when `modal` covers `fiber`, or
190
+ * `fiber` is inside a modal that cannot be placed.
191
+ */
192
+ export function measureOriginOf(fiber: AnyFiber, modal: PresentedModal | null): Point | null {
193
+ if (!modal) return ZERO;
194
+ if (!fiberIsUnder(fiber, modal.host)) return null;
195
+ return modal.origin;
196
+ }
197
+
198
+ /** `rect`, measured in `modal`'s content space, in window coordinates. */
199
+ export function rectInWindow<T extends Point>(rect: T, modal: PresentedModal): T {
200
+ const origin = modal.origin ?? ZERO;
201
+ if (origin.x === 0 && origin.y === 0) return rect;
202
+ return { ...rect, x: rect.x + origin.x, y: rect.y + origin.y };
203
+ }
@@ -73,9 +73,10 @@ function nativeTagForTouch(
73
73
  event: GestureResponderEvent,
74
74
  identifier: number | string | undefined,
75
75
  ): number | undefined {
76
+ // Readonly: React Native 0.88 types changedTouches as a readonly array.
76
77
  const native = event.nativeEvent as {
77
78
  target?: unknown;
78
- changedTouches?: Array<{ identifier?: number | string; target?: unknown }>;
79
+ changedTouches?: ReadonlyArray<{ identifier?: number | string; target?: unknown }>;
79
80
  };
80
81
  if (identifier != null && native.changedTouches) {
81
82
  const touch = native.changedTouches.find((entry) => entry.identifier === identifier);
@@ -17,6 +17,7 @@ import {
17
17
  } from './fiberInternals';
18
18
  import { findScrollAncestors } from './findScrollAncestors';
19
19
  import { measureHostFiber } from './measureHostFiber';
20
+ import { isFiberOnVisibleScreen } from './visibleScreens';
20
21
 
21
22
  export interface VisibleRect {
22
23
  x: number;
@@ -30,6 +31,9 @@ const MEASURE_TIMEOUT_MS = 400;
30
31
  /** Paper and Fabric names for React Native's `<Modal>`. */
31
32
  const MODAL_HOST_TYPES = new Set(['RCTModalHostView', 'ModalHostView']);
32
33
 
34
+ /** react-native-screens' iOS host for `modal`, `transparentModal`, `formSheet` and other presented screens. */
35
+ const SCREENS_MODAL_TYPE = 'RNSModalScreen';
36
+
33
37
  type MeasureCallback = (x: number, y: number, width: number, height: number) => void;
34
38
 
35
39
  function measureFiberRect(fiber: AnyFiber): Promise<VisibleRect | null> {
@@ -99,10 +103,12 @@ export async function clipToScrollViewports(
99
103
 
100
104
  function isModalHost(fiber: AnyFiber): boolean {
101
105
  const type = getHostTypeName(fiber);
102
- return type !== undefined && MODAL_HOST_TYPES.has(type);
106
+ return type !== undefined && (MODAL_HOST_TYPES.has(type) || type === SCREENS_MODAL_TYPE);
103
107
  }
104
108
 
105
109
  function isModalVisible(fiber: AnyFiber): boolean {
110
+ // A presented screen stays mounted under the next one; only the top of its stack is visible.
111
+ if (getHostTypeName(fiber) === SCREENS_MODAL_TYPE) return isFiberOnVisibleScreen(fiber);
106
112
  const props = getMemoizedProps(fiber);
107
113
  if (!props) return true;
108
114
  if (props.visible === false) return false;
@@ -110,8 +116,11 @@ function isModalVisible(fiber: AnyFiber): boolean {
110
116
  }
111
117
 
112
118
  /**
113
- * The visible modal host drawn on top, or null. Later siblings win: React
114
- * Native mounts a newer `<Modal>` after the previous one.
119
+ * The visible modal host drawn on top, or null: a React Native `<Modal>` or a
120
+ * screen react-native-screens presents natively. Later fibers win: React Native
121
+ * mounts a newer `<Modal>` after the previous one, a native stack's newest
122
+ * screen is its last child, and a modal presented from inside another one sits
123
+ * deeper in the tree.
115
124
  */
116
125
  export function topmostVisibleModalHost(root: AnyFiber | null, maxNodes = 8_000): AnyFiber | null {
117
126
  if (!root) return null;
@@ -1,7 +1,6 @@
1
1
  import * as React from 'react';
2
- import type { View } from 'react-native';
3
2
 
4
- import { anchorRegistry, type AnchorHost } from './AnchorRegistry';
3
+ import { anchorRegistry, type AnchorHost, type MeasurableNode } from './AnchorRegistry';
5
4
 
6
5
  /**
7
6
  * Register a view as a manual Userflow tooltip / embed target.
@@ -29,7 +28,7 @@ import { anchorRegistry, type AnchorHost } from './AnchorRegistry';
29
28
  *
30
29
  * Phase 3 resolves targets via `step.selector.css` (leading `#` stripped).
31
30
  */
32
- export function useUserflowAnchor(id: string): React.RefCallback<View> {
31
+ export function useUserflowAnchor(id: string): React.RefCallback<MeasurableNode> {
33
32
  const hostRef = React.useRef<AnchorHost | null>(null);
34
33
  const idRef = React.useRef(id);
35
34
 
@@ -55,7 +54,7 @@ export function useUserflowAnchor(id: string): React.RefCallback<View> {
55
54
  };
56
55
  }, []);
57
56
 
58
- return React.useCallback((node: View | null) => {
57
+ return React.useCallback((node: MeasurableNode | null) => {
59
58
  const previous = hostRef.current;
60
59
  const currentId = idRef.current;
61
60
  if (previous) {
@@ -73,7 +72,7 @@ export function useUserflowAnchor(id: string): React.RefCallback<View> {
73
72
  },
74
73
  node,
75
74
  scrollIntoView: () => {
76
- const scrollable = node as View & {
75
+ const scrollable = node as MeasurableNode & {
77
76
  scrollIntoView?: (options?: { block?: string; inline?: string }) => void;
78
77
  };
79
78
  if (typeof scrollable.scrollIntoView === 'function') {
@@ -1,15 +1,16 @@
1
1
  import * as React from 'react';
2
- import type { NativeScrollEvent, NativeSyntheticEvent, ScrollView } from 'react-native';
2
+ import type { NativeScrollEvent, NativeSyntheticEvent } from 'react-native';
3
3
 
4
4
  import {
5
5
  createScrollContainerHost,
6
6
  scrollContainerRegistry,
7
7
  type ScrollContainerHost,
8
+ type ScrollContainerNode,
8
9
  } from './ScrollContainerRegistry';
9
10
 
10
11
  export interface UserflowScrollContainerProps {
11
12
  /** Attach to the host ScrollView (or merge with an existing ref). */
12
- ref: React.RefCallback<ScrollView>;
13
+ ref: React.RefCallback<ScrollContainerNode>;
13
14
  /** Forward to ScrollView so content offsets stay in sync for scroll-into-view. */
14
15
  onScroll: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;
15
16
  /** Required for frequent offset updates while scrolling. */
@@ -42,7 +43,7 @@ export function useUserflowScrollContainer(
42
43
  onScrollProp?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void,
43
44
  ): UserflowScrollContainerProps {
44
45
  const hostRef = React.useRef<ScrollContainerHost | null>(null);
45
- const nodeRef = React.useRef<ScrollView | null>(null);
46
+ const nodeRef = React.useRef<ScrollContainerNode | null>(null);
46
47
  const offsetRef = React.useRef({ x: 0, y: 0 });
47
48
 
48
49
  React.useEffect(() => {
@@ -55,7 +56,7 @@ export function useUserflowScrollContainer(
55
56
  };
56
57
  }, []);
57
58
 
58
- const ref = React.useCallback((node: ScrollView | null) => {
59
+ const ref = React.useCallback((node: ScrollContainerNode | null) => {
59
60
  const previous = hostRef.current;
60
61
  if (previous) {
61
62
  scrollContainerRegistry.unregister(previous);