react-native-layout-dnd 0.1.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (340) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +262 -0
  3. package/lib/module/adapters/coordinates.js +135 -0
  4. package/lib/module/adapters/coordinates.js.map +1 -0
  5. package/lib/module/adapters/scroll.js +81 -0
  6. package/lib/module/adapters/scroll.js.map +1 -0
  7. package/lib/module/adapters/virtualizedList.js +69 -0
  8. package/lib/module/adapters/virtualizedList.js.map +1 -0
  9. package/lib/module/components/DndProvider.js +1144 -0
  10. package/lib/module/components/DndProvider.js.map +1 -0
  11. package/lib/module/components/DragHandle.js +65 -0
  12. package/lib/module/components/DragHandle.js.map +1 -0
  13. package/lib/module/components/GridController.js +151 -0
  14. package/lib/module/components/GridController.js.map +1 -0
  15. package/lib/module/components/GridDragHandle.js +15 -0
  16. package/lib/module/components/GridDragHandle.js.map +1 -0
  17. package/lib/module/components/GridZoneView.js +59 -0
  18. package/lib/module/components/GridZoneView.js.map +1 -0
  19. package/lib/module/components/SortableGrid.js +305 -0
  20. package/lib/module/components/SortableGrid.js.map +1 -0
  21. package/lib/module/components/SortableList.js +714 -0
  22. package/lib/module/components/SortableList.js.map +1 -0
  23. package/lib/module/components/dndTypes.js +4 -0
  24. package/lib/module/components/dndTypes.js.map +1 -0
  25. package/lib/module/components/gridTypes.js +4 -0
  26. package/lib/module/components/gridTypes.js.map +1 -0
  27. package/lib/module/components/handleViewProps.js +13 -0
  28. package/lib/module/components/handleViewProps.js.map +1 -0
  29. package/lib/module/contracts.js +4 -0
  30. package/lib/module/contracts.js.map +1 -0
  31. package/lib/module/controller/approval.js +98 -0
  32. package/lib/module/controller/approval.js.map +1 -0
  33. package/lib/module/controller/coordinatorBase.js +93 -0
  34. package/lib/module/controller/coordinatorBase.js.map +1 -0
  35. package/lib/module/controller/dndSession.js +621 -0
  36. package/lib/module/controller/dndSession.js.map +1 -0
  37. package/lib/module/controller/dndState.js +103 -0
  38. package/lib/module/controller/dndState.js.map +1 -0
  39. package/lib/module/controller/gridAdapter.js +191 -0
  40. package/lib/module/controller/gridAdapter.js.map +1 -0
  41. package/lib/module/controller/gridState.js +101 -0
  42. package/lib/module/controller/gridState.js.map +1 -0
  43. package/lib/module/controller/locations.js +48 -0
  44. package/lib/module/controller/locations.js.map +1 -0
  45. package/lib/module/controller/previewPath.js +73 -0
  46. package/lib/module/controller/previewPath.js.map +1 -0
  47. package/lib/module/controller/sessionCore.js +222 -0
  48. package/lib/module/controller/sessionCore.js.map +1 -0
  49. package/lib/module/controller/useDndState.js +9 -0
  50. package/lib/module/controller/useDndState.js.map +1 -0
  51. package/lib/module/controller/useGridState.js +9 -0
  52. package/lib/module/controller/useGridState.js.map +1 -0
  53. package/lib/module/controller/useStoreState.js +15 -0
  54. package/lib/module/controller/useStoreState.js.map +1 -0
  55. package/lib/module/defaults.js +7 -0
  56. package/lib/module/defaults.js.map +1 -0
  57. package/lib/module/diagnostics.js +16 -0
  58. package/lib/module/diagnostics.js.map +1 -0
  59. package/lib/module/engine/gridPlacements.js +54 -0
  60. package/lib/module/engine/gridPlacements.js.map +1 -0
  61. package/lib/module/engine/index.js +19 -0
  62. package/lib/module/engine/index.js.map +1 -0
  63. package/lib/module/engine/layout.js +36 -0
  64. package/lib/module/engine/layout.js.map +1 -0
  65. package/lib/module/engine/layoutMove.js +326 -0
  66. package/lib/module/engine/layoutMove.js.map +1 -0
  67. package/lib/module/engine/layoutState.js +344 -0
  68. package/lib/module/engine/layoutState.js.map +1 -0
  69. package/lib/module/engine/list.js +172 -0
  70. package/lib/module/engine/list.js.map +1 -0
  71. package/lib/module/engine/listIndex.js +125 -0
  72. package/lib/module/engine/listIndex.js.map +1 -0
  73. package/lib/module/engine/move.js +216 -0
  74. package/lib/module/engine/move.js.map +1 -0
  75. package/lib/module/engine/movementPolicy.js +77 -0
  76. package/lib/module/engine/movementPolicy.js.map +1 -0
  77. package/lib/module/engine/orderedTarget.js +71 -0
  78. package/lib/module/engine/orderedTarget.js.map +1 -0
  79. package/lib/module/engine/pack.js +30 -0
  80. package/lib/module/engine/pack.js.map +1 -0
  81. package/lib/module/engine/rectangles.js +12 -0
  82. package/lib/module/engine/rectangles.js.map +1 -0
  83. package/lib/module/engine/sameLayout.js +29 -0
  84. package/lib/module/engine/sameLayout.js.map +1 -0
  85. package/lib/module/engine/search.js +159 -0
  86. package/lib/module/engine/search.js.map +1 -0
  87. package/lib/module/engine/spatial.js +27 -0
  88. package/lib/module/engine/spatial.js.map +1 -0
  89. package/lib/module/engine/spatialAppRotation.js +39 -0
  90. package/lib/module/engine/spatialAppRotation.js.map +1 -0
  91. package/lib/module/engine/spatialExchange.js +164 -0
  92. package/lib/module/engine/spatialExchange.js.map +1 -0
  93. package/lib/module/engine/spatialInsertion.js +135 -0
  94. package/lib/module/engine/spatialInsertion.js.map +1 -0
  95. package/lib/module/engine/spatialPolicy.js +41 -0
  96. package/lib/module/engine/spatialPolicy.js.map +1 -0
  97. package/lib/module/engine/spatialRotation.js +48 -0
  98. package/lib/module/engine/spatialRotation.js.map +1 -0
  99. package/lib/module/engine/validation.js +205 -0
  100. package/lib/module/engine/validation.js.map +1 -0
  101. package/lib/module/gesture/DndGestureGroup.js +268 -0
  102. package/lib/module/gesture/DndGestureGroup.js.map +1 -0
  103. package/lib/module/gesture/DndGestureHost.js +32 -0
  104. package/lib/module/gesture/DndGestureHost.js.map +1 -0
  105. package/lib/module/gesture/gestureConfig.js +81 -0
  106. package/lib/module/gesture/gestureConfig.js.map +1 -0
  107. package/lib/module/gesture/gestureGrouping.js +122 -0
  108. package/lib/module/gesture/gestureGrouping.js.map +1 -0
  109. package/lib/module/gesture/gestureHost.js +106 -0
  110. package/lib/module/gesture/gestureHost.js.map +1 -0
  111. package/lib/module/index.js +23 -0
  112. package/lib/module/index.js.map +1 -0
  113. package/lib/module/package.json +1 -0
  114. package/lib/module/pointer/dndTarget.js +101 -0
  115. package/lib/module/pointer/dndTarget.js.map +1 -0
  116. package/lib/module/pointer/geometry.js +363 -0
  117. package/lib/module/pointer/geometry.js.map +1 -0
  118. package/lib/module/pointer/layoutTarget.js +307 -0
  119. package/lib/module/pointer/layoutTarget.js.map +1 -0
  120. package/lib/module/pointer/listCellMotion.js +99 -0
  121. package/lib/module/pointer/listCellMotion.js.map +1 -0
  122. package/lib/module/pointer/listTarget.js +42 -0
  123. package/lib/module/pointer/listTarget.js.map +1 -0
  124. package/lib/module/pointer/motion.js +37 -0
  125. package/lib/module/pointer/motion.js.map +1 -0
  126. package/lib/module/runtime/dndPresentation.js +81 -0
  127. package/lib/module/runtime/dndPresentation.js.map +1 -0
  128. package/lib/module/runtime/dndRenderStore.js +129 -0
  129. package/lib/module/runtime/dndRenderStore.js.map +1 -0
  130. package/lib/module/runtime/dndRuntime.js +135 -0
  131. package/lib/module/runtime/dndRuntime.js.map +1 -0
  132. package/lib/module/runtime/dndSettlement.js +77 -0
  133. package/lib/module/runtime/dndSettlement.js.map +1 -0
  134. package/lib/module/runtime/gridRuntime.js +37 -0
  135. package/lib/module/runtime/gridRuntime.js.map +1 -0
  136. package/lib/module/types.js +4 -0
  137. package/lib/module/types.js.map +1 -0
  138. package/lib/typescript/package.json +1 -0
  139. package/lib/typescript/src/adapters/coordinates.d.ts +9 -0
  140. package/lib/typescript/src/adapters/coordinates.d.ts.map +1 -0
  141. package/lib/typescript/src/adapters/scroll.d.ts +49 -0
  142. package/lib/typescript/src/adapters/scroll.d.ts.map +1 -0
  143. package/lib/typescript/src/adapters/virtualizedList.d.ts +22 -0
  144. package/lib/typescript/src/adapters/virtualizedList.d.ts.map +1 -0
  145. package/lib/typescript/src/components/DndProvider.d.ts +4 -0
  146. package/lib/typescript/src/components/DndProvider.d.ts.map +1 -0
  147. package/lib/typescript/src/components/DragHandle.d.ts +4 -0
  148. package/lib/typescript/src/components/DragHandle.d.ts.map +1 -0
  149. package/lib/typescript/src/components/GridController.d.ts +21 -0
  150. package/lib/typescript/src/components/GridController.d.ts.map +1 -0
  151. package/lib/typescript/src/components/GridDragHandle.d.ts +8 -0
  152. package/lib/typescript/src/components/GridDragHandle.d.ts.map +1 -0
  153. package/lib/typescript/src/components/GridZoneView.d.ts +8 -0
  154. package/lib/typescript/src/components/GridZoneView.d.ts.map +1 -0
  155. package/lib/typescript/src/components/SortableGrid.d.ts +4 -0
  156. package/lib/typescript/src/components/SortableGrid.d.ts.map +1 -0
  157. package/lib/typescript/src/components/SortableList.d.ts +4 -0
  158. package/lib/typescript/src/components/SortableList.d.ts.map +1 -0
  159. package/lib/typescript/src/components/dndTypes.d.ts +94 -0
  160. package/lib/typescript/src/components/dndTypes.d.ts.map +1 -0
  161. package/lib/typescript/src/components/gridTypes.d.ts +84 -0
  162. package/lib/typescript/src/components/gridTypes.d.ts.map +1 -0
  163. package/lib/typescript/src/components/handleViewProps.d.ts +6 -0
  164. package/lib/typescript/src/components/handleViewProps.d.ts.map +1 -0
  165. package/lib/typescript/src/contracts.d.ts +145 -0
  166. package/lib/typescript/src/contracts.d.ts.map +1 -0
  167. package/lib/typescript/src/controller/approval.d.ts +66 -0
  168. package/lib/typescript/src/controller/approval.d.ts.map +1 -0
  169. package/lib/typescript/src/controller/coordinatorBase.d.ts +37 -0
  170. package/lib/typescript/src/controller/coordinatorBase.d.ts.map +1 -0
  171. package/lib/typescript/src/controller/dndSession.d.ts +152 -0
  172. package/lib/typescript/src/controller/dndSession.d.ts.map +1 -0
  173. package/lib/typescript/src/controller/dndState.d.ts +27 -0
  174. package/lib/typescript/src/controller/dndState.d.ts.map +1 -0
  175. package/lib/typescript/src/controller/gridAdapter.d.ts +44 -0
  176. package/lib/typescript/src/controller/gridAdapter.d.ts.map +1 -0
  177. package/lib/typescript/src/controller/gridState.d.ts +18 -0
  178. package/lib/typescript/src/controller/gridState.d.ts.map +1 -0
  179. package/lib/typescript/src/controller/locations.d.ts +9 -0
  180. package/lib/typescript/src/controller/locations.d.ts.map +1 -0
  181. package/lib/typescript/src/controller/previewPath.d.ts +49 -0
  182. package/lib/typescript/src/controller/previewPath.d.ts.map +1 -0
  183. package/lib/typescript/src/controller/sessionCore.d.ts +106 -0
  184. package/lib/typescript/src/controller/sessionCore.d.ts.map +1 -0
  185. package/lib/typescript/src/controller/useDndState.d.ts +8 -0
  186. package/lib/typescript/src/controller/useDndState.d.ts.map +1 -0
  187. package/lib/typescript/src/controller/useGridState.d.ts +8 -0
  188. package/lib/typescript/src/controller/useGridState.d.ts.map +1 -0
  189. package/lib/typescript/src/controller/useStoreState.d.ts +16 -0
  190. package/lib/typescript/src/controller/useStoreState.d.ts.map +1 -0
  191. package/lib/typescript/src/defaults.d.ts +5 -0
  192. package/lib/typescript/src/defaults.d.ts.map +1 -0
  193. package/lib/typescript/src/diagnostics.d.ts +9 -0
  194. package/lib/typescript/src/diagnostics.d.ts.map +1 -0
  195. package/lib/typescript/src/engine/gridPlacements.d.ts +22 -0
  196. package/lib/typescript/src/engine/gridPlacements.d.ts.map +1 -0
  197. package/lib/typescript/src/engine/index.d.ts +28 -0
  198. package/lib/typescript/src/engine/index.d.ts.map +1 -0
  199. package/lib/typescript/src/engine/layout.d.ts +4 -0
  200. package/lib/typescript/src/engine/layout.d.ts.map +1 -0
  201. package/lib/typescript/src/engine/layoutMove.d.ts +46 -0
  202. package/lib/typescript/src/engine/layoutMove.d.ts.map +1 -0
  203. package/lib/typescript/src/engine/layoutState.d.ts +22 -0
  204. package/lib/typescript/src/engine/layoutState.d.ts.map +1 -0
  205. package/lib/typescript/src/engine/list.d.ts +68 -0
  206. package/lib/typescript/src/engine/list.d.ts.map +1 -0
  207. package/lib/typescript/src/engine/listIndex.d.ts +32 -0
  208. package/lib/typescript/src/engine/listIndex.d.ts.map +1 -0
  209. package/lib/typescript/src/engine/move.d.ts +10 -0
  210. package/lib/typescript/src/engine/move.d.ts.map +1 -0
  211. package/lib/typescript/src/engine/movementPolicy.d.ts +34 -0
  212. package/lib/typescript/src/engine/movementPolicy.d.ts.map +1 -0
  213. package/lib/typescript/src/engine/orderedTarget.d.ts +32 -0
  214. package/lib/typescript/src/engine/orderedTarget.d.ts.map +1 -0
  215. package/lib/typescript/src/engine/pack.d.ts +3 -0
  216. package/lib/typescript/src/engine/pack.d.ts.map +1 -0
  217. package/lib/typescript/src/engine/rectangles.d.ts +9 -0
  218. package/lib/typescript/src/engine/rectangles.d.ts.map +1 -0
  219. package/lib/typescript/src/engine/sameLayout.d.ts +4 -0
  220. package/lib/typescript/src/engine/sameLayout.d.ts.map +1 -0
  221. package/lib/typescript/src/engine/search.d.ts +28 -0
  222. package/lib/typescript/src/engine/search.d.ts.map +1 -0
  223. package/lib/typescript/src/engine/spatial.d.ts +16 -0
  224. package/lib/typescript/src/engine/spatial.d.ts.map +1 -0
  225. package/lib/typescript/src/engine/spatialAppRotation.d.ts +4 -0
  226. package/lib/typescript/src/engine/spatialAppRotation.d.ts.map +1 -0
  227. package/lib/typescript/src/engine/spatialExchange.d.ts +5 -0
  228. package/lib/typescript/src/engine/spatialExchange.d.ts.map +1 -0
  229. package/lib/typescript/src/engine/spatialInsertion.d.ts +5 -0
  230. package/lib/typescript/src/engine/spatialInsertion.d.ts.map +1 -0
  231. package/lib/typescript/src/engine/spatialPolicy.d.ts +9 -0
  232. package/lib/typescript/src/engine/spatialPolicy.d.ts.map +1 -0
  233. package/lib/typescript/src/engine/spatialRotation.d.ts +8 -0
  234. package/lib/typescript/src/engine/spatialRotation.d.ts.map +1 -0
  235. package/lib/typescript/src/engine/validation.d.ts +9 -0
  236. package/lib/typescript/src/engine/validation.d.ts.map +1 -0
  237. package/lib/typescript/src/gesture/DndGestureGroup.d.ts +33 -0
  238. package/lib/typescript/src/gesture/DndGestureGroup.d.ts.map +1 -0
  239. package/lib/typescript/src/gesture/DndGestureHost.d.ts +12 -0
  240. package/lib/typescript/src/gesture/DndGestureHost.d.ts.map +1 -0
  241. package/lib/typescript/src/gesture/gestureConfig.d.ts +15 -0
  242. package/lib/typescript/src/gesture/gestureConfig.d.ts.map +1 -0
  243. package/lib/typescript/src/gesture/gestureGrouping.d.ts +66 -0
  244. package/lib/typescript/src/gesture/gestureGrouping.d.ts.map +1 -0
  245. package/lib/typescript/src/gesture/gestureHost.d.ts +23 -0
  246. package/lib/typescript/src/gesture/gestureHost.d.ts.map +1 -0
  247. package/lib/typescript/src/index.d.ts +38 -0
  248. package/lib/typescript/src/index.d.ts.map +1 -0
  249. package/lib/typescript/src/pointer/dndTarget.d.ts +14 -0
  250. package/lib/typescript/src/pointer/dndTarget.d.ts.map +1 -0
  251. package/lib/typescript/src/pointer/geometry.d.ts +28 -0
  252. package/lib/typescript/src/pointer/geometry.d.ts.map +1 -0
  253. package/lib/typescript/src/pointer/layoutTarget.d.ts +43 -0
  254. package/lib/typescript/src/pointer/layoutTarget.d.ts.map +1 -0
  255. package/lib/typescript/src/pointer/listCellMotion.d.ts +43 -0
  256. package/lib/typescript/src/pointer/listCellMotion.d.ts.map +1 -0
  257. package/lib/typescript/src/pointer/listTarget.d.ts +7 -0
  258. package/lib/typescript/src/pointer/listTarget.d.ts.map +1 -0
  259. package/lib/typescript/src/pointer/motion.d.ts +20 -0
  260. package/lib/typescript/src/pointer/motion.d.ts.map +1 -0
  261. package/lib/typescript/src/runtime/dndPresentation.d.ts +37 -0
  262. package/lib/typescript/src/runtime/dndPresentation.d.ts.map +1 -0
  263. package/lib/typescript/src/runtime/dndRenderStore.d.ts +46 -0
  264. package/lib/typescript/src/runtime/dndRenderStore.d.ts.map +1 -0
  265. package/lib/typescript/src/runtime/dndRuntime.d.ts +138 -0
  266. package/lib/typescript/src/runtime/dndRuntime.d.ts.map +1 -0
  267. package/lib/typescript/src/runtime/dndSettlement.d.ts +18 -0
  268. package/lib/typescript/src/runtime/dndSettlement.d.ts.map +1 -0
  269. package/lib/typescript/src/runtime/gridRuntime.d.ts +54 -0
  270. package/lib/typescript/src/runtime/gridRuntime.d.ts.map +1 -0
  271. package/lib/typescript/src/types.d.ts +180 -0
  272. package/lib/typescript/src/types.d.ts.map +1 -0
  273. package/package.json +136 -0
  274. package/src/adapters/coordinates.ts +181 -0
  275. package/src/adapters/scroll.ts +147 -0
  276. package/src/adapters/virtualizedList.ts +112 -0
  277. package/src/components/DndProvider.tsx +1836 -0
  278. package/src/components/DragHandle.tsx +89 -0
  279. package/src/components/GridController.tsx +213 -0
  280. package/src/components/GridDragHandle.tsx +11 -0
  281. package/src/components/GridZoneView.tsx +57 -0
  282. package/src/components/SortableGrid.tsx +449 -0
  283. package/src/components/SortableList.tsx +1028 -0
  284. package/src/components/dndTypes.ts +102 -0
  285. package/src/components/gridTypes.ts +90 -0
  286. package/src/components/handleViewProps.ts +35 -0
  287. package/src/contracts.ts +149 -0
  288. package/src/controller/approval.ts +179 -0
  289. package/src/controller/coordinatorBase.ts +118 -0
  290. package/src/controller/dndSession.ts +1058 -0
  291. package/src/controller/dndState.ts +198 -0
  292. package/src/controller/gridAdapter.ts +268 -0
  293. package/src/controller/gridState.ts +187 -0
  294. package/src/controller/locations.ts +67 -0
  295. package/src/controller/previewPath.ts +90 -0
  296. package/src/controller/sessionCore.ts +390 -0
  297. package/src/controller/useDndState.ts +26 -0
  298. package/src/controller/useGridState.ts +22 -0
  299. package/src/controller/useStoreState.ts +27 -0
  300. package/src/defaults.ts +4 -0
  301. package/src/diagnostics.ts +23 -0
  302. package/src/engine/gridPlacements.ts +85 -0
  303. package/src/engine/index.ts +99 -0
  304. package/src/engine/layout.ts +29 -0
  305. package/src/engine/layoutMove.ts +401 -0
  306. package/src/engine/layoutState.ts +490 -0
  307. package/src/engine/list.ts +307 -0
  308. package/src/engine/listIndex.ts +174 -0
  309. package/src/engine/move.ts +274 -0
  310. package/src/engine/movementPolicy.ts +151 -0
  311. package/src/engine/orderedTarget.ts +131 -0
  312. package/src/engine/pack.ts +24 -0
  313. package/src/engine/rectangles.ts +18 -0
  314. package/src/engine/sameLayout.ts +50 -0
  315. package/src/engine/search.ts +174 -0
  316. package/src/engine/spatial.ts +36 -0
  317. package/src/engine/spatialAppRotation.ts +53 -0
  318. package/src/engine/spatialExchange.ts +212 -0
  319. package/src/engine/spatialInsertion.ts +157 -0
  320. package/src/engine/spatialPolicy.ts +48 -0
  321. package/src/engine/spatialRotation.ts +56 -0
  322. package/src/engine/validation.ts +358 -0
  323. package/src/gesture/DndGestureGroup.tsx +357 -0
  324. package/src/gesture/DndGestureHost.tsx +50 -0
  325. package/src/gesture/gestureConfig.ts +123 -0
  326. package/src/gesture/gestureGrouping.ts +210 -0
  327. package/src/gesture/gestureHost.tsx +163 -0
  328. package/src/index.ts +162 -0
  329. package/src/pointer/dndTarget.ts +213 -0
  330. package/src/pointer/geometry.ts +584 -0
  331. package/src/pointer/layoutTarget.ts +515 -0
  332. package/src/pointer/listCellMotion.ts +174 -0
  333. package/src/pointer/listTarget.ts +56 -0
  334. package/src/pointer/motion.ts +66 -0
  335. package/src/runtime/dndPresentation.ts +113 -0
  336. package/src/runtime/dndRenderStore.ts +246 -0
  337. package/src/runtime/dndRuntime.ts +311 -0
  338. package/src/runtime/dndSettlement.ts +117 -0
  339. package/src/runtime/gridRuntime.ts +73 -0
  340. package/src/types.ts +189 -0
@@ -0,0 +1,357 @@
1
+ import { useLayoutEffect, useMemo, useRef } from 'react';
2
+ import type { HostInstance } from 'react-native';
3
+ import {
4
+ GestureStateManager,
5
+ usePanGesture,
6
+ type PanGestureConfig,
7
+ } from 'react-native-gesture-handler';
8
+ import {
9
+ useSharedValue,
10
+ type AnimatedRef,
11
+ type SharedValue,
12
+ } from 'react-native-reanimated';
13
+ import { scheduleOnRN } from 'react-native-worklets';
14
+
15
+ import { constrainDragPoint } from '../adapters/scroll';
16
+ import {
17
+ EMPTY_DND_MOTION,
18
+ measureDndRect,
19
+ pointInRect,
20
+ readListViewports,
21
+ type DndMotion,
22
+ type DndRuntime,
23
+ } from '../runtime/dndRuntime';
24
+ import {
25
+ createTargetChannel as createChannel,
26
+ type GestureGroupProps,
27
+ type PublishedTargetChannel,
28
+ } from './gestureGrouping';
29
+
30
+ export type DndGestureRuntime = Pick<
31
+ DndRuntime,
32
+ | 'motion'
33
+ | 'token'
34
+ | 'zones'
35
+ | 'disabled'
36
+ | 'rootRef'
37
+ | 'begin'
38
+ | 'move'
39
+ | 'release'
40
+ | 'dragAxis'
41
+ | 'activationDelayMs'
42
+ | 'gestureConfigRevision'
43
+ | 'frameDriven'
44
+ > & {
45
+ enabled: SharedValue<boolean>;
46
+ revision: number | SharedValue<number>;
47
+ prepareRelease?(state: DndMotion): void;
48
+ };
49
+
50
+ /**
51
+ * UI-thread hit target of one registered handle. The host keeps the object
52
+ * identical while its registration is unchanged, so Worklets reuses the
53
+ * serialized copy when the group's target list is published again.
54
+ */
55
+ export type DndHandleTarget = {
56
+ id: number;
57
+ itemId: string;
58
+ zoneId: string;
59
+ ref: AnimatedRef<HostInstance>;
60
+ sourceRef: AnimatedRef<HostInstance>;
61
+ disabled: boolean;
62
+ };
63
+
64
+ /** Delivers a group's hit targets without re-rendering the group. */
65
+ export function createTargetChannel(
66
+ initial: readonly DndHandleTarget[],
67
+ ): PublishedTargetChannel<DndHandleTarget> {
68
+ return createChannel(initial);
69
+ }
70
+
71
+ export type DndGestureGroupProps = GestureGroupProps<
72
+ DndGestureRuntime,
73
+ DndHandleTarget
74
+ >;
75
+
76
+ /**
77
+ * One native Pan serves every handle that shares a gesture relation signature.
78
+ * The recognizer belongs to the Provider, so a source cell can leave the
79
+ * virtualized window or remount without touching the active gesture; the hit
80
+ * target list only decides which handle an initial touch may activate.
81
+ */
82
+ export function DndGestureGroup({
83
+ groupId,
84
+ relations,
85
+ channel,
86
+ runtime,
87
+ publish,
88
+ }: DndGestureGroupProps) {
89
+ const ownToken = useSharedValue(0);
90
+ const ownHandle = useSharedValue(-1);
91
+ const uiTargets = useSharedValue<readonly DndHandleTarget[]>(channel.targets);
92
+ const publishedTargets = useRef(channel.targets);
93
+ useLayoutEffect(() => {
94
+ const sync = (targets: readonly DndHandleTarget[]) => {
95
+ if (publishedTargets.current === targets) return;
96
+ publishedTargets.current = targets;
97
+ uiTargets.set(targets);
98
+ };
99
+ sync(channel.targets);
100
+ return channel.subscribe(sync);
101
+ }, [channel, uiTargets]);
102
+ const {
103
+ motion,
104
+ token,
105
+ zones,
106
+ disabled: providerDisabled,
107
+ rootRef,
108
+ begin,
109
+ move,
110
+ release,
111
+ prepareRelease,
112
+ dragAxis,
113
+ revision,
114
+ activationDelayMs,
115
+ gestureConfigRevision,
116
+ frameDriven,
117
+ enabled,
118
+ } = runtime;
119
+ const config = useMemo<PanGestureConfig>(() => {
120
+ const currentRevision = () => {
121
+ 'worklet';
122
+ return typeof revision === 'number' ? revision : revision.get();
123
+ };
124
+ // Every provider-owned recognizer receives the initial root touch. Find the
125
+ // enabled handle under the pointer before measuring the root or any scroll
126
+ // viewport; a handle that does not contain the pointer costs one measure.
127
+ const hit = (
128
+ x: number,
129
+ y: number,
130
+ committedRevision: number,
131
+ ): DndHandleTarget | null => {
132
+ 'worklet';
133
+ if (!Number.isFinite(x) || !Number.isFinite(y) || providerDisabled.get())
134
+ return null;
135
+ const pointer = { x, y };
136
+ const list = uiTargets.get();
137
+ let target: DndHandleTarget | null = null;
138
+ for (let index = 0; index < list.length; index++) {
139
+ const candidate = list[index]!;
140
+ if (candidate.disabled) continue;
141
+ const handle = measureDndRect(candidate.ref);
142
+ if (handle && pointInRect(pointer, handle)) {
143
+ target = candidate;
144
+ break;
145
+ }
146
+ }
147
+ if (!target) return null;
148
+ const root = measureDndRect(rootRef);
149
+ if (!root || !pointInRect(pointer, root)) return null;
150
+ const sourceZoneId = target.zoneId;
151
+ const source = zones.get().find(zone => zone.zoneId === sourceZoneId);
152
+ if (
153
+ !source ||
154
+ source.revision !== committedRevision ||
155
+ (source.kind === 'list' && !Number.isFinite(source.offset.get()))
156
+ )
157
+ return null;
158
+ const viewport = measureDndRect(source.ref);
159
+ return viewport && pointInRect(pointer, viewport) ? target : null;
160
+ };
161
+ const owned = (current: DndMotion) => {
162
+ 'worklet';
163
+ return (
164
+ current.phase === 'dragging' &&
165
+ current.token === ownToken.get() &&
166
+ current.handleId === ownHandle.get()
167
+ );
168
+ };
169
+ const cancelOwned = () => {
170
+ 'worklet';
171
+ const current = motion.get();
172
+ if (!owned(current)) return;
173
+ const next: DndMotion = {
174
+ ...current,
175
+ phase: 'released',
176
+ seq: current.seq + 1,
177
+ };
178
+ motion.set(next);
179
+ scheduleOnRN(release, next, true);
180
+ };
181
+ return {
182
+ block: relations?.block,
183
+ requireToFail: relations?.requireToFail,
184
+ simultaneousWith: relations?.simultaneousWith,
185
+ enabled,
186
+ maxPointers: 1,
187
+ activateAfterLongPress: activationDelayMs,
188
+ cancelsTouchesInView: true,
189
+ onBegin: () => {
190
+ 'worklet';
191
+ ownToken.set(0);
192
+ ownHandle.set(-1);
193
+ },
194
+ onTouchesDown: event => {
195
+ 'worklet';
196
+ if (event.numberOfTouches > 1) {
197
+ cancelOwned();
198
+ GestureStateManager.fail(event.handlerTag);
199
+ return;
200
+ }
201
+ const touch = event.changedTouches[0];
202
+ // Root-attached recognizers must restrict activation to a visible handle.
203
+ if (
204
+ !touch ||
205
+ !hit(touch.absoluteX, touch.absoluteY, currentRevision()) ||
206
+ motion.get().phase !== 'idle'
207
+ ) {
208
+ GestureStateManager.fail(event.handlerTag);
209
+ }
210
+ },
211
+ onActivate: event => {
212
+ 'worklet';
213
+ // Read committed state at activation without rebuilding the native
214
+ // handler when another drop advances the layout revision.
215
+ const committedRevision = currentRevision();
216
+ const target =
217
+ motion.get().phase === 'idle'
218
+ ? hit(event.absoluteX, event.absoluteY, committedRevision)
219
+ : null;
220
+ if (!target) {
221
+ GestureStateManager.fail(event.handlerTag);
222
+ return;
223
+ }
224
+ const source = measureDndRect(target.sourceRef);
225
+ const root = measureDndRect(rootRef);
226
+ if (!source || !root) {
227
+ GestureStateManager.fail(event.handlerTag);
228
+ return;
229
+ }
230
+ const nextToken = token.get() + 1;
231
+ token.set(nextToken);
232
+ ownToken.set(nextToken);
233
+ ownHandle.set(target.id);
234
+ const pointer = { x: event.absoluteX, y: event.absoluteY };
235
+ const next: DndMotion = {
236
+ ...EMPTY_DND_MOTION,
237
+ token: nextToken,
238
+ handleId: target.id,
239
+ seq: 1,
240
+ phase: 'dragging',
241
+ itemId: target.itemId,
242
+ sourceZoneId: target.zoneId,
243
+ revision: committedRevision,
244
+ pointer,
245
+ origin: pointer,
246
+ axis: dragAxis,
247
+ activationDelayMs,
248
+ configRevision: gestureConfigRevision,
249
+ grip: { x: pointer.x - source.x, y: pointer.y - source.y },
250
+ width: source.width,
251
+ height: source.height,
252
+ root,
253
+ zones: readListViewports(zones.get()),
254
+ };
255
+ motion.set(next);
256
+ scheduleOnRN(begin, next);
257
+ },
258
+ onUpdate: event => {
259
+ 'worklet';
260
+ if (
261
+ !Number.isFinite(event.absoluteX) ||
262
+ !Number.isFinite(event.absoluteY)
263
+ )
264
+ return;
265
+ const current = motion.get();
266
+ if (!owned(current)) return;
267
+ if (providerDisabled.get() || event.numberOfPointers > 1) {
268
+ cancelOwned();
269
+ return;
270
+ }
271
+ const root = frameDriven ? current.root : measureDndRect(rootRef);
272
+ const next: DndMotion = {
273
+ ...current,
274
+ pointer: constrainDragPoint(
275
+ { x: event.absoluteX, y: event.absoluteY },
276
+ current.origin,
277
+ current.axis,
278
+ ),
279
+ zones: frameDriven
280
+ ? current.zones
281
+ : root
282
+ ? readListViewports(zones.get())
283
+ : [],
284
+ root: root ?? current.root,
285
+ seq: current.seq + 1,
286
+ };
287
+ motion.set(next);
288
+ if (!frameDriven) scheduleOnRN(move, next);
289
+ },
290
+ onDeactivate: event => {
291
+ 'worklet';
292
+ if (
293
+ !Number.isFinite(event.absoluteX) ||
294
+ !Number.isFinite(event.absoluteY)
295
+ ) {
296
+ cancelOwned();
297
+ return;
298
+ }
299
+ const current = motion.get();
300
+ if (!owned(current)) return;
301
+ if (event.canceled || providerDisabled.get()) {
302
+ cancelOwned();
303
+ return;
304
+ }
305
+ const root = measureDndRect(rootRef);
306
+ const next: DndMotion = {
307
+ ...current,
308
+ phase: 'released',
309
+ pointer: constrainDragPoint(
310
+ { x: event.absoluteX, y: event.absoluteY },
311
+ current.origin,
312
+ current.axis,
313
+ ),
314
+ zones: root ? readListViewports(zones.get()) : [],
315
+ root: root ?? current.root,
316
+ seq: current.seq + 1,
317
+ };
318
+ if (root) prepareRelease?.(next);
319
+ motion.set(next);
320
+ scheduleOnRN(release, next, root ? false : 'measure-failed');
321
+ },
322
+ onTouchesCancel: cancelOwned,
323
+ onFinalize: () => {
324
+ 'worklet';
325
+ cancelOwned();
326
+ ownToken.set(0);
327
+ ownHandle.set(-1);
328
+ },
329
+ };
330
+ }, [
331
+ relations,
332
+ motion,
333
+ token,
334
+ zones,
335
+ providerDisabled,
336
+ rootRef,
337
+ begin,
338
+ move,
339
+ release,
340
+ prepareRelease,
341
+ dragAxis,
342
+ revision,
343
+ activationDelayMs,
344
+ gestureConfigRevision,
345
+ frameDriven,
346
+ enabled,
347
+ ownToken,
348
+ ownHandle,
349
+ uiTargets,
350
+ ]);
351
+ const pan = usePanGesture(config);
352
+ useLayoutEffect(() => {
353
+ publish(groupId, pan);
354
+ }, [groupId, pan, publish]);
355
+ useLayoutEffect(() => () => publish(groupId, null), [groupId, publish]);
356
+ return null;
357
+ }
@@ -0,0 +1,50 @@
1
+ import {
2
+ DndGestureGroup,
3
+ type DndGestureRuntime,
4
+ type DndHandleTarget,
5
+ } from './DndGestureGroup';
6
+ import type { DndHandleRegistration } from '../runtime/dndRuntime';
7
+ import {
8
+ createGestureRegistry,
9
+ groupGestureOwners as groupOwners,
10
+ type GestureGroupSnapshot,
11
+ type GestureOwner,
12
+ type GestureRegistry,
13
+ type GroupingState,
14
+ } from './gestureGrouping';
15
+ import { createGestureHost } from './gestureHost';
16
+
17
+ function toDndTarget({
18
+ id,
19
+ registration,
20
+ }: GestureOwner<DndHandleRegistration>): DndHandleTarget {
21
+ return {
22
+ id,
23
+ itemId: registration.itemId,
24
+ zoneId: registration.zoneId,
25
+ ref: registration.ref,
26
+ sourceRef: registration.sourceRef,
27
+ disabled: registration.disabled,
28
+ };
29
+ }
30
+
31
+ /** Handle mounts update their native owners without rendering the Provider. */
32
+ export function createDndGestureRegistry(): GestureRegistry<DndHandleRegistration> {
33
+ return createGestureRegistry<DndHandleRegistration>();
34
+ }
35
+
36
+ export type DndGestureRegistry = GestureRegistry<DndHandleRegistration>;
37
+
38
+ /** Groups the published owners by gesture relation signature; see `groupGestureOwners`. */
39
+ export function groupGestureOwners(
40
+ owners: readonly GestureOwner<DndHandleRegistration>[],
41
+ state: GroupingState<DndHandleRegistration, DndHandleTarget>,
42
+ ): readonly GestureGroupSnapshot<DndHandleTarget>[] {
43
+ return groupOwners(owners, state, toDndTarget);
44
+ }
45
+
46
+ export const DndGestureHost = createGestureHost<
47
+ DndHandleRegistration,
48
+ DndHandleTarget,
49
+ DndGestureRuntime
50
+ >({ Group: DndGestureGroup, toTarget: toDndTarget });
@@ -0,0 +1,123 @@
1
+ import type { GestureRelations } from '../components/gridTypes';
2
+ import type { ValidationIssue } from '../types';
3
+
4
+ type GestureRelationResult =
5
+ | { valid: true; relations: GestureRelations | undefined }
6
+ | { valid: false; issues: ValidationIssue[] };
7
+
8
+ function record(value: unknown): value is Record<string, unknown> {
9
+ return !!value && typeof value === 'object' && !Array.isArray(value);
10
+ }
11
+
12
+ function tags(value: unknown): value is number[] {
13
+ return (
14
+ Array.isArray(value) &&
15
+ value.every(tag => Number.isSafeInteger(tag) && tag > 0)
16
+ );
17
+ }
18
+
19
+ /** Published RNGH v3 gesture surface, without probing detector internals. */
20
+ function gestureTags(gesture: unknown): number[] | null {
21
+ if (
22
+ !record(gesture) ||
23
+ typeof gesture.type !== 'string' ||
24
+ !gesture.type ||
25
+ !record(gesture.config) ||
26
+ !record(gesture.detectorCallbacks)
27
+ )
28
+ return null;
29
+ if ('handlerTags' in gesture) {
30
+ return tags(gesture.handlerTags) &&
31
+ tags(gesture.externalSimultaneousHandlers) &&
32
+ Array.isArray(gesture.gestures)
33
+ ? gesture.handlerTags
34
+ : null;
35
+ }
36
+ const relations = gesture.gestureRelations;
37
+ if (
38
+ !Number.isSafeInteger(gesture.handlerTag) ||
39
+ (gesture.handlerTag as number) <= 0 ||
40
+ !record(relations) ||
41
+ !tags(relations.simultaneousHandlers) ||
42
+ !tags(relations.waitFor) ||
43
+ !tags(relations.blocksHandlers)
44
+ )
45
+ return null;
46
+ return [gesture.handlerTag as number];
47
+ }
48
+
49
+ /** Element-wise equality of the three relation lists; a single gesture equals a one-element list. */
50
+ export function sameGestureRelations(
51
+ first: GestureRelations | undefined,
52
+ second: GestureRelations | undefined,
53
+ ): boolean {
54
+ return (['block', 'requireToFail', 'simultaneousWith'] as const).every(
55
+ key => {
56
+ const a = first?.[key];
57
+ const b = second?.[key];
58
+ const aa = a === undefined ? [] : Array.isArray(a) ? a : [a];
59
+ const bb = b === undefined ? [] : Array.isArray(b) ? b : [b];
60
+ return (
61
+ aa.length === bb.length &&
62
+ aa.every((gesture, index) => gesture === bb[index])
63
+ );
64
+ },
65
+ );
66
+ }
67
+
68
+ /** Attachment to an actual detector still requires device validation by the caller. */
69
+ export function validateGestureRelations(
70
+ value: unknown,
71
+ ): GestureRelationResult {
72
+ if (value === undefined) return { valid: true, relations: undefined };
73
+ const fail = (message: string): GestureRelationResult => ({
74
+ valid: false,
75
+ issues: [{ code: 'invalid-configuration', message }],
76
+ });
77
+ const keys = ['block', 'requireToFail', 'simultaneousWith'] as const;
78
+ if (
79
+ !record(value) ||
80
+ Object.keys(value).some(key => !keys.some(known => known === key))
81
+ ) {
82
+ return fail(
83
+ 'gestureRelations must contain only block, requireToFail and simultaneousWith.',
84
+ );
85
+ }
86
+ const normalized: GestureRelations = {};
87
+ const objectOwners = new Map<object, string>();
88
+ const tagOwners = new Map<number, string>();
89
+ for (const key of keys) {
90
+ const relation = value[key];
91
+ if (relation === undefined) continue;
92
+ const gestures: unknown[] = Array.isArray(relation) ? relation : [relation];
93
+ const unique = new Set<object>();
94
+ for (const gesture of gestures) {
95
+ const handlerTags = gestureTags(gesture);
96
+ if (!handlerTags || !record(gesture)) {
97
+ return fail(
98
+ `${key} requires v3 gesture objects, not refs or incomplete objects.`,
99
+ );
100
+ }
101
+ const prior = objectOwners.get(gesture);
102
+ if (prior && prior !== key)
103
+ return fail(`The same gesture cannot be in both ${prior} and ${key}.`);
104
+ objectOwners.set(gesture, key);
105
+ for (const tag of handlerTags) {
106
+ const owner = tagOwners.get(tag);
107
+ if (owner && owner !== key)
108
+ return fail(
109
+ `The same native handler cannot be in both ${owner} and ${key}.`,
110
+ );
111
+ tagOwners.set(tag, key);
112
+ }
113
+ unique.add(gesture);
114
+ }
115
+ // Preserve actual gesture object identities; v3 connects relations through
116
+ // these objects and mutates their symmetric relation lists itself.
117
+ normalized[key] = [...unique] as Exclude<
118
+ GestureRelations[typeof key],
119
+ undefined
120
+ >;
121
+ }
122
+ return { valid: true, relations: normalized };
123
+ }