react-native-gtkx 0.2.0-alpha.2 → 0.3.0-alpha.1

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 (340) hide show
  1. package/README.md +5 -2
  2. package/dist/aliases/index.d.ts +84 -0
  3. package/dist/aliases/index.js +208 -0
  4. package/dist/aliases/index.js.map +1 -0
  5. package/dist/animated/index.d.ts +2 -0
  6. package/dist/animated/index.js +5 -0
  7. package/dist/animated/index.js.map +1 -1
  8. package/dist/animated/types.d.ts +1 -0
  9. package/dist/animated/types.js.map +1 -1
  10. package/dist/animated/value-animation.js +17 -4
  11. package/dist/animated/value-animation.js.map +1 -1
  12. package/dist/apis/host.gtkx.js +9 -12
  13. package/dist/apis/host.gtkx.js.map +1 -1
  14. package/dist/apis/index.d.ts +4 -2
  15. package/dist/apis/index.js +2 -0
  16. package/dist/apis/index.js.map +1 -1
  17. package/dist/apis/keyboard.d.ts +60 -0
  18. package/dist/apis/keyboard.js +63 -0
  19. package/dist/apis/keyboard.js.map +1 -0
  20. package/dist/apis/log-box.d.ts +15 -0
  21. package/dist/apis/log-box.js +46 -0
  22. package/dist/apis/log-box.js.map +1 -0
  23. package/dist/apis/platform.d.ts +18 -1
  24. package/dist/apis/platform.js.map +1 -1
  25. package/dist/common/index.d.ts +0 -1
  26. package/dist/common/index.js +24 -1
  27. package/dist/common/index.js.map +1 -1
  28. package/dist/components/animated.d.ts +70 -6
  29. package/dist/components/animated.js +559 -46
  30. package/dist/components/animated.js.map +1 -1
  31. package/dist/components/driven-size.d.ts +27 -0
  32. package/dist/components/driven-size.js +85 -0
  33. package/dist/components/driven-size.js.map +1 -0
  34. package/dist/components/find-node-handle.d.ts +11 -0
  35. package/dist/components/find-node-handle.js +53 -0
  36. package/dist/components/find-node-handle.js.map +1 -0
  37. package/dist/components/flat-list.d.ts +3 -2
  38. package/dist/components/flat-list.js.map +1 -1
  39. package/dist/components/frame-scheduler.d.ts +16 -0
  40. package/dist/components/frame-scheduler.js +37 -0
  41. package/dist/components/frame-scheduler.js.map +1 -0
  42. package/dist/components/image.d.ts +6 -1
  43. package/dist/components/image.js +15 -4
  44. package/dist/components/image.js.map +1 -1
  45. package/dist/components/index.d.ts +7 -5
  46. package/dist/components/index.js +5 -3
  47. package/dist/components/index.js.map +1 -1
  48. package/dist/components/measure.d.ts +51 -1
  49. package/dist/components/measure.js +101 -2
  50. package/dist/components/measure.js.map +1 -1
  51. package/dist/components/pressable.d.ts +61 -1
  52. package/dist/components/pressable.js +151 -4
  53. package/dist/components/pressable.js.map +1 -1
  54. package/dist/components/rect-store.d.ts +58 -0
  55. package/dist/components/rect-store.js +124 -3
  56. package/dist/components/rect-store.js.map +1 -1
  57. package/dist/components/root.js +6 -1
  58. package/dist/components/root.js.map +1 -1
  59. package/dist/components/scroll-phase.d.ts +35 -0
  60. package/dist/components/scroll-phase.js +26 -0
  61. package/dist/components/scroll-phase.js.map +1 -0
  62. package/dist/components/scroll-view.d.ts +39 -3
  63. package/dist/components/scroll-view.js +378 -43
  64. package/dist/components/scroll-view.js.map +1 -1
  65. package/dist/components/text-input.js +9 -25
  66. package/dist/components/text-input.js.map +1 -1
  67. package/dist/components/text.d.ts +6 -2
  68. package/dist/components/text.js +43 -8
  69. package/dist/components/text.js.map +1 -1
  70. package/dist/components/use-focus.d.ts +27 -0
  71. package/dist/components/use-focus.js +116 -0
  72. package/dist/components/use-focus.js.map +1 -0
  73. package/dist/components/use-layout-child.d.ts +13 -1
  74. package/dist/components/use-layout-child.js +188 -5
  75. package/dist/components/use-layout-child.js.map +1 -1
  76. package/dist/components/view.d.ts +5 -2
  77. package/dist/components/view.js +18 -13
  78. package/dist/components/view.js.map +1 -1
  79. package/dist/components/virtualized-list.d.ts +45 -5
  80. package/dist/components/virtualized-list.js +90 -24
  81. package/dist/components/virtualized-list.js.map +1 -1
  82. package/dist/components/wheel-scroll-session.d.ts +7 -0
  83. package/dist/components/wheel-scroll-session.js +53 -0
  84. package/dist/components/wheel-scroll-session.js.map +1 -0
  85. package/dist/components/widget-retention.d.ts +35 -0
  86. package/dist/components/widget-retention.js +169 -0
  87. package/dist/components/widget-retention.js.map +1 -0
  88. package/dist/contracts.d.ts +4 -0
  89. package/dist/contracts.js.map +1 -1
  90. package/dist/dnd/context.d.ts +69 -0
  91. package/dist/dnd/context.js +149 -0
  92. package/dist/dnd/context.js.map +1 -0
  93. package/dist/dnd/draggable.d.ts +59 -0
  94. package/dist/dnd/draggable.js +149 -0
  95. package/dist/dnd/draggable.js.map +1 -0
  96. package/dist/dnd/droppable.d.ts +24 -0
  97. package/dist/dnd/droppable.js +74 -0
  98. package/dist/dnd/droppable.js.map +1 -0
  99. package/dist/dnd/gtk-controllers.d.ts +39 -0
  100. package/dist/dnd/gtk-controllers.js +110 -0
  101. package/dist/dnd/gtk-controllers.js.map +1 -0
  102. package/dist/dnd/index.d.ts +6 -0
  103. package/dist/dnd/index.js +31 -0
  104. package/dist/dnd/index.js.map +1 -0
  105. package/dist/dnd/order.d.ts +7 -0
  106. package/dist/dnd/order.js +20 -0
  107. package/dist/dnd/order.js.map +1 -0
  108. package/dist/dnd/payload.d.ts +14 -0
  109. package/dist/dnd/payload.js +41 -0
  110. package/dist/dnd/payload.js.map +1 -0
  111. package/dist/dnd/sortable.d.ts +49 -0
  112. package/dist/dnd/sortable.js +307 -0
  113. package/dist/dnd/sortable.js.map +1 -0
  114. package/dist/dnd/types.d.ts +290 -0
  115. package/dist/dnd/types.js +25 -0
  116. package/dist/dnd/types.js.map +1 -0
  117. package/dist/gesture-handler-compat/builder.d.ts +251 -0
  118. package/dist/gesture-handler-compat/builder.js +513 -0
  119. package/dist/gesture-handler-compat/builder.js.map +1 -0
  120. package/dist/gesture-handler-compat/composition.d.ts +23 -0
  121. package/dist/gesture-handler-compat/composition.js +111 -0
  122. package/dist/gesture-handler-compat/composition.js.map +1 -0
  123. package/dist/gesture-handler-compat/deciders.d.ts +3 -0
  124. package/dist/gesture-handler-compat/deciders.js +47 -0
  125. package/dist/gesture-handler-compat/deciders.js.map +1 -0
  126. package/dist/gesture-handler-compat/detector-runtime.d.ts +44 -0
  127. package/dist/gesture-handler-compat/detector-runtime.js +374 -0
  128. package/dist/gesture-handler-compat/detector-runtime.js.map +1 -0
  129. package/dist/gesture-handler-compat/detector.d.ts +22 -0
  130. package/dist/gesture-handler-compat/detector.js +104 -0
  131. package/dist/gesture-handler-compat/detector.js.map +1 -0
  132. package/dist/gesture-handler-compat/fling.d.ts +24 -0
  133. package/dist/gesture-handler-compat/fling.js +123 -0
  134. package/dist/gesture-handler-compat/fling.js.map +1 -0
  135. package/dist/gesture-handler-compat/force-touch.d.ts +13 -0
  136. package/dist/gesture-handler-compat/force-touch.js +40 -0
  137. package/dist/gesture-handler-compat/force-touch.js.map +1 -0
  138. package/dist/gesture-handler-compat/hooks.d.ts +157 -0
  139. package/dist/gesture-handler-compat/hooks.js +268 -0
  140. package/dist/gesture-handler-compat/hooks.js.map +1 -0
  141. package/dist/gesture-handler-compat/hover.d.ts +2 -0
  142. package/dist/gesture-handler-compat/hover.js +22 -0
  143. package/dist/gesture-handler-compat/hover.js.map +1 -0
  144. package/dist/gesture-handler-compat/index.d.ts +98 -0
  145. package/dist/gesture-handler-compat/index.js +255 -0
  146. package/dist/gesture-handler-compat/index.js.map +1 -0
  147. package/dist/gesture-handler-compat/long-press.d.ts +6 -0
  148. package/dist/gesture-handler-compat/long-press.js +21 -0
  149. package/dist/gesture-handler-compat/long-press.js.map +1 -0
  150. package/dist/gesture-handler-compat/manual.d.ts +2 -0
  151. package/dist/gesture-handler-compat/manual.js +18 -0
  152. package/dist/gesture-handler-compat/manual.js.map +1 -0
  153. package/dist/gesture-handler-compat/native.d.ts +7 -0
  154. package/dist/gesture-handler-compat/native.js +34 -0
  155. package/dist/gesture-handler-compat/native.js.map +1 -0
  156. package/dist/gesture-handler-compat/orchestrator.d.ts +77 -0
  157. package/dist/gesture-handler-compat/orchestrator.js +284 -0
  158. package/dist/gesture-handler-compat/orchestrator.js.map +1 -0
  159. package/dist/gesture-handler-compat/pan.d.ts +23 -0
  160. package/dist/gesture-handler-compat/pan.js +116 -0
  161. package/dist/gesture-handler-compat/pan.js.map +1 -0
  162. package/dist/gesture-handler-compat/recognizer.d.ts +268 -0
  163. package/dist/gesture-handler-compat/recognizer.js +1056 -0
  164. package/dist/gesture-handler-compat/recognizer.js.map +1 -0
  165. package/dist/gesture-handler-compat/relations.d.ts +43 -0
  166. package/dist/gesture-handler-compat/relations.js +128 -0
  167. package/dist/gesture-handler-compat/relations.js.map +1 -0
  168. package/dist/gesture-handler-compat/tap.d.ts +6 -0
  169. package/dist/gesture-handler-compat/tap.js +29 -0
  170. package/dist/gesture-handler-compat/tap.js.map +1 -0
  171. package/dist/gesture-handler-compat/touchpad.d.ts +41 -0
  172. package/dist/gesture-handler-compat/touchpad.js +64 -0
  173. package/dist/gesture-handler-compat/touchpad.js.map +1 -0
  174. package/dist/gesture-handler-compat/types.d.ts +441 -0
  175. package/dist/gesture-handler-compat/types.js +167 -0
  176. package/dist/gesture-handler-compat/types.js.map +1 -0
  177. package/dist/gtk/controllers.d.ts +39 -0
  178. package/dist/gtk/controllers.js +92 -0
  179. package/dist/gtk/controllers.js.map +1 -0
  180. package/dist/gtk/index.d.ts +2 -1
  181. package/dist/gtk/index.js +7 -1
  182. package/dist/gtk/index.js.map +1 -1
  183. package/dist/gtkx/bridge/geometry.js +6 -4
  184. package/dist/gtkx/bridge/geometry.js.map +1 -1
  185. package/dist/gtkx/bridge/index.d.ts +5 -3
  186. package/dist/gtkx/bridge/index.js +6 -3
  187. package/dist/gtkx/bridge/index.js.map +1 -1
  188. package/dist/gtkx/bridge/slot-portal.js.map +1 -1
  189. package/dist/gtkx/bridge/use-signal.js +1 -1
  190. package/dist/gtkx/bridge/use-signal.js.map +1 -1
  191. package/dist/gtkx/bridge/view-box.d.ts +56 -0
  192. package/dist/gtkx/bridge/view-box.js +394 -9
  193. package/dist/gtkx/bridge/view-box.js.map +1 -1
  194. package/dist/gtkx/bridge/widget-css.d.ts +17 -0
  195. package/dist/gtkx/bridge/widget-css.js +72 -0
  196. package/dist/gtkx/bridge/widget-css.js.map +1 -0
  197. package/dist/index.d.ts +3 -3
  198. package/dist/index.js +2 -2
  199. package/dist/index.js.map +1 -1
  200. package/dist/layout/driven-size.d.ts +12 -0
  201. package/dist/layout/driven-size.js +70 -0
  202. package/dist/layout/driven-size.js.map +1 -0
  203. package/dist/layout/engine.d.ts +17 -1
  204. package/dist/layout/engine.js +3 -20
  205. package/dist/layout/engine.js.map +1 -1
  206. package/dist/layout/node.d.ts +13 -0
  207. package/dist/layout/node.js +14 -0
  208. package/dist/layout/node.js.map +1 -1
  209. package/dist/layout/yoga.d.ts +3 -2
  210. package/dist/layout/yoga.js +5 -2
  211. package/dist/layout/yoga.js.map +1 -1
  212. package/dist/mcp/data/generated.d.ts +257 -60
  213. package/dist/mcp/data/generated.js +306 -62
  214. package/dist/mcp/data/generated.js.map +1 -1
  215. package/dist/metro/index.d.ts +10 -0
  216. package/dist/metro/index.js +21 -12
  217. package/dist/metro/index.js.map +1 -1
  218. package/dist/navigation/sidebar.d.ts +16 -0
  219. package/dist/navigation/sidebar.js +65 -1
  220. package/dist/navigation/sidebar.js.map +1 -1
  221. package/dist/reanimated-compat/animated-ref.d.ts +32 -0
  222. package/dist/reanimated-compat/animated-ref.js +57 -0
  223. package/dist/reanimated-compat/animated-ref.js.map +1 -0
  224. package/dist/reanimated-compat/animation.d.ts +177 -0
  225. package/dist/reanimated-compat/animation.js +540 -0
  226. package/dist/reanimated-compat/animation.js.map +1 -0
  227. package/dist/reanimated-compat/color.d.ts +28 -0
  228. package/dist/reanimated-compat/color.js +249 -0
  229. package/dist/reanimated-compat/color.js.map +1 -0
  230. package/dist/reanimated-compat/decay.d.ts +39 -0
  231. package/dist/reanimated-compat/decay.js +96 -0
  232. package/dist/reanimated-compat/decay.js.map +1 -0
  233. package/dist/reanimated-compat/easing.d.ts +30 -0
  234. package/dist/reanimated-compat/easing.js +76 -0
  235. package/dist/reanimated-compat/easing.js.map +1 -0
  236. package/dist/reanimated-compat/hooks.d.ts +14 -0
  237. package/dist/reanimated-compat/hooks.js +217 -0
  238. package/dist/reanimated-compat/hooks.js.map +1 -0
  239. package/dist/reanimated-compat/index.d.ts +258 -0
  240. package/dist/reanimated-compat/index.js +464 -0
  241. package/dist/reanimated-compat/index.js.map +1 -0
  242. package/dist/reanimated-compat/interpolation.d.ts +18 -0
  243. package/dist/reanimated-compat/interpolation.js +122 -0
  244. package/dist/reanimated-compat/interpolation.js.map +1 -0
  245. package/dist/reanimated-compat/layout-animation-config.d.ts +43 -0
  246. package/dist/reanimated-compat/layout-animation-config.js +78 -0
  247. package/dist/reanimated-compat/layout-animation-config.js.map +1 -0
  248. package/dist/reanimated-compat/layout-animation-presets.d.ts +117 -0
  249. package/dist/reanimated-compat/layout-animation-presets.js +498 -0
  250. package/dist/reanimated-compat/layout-animation-presets.js.map +1 -0
  251. package/dist/reanimated-compat/layout-animation-runtime.d.ts +21 -0
  252. package/dist/reanimated-compat/layout-animation-runtime.js +311 -0
  253. package/dist/reanimated-compat/layout-animation-runtime.js.map +1 -0
  254. package/dist/reanimated-compat/layout-animation-view.d.ts +27 -0
  255. package/dist/reanimated-compat/layout-animation-view.js +266 -0
  256. package/dist/reanimated-compat/layout-animation-view.js.map +1 -0
  257. package/dist/reanimated-compat/layout-animation.d.ts +171 -0
  258. package/dist/reanimated-compat/layout-animation.js +469 -0
  259. package/dist/reanimated-compat/layout-animation.js.map +1 -0
  260. package/dist/reanimated-compat/layout-transitions.d.ts +83 -0
  261. package/dist/reanimated-compat/layout-transitions.js +350 -0
  262. package/dist/reanimated-compat/layout-transitions.js.map +1 -0
  263. package/dist/reanimated-compat/mutable.d.ts +29 -0
  264. package/dist/reanimated-compat/mutable.js +139 -0
  265. package/dist/reanimated-compat/mutable.js.map +1 -0
  266. package/dist/reanimated-compat/props.d.ts +18 -0
  267. package/dist/reanimated-compat/props.js +111 -0
  268. package/dist/reanimated-compat/props.js.map +1 -0
  269. package/dist/reanimated-compat/scroll-handler.d.ts +119 -0
  270. package/dist/reanimated-compat/scroll-handler.js +274 -0
  271. package/dist/reanimated-compat/scroll-handler.js.map +1 -0
  272. package/dist/reanimated-compat/scroll-offset.d.ts +12 -0
  273. package/dist/reanimated-compat/scroll-offset.js +104 -0
  274. package/dist/reanimated-compat/scroll-offset.js.map +1 -0
  275. package/dist/reanimated-compat/style.d.ts +90 -0
  276. package/dist/reanimated-compat/style.js +452 -0
  277. package/dist/reanimated-compat/style.js.map +1 -0
  278. package/dist/reanimated-compat/test-timers.d.ts +28 -0
  279. package/dist/reanimated-compat/test-timers.js +136 -0
  280. package/dist/reanimated-compat/test-timers.js.map +1 -0
  281. package/dist/reanimated-compat/threads.d.ts +13 -0
  282. package/dist/reanimated-compat/threads.js +41 -0
  283. package/dist/reanimated-compat/threads.js.map +1 -0
  284. package/dist/reanimated-compat/tracking.d.ts +41 -0
  285. package/dist/reanimated-compat/tracking.js +106 -0
  286. package/dist/reanimated-compat/tracking.js.map +1 -0
  287. package/dist/reanimated-compat/updater-animations.d.ts +36 -0
  288. package/dist/reanimated-compat/updater-animations.js +273 -0
  289. package/dist/reanimated-compat/updater-animations.js.map +1 -0
  290. package/dist/responder/system.d.ts +80 -7
  291. package/dist/responder/system.js +143 -23
  292. package/dist/responder/system.js.map +1 -1
  293. package/dist/responder/use-responder.d.ts +11 -0
  294. package/dist/responder/use-responder.js +225 -6
  295. package/dist/responder/use-responder.js.map +1 -1
  296. package/dist/runner/host-dev.js +1 -1
  297. package/dist/runner/host-dev.js.map +1 -1
  298. package/dist/runner/host.js +1 -1
  299. package/dist/runner/host.js.map +1 -1
  300. package/dist/runner/index.js +3 -3
  301. package/dist/runner/index.js.map +1 -1
  302. package/dist/sea/gtkx-config-module.js +1 -1
  303. package/dist/sea/gtkx-config-module.js.map +1 -1
  304. package/dist/style/absolute-insets.d.ts +26 -0
  305. package/dist/style/absolute-insets.js +113 -0
  306. package/dist/style/absolute-insets.js.map +1 -0
  307. package/dist/style/animated-size.d.ts +25 -0
  308. package/dist/style/animated-size.js +225 -0
  309. package/dist/style/animated-size.js.map +1 -0
  310. package/dist/style/colors.d.ts +17 -0
  311. package/dist/style/colors.js +25 -6
  312. package/dist/style/colors.js.map +1 -1
  313. package/dist/style/imperative-css.d.ts +21 -0
  314. package/dist/style/imperative-css.js +63 -0
  315. package/dist/style/imperative-css.js.map +1 -0
  316. package/dist/style/index.d.ts +2 -1
  317. package/dist/style/index.js +2 -1
  318. package/dist/style/index.js.map +1 -1
  319. package/dist/style/split-style.js +5 -0
  320. package/dist/style/split-style.js.map +1 -1
  321. package/dist/testing/index.js.map +1 -1
  322. package/dist/unsupported-export.d.ts +8 -0
  323. package/dist/unsupported-export.js +66 -0
  324. package/dist/unsupported-export.js.map +1 -0
  325. package/dist/vite/index.d.ts +21 -8
  326. package/dist/vite/index.js +127 -82
  327. package/dist/vite/index.js.map +1 -1
  328. package/dist/vitest/index.d.ts +2 -2
  329. package/dist/vitest/index.js.map +1 -1
  330. package/dist/worklets-compat/index.d.ts +4 -0
  331. package/dist/worklets-compat/index.js +28 -0
  332. package/dist/worklets-compat/index.js.map +1 -0
  333. package/dist/worklets-compat/surface.d.ts +110 -0
  334. package/dist/worklets-compat/surface.js +153 -0
  335. package/dist/worklets-compat/surface.js.map +1 -0
  336. package/package.json +25 -9
  337. package/types.d.ts +9 -0
  338. package/dist/common/list.d.ts +0 -82
  339. package/dist/common/list.js +0 -166
  340. package/dist/common/list.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"pressable.js","sourceRoot":"","sources":["../../src/components/pressable.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n useLayoutEffect,\n useReducer,\n useRef,\n useState,\n type ReactNode,\n} from \"react\"\nimport { splitStyle, StyleSheet } from \"../style/index\"\nimport { defaultCssRegistry } from \"../style/registry.gtkx\"\nimport type { StyleProp } from \"../contracts\"\nimport { Gtk, GtkBox } from \"../gtkx/bridge/index\"\nimport { perfAddTime, perfCount, perfEnabled, perfNow } from \"../perf\"\nimport { HostNodeContext } from \"./host-node\"\nimport { createPressEvent, createTouch, type PressEvent } from \"./press-event\"\nimport {\n useLayoutChild,\n useRnContainer,\n type LayoutEvent,\n} from \"./use-layout-child\"\n\nexport type PressableStateCallbackType = {\n pressed: boolean\n hovered: boolean\n}\n\nexport type { NativeTouch, PressEvent } from \"./press-event\"\n\nexport type PressableProps = {\n style?: StyleProp | ((state: PressableStateCallbackType) => StyleProp)\n children?: ReactNode | ((state: PressableStateCallbackType) => ReactNode)\n onPress?: (event: PressEvent) => void\n onPressIn?: (event: PressEvent) => void\n onPressOut?: (event: PressEvent) => void\n onLongPress?: (event: PressEvent) => void\n onHoverIn?: () => void\n onHoverOut?: () => void\n disabled?: boolean\n delayLongPress?: number\n onLayout?: (event: LayoutEvent) => void\n testID?: string\n}\n\n// Coordinates arrive from GtkGestureClick in the widget's own space, which\n// is exactly RN's locationX/locationY; createTouch translates them into the\n// window for pageX/pageY.\nconst pressEvent = (\n widget: Gtk.Widget | null,\n x: number,\n y: number,\n): PressEvent => createPressEvent(createTouch(widget, x, y))\n\n// A View with a click gesture and hover tracking. State-dependent style and\n// children follow the RN Pressable function-prop contract.\nexport const Pressable = ({\n style,\n children,\n onPress,\n onPressIn,\n onPressOut,\n onLongPress,\n onHoverIn,\n onHoverOut,\n disabled = false,\n delayLongPress = 500,\n onLayout,\n testID,\n}: PressableProps) => {\n const widgetRef = useRef<Gtk.Box | null>(null)\n const [pressed, setPressed] = useState(false)\n // Hover is not React state: a boundary crossing should cost what it costs\n // a native GtkListBox row to swap a CSS class, not a setState + render +\n // Yoga + allocate cycle (measured: roughly 500x the latency of a native\n // row at rest, see docs/research/scroll-performance.md, task 007).\n // `hoveredRef` is the single source of truth, read directly at render\n // time — safe here because this component already mutates\n // `handlersRef.current` in the render body below, so render was never\n // React-DOM-pure to begin with. `forceRender` is used only for the two\n // cases that genuinely need a real render: `children` reads `hovered`,\n // or hovering would itself change layout (not just paint).\n const hoveredRef = useRef(false)\n const [, forceRender] = useReducer((n: number) => n + 1, 0)\n const longPressTimer = useRef<ReturnType<typeof setTimeout> | null>(null)\n const longPressFired = useRef(false)\n // TEMPORARY perf instrumentation (task 007, see\n // docs/research/scroll-performance.md): timestamp the native enter/leave\n // signal so hover's real signal-to-applied latency can be reported —\n // synchronously for the fast path below, after the resulting commit for\n // the slow one. perf.ts hooks are no-ops unless GTKX_PERF=1.\n const hoverSignalAt = useRef<number | null>(null)\n\n const state: PressableStateCallbackType = {\n pressed,\n hovered: hoveredRef.current,\n }\n\n // Gestures are attached imperatively even though rc.3 has a declarative\n // `controllers` slot: the controllers are wired exactly once per widget and\n // the handlers read the latest props through a ref, so a re-render never\n // detaches and re-adds a gesture mid-press.\n const handlersRef = useRef({\n handlePressed: (n: number, x: number, y: number): void => {\n void n\n void x\n void y\n },\n handleReleased: (n: number, x: number, y: number): void => {\n void n\n void x\n void y\n },\n handleCancel: (): void => {},\n handleEnter: (): void => {},\n handleLeave: (): void => {},\n })\n const resolvedStyle = typeof style === \"function\" ? style(state) : style\n const resolvedChildren =\n typeof children === \"function\" ? children(state) : children\n\n const { host, node, cssClass, flat } = useLayoutChild(widgetRef, {\n style: resolvedStyle,\n onLayout,\n })\n useRnContainer(widgetRef, node)\n\n // Hover fast path: when `children` does not read state, hovering can\n // never change what is rendered — only `style` might. Precompute the CSS\n // class for the OTHER hover value so the native enter/leave handlers\n // below can swap classes directly on the widget, with no React involved\n // at all. If hovering would also change LAYOUT (rare — every hover style\n // in this codebase's own examples is background/border) that swap is\n // unsafe, since a real reflow is required; fall back to the ordinary\n // render in that case, exactly as before this change.\n let hoverOnClass: string | null = null\n let hoverOffClass: string | null = null\n let canSwapHoverClass = typeof children !== \"function\"\n if (canSwapHoverClass && typeof style === \"function\") {\n const otherState: PressableStateCallbackType = {\n pressed,\n hovered: !hoveredRef.current,\n }\n const otherFlat = StyleSheet.flatten(style(otherState))\n const otherSplit = splitStyle(otherFlat)\n const currentLayout = splitStyle(flat).layout\n if (JSON.stringify(currentLayout) !== JSON.stringify(otherSplit.layout)) {\n // Hovering resizes or repositions this widget — a CSS class alone\n // cannot do that, it needs Yoga. Fall back to a real render.\n canSwapHoverClass = false\n } else {\n const otherClass = defaultCssRegistry.getClassName(otherSplit.visual)\n hoverOnClass = hoveredRef.current ? cssClass : otherClass\n hoverOffClass = hoveredRef.current ? otherClass : cssClass\n }\n }\n\n // TEMPORARY perf instrumentation (task 007): runs after every commit, so\n // it always lands right after whatever render the SLOW hover path\n // triggered. A no-op when no hover signal is pending (the common case:\n // renders triggered by anything else, or the fast path above, which\n // measures itself synchronously) or when GTKX_PERF is unset.\n useLayoutEffect(() => {\n if (!perfEnabled || hoverSignalAt.current === null) {\n return\n }\n perfAddTime(\"pressable.hoverApply\", perfNow() - hoverSignalAt.current)\n perfCount(\"pressable.hoverFullCycle\")\n hoverSignalAt.current = null\n })\n\n const clearLongPress = (): void => {\n if (longPressTimer.current !== null) {\n clearTimeout(longPressTimer.current)\n longPressTimer.current = null\n }\n }\n\n const handlePressed = (_n: number, x: number, y: number): void => {\n if (disabled) {\n return\n }\n longPressFired.current = false\n setPressed(true)\n const widget = widgetRef.current\n onPressIn?.(pressEvent(widget, x, y))\n if (onLongPress) {\n clearLongPress()\n longPressTimer.current = setTimeout(() => {\n longPressFired.current = true\n // Timestamped when it FIRES, not when the press started — the delay\n // is the whole point of the event.\n onLongPress(pressEvent(widgetRef.current, x, y))\n }, delayLongPress)\n }\n }\n\n const handleReleased = (_n: number, x: number, y: number): void => {\n if (disabled) {\n return\n }\n clearLongPress()\n setPressed(false)\n const widget = widgetRef.current\n onPressOut?.(pressEvent(widget, x, y))\n if (!longPressFired.current) {\n onPress?.(pressEvent(widget, x, y))\n }\n }\n\n const handleCancel = (): void => {\n clearLongPress()\n setPressed(false)\n }\n\n // Applies a hover transition: fires the RN callback, then either swaps\n // the precomputed CSS class directly on the widget (fast path) or forces\n // the ordinary render (slow path) — see the `canSwapHoverClass` block\n // above for which one applies this render.\n const applyHover = (next: boolean, fire: (() => void) | undefined): void => {\n const t0 = perfEnabled ? perfNow() : 0\n hoveredRef.current = next\n fire?.()\n if (!canSwapHoverClass) {\n if (perfEnabled) {\n hoverSignalAt.current = t0\n perfCount(\"pressable.hoverEvent\")\n }\n forceRender()\n return\n }\n const widget = widgetRef.current\n const applyClass = next ? hoverOnClass : hoverOffClass\n const removeClass = next ? hoverOffClass : hoverOnClass\n if (widget && hoverOnClass !== hoverOffClass) {\n if (removeClass) {\n widget.removeCssClass(removeClass)\n }\n if (applyClass) {\n widget.addCssClass(applyClass)\n }\n }\n if (perfEnabled) {\n perfAddTime(\"pressable.hoverApply\", perfNow() - t0)\n perfCount(\"pressable.hoverEvent\")\n perfCount(\"pressable.hoverFast\")\n }\n }\n\n handlersRef.current = {\n handlePressed,\n handleReleased,\n handleCancel,\n handleEnter: () => applyHover(true, onHoverIn),\n handleLeave: () => applyHover(false, onHoverOut),\n }\n\n useLayoutEffect(() => {\n const widget = widgetRef.current\n if (!widget) {\n return\n }\n const click = new Gtk.GestureClick()\n click.on(\"pressed\", (n: number, x: number, y: number) =>\n handlersRef.current.handlePressed(n, x, y),\n )\n click.on(\"released\", (n: number, x: number, y: number) =>\n handlersRef.current.handleReleased(n, x, y),\n )\n click.on(\"cancel\", () => handlersRef.current.handleCancel())\n widget.addController(click)\n\n const motion = new Gtk.EventControllerMotion()\n motion.on(\"enter\", () => handlersRef.current.handleEnter())\n motion.on(\"leave\", () => handlersRef.current.handleLeave())\n widget.addController(motion)\n\n return () => {\n widget.removeController(click)\n widget.removeController(motion)\n }\n }, [])\n\n return (\n <GtkBox\n ref={widgetRef}\n name={testID}\n cssClasses={cssClass ? [cssClass] : []}\n >\n <HostNodeContext.Provider\n value={{ engine: host.engine, node, widgetRef }}\n >\n {resolvedChildren}\n </HostNodeContext.Provider>\n </GtkBox>\n )\n}\n\nexport type TouchableOpacityProps = Omit<PressableProps, \"style\"> & {\n style?: StyleProp\n activeOpacity?: number\n}\n\n// Classic RN touchable: dims itself while pressed via widget opacity.\nexport const TouchableOpacity = ({\n style,\n activeOpacity = 0.5,\n ...rest\n}: TouchableOpacityProps) => (\n <Pressable\n {...rest}\n style={({ pressed }) => [style, pressed && { opacity: activeOpacity }]}\n />\n)\n"]}
1
+ {"version":3,"file":"pressable.js","sourceRoot":"","sources":["../../src/components/pressable.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n useLayoutEffect,\n useReducer,\n useRef,\n useState,\n type ReactNode,\n} from \"react\"\nimport { splitStyle, StyleSheet } from \"../style/index\"\nimport { defaultCssRegistry } from \"../style/registry.gtkx\"\nimport type { StyleProp } from \"../contracts\"\nimport {\n getViewBoxComponent,\n Gtk,\n GtkBox,\n setHitSlop,\n type HitSlop,\n} from \"../gtkx/bridge/index\"\nimport { perfAddTime, perfCount, perfEnabled, perfNow } from \"../perf\"\nimport { HostNodeContext } from \"./host-node\"\nimport { createPressEvent, createTouch, type PressEvent } from \"./press-event\"\nimport { useActivateOnKey, useFocusable, useFocusController } from \"./use-focus\"\nimport {\n useLayoutChild,\n useRnContainer,\n type LayoutEvent,\n} from \"./use-layout-child\"\n\n// react-native-web's own Pressable state is `{focused, hovered, pressed}`.\n// `hovered` was already a documented extension here for that reason;\n// `focused` is the same move, and it is what lets a row draw the focus ring\n// `outlineWidth`/`outlineColor` made drawable.\nexport type PressableStateCallbackType = {\n pressed: boolean\n hovered: boolean\n focused: boolean\n}\n\nexport type { NativeTouch, PressEvent } from \"./press-event\"\n\nexport type PressableProps = {\n style?: StyleProp | ((state: PressableStateCallbackType) => StyleProp)\n children?: ReactNode | ((state: PressableStateCallbackType) => ReactNode)\n onPress?: (event: PressEvent) => void\n onPressIn?: (event: PressEvent) => void\n onPressOut?: (event: PressEvent) => void\n onLongPress?: (event: PressEvent) => void\n onHoverIn?: () => void\n onHoverOut?: () => void\n onFocus?: () => void\n onBlur?: () => void\n /** Whether Tab and the arrow keys can reach this pressable. Defaults to\n * true when `onPress` is set, which is react-native-web's own rule — a\n * control you can click and cannot reach from the keyboard is an\n * accessibility bug, and on a desktop that matters more, not less. */\n focusable?: boolean\n disabled?: boolean\n delayLongPress?: number\n /** RN's hitSlop: how far OUTSIDE its bounds this pressable still counts\n * as pressed. A number is all four edges. Limited by an ancestor that\n * clips — a ScrollView's viewport, say — because GTK stops picking at\n * the clip, the same constraint RN documents on Android. */\n hitSlop?: number | Partial<HitSlop>\n /** RN's pressRetentionOffset: how far the pointer may drift outside the\n * hit rect after pressing and still activate on release. Defaults to\n * RN's own {top: 20, left: 20, right: 20, bottom: 30}. */\n pressRetentionOffset?: number | Partial<HitSlop>\n onLayout?: (event: LayoutEvent) => void\n testID?: string\n}\n\nconst NO_SLOP: HitSlop = { top: 0, right: 0, bottom: 0, left: 0 }\n\n/**\n * RN's own DEFAULT_PRESS_RECT_OFFSETS, from Libraries/Pressability. The\n * bottom edge is deliberately larger: a thumb rolls downwards off a target\n * far more often than upwards.\n */\nconst DEFAULT_PRESS_RECT: HitSlop = { top: 20, right: 20, bottom: 30, left: 20 }\n\nconst toRect = (\n value: number | Partial<HitSlop> | undefined,\n fallback: HitSlop,\n): HitSlop => {\n if (value === undefined) {\n return fallback\n }\n if (typeof value === \"number\") {\n return { top: value, right: value, bottom: value, left: value }\n }\n return {\n top: value.top ?? 0,\n right: value.right ?? 0,\n bottom: value.bottom ?? 0,\n left: value.left ?? 0,\n }\n}\n\n// Coordinates arrive from GtkGestureClick in the widget's own space, which\n// is exactly RN's locationX/locationY; createTouch translates them into the\n// window for pageX/pageY.\nconst pressEvent = (\n widget: Gtk.Widget | null,\n x: number,\n y: number,\n): PressEvent => createPressEvent(createTouch(widget, x, y))\n\n// A View with a click gesture and hover tracking. State-dependent style and\n// children follow the RN Pressable function-prop contract.\nexport const Pressable = ({\n style,\n children,\n onPress,\n onPressIn,\n onPressOut,\n onLongPress,\n onHoverIn,\n onHoverOut,\n onFocus,\n onBlur,\n focusable,\n disabled = false,\n delayLongPress = 500,\n hitSlop,\n pressRetentionOffset,\n onLayout,\n testID,\n}: PressableProps) => {\n const widgetRef = useRef<Gtk.Box | null>(null)\n const [pressed, setPressed] = useState(false)\n // Focus IS React state, unlike hover: it changes at human-decision rates\n // (a Tab press), not at pointer-motion rates, so the fast path hover needs\n // would be complexity with nothing to buy.\n const [focused, setFocused] = useState(false)\n // Hover is not React state: a boundary crossing should cost what it costs\n // a native GtkListBox row to swap a CSS class, not a setState + render +\n // Yoga + allocate cycle (measured: roughly 500x the latency of a native\n // row at rest, see docs/research/scroll-performance.md, task 007).\n // `hoveredRef` is the single source of truth, read directly at render\n // time — safe here because this component already mutates\n // `handlersRef.current` in the render body below, so render was never\n // React-DOM-pure to begin with. `forceRender` is used only for the two\n // cases that genuinely need a real render: `children` reads `hovered`,\n // or hovering would itself change layout (not just paint).\n const hoveredRef = useRef(false)\n const [, forceRender] = useReducer((n: number) => n + 1, 0)\n const longPressTimer = useRef<ReturnType<typeof setTimeout> | null>(null)\n const longPressFired = useRef(false)\n // TEMPORARY perf instrumentation (task 007, see\n // docs/research/scroll-performance.md): timestamp the native enter/leave\n // signal so hover's real signal-to-applied latency can be reported —\n // synchronously for the fast path below, after the resulting commit for\n // the slow one. perf.ts hooks are no-ops unless GTKX_PERF=1.\n const hoverSignalAt = useRef<number | null>(null)\n\n const state: PressableStateCallbackType = {\n pressed,\n hovered: hoveredRef.current,\n focused,\n }\n\n // Gestures are attached imperatively even though rc.3 has a declarative\n // `controllers` slot: the controllers are wired exactly once per widget and\n // the handlers read the latest props through a ref, so a re-render never\n // detaches and re-adds a gesture mid-press.\n const handlersRef = useRef({\n handlePressed: (n: number, x: number, y: number): void => {\n void n\n void x\n void y\n },\n handleReleased: (n: number, x: number, y: number): void => {\n void n\n void x\n void y\n },\n handleCancel: (): void => {},\n handleEnter: (): void => {},\n handleLeave: (): void => {},\n })\n const resolvedStyle = typeof style === \"function\" ? style(state) : style\n const resolvedChildren =\n typeof children === \"function\" ? children(state) : children\n\n const { host, node, cssClass, flat } = useLayoutChild(widgetRef, {\n style: resolvedStyle,\n onLayout,\n })\n useRnContainer(widgetRef, node)\n\n // Hover fast path: when `children` does not read state, hovering can\n // never change what is rendered — only `style` might. Precompute the CSS\n // class for the OTHER hover value so the native enter/leave handlers\n // below can swap classes directly on the widget, with no React involved\n // at all. If hovering would also change LAYOUT (rare — every hover style\n // in this codebase's own examples is background/border) that swap is\n // unsafe, since a real reflow is required; fall back to the ordinary\n // render in that case, exactly as before this change.\n let hoverOnClass: string | null = null\n let hoverOffClass: string | null = null\n let canSwapHoverClass = typeof children !== \"function\"\n if (canSwapHoverClass && typeof style === \"function\") {\n const otherState: PressableStateCallbackType = {\n pressed,\n hovered: !hoveredRef.current,\n focused,\n }\n const otherFlat = StyleSheet.flatten(style(otherState))\n const otherSplit = splitStyle(otherFlat)\n const currentLayout = splitStyle(flat).layout\n if (JSON.stringify(currentLayout) !== JSON.stringify(otherSplit.layout)) {\n // Hovering resizes or repositions this widget — a CSS class alone\n // cannot do that, it needs Yoga. Fall back to a real render.\n canSwapHoverClass = false\n } else {\n const otherClass = defaultCssRegistry.getClassName(otherSplit.visual)\n hoverOnClass = hoveredRef.current ? cssClass : otherClass\n hoverOffClass = hoveredRef.current ? otherClass : cssClass\n }\n }\n\n // TEMPORARY perf instrumentation (task 007): runs after every commit, so\n // it always lands right after whatever render the SLOW hover path\n // triggered. A no-op when no hover signal is pending (the common case:\n // renders triggered by anything else, or the fast path above, which\n // measures itself synchronously) or when GTKX_PERF is unset.\n useLayoutEffect(() => {\n if (!perfEnabled || hoverSignalAt.current === null) {\n return\n }\n perfAddTime(\"pressable.hoverApply\", perfNow() - hoverSignalAt.current)\n perfCount(\"pressable.hoverFullCycle\")\n hoverSignalAt.current = null\n })\n\n const clearLongPress = (): void => {\n if (longPressTimer.current !== null) {\n clearTimeout(longPressTimer.current)\n longPressTimer.current = null\n }\n }\n\n const handlePressed = (_n: number, x: number, y: number): void => {\n if (disabled) {\n return\n }\n longPressFired.current = false\n setPressed(true)\n const widget = widgetRef.current\n onPressIn?.(pressEvent(widget, x, y))\n if (onLongPress) {\n clearLongPress()\n longPressTimer.current = setTimeout(() => {\n longPressFired.current = true\n // Timestamped when it FIRES, not when the press started — the delay\n // is the whole point of the event.\n onLongPress(pressEvent(widgetRef.current, x, y))\n }, delayLongPress)\n }\n }\n\n /**\n * Whether a release at (x, y) — in the widget's own coordinates — still\n * counts as pressing this control. RN's press rect is the hit rect plus\n * pressRetentionOffset, and a release outside it is a cancel, not a\n * press: dragging off a button to change your mind is how every toolkit\n * works, GTK's own GtkButton included. GtkGestureClick keeps an implicit\n * grab for the whole press, so `released` arrives here wherever the\n * pointer ended up and the check has to be ours.\n */\n const withinPressRect = (x: number, y: number): boolean => {\n const widget = widgetRef.current\n if (!widget) {\n return false\n }\n const slop = slopRef.current\n const retention = retentionRef.current\n return (\n x >= -(slop.left + retention.left) &&\n y >= -(slop.top + retention.top) &&\n x < widget.getWidth() + slop.right + retention.right &&\n y < widget.getHeight() + slop.bottom + retention.bottom\n )\n }\n\n const handleReleased = (_n: number, x: number, y: number): void => {\n if (disabled) {\n return\n }\n clearLongPress()\n setPressed(false)\n const widget = widgetRef.current\n // onPressOut fires either way — RN reports the end of the press whether\n // it turned into an activation or not.\n onPressOut?.(pressEvent(widget, x, y))\n if (!longPressFired.current && withinPressRect(x, y)) {\n onPress?.(pressEvent(widget, x, y))\n }\n }\n\n const handleCancel = (): void => {\n clearLongPress()\n setPressed(false)\n }\n\n // Applies a hover transition: fires the RN callback, then either swaps\n // the precomputed CSS class directly on the widget (fast path) or forces\n // the ordinary render (slow path) — see the `canSwapHoverClass` block\n // above for which one applies this render.\n const applyHover = (next: boolean, fire: (() => void) | undefined): void => {\n const t0 = perfEnabled ? perfNow() : 0\n hoveredRef.current = next\n fire?.()\n if (!canSwapHoverClass) {\n if (perfEnabled) {\n hoverSignalAt.current = t0\n perfCount(\"pressable.hoverEvent\")\n }\n forceRender()\n return\n }\n const widget = widgetRef.current\n const applyClass = next ? hoverOnClass : hoverOffClass\n const removeClass = next ? hoverOffClass : hoverOnClass\n if (widget && hoverOnClass !== hoverOffClass) {\n if (removeClass) {\n widget.removeCssClass(removeClass)\n }\n if (applyClass) {\n widget.addCssClass(applyClass)\n }\n }\n if (perfEnabled) {\n perfAddTime(\"pressable.hoverApply\", perfNow() - t0)\n perfCount(\"pressable.hoverEvent\")\n perfCount(\"pressable.hoverFast\")\n }\n }\n\n handlersRef.current = {\n handlePressed,\n handleReleased,\n handleCancel,\n handleEnter: () => applyHover(true, onHoverIn),\n handleLeave: () => applyHover(false, onHoverOut),\n }\n\n // A pressable that can be clicked should be reachable from the keyboard;\n // one that only hovers or lays out should not join the Tab order. That is\n // react-native-web's rule, and it keeps every existing Pressable in this\n // repo behaving as before unless it had an onPress to begin with.\n useFocusable(widgetRef, focusable ?? onPress !== undefined)\n useFocusController(\n widgetRef,\n () => {\n setFocused(true)\n onFocus?.()\n },\n () => {\n setFocused(false)\n onBlur?.()\n },\n )\n // Enter and Space activate a focused control on web and on Android, so\n // they do here. The press event is synthesised at the widget's own origin\n // — a keyboard press has no coordinates, and RN's own handlers read\n // locationX/Y unconditionally.\n useActivateOnKey(\n widgetRef,\n disabled || !onPress\n ? undefined\n : () => onPress(pressEvent(widgetRef.current, 0, 0)),\n )\n\n // Read from the gesture handlers, which are installed once and must not\n // close over a stale prop.\n const slopRef = useRef(NO_SLOP)\n const retentionRef = useRef(DEFAULT_PRESS_RECT)\n slopRef.current = toRect(hitSlop, NO_SLOP)\n retentionRef.current = toRect(pressRetentionOffset, DEFAULT_PRESS_RECT)\n\n const slop = slopRef.current\n useLayoutEffect(() => {\n const widget = widgetRef.current\n if (!widget) {\n return\n }\n const empty =\n slop.top === 0 && slop.right === 0 && slop.bottom === 0 && slop.left === 0\n setHitSlop(widget, empty ? null : slop)\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [slop.top, slop.right, slop.bottom, slop.left])\n\n useLayoutEffect(() => {\n const widget = widgetRef.current\n if (!widget) {\n return\n }\n const click = new Gtk.GestureClick()\n click.on(\"pressed\", (n: number, x: number, y: number) =>\n handlersRef.current.handlePressed(n, x, y),\n )\n click.on(\"released\", (n: number, x: number, y: number) =>\n handlersRef.current.handleReleased(n, x, y),\n )\n click.on(\"cancel\", () => handlersRef.current.handleCancel())\n widget.addController(click)\n\n // Hover fires from touch as well as from a mouse, and that is left\n // alone deliberately. react-native-web filters it — `useHover` drops\n // any event whose pointerType is \"touch\", because on a phone every tap\n // would otherwise leave a view looking hovered. Three measurements say\n // not to copy it here. GTK gives a crossing event no device at all:\n // inside `enter` and `leave` both `get_current_event()` and\n // `get_current_event_device()` are null, because GTK routes crossings\n // through a path that never sets the controller's current event, so the\n // filter would have to come from somewhere else entirely — a raw event\n // tap on the toplevel recording the last input source, which is\n // per-event JS work on every window for a filter nobody can check.\n // GTK also sends a matching leave when a touch sequence ends, so the\n // stuck phantom hover that motivates RNW's filter does not arise, and\n // GTK's own CSS `:hover` lights up on touch — filtering would make this\n // platform's Pressable behave unlike every widget beside it. And it\n // cannot be verified either way here: there is no way to inject a touch\n // on this rig (docs/research/gestures.md). Revisit with a touchscreen\n // and a reason, not before.\n const motion = new Gtk.EventControllerMotion()\n motion.on(\"enter\", () => handlersRef.current.handleEnter())\n motion.on(\"leave\", () => handlersRef.current.handleLeave())\n widget.addController(motion)\n\n return () => {\n widget.removeController(click)\n widget.removeController(motion)\n }\n }, [])\n\n // The same GtkBox subclass a View renders, for its contains() override:\n // hitSlop is a picking change and nothing in JS can substitute for one,\n // because a press outside the widget is never delivered to it at all.\n const PressableBox = getViewBoxComponent() as typeof GtkBox\n return (\n <PressableBox\n ref={widgetRef}\n name={testID}\n cssClasses={cssClass ? [cssClass] : []}\n >\n <HostNodeContext.Provider\n value={{ engine: host.engine, node, widgetRef }}\n >\n {resolvedChildren}\n </HostNodeContext.Provider>\n </PressableBox>\n )\n}\n\nexport type TouchableOpacityProps = Omit<PressableProps, \"style\"> & {\n style?: StyleProp\n activeOpacity?: number\n}\n\n// Classic RN touchable: dims itself while pressed via widget opacity.\nexport const TouchableOpacity = ({\n style,\n activeOpacity = 0.5,\n ...rest\n}: TouchableOpacityProps) => (\n <Pressable\n {...rest}\n style={({ pressed }) => [style, pressed && { opacity: activeOpacity }]}\n />\n)\n\nexport type TouchableHighlightProps = Omit<PressableProps, \"style\"> & {\n style?: StyleProp\n /**\n * RN's default is `\"black\"`, and its default `activeOpacity` is `0.85` — the\n * underlay shows through the dimmed child rather than replacing it. Here the\n * underlay IS the background, because there is no separate underlay view to\n * put behind a child that may be opaque, so an app that wants RN's exact\n * blend gives the child a translucent background itself.\n */\n underlayColor?: string\n activeOpacity?: number\n onShowUnderlay?: () => void\n onHideUnderlay?: () => void\n}\n\n/**\n * RN's `TouchableHighlight`: a background colour while held.\n *\n * Here because `@gorhom/bottom-sheet` re-exports it from its own public entry\n * as `BottomSheetTouchable` on every platform except iOS — it is upstream's\n * export, not an app's choice, so an app cannot avoid it. It is also an\n * ordinary `react-native` component that this surface was simply missing.\n *\n * One structural difference, stated rather than papered over: RN renders a\n * separate underlay VIEW behind the child and lowers the child's opacity onto\n * it. Reproducing that needs a second box, and an extra box changes flex\n * layout and what `measureLayout` is relative to — the same reason\n * `GestureDetector` and `createAnimatedComponent` add none. So the highlight\n * is this view's own `backgroundColor` while pressed.\n */\nexport const TouchableHighlight = ({\n style,\n underlayColor = \"black\",\n activeOpacity,\n onShowUnderlay,\n onHideUnderlay,\n onPressIn,\n onPressOut,\n ...rest\n}: TouchableHighlightProps) => (\n <Pressable\n {...rest}\n onPressIn={(event) => {\n onShowUnderlay?.()\n onPressIn?.(event)\n }}\n onPressOut={(event) => {\n onHideUnderlay?.()\n onPressOut?.(event)\n }}\n style={({ pressed }) => [\n style,\n pressed && {\n backgroundColor: underlayColor,\n ...(activeOpacity === undefined ? null : { opacity: activeOpacity }),\n },\n ]}\n />\n)\n\nexport type TouchableWithoutFeedbackProps = PressableProps\n\n/**\n * RN's `TouchableWithoutFeedback`: the press callbacks and nothing visual.\n *\n * RN's own version clones its single child rather than rendering a box, and\n * its documentation calls that a mistake it kept for compatibility. This one\n * renders the `Pressable` box, which is what `Pressable` already is with no\n * `style` callback — the difference is invisible unless the child was relying\n * on being laid out by ITS parent, and RN's own docs tell you to use\n * `Pressable` instead for exactly that reason.\n */\nexport const TouchableWithoutFeedback = (props: PressableProps) => (\n <Pressable {...props} />\n)\n"]}
@@ -9,10 +9,68 @@ export type StoredOffset = {
9
9
  dx: number;
10
10
  dy: number;
11
11
  matrix: Transform2D | null;
12
+ /**
13
+ * The box an animated SIZE is currently driving this child to, or null when
14
+ * nothing is. Composed here rather than written over the committed rect for
15
+ * the reason the `dx`/`dy` above are: the committed rect belongs to the
16
+ * engine and is rewritten by any flush, and an animation must not lose a
17
+ * frame to one that had nothing to do with it.
18
+ */
19
+ driven: DrivenBox | null;
12
20
  };
21
+ /**
22
+ * A partial rect: every field the animation is NOT driving stays null and the
23
+ * engine's committed value is used instead.
24
+ *
25
+ * Partial rather than whole so that nothing can go stale. The animated node
26
+ * overrides only the axis being driven — its origin and its other axis keep
27
+ * following the engine, so a window resize mid-animation moves it exactly as
28
+ * it moves everything else. Its descendants override the whole rect, which is
29
+ * safe for the same reason: those are relative to the node, and re-laying its
30
+ * subtree out is precisely what decides them.
31
+ */
32
+ export type DrivenBox = {
33
+ x: number | null;
34
+ y: number | null;
35
+ width: number | null;
36
+ height: number | null;
37
+ };
38
+ /**
39
+ * Told when a child's committed rect changes, which is the only moment a
40
+ * layout transition can know it has something to animate: a moved child is
41
+ * exactly a child whose engine rect is not the one it had.
42
+ *
43
+ * A WeakMap plus a counter rather than a Map, because the key is a widget and
44
+ * an observer must never be the reason one stays alive; the counter is what
45
+ * keeps `setStoredRect` free (one integer compare) for the overwhelming
46
+ * majority of children, which have no observer.
47
+ */
48
+ export type RectObserver = (next: StoredRect, previous: StoredRect | undefined) => void;
49
+ /** Subscribes to `widget`'s committed rect. Returns the unsubscribe. */
50
+ export declare const observeStoredRect: (widget: object, observer: RectObserver) => (() => void);
13
51
  export declare const setStoredRect: (widget: object, rect: StoredRect) => void;
14
52
  export declare const getStoredRect: (widget: object) => StoredRect | undefined;
15
53
  export declare const setStoredOffset: (widget: object, dx: number, dy: number, matrix?: Transform2D | null) => void;
54
+ export declare const setStoredDrivenBox: (widget: object, box: DrivenBox) => void;
55
+ export declare const clearStoredDrivenBox: (widget: object) => void;
56
+ /**
57
+ * The box an animation is currently driving this widget to, if any. Read by
58
+ * the container's own `measure` as well as by its parent's `allocate`, so the
59
+ * widget's size request agrees with the size it is being given.
60
+ */
61
+ export declare const getStoredDrivenBox: (widget: object) => DrivenBox | undefined;
62
+ export declare const setStoredLayoutOffset: (widget: object, dx: number, dy: number) => void;
63
+ export declare const clearStoredLayoutOffset: (widget: object) => void;
64
+ /**
65
+ * Where a layout transition currently has this child, relative to the rect
66
+ * the engine gave it. Read when a transition is INTERRUPTED by another one:
67
+ * the new run has to start from where the child is being drawn, not from
68
+ * where it was before the first run began.
69
+ */
70
+ export declare const getStoredLayoutOffset: (widget: object) => {
71
+ dx: number;
72
+ dy: number;
73
+ };
16
74
  export declare const getStoredOffset: (widget: object) => StoredOffset;
17
75
  /**
18
76
  * Stores a child's whole RN `transform` array, split the way the allocate
@@ -3,17 +3,138 @@
3
3
  // read by the parent container's RnGtkxLayout allocate() hook. Pure data —
4
4
  // no FFI here, so both writers and the bridge-side reader stay testable.
5
5
  import { composeTransform, isTranslationOnly } from "../style/transform";
6
- const ZERO_OFFSET = { dx: 0, dy: 0, matrix: null };
6
+ const ZERO_OFFSET = { dx: 0, dy: 0, matrix: null, driven: null };
7
7
  const rects = new WeakMap();
8
8
  const offsets = new WeakMap();
9
+ const rectObservers = new WeakMap();
10
+ let rectObserverCount = 0;
11
+ /** Subscribes to `widget`'s committed rect. Returns the unsubscribe. */
12
+ export const observeStoredRect = (widget, observer) => {
13
+ if (!rectObservers.has(widget)) {
14
+ rectObserverCount += 1;
15
+ }
16
+ rectObservers.set(widget, observer);
17
+ return () => {
18
+ if (rectObservers.delete(widget)) {
19
+ rectObserverCount -= 1;
20
+ }
21
+ };
22
+ };
9
23
  export const setStoredRect = (widget, rect) => {
24
+ if (rectObserverCount === 0) {
25
+ rects.set(widget, rect);
26
+ return;
27
+ }
28
+ const previous = rects.get(widget);
10
29
  rects.set(widget, rect);
30
+ rectObservers.get(widget)?.(rect, previous);
11
31
  };
12
32
  export const getStoredRect = (widget) => rects.get(widget);
13
33
  export const setStoredOffset = (widget, dx, dy, matrix = null) => {
14
- offsets.set(widget, { dx, dy, matrix });
34
+ offsets.set(widget, { dx, dy, matrix, driven: null });
35
+ };
36
+ // The THIRD layer, and the one that is not a translation at all.
37
+ //
38
+ // An animated `width`/`height` in the subset where the change is confined to
39
+ // the node that owns it (../style/animated-size.ts) is driven by re-laying out
40
+ // that node's own subtree and putting the result HERE — one record for the
41
+ // node, one for each of its descendants, because a wider box re-wraps the text
42
+ // inside it and those rects move too.
43
+ //
44
+ // Deliberately not a write over the committed rect, which is what the recon
45
+ // spike did (docs/research/animated-size.md, "Not implemented"). The committed
46
+ // rect is the engine's: any flush may rewrite it, and a measure-backed leaf —
47
+ // every `Text` — is re-committed by every walk that reaches it whether its
48
+ // rect changed or not (layout/node.ts, `hasMeasure`). An animation that lost a
49
+ // frame to an unrelated `setState` somewhere else in the tree would be exactly
50
+ // the kind of bug nobody can reproduce. Kept apart, the engine writes what it
51
+ // computed, this layer writes what the animation is showing, and the allocate
52
+ // hook is the only place the two meet.
53
+ const drivenBoxes = new WeakMap();
54
+ let drivenBoxCount = 0;
55
+ export const setStoredDrivenBox = (widget, box) => {
56
+ if (!drivenBoxes.has(widget)) {
57
+ drivenBoxCount += 1;
58
+ }
59
+ drivenBoxes.set(widget, box);
60
+ };
61
+ export const clearStoredDrivenBox = (widget) => {
62
+ if (drivenBoxes.delete(widget)) {
63
+ drivenBoxCount -= 1;
64
+ }
65
+ };
66
+ /**
67
+ * The box an animation is currently driving this widget to, if any. Read by
68
+ * the container's own `measure` as well as by its parent's `allocate`, so the
69
+ * widget's size request agrees with the size it is being given.
70
+ */
71
+ export const getStoredDrivenBox = (widget) => drivenBoxCount === 0 ? undefined : drivenBoxes.get(widget);
72
+ // The SECOND translation layer, and the reason there are two.
73
+ //
74
+ // The offset above belongs to the style: whatever `transform` the component
75
+ // declared, animated or not, and there is exactly one writer for it. A layout
76
+ // transition (Reanimated's `layout`/`LinearTransition`) is a different claim
77
+ // on the same child — "draw it where it used to be and walk it to where Yoga
78
+ // just put it" — and it has to survive alongside a style transform rather
79
+ // than overwrite it, because a reordering list whose rows also scale is not
80
+ // an exotic case. Composed here, in the one place both are read, so the
81
+ // allocate hook still does a single lookup per child and neither writer has
82
+ // to know the other exists.
83
+ //
84
+ // Translation only. A layout transition that changed a child's SIZE would
85
+ // need a Yoga pass per frame, which is refused on measured grounds
86
+ // (docs/research/animated-colors.md); the size lands immediately and the
87
+ // position is what animates.
88
+ const layoutOffsets = new WeakMap();
89
+ let layoutOffsetCount = 0;
90
+ export const setStoredLayoutOffset = (widget, dx, dy) => {
91
+ if (!layoutOffsets.has(widget)) {
92
+ layoutOffsetCount += 1;
93
+ }
94
+ layoutOffsets.set(widget, { dx, dy });
95
+ };
96
+ export const clearStoredLayoutOffset = (widget) => {
97
+ if (layoutOffsets.delete(widget)) {
98
+ layoutOffsetCount -= 1;
99
+ }
100
+ };
101
+ /**
102
+ * Where a layout transition currently has this child, relative to the rect
103
+ * the engine gave it. Read when a transition is INTERRUPTED by another one:
104
+ * the new run has to start from where the child is being drawn, not from
105
+ * where it was before the first run began.
106
+ */
107
+ export const getStoredLayoutOffset = (widget) => layoutOffsets.get(widget) ?? { dx: 0, dy: 0 };
108
+ export const getStoredOffset = (widget) => {
109
+ const base = offsets.get(widget) ?? ZERO_OFFSET;
110
+ const driven = drivenBoxCount === 0 ? undefined : drivenBoxes.get(widget);
111
+ const extra = layoutOffsetCount === 0 ? undefined : layoutOffsets.get(widget);
112
+ if (extra === undefined) {
113
+ return driven === undefined ? base : { ...base, driven };
114
+ }
115
+ if (base.matrix === null) {
116
+ return {
117
+ dx: base.dx + extra.dx,
118
+ dy: base.dy + extra.dy,
119
+ matrix: null,
120
+ driven: driven ?? null,
121
+ };
122
+ }
123
+ // Added to the composed matrix's translation, which allocateChild applies
124
+ // last and in the PARENT's coordinate space — so a rotated child still
125
+ // slides along the parent's axes, which is what "it moved in the list"
126
+ // means.
127
+ return {
128
+ dx: 0,
129
+ dy: 0,
130
+ matrix: {
131
+ ...base.matrix,
132
+ dx: base.matrix.dx + extra.dx,
133
+ dy: base.matrix.dy + extra.dy,
134
+ },
135
+ driven: driven ?? null,
136
+ };
15
137
  };
16
- export const getStoredOffset = (widget) => offsets.get(widget) ?? ZERO_OFFSET;
17
138
  /**
18
139
  * Stores a child's whole RN `transform` array, split the way the allocate
19
140
  * hook wants it: a pure translation keeps the positional path (offset the
@@ -1 +1 @@
1
- {"version":3,"file":"rect-store.js","sourceRoot":"","sources":["../../src/components/rect-store.ts"],"names":[],"mappings":"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","sourcesContent":["// Committed engine rects and animated offsets, keyed by the CHILD widget.\n// Written by commit callbacks (use-layout-child) and by Animated bindings;\n// read by the parent container's RnGtkxLayout allocate() hook. Pure data —\n// no FFI here, so both writers and the bridge-side reader stay testable.\nimport { composeTransform, isTranslationOnly } from \"../style/transform\"\nimport type { Transform2D, TransformPart } from \"../contracts\"\n\nexport type StoredRect = {\n x: number\n y: number\n width: number\n height: number\n}\n\n// The visual transform of one child, split by cost. A pure translation stays\n// `matrix: null` and is applied by simply offsetting the rect — the path that\n// existed before rotate/scale and that costs no GskTransform. Anything that\n// rotates or scales carries the whole composed matrix (translations\n// included, so the RN ordering is preserved) and pays one gsk call per\n// allocation. Both live in ONE record on purpose: the allocate hook already\n// reads it per child, so a transform costs no extra WeakMap lookup.\nexport type StoredOffset = {\n dx: number\n dy: number\n matrix: Transform2D | null\n}\n\nconst ZERO_OFFSET: StoredOffset = { dx: 0, dy: 0, matrix: null }\n\nconst rects = new WeakMap<object, StoredRect>()\nconst offsets = new WeakMap<object, StoredOffset>()\n\nexport const setStoredRect = (widget: object, rect: StoredRect): void => {\n rects.set(widget, rect)\n}\n\nexport const getStoredRect = (widget: object): StoredRect | undefined =>\n rects.get(widget)\n\nexport const setStoredOffset = (\n widget: object,\n dx: number,\n dy: number,\n matrix: Transform2D | null = null,\n): void => {\n offsets.set(widget, { dx, dy, matrix })\n}\n\nexport const getStoredOffset = (widget: object): StoredOffset =>\n offsets.get(widget) ?? ZERO_OFFSET\n\n/**\n * Stores a child's whole RN `transform` array, split the way the allocate\n * hook wants it: a pure translation keeps the positional path (offset the\n * rect, no GskTransform at all — the pre-rotate/scale behaviour), anything\n * that rotates or scales carries the composed matrix instead, translations\n * folded in so the array's order is preserved exactly.\n */\nexport const setStoredTransform = (\n widget: object,\n parts: readonly TransformPart[] | undefined,\n): void => {\n if (!parts || parts.length === 0) {\n setStoredOffset(widget, 0, 0, null)\n return\n }\n const matrix = composeTransform(parts)\n if (isTranslationOnly(matrix)) {\n setStoredOffset(widget, matrix.dx, matrix.dy, null)\n return\n }\n setStoredOffset(widget, 0, 0, matrix)\n}\n\n// While a window-root allocate() pass runs the engine synchronously, commit\n// callbacks must not queue GTK resizes mid-pass — the pass itself is about to\n// place everything. Queue jobs are deferred (deduped per widget) and run once\n// the pass ends; commits whose rect did not change never re-defer, so the\n// follow-up converges.\nlet allocatePassDepth = 0\nconst deferredJobs = new Map<object, () => void>()\n\nexport const beginAllocatePass = (): void => {\n allocatePassDepth += 1\n}\n\nexport const endAllocatePass = (): void => {\n allocatePassDepth -= 1\n if (allocatePassDepth === 0 && deferredJobs.size > 0) {\n const jobs = [...deferredJobs.values()]\n deferredJobs.clear()\n for (const job of jobs) {\n job()\n }\n }\n}\n\n// Returns true when the job was deferred (an allocate pass is running).\nexport const deferDuringAllocate = (\n widget: object,\n job: () => void,\n): boolean => {\n if (allocatePassDepth === 0) {\n return false\n }\n deferredJobs.set(widget, job)\n return true\n}\n"]}
1
+ {"version":3,"file":"rect-store.js","sourceRoot":"","sources":["../../src/components/rect-store.ts"],"names":[],"mappings":"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","sourcesContent":["// Committed engine rects and animated offsets, keyed by the CHILD widget.\n// Written by commit callbacks (use-layout-child) and by Animated bindings;\n// read by the parent container's RnGtkxLayout allocate() hook. Pure data —\n// no FFI here, so both writers and the bridge-side reader stay testable.\nimport { composeTransform, isTranslationOnly } from \"../style/transform\"\nimport type { Transform2D, TransformPart } from \"../contracts\"\n\nexport type StoredRect = {\n x: number\n y: number\n width: number\n height: number\n}\n\n// The visual transform of one child, split by cost. A pure translation stays\n// `matrix: null` and is applied by simply offsetting the rect — the path that\n// existed before rotate/scale and that costs no GskTransform. Anything that\n// rotates or scales carries the whole composed matrix (translations\n// included, so the RN ordering is preserved) and pays one gsk call per\n// allocation. Both live in ONE record on purpose: the allocate hook already\n// reads it per child, so a transform costs no extra WeakMap lookup.\nexport type StoredOffset = {\n dx: number\n dy: number\n matrix: Transform2D | null\n /**\n * The box an animated SIZE is currently driving this child to, or null when\n * nothing is. Composed here rather than written over the committed rect for\n * the reason the `dx`/`dy` above are: the committed rect belongs to the\n * engine and is rewritten by any flush, and an animation must not lose a\n * frame to one that had nothing to do with it.\n */\n driven: DrivenBox | null\n}\n\n/**\n * A partial rect: every field the animation is NOT driving stays null and the\n * engine's committed value is used instead.\n *\n * Partial rather than whole so that nothing can go stale. The animated node\n * overrides only the axis being driven — its origin and its other axis keep\n * following the engine, so a window resize mid-animation moves it exactly as\n * it moves everything else. Its descendants override the whole rect, which is\n * safe for the same reason: those are relative to the node, and re-laying its\n * subtree out is precisely what decides them.\n */\nexport type DrivenBox = {\n x: number | null\n y: number | null\n width: number | null\n height: number | null\n}\n\nconst ZERO_OFFSET: StoredOffset = { dx: 0, dy: 0, matrix: null, driven: null }\n\nconst rects = new WeakMap<object, StoredRect>()\nconst offsets = new WeakMap<object, StoredOffset>()\n\n/**\n * Told when a child's committed rect changes, which is the only moment a\n * layout transition can know it has something to animate: a moved child is\n * exactly a child whose engine rect is not the one it had.\n *\n * A WeakMap plus a counter rather than a Map, because the key is a widget and\n * an observer must never be the reason one stays alive; the counter is what\n * keeps `setStoredRect` free (one integer compare) for the overwhelming\n * majority of children, which have no observer.\n */\nexport type RectObserver = (\n next: StoredRect,\n previous: StoredRect | undefined,\n) => void\n\nconst rectObservers = new WeakMap<object, RectObserver>()\nlet rectObserverCount = 0\n\n/** Subscribes to `widget`'s committed rect. Returns the unsubscribe. */\nexport const observeStoredRect = (\n widget: object,\n observer: RectObserver,\n): (() => void) => {\n if (!rectObservers.has(widget)) {\n rectObserverCount += 1\n }\n rectObservers.set(widget, observer)\n return () => {\n if (rectObservers.delete(widget)) {\n rectObserverCount -= 1\n }\n }\n}\n\nexport const setStoredRect = (widget: object, rect: StoredRect): void => {\n if (rectObserverCount === 0) {\n rects.set(widget, rect)\n return\n }\n const previous = rects.get(widget)\n rects.set(widget, rect)\n rectObservers.get(widget)?.(rect, previous)\n}\n\nexport const getStoredRect = (widget: object): StoredRect | undefined =>\n rects.get(widget)\n\nexport const setStoredOffset = (\n widget: object,\n dx: number,\n dy: number,\n matrix: Transform2D | null = null,\n): void => {\n offsets.set(widget, { dx, dy, matrix, driven: null })\n}\n\n// The THIRD layer, and the one that is not a translation at all.\n//\n// An animated `width`/`height` in the subset where the change is confined to\n// the node that owns it (../style/animated-size.ts) is driven by re-laying out\n// that node's own subtree and putting the result HERE — one record for the\n// node, one for each of its descendants, because a wider box re-wraps the text\n// inside it and those rects move too.\n//\n// Deliberately not a write over the committed rect, which is what the recon\n// spike did (docs/research/animated-size.md, \"Not implemented\"). The committed\n// rect is the engine's: any flush may rewrite it, and a measure-backed leaf —\n// every `Text` — is re-committed by every walk that reaches it whether its\n// rect changed or not (layout/node.ts, `hasMeasure`). An animation that lost a\n// frame to an unrelated `setState` somewhere else in the tree would be exactly\n// the kind of bug nobody can reproduce. Kept apart, the engine writes what it\n// computed, this layer writes what the animation is showing, and the allocate\n// hook is the only place the two meet.\nconst drivenBoxes = new WeakMap<object, DrivenBox>()\nlet drivenBoxCount = 0\n\nexport const setStoredDrivenBox = (widget: object, box: DrivenBox): void => {\n if (!drivenBoxes.has(widget)) {\n drivenBoxCount += 1\n }\n drivenBoxes.set(widget, box)\n}\n\nexport const clearStoredDrivenBox = (widget: object): void => {\n if (drivenBoxes.delete(widget)) {\n drivenBoxCount -= 1\n }\n}\n\n/**\n * The box an animation is currently driving this widget to, if any. Read by\n * the container's own `measure` as well as by its parent's `allocate`, so the\n * widget's size request agrees with the size it is being given.\n */\nexport const getStoredDrivenBox = (widget: object): DrivenBox | undefined =>\n drivenBoxCount === 0 ? undefined : drivenBoxes.get(widget)\n\n// The SECOND translation layer, and the reason there are two.\n//\n// The offset above belongs to the style: whatever `transform` the component\n// declared, animated or not, and there is exactly one writer for it. A layout\n// transition (Reanimated's `layout`/`LinearTransition`) is a different claim\n// on the same child — \"draw it where it used to be and walk it to where Yoga\n// just put it\" — and it has to survive alongside a style transform rather\n// than overwrite it, because a reordering list whose rows also scale is not\n// an exotic case. Composed here, in the one place both are read, so the\n// allocate hook still does a single lookup per child and neither writer has\n// to know the other exists.\n//\n// Translation only. A layout transition that changed a child's SIZE would\n// need a Yoga pass per frame, which is refused on measured grounds\n// (docs/research/animated-colors.md); the size lands immediately and the\n// position is what animates.\nconst layoutOffsets = new WeakMap<object, { dx: number; dy: number }>()\nlet layoutOffsetCount = 0\n\nexport const setStoredLayoutOffset = (\n widget: object,\n dx: number,\n dy: number,\n): void => {\n if (!layoutOffsets.has(widget)) {\n layoutOffsetCount += 1\n }\n layoutOffsets.set(widget, { dx, dy })\n}\n\nexport const clearStoredLayoutOffset = (widget: object): void => {\n if (layoutOffsets.delete(widget)) {\n layoutOffsetCount -= 1\n }\n}\n\n/**\n * Where a layout transition currently has this child, relative to the rect\n * the engine gave it. Read when a transition is INTERRUPTED by another one:\n * the new run has to start from where the child is being drawn, not from\n * where it was before the first run began.\n */\nexport const getStoredLayoutOffset = (\n widget: object,\n): { dx: number; dy: number } => layoutOffsets.get(widget) ?? { dx: 0, dy: 0 }\n\nexport const getStoredOffset = (widget: object): StoredOffset => {\n const base = offsets.get(widget) ?? ZERO_OFFSET\n const driven = drivenBoxCount === 0 ? undefined : drivenBoxes.get(widget)\n const extra = layoutOffsetCount === 0 ? undefined : layoutOffsets.get(widget)\n if (extra === undefined) {\n return driven === undefined ? base : { ...base, driven }\n }\n if (base.matrix === null) {\n return {\n dx: base.dx + extra.dx,\n dy: base.dy + extra.dy,\n matrix: null,\n driven: driven ?? null,\n }\n }\n // Added to the composed matrix's translation, which allocateChild applies\n // last and in the PARENT's coordinate space — so a rotated child still\n // slides along the parent's axes, which is what \"it moved in the list\"\n // means.\n return {\n dx: 0,\n dy: 0,\n matrix: {\n ...base.matrix,\n dx: base.matrix.dx + extra.dx,\n dy: base.matrix.dy + extra.dy,\n },\n driven: driven ?? null,\n }\n}\n\n/**\n * Stores a child's whole RN `transform` array, split the way the allocate\n * hook wants it: a pure translation keeps the positional path (offset the\n * rect, no GskTransform at all — the pre-rotate/scale behaviour), anything\n * that rotates or scales carries the composed matrix instead, translations\n * folded in so the array's order is preserved exactly.\n */\nexport const setStoredTransform = (\n widget: object,\n parts: readonly TransformPart[] | undefined,\n): void => {\n if (!parts || parts.length === 0) {\n setStoredOffset(widget, 0, 0, null)\n return\n }\n const matrix = composeTransform(parts)\n if (isTranslationOnly(matrix)) {\n setStoredOffset(widget, matrix.dx, matrix.dy, null)\n return\n }\n setStoredOffset(widget, 0, 0, matrix)\n}\n\n// While a window-root allocate() pass runs the engine synchronously, commit\n// callbacks must not queue GTK resizes mid-pass — the pass itself is about to\n// place everything. Queue jobs are deferred (deduped per widget) and run once\n// the pass ends; commits whose rect did not change never re-defer, so the\n// follow-up converges.\nlet allocatePassDepth = 0\nconst deferredJobs = new Map<object, () => void>()\n\nexport const beginAllocatePass = (): void => {\n allocatePassDepth += 1\n}\n\nexport const endAllocatePass = (): void => {\n allocatePassDepth -= 1\n if (allocatePassDepth === 0 && deferredJobs.size > 0) {\n const jobs = [...deferredJobs.values()]\n deferredJobs.clear()\n for (const job of jobs) {\n job()\n }\n }\n}\n\n// Returns true when the job was deferred (an allocate pass is running).\nexport const deferDuringAllocate = (\n widget: object,\n job: () => void,\n): boolean => {\n if (allocatePassDepth === 0) {\n return false\n }\n deferredJobs.set(widget, job)\n return true\n}\n"]}
@@ -74,7 +74,12 @@ export const NestedRoot = ({ children }) => (_jsx(Root, { width: 0, height: 0, f
74
74
  // recomputes at the real size and commits.
75
75
  export const IntrinsicRoot = ({ children }) => {
76
76
  const widgetRef = useRef(null);
77
- const [engine] = useState(() => new LayoutEngine({ width: 0, height: 0 }));
77
+ const [engine] = useState(
78
+ // `contentSized`: this root's own size REQUEST is its Yoga content size,
79
+ // so unlike every other root a size change under it does reach the
80
+ // toplevel. The animated-size carve-out reads the flag and keeps the
81
+ // refusal here (docs/research/animated-size.md §4).
82
+ () => new LayoutEngine({ width: 0, height: 0 }, { contentSized: true }));
78
83
  useEffect(() => () => {
79
84
  engine.dispose();
80
85
  }, [engine]);
@@ -1 +1 @@
1
- {"version":3,"file":"root.js","sourceRoot":"","sources":["../../src/components/root.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from \"react\"\nimport { LayoutEngine } from \"../layout/index\"\nimport { GtkBox, queueResize, type Gtk } from \"../gtkx/bridge/index\"\nimport { HostNodeContext } from \"./host-node\"\nimport { beginAllocatePass, endAllocatePass } from \"./rect-store\"\nimport { useRnContainer } from \"./use-layout-child\"\n\nexport type RootProps = {\n width: number\n height: number\n // Window mode: report a zero minimum (the window may shrink freely) and\n // adopt whatever the window actually allocates as the engine viewport —\n // the allocation IS the layout viewport, headerbar excluded by GTK itself.\n followAllocation?: boolean\n // Claim the parent slot: a zero-minimum box inside a plain GTK container\n // gets no space unless it expands (window children fill implicitly, other\n // containers honor the expand flags).\n expand?: boolean\n children?: ReactNode\n}\n\n// Layout root: one engine per window (or per test harness). The root GtkBox\n// reports the engine viewport as its measure (via RnGtkxLayout) and is sized\n// by its parent (window/harness); the owner keeps the engine viewport in sync\n// (AppRegistry does it from window-size changes).\nexport const Root = ({\n width,\n height,\n followAllocation = false,\n expand = false,\n children,\n}: RootProps) => {\n const widgetRef = useRef<Gtk.Box | null>(null)\n\n // useState lazy init — see the note in use-layout-child.ts (React Compiler).\n const [engine] = useState<LayoutEngine>(\n () => new LayoutEngine({ width, height }),\n )\n\n useLayoutEffect(() => {\n if (followAllocation) {\n return\n }\n engine.setViewport({ width, height })\n // The viewport is this widget's measure — invalidate the cached one.\n const widget = widgetRef.current\n if (widget) {\n queueResize(widget)\n }\n }, [engine, followAllocation, width, height])\n\n useEffect(\n () => () => {\n engine.dispose()\n },\n [engine],\n )\n\n const host = useMemo(\n () => ({ engine, node: engine.root, widgetRef }),\n [engine],\n )\n\n useRnContainer(\n widgetRef,\n engine.root,\n followAllocation\n ? {\n measure: () => 0,\n beforeAllocate: (allocatedWidth, allocatedHeight) => {\n const current = engine.root.getRect()\n if (\n current &&\n current.width === allocatedWidth &&\n current.height === allocatedHeight\n ) {\n return\n }\n // Synchronous reflow inside the allocation pass: commits fill the\n // rect store now; their GTK queue calls are deferred past the pass.\n beginAllocatePass()\n try {\n engine.setViewport({\n width: allocatedWidth,\n height: allocatedHeight,\n })\n engine.flushSync()\n } finally {\n endAllocatePass()\n }\n },\n }\n : undefined,\n )\n\n return (\n <GtkBox\n ref={widgetRef}\n hexpand={expand}\n vexpand={expand}\n >\n <HostNodeContext.Provider value={host}>\n {children}\n </HostNodeContext.Provider>\n </GtkBox>\n )\n}\n\nexport type NestedRootProps = {\n children?: ReactNode\n}\n\n// Nested layout root: a full Yoga engine mounted inside ANY GTK container\n// slot — an Adw.NavigationPage, a toolbar view content area, a future\n// gtk-components container. The slot's allocation is the layout viewport\n// (viewport-following; the initial 0×0 viewport is replaced synchronously\n// inside the first allocation pass, so nothing paints at zero). Attach is\n// the JSX mount; detach is the unmount — the engine is disposed with it.\n// Allocate passes of sibling/nested roots may overlap: the rect-store\n// tracks pass depth, so deferred GTK queue jobs run only after the\n// outermost pass ends.\nexport const NestedRoot = ({ children }: NestedRootProps) => (\n <Root\n width={0}\n height={0}\n followAllocation\n expand\n >\n {children}\n </Root>\n)\n\nexport type IntrinsicRootProps = {\n children?: ReactNode\n}\n\n// Content-sized layout root: unlike NestedRoot (which fills a slot), the\n// intrinsic root REPORTS its Yoga-computed content size to GTK — this is\n// what lets RN content live in size-to-content chrome slots (HeaderBar\n// start/end, sidebar rows). Measure runs a speculative uncommitted Yoga\n// pass (height honors the width constraint); the allocation pass then\n// recomputes at the real size and commits.\nexport const IntrinsicRoot = ({ children }: IntrinsicRootProps) => {\n const widgetRef = useRef<Gtk.Box | null>(null)\n const [engine] = useState<LayoutEngine>(\n () => new LayoutEngine({ width: 0, height: 0 }),\n )\n useEffect(\n () => () => {\n engine.dispose()\n },\n [engine],\n )\n const host = useMemo(\n () => ({ engine, node: engine.root, widgetRef }),\n [engine],\n )\n useRnContainer(widgetRef, engine.root, {\n measure: (orientation, forSize) =>\n engine.measureContent(orientation, forSize),\n beforeAllocate: (allocatedWidth, allocatedHeight) => {\n beginAllocatePass()\n try {\n engine.setViewport({ width: allocatedWidth, height: allocatedHeight })\n engine.flushSync()\n } finally {\n endAllocatePass()\n }\n },\n })\n return (\n <GtkBox ref={widgetRef}>\n <HostNodeContext.Provider value={host}>\n {children}\n </HostNodeContext.Provider>\n </GtkBox>\n )\n}\n"]}
1
+ {"version":3,"file":"root.js","sourceRoot":"","sources":["../../src/components/root.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from \"react\"\nimport { LayoutEngine } from \"../layout/index\"\nimport { GtkBox, queueResize, type Gtk } from \"../gtkx/bridge/index\"\nimport { HostNodeContext } from \"./host-node\"\nimport { beginAllocatePass, endAllocatePass } from \"./rect-store\"\nimport { useRnContainer } from \"./use-layout-child\"\n\nexport type RootProps = {\n width: number\n height: number\n // Window mode: report a zero minimum (the window may shrink freely) and\n // adopt whatever the window actually allocates as the engine viewport —\n // the allocation IS the layout viewport, headerbar excluded by GTK itself.\n followAllocation?: boolean\n // Claim the parent slot: a zero-minimum box inside a plain GTK container\n // gets no space unless it expands (window children fill implicitly, other\n // containers honor the expand flags).\n expand?: boolean\n children?: ReactNode\n}\n\n// Layout root: one engine per window (or per test harness). The root GtkBox\n// reports the engine viewport as its measure (via RnGtkxLayout) and is sized\n// by its parent (window/harness); the owner keeps the engine viewport in sync\n// (AppRegistry does it from window-size changes).\nexport const Root = ({\n width,\n height,\n followAllocation = false,\n expand = false,\n children,\n}: RootProps) => {\n const widgetRef = useRef<Gtk.Box | null>(null)\n\n // useState lazy init — see the note in use-layout-child.ts (React Compiler).\n const [engine] = useState<LayoutEngine>(\n () => new LayoutEngine({ width, height }),\n )\n\n useLayoutEffect(() => {\n if (followAllocation) {\n return\n }\n engine.setViewport({ width, height })\n // The viewport is this widget's measure — invalidate the cached one.\n const widget = widgetRef.current\n if (widget) {\n queueResize(widget)\n }\n }, [engine, followAllocation, width, height])\n\n useEffect(\n () => () => {\n engine.dispose()\n },\n [engine],\n )\n\n const host = useMemo(\n () => ({ engine, node: engine.root, widgetRef }),\n [engine],\n )\n\n useRnContainer(\n widgetRef,\n engine.root,\n followAllocation\n ? {\n measure: () => 0,\n beforeAllocate: (allocatedWidth, allocatedHeight) => {\n const current = engine.root.getRect()\n if (\n current &&\n current.width === allocatedWidth &&\n current.height === allocatedHeight\n ) {\n return\n }\n // Synchronous reflow inside the allocation pass: commits fill the\n // rect store now; their GTK queue calls are deferred past the pass.\n beginAllocatePass()\n try {\n engine.setViewport({\n width: allocatedWidth,\n height: allocatedHeight,\n })\n engine.flushSync()\n } finally {\n endAllocatePass()\n }\n },\n }\n : undefined,\n )\n\n return (\n <GtkBox\n ref={widgetRef}\n hexpand={expand}\n vexpand={expand}\n >\n <HostNodeContext.Provider value={host}>\n {children}\n </HostNodeContext.Provider>\n </GtkBox>\n )\n}\n\nexport type NestedRootProps = {\n children?: ReactNode\n}\n\n// Nested layout root: a full Yoga engine mounted inside ANY GTK container\n// slot — an Adw.NavigationPage, a toolbar view content area, a future\n// gtk-components container. The slot's allocation is the layout viewport\n// (viewport-following; the initial 0×0 viewport is replaced synchronously\n// inside the first allocation pass, so nothing paints at zero). Attach is\n// the JSX mount; detach is the unmount — the engine is disposed with it.\n// Allocate passes of sibling/nested roots may overlap: the rect-store\n// tracks pass depth, so deferred GTK queue jobs run only after the\n// outermost pass ends.\nexport const NestedRoot = ({ children }: NestedRootProps) => (\n <Root\n width={0}\n height={0}\n followAllocation\n expand\n >\n {children}\n </Root>\n)\n\nexport type IntrinsicRootProps = {\n children?: ReactNode\n}\n\n// Content-sized layout root: unlike NestedRoot (which fills a slot), the\n// intrinsic root REPORTS its Yoga-computed content size to GTK — this is\n// what lets RN content live in size-to-content chrome slots (HeaderBar\n// start/end, sidebar rows). Measure runs a speculative uncommitted Yoga\n// pass (height honors the width constraint); the allocation pass then\n// recomputes at the real size and commits.\nexport const IntrinsicRoot = ({ children }: IntrinsicRootProps) => {\n const widgetRef = useRef<Gtk.Box | null>(null)\n const [engine] = useState<LayoutEngine>(\n // `contentSized`: this root's own size REQUEST is its Yoga content size,\n // so unlike every other root a size change under it does reach the\n // toplevel. The animated-size carve-out reads the flag and keeps the\n // refusal here (docs/research/animated-size.md §4).\n () => new LayoutEngine({ width: 0, height: 0 }, { contentSized: true }),\n )\n useEffect(\n () => () => {\n engine.dispose()\n },\n [engine],\n )\n const host = useMemo(\n () => ({ engine, node: engine.root, widgetRef }),\n [engine],\n )\n useRnContainer(widgetRef, engine.root, {\n measure: (orientation, forSize) =>\n engine.measureContent(orientation, forSize),\n beforeAllocate: (allocatedWidth, allocatedHeight) => {\n beginAllocatePass()\n try {\n engine.setViewport({ width: allocatedWidth, height: allocatedHeight })\n engine.flushSync()\n } finally {\n endAllocatePass()\n }\n },\n })\n return (\n <GtkBox ref={widgetRef}>\n <HostNodeContext.Provider value={host}>\n {children}\n </HostNodeContext.Provider>\n </GtkBox>\n )\n}\n"]}
@@ -0,0 +1,35 @@
1
+ import type { ScrollEvent } from "./scroll-view";
2
+ /**
3
+ * The four phases RN reports around a scroll, in the order they can occur:
4
+ * the user starts driving the scroller, stops driving it, its own inertia
5
+ * takes over, its inertia runs out. What each one MEANS on GTK — and which
6
+ * input devices produce any of them at all — is measured in
7
+ * docs/research/scroll-phases.md.
8
+ */
9
+ export type ScrollPhase = "beginDrag" | "endDrag" | "momentumBegin" | "momentumEnd";
10
+ /**
11
+ * What a phase-aware handler offers a scrollable.
12
+ *
13
+ * `wants()` is separate from `deliver()` on purpose, and it is what keeps the
14
+ * machinery free: a Reanimated handler is one stable function whose handler
15
+ * OBJECT is rebuilt every render, so whether it currently asks for any phase
16
+ * is a question with a changing answer and no event to ask it on. A
17
+ * `ScrollView` asks it during render; while the answer is false it installs
18
+ * no GTK controller at all.
19
+ */
20
+ export type ScrollPhaseSink = {
21
+ /**
22
+ * Whether the handler wants any phase, or one phase in particular.
23
+ *
24
+ * The per-phase form lets ScrollView avoid handling every wheel detent for
25
+ * a consumer that asks only for momentum: a wheel has no momentum, while
26
+ * its begin/end pair is the desktop scroll-session extension documented in
27
+ * docs/research/scroll-phases.md.
28
+ */
29
+ wants(phase?: ScrollPhase): boolean;
30
+ deliver(phase: ScrollPhase, event: ScrollEvent): void;
31
+ };
32
+ /** @internal Marks `handler` as able to receive the phases. */
33
+ export declare const setScrollPhaseSink: (handler: object, sink: ScrollPhaseSink) => void;
34
+ /** @internal The phase sink `handler` carries, or null when it carries none. */
35
+ export declare const scrollPhaseSink: (handler: unknown) => ScrollPhaseSink | null;
@@ -0,0 +1,26 @@
1
+ /**
2
+ * The property a phase-aware handler carries. A string rather than a Symbol
3
+ * so that a handler built by one copy of the package is still understood by
4
+ * another — an app and a library can resolve different instances of
5
+ * `react-native-gtkx` through their own `node_modules`, and a Symbol would
6
+ * make those two silently stop talking.
7
+ *
8
+ * @internal
9
+ */
10
+ const PHASE_SINK = "__rnGtkxScrollPhaseSink";
11
+ /** @internal Marks `handler` as able to receive the phases. */
12
+ export const setScrollPhaseSink = (handler, sink) => {
13
+ ;
14
+ handler[PHASE_SINK] = sink;
15
+ };
16
+ /** @internal The phase sink `handler` carries, or null when it carries none. */
17
+ export const scrollPhaseSink = (handler) => {
18
+ if (handler === null || handler === undefined) {
19
+ return null;
20
+ }
21
+ if (typeof handler !== "function" && typeof handler !== "object") {
22
+ return null;
23
+ }
24
+ return handler[PHASE_SINK] ?? null;
25
+ };
26
+ //# sourceMappingURL=scroll-phase.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scroll-phase.js","sourceRoot":"","sources":["../../src/components/scroll-phase.ts"],"names":[],"mappings":"AAoDA;;;;;;;;GAQG;AACH,MAAM,UAAU,GAAG,yBAAyB,CAAA;AAI5C,+DAA+D;AAC/D,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAChC,OAAe,EACf,IAAqB,EACf,EAAE;IACR,CAAC;IAAC,OAAsB,CAAC,UAAU,CAAC,GAAG,IAAI,CAAA;AAC7C,CAAC,CAAA;AAED,gFAAgF;AAChF,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,OAAgB,EAA0B,EAAE;IAC1E,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC9C,OAAO,IAAI,CAAA;IACb,CAAC;IACD,IAAI,OAAO,OAAO,KAAK,UAAU,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QACjE,OAAO,IAAI,CAAA;IACb,CAAC;IACD,OAAQ,OAAsB,CAAC,UAAU,CAAC,IAAI,IAAI,CAAA;AACpD,CAAC,CAAA","sourcesContent":["// The seam between a scrollable's PHASE events and a handler object that\n// wants all of them through one prop.\n//\n// RN's `ScrollView` reports the phases as four separate props\n// (`onScrollBeginDrag` and friends) and an app writes them separately. A\n// Reanimated scroll handler is the other shape: `useAnimatedScrollHandler`\n// returns ONE value, an app writes `onScroll={handler}` and nothing else, and\n// on mobile the native side routes all five event names into it —\n// `@gorhom/bottom-sheet` does exactly that and passes no phase prop at all.\n//\n// So something has to fan one prop out into five callbacks, and on RN that\n// something is native. Here it is this: a scroll handler may carry a phase\n// SINK, and `ScrollView` delivers the phases into it as well as to its own\n// props. Both shapes work, neither knows about the other, and this module is\n// the only thing they share — which is why it lives in `components/` with no\n// import of its own. `reanimated-compat` may depend on the platform; the\n// platform may not depend on `reanimated-compat`.\nimport type { ScrollEvent } from \"./scroll-view\"\n\n/**\n * The four phases RN reports around a scroll, in the order they can occur:\n * the user starts driving the scroller, stops driving it, its own inertia\n * takes over, its inertia runs out. What each one MEANS on GTK — and which\n * input devices produce any of them at all — is measured in\n * docs/research/scroll-phases.md.\n */\nexport type ScrollPhase =\n \"beginDrag\" | \"endDrag\" | \"momentumBegin\" | \"momentumEnd\"\n\n/**\n * What a phase-aware handler offers a scrollable.\n *\n * `wants()` is separate from `deliver()` on purpose, and it is what keeps the\n * machinery free: a Reanimated handler is one stable function whose handler\n * OBJECT is rebuilt every render, so whether it currently asks for any phase\n * is a question with a changing answer and no event to ask it on. A\n * `ScrollView` asks it during render; while the answer is false it installs\n * no GTK controller at all.\n */\nexport type ScrollPhaseSink = {\n /**\n * Whether the handler wants any phase, or one phase in particular.\n *\n * The per-phase form lets ScrollView avoid handling every wheel detent for\n * a consumer that asks only for momentum: a wheel has no momentum, while\n * its begin/end pair is the desktop scroll-session extension documented in\n * docs/research/scroll-phases.md.\n */\n wants(phase?: ScrollPhase): boolean\n deliver(phase: ScrollPhase, event: ScrollEvent): void\n}\n\n/**\n * The property a phase-aware handler carries. A string rather than a Symbol\n * so that a handler built by one copy of the package is still understood by\n * another — an app and a library can resolve different instances of\n * `react-native-gtkx` through their own `node_modules`, and a Symbol would\n * make those two silently stop talking.\n *\n * @internal\n */\nconst PHASE_SINK = \"__rnGtkxScrollPhaseSink\"\n\ntype PhaseAware = { [PHASE_SINK]?: ScrollPhaseSink | null }\n\n/** @internal Marks `handler` as able to receive the phases. */\nexport const setScrollPhaseSink = (\n handler: object,\n sink: ScrollPhaseSink,\n): void => {\n ;(handler as PhaseAware)[PHASE_SINK] = sink\n}\n\n/** @internal The phase sink `handler` carries, or null when it carries none. */\nexport const scrollPhaseSink = (handler: unknown): ScrollPhaseSink | null => {\n if (handler === null || handler === undefined) {\n return null\n }\n if (typeof handler !== \"function\" && typeof handler !== \"object\") {\n return null\n }\n return (handler as PhaseAware)[PHASE_SINK] ?? null\n}\n"]}
@@ -1,8 +1,15 @@
1
1
  import { type ReactNode } from "react";
2
2
  import type { StyleProp } from "../contracts";
3
3
  import { Gtk } from "../gtkx/bridge/index";
4
+ import type { ResponderProps } from "../responder/types";
5
+ import { type MeasureHandle } from "./measure";
4
6
  import { type LayoutEvent } from "./use-layout-child";
5
- export type ScrollViewHandle = {
7
+ /**
8
+ * The scroll half on its own, because the windowed list core builds its own
9
+ * handle on top of it and is a COMPOSITE — it owns no widget, so it has no
10
+ * honest geometry to report and does not claim any.
11
+ */
12
+ export type ScrollHandle = {
6
13
  scrollTo(options: {
7
14
  x?: number;
8
15
  y?: number;
@@ -12,6 +19,7 @@ export type ScrollViewHandle = {
12
19
  animated?: boolean;
13
20
  }): void;
14
21
  };
22
+ export type ScrollViewHandle = MeasureHandle & ScrollHandle;
15
23
  export type ScrollEvent = {
16
24
  nativeEvent: {
17
25
  contentOffset: {
@@ -28,12 +36,26 @@ export type ScrollEvent = {
28
36
  };
29
37
  };
30
38
  };
31
- export type ScrollViewProps = {
39
+ /**
40
+ * `ResponderProps` because a `ScrollView` is a HOST component in RN, and every
41
+ * host component takes them. It matters more here than it reads: a
42
+ * `GestureDetector` reaches its child through the child's own responder
43
+ * registration, so a scrollable that did not accept them could never carry a
44
+ * gesture — and `Gesture.Native()` exists precisely to put a scrollable into
45
+ * the arbitration (`@gorhom/bottom-sheet` wraps its scrollable in exactly that
46
+ * shape). `useResponder` installs nothing unless some responder prop is
47
+ * actually present, so a plain `ScrollView` gains no controller.
48
+ */
49
+ export type ScrollViewProps = ResponderProps & {
32
50
  style?: StyleProp;
33
51
  contentContainerStyle?: StyleProp;
34
52
  horizontal?: boolean;
35
53
  stickyHeaderIndices?: readonly number[];
36
54
  onScroll?: (event: ScrollEvent) => void;
55
+ onScrollBeginDrag?: (event: ScrollEvent) => void;
56
+ onScrollEndDrag?: (event: ScrollEvent) => void;
57
+ onMomentumScrollBegin?: (event: ScrollEvent) => void;
58
+ onMomentumScrollEnd?: (event: ScrollEvent) => void;
37
59
  onContentSizeChange?: (width: number, height: number) => void;
38
60
  onLayout?: (event: LayoutEvent) => void;
39
61
  children?: ReactNode;
@@ -56,5 +78,19 @@ export declare const StickySlot: ({ stickyKey, style, top, onLayout, children, }
56
78
  onLayout?: (event: LayoutEvent) => void;
57
79
  children?: ReactNode;
58
80
  }) => React.JSX.Element;
59
- export declare const ScrollView: React.ForwardRefExoticComponent<ScrollViewProps & React.RefAttributes<ScrollViewHandle>>;
81
+ export declare const ScrollView: React.ForwardRefExoticComponent<ResponderProps & {
82
+ style?: StyleProp;
83
+ contentContainerStyle?: StyleProp;
84
+ horizontal?: boolean;
85
+ stickyHeaderIndices?: readonly number[];
86
+ onScroll?: (event: ScrollEvent) => void;
87
+ onScrollBeginDrag?: (event: ScrollEvent) => void;
88
+ onScrollEndDrag?: (event: ScrollEvent) => void;
89
+ onMomentumScrollBegin?: (event: ScrollEvent) => void;
90
+ onMomentumScrollEnd?: (event: ScrollEvent) => void;
91
+ onContentSizeChange?: (width: number, height: number) => void;
92
+ onLayout?: (event: LayoutEvent) => void;
93
+ children?: ReactNode;
94
+ testID?: string;
95
+ } & React.RefAttributes<ScrollViewHandle>>;
60
96
  export {};