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,449 @@
1
+ import { memo, useLayoutEffect, useMemo, useRef, useState } from 'react';
2
+ import { PixelRatio, StyleSheet } from 'react-native';
3
+ import Animated, {
4
+ type ReduceMotion,
5
+ type SharedValue,
6
+ useAnimatedRef,
7
+ useAnimatedStyle,
8
+ useDerivedValue,
9
+ withTiming,
10
+ } from 'react-native-reanimated';
11
+
12
+ import type { DndItem, GridPlacement } from '../contracts';
13
+ import {
14
+ DndItemContext,
15
+ useDndRuntime,
16
+ useDndZoneSnapshot,
17
+ useDndItemSnapshot,
18
+ type DndRuntime,
19
+ } from '../runtime/dndRuntime';
20
+ import type { GridItemRenderArgs, SortableGridProps } from './dndTypes';
21
+ import { presentationRect } from '../runtime/dndPresentation';
22
+ import { getCellGeometry, itemRect } from '../pointer/geometry';
23
+
24
+ function GridCellContent<T>({
25
+ item,
26
+ placement,
27
+ row,
28
+ col,
29
+ rows,
30
+ cols,
31
+ index,
32
+ zoneId,
33
+ revision,
34
+ committedRevision,
35
+ x,
36
+ y,
37
+ width,
38
+ height,
39
+ renderItem,
40
+ hiddenItemId,
41
+ animation,
42
+ presentation,
43
+ isDragging,
44
+ }: {
45
+ item: DndItem<T>;
46
+ placement: GridPlacement['placement'];
47
+ row: number;
48
+ col: number;
49
+ rows: number;
50
+ cols: number;
51
+ index: number;
52
+ zoneId: string;
53
+ revision: number;
54
+ committedRevision?: SharedValue<number>;
55
+ x: number;
56
+ y: number;
57
+ width: number;
58
+ height: number;
59
+ renderItem(args: GridItemRenderArgs<T>): React.ReactNode;
60
+ hiddenItemId: SharedValue<string | null>;
61
+ animation: DndRuntime['animation'];
62
+ presentation: DndRuntime['presentation'];
63
+ isDragging: boolean;
64
+ }) {
65
+ const ref = useAnimatedRef();
66
+ const itemId = item.id;
67
+ const publicSlot = useDndItemSnapshot(useDndRuntime(), zoneId, itemId);
68
+ const itemContext = useMemo(
69
+ () => ({ itemId, zoneId, ref }),
70
+ [itemId, zoneId, ref],
71
+ );
72
+ const publicIndex = publicSlot?.index ?? index;
73
+ const publicRow = publicSlot?.row ?? row;
74
+ const publicCol = publicSlot?.col ?? col;
75
+ const content = useMemo(
76
+ () =>
77
+ renderItem({
78
+ item,
79
+ index: publicIndex,
80
+ zoneId,
81
+ position: { row: publicRow, col: publicCol },
82
+ span: { rows, cols },
83
+ placement,
84
+ width,
85
+ height,
86
+ isDragging,
87
+ }),
88
+ [
89
+ item,
90
+ publicIndex,
91
+ zoneId,
92
+ publicRow,
93
+ publicCol,
94
+ rows,
95
+ cols,
96
+ placement,
97
+ width,
98
+ height,
99
+ isDragging,
100
+ renderItem,
101
+ ],
102
+ );
103
+ const fallback = useMemo(
104
+ () => ({ x, y, width, height }),
105
+ [x, y, width, height],
106
+ );
107
+ const revisionSource = committedRevision ?? revision;
108
+ const targetRect = useDerivedValue(() => {
109
+ const current = presentation?.get();
110
+ const currentRevision =
111
+ typeof revisionSource === 'number'
112
+ ? revisionSource
113
+ : revisionSource.get();
114
+ return current?.revision === currentRevision
115
+ ? (presentationRect(current, zoneId, itemId) ?? fallback)
116
+ : fallback;
117
+ });
118
+ const animated = useAnimatedStyle(() => {
119
+ const hidden = hiddenItemId.get() === itemId;
120
+ const target = targetRect.get();
121
+ return {
122
+ opacity: hidden ? 0 : 1,
123
+ width: target.width,
124
+ height: target.height,
125
+ transform: [
126
+ {
127
+ // The overlay owns motion for the hidden active cell. Put its native
128
+ // view in the committed slot immediately so handoff can measure it.
129
+ translateX: hidden
130
+ ? target.x
131
+ : withTiming(target.x, {
132
+ duration: animation.durationMs,
133
+ reduceMotion: animation.reduceMotion as ReduceMotion,
134
+ }),
135
+ },
136
+ {
137
+ translateY: hidden
138
+ ? target.y
139
+ : withTiming(target.y, {
140
+ duration: animation.durationMs,
141
+ reduceMotion: animation.reduceMotion as ReduceMotion,
142
+ }),
143
+ },
144
+ ],
145
+ };
146
+ });
147
+ return (
148
+ <DndItemContext value={itemContext}>
149
+ <Animated.View
150
+ ref={ref}
151
+ collapsable={false}
152
+ style={[styles.cell, animated]}
153
+ >
154
+ {content}
155
+ </Animated.View>
156
+ </DndItemContext>
157
+ );
158
+ }
159
+
160
+ // Session/target changes only rerender cells whose public render arguments or
161
+ // geometry changed. Cells deliberately do not consume the provider context.
162
+ const GridCell = memo(GridCellContent) as typeof GridCellContent;
163
+
164
+ /** Spatial cells in the same provider/session as SortableList. */
165
+ export function SortableGrid<T>({
166
+ zoneId,
167
+ geometry,
168
+ renderItem,
169
+ dropIndicatorStyle,
170
+ children,
171
+ style,
172
+ onLayout,
173
+ ...viewProps
174
+ }: SortableGridProps<T>) {
175
+ const runtime = useDndRuntime();
176
+ const { registerZone, unregisterZone, reportIssues } = runtime;
177
+ const snapshot = useDndZoneSnapshot(runtime, zoneId);
178
+ const { motion, presentation } = runtime;
179
+ // Only visibility changes affect cells; pointer updates belong to the overlay.
180
+ const hiddenItemId = useDerivedValue(() => {
181
+ const state = motion.get();
182
+ return state.visible ? state.itemId : null;
183
+ });
184
+ const activeToken = useDerivedValue(() => motion.get().token);
185
+ const identity = useRef({}).current;
186
+ const mounted = useRef(false);
187
+ useLayoutEffect(() => {
188
+ mounted.current = true;
189
+ return () => {
190
+ mounted.current = false;
191
+ };
192
+ }, []);
193
+ const ref = useAnimatedRef();
194
+ const [size, setSize] = useState<{ width: number; height: number } | null>(
195
+ null,
196
+ );
197
+ const zone = snapshot.zone;
198
+ const display = snapshot.display;
199
+ const revision = snapshot.revision;
200
+ const indicator = useAnimatedStyle(() => {
201
+ const approved = presentation?.get();
202
+ const itemId = hiddenItemId.get();
203
+ const rect =
204
+ approved?.revision === revision &&
205
+ approved.token === activeToken.get() &&
206
+ approved.releaseTarget?.target.zoneId === zoneId &&
207
+ itemId !== null
208
+ ? presentationRect(approved, zoneId, itemId)
209
+ : undefined;
210
+ return {
211
+ opacity: rect ? 1 : 0,
212
+ left: rect?.x ?? 0,
213
+ top: rect?.y ?? 0,
214
+ width: rect?.width ?? 0,
215
+ height: rect?.height ?? 0,
216
+ };
217
+ });
218
+ const pixelRatio = PixelRatio.get();
219
+ const cells =
220
+ zone?.kind === 'grid' && size
221
+ ? getCellGeometry(zone, geometry, size.width, size.height, pixelRatio)
222
+ : null;
223
+ // Compare values so mutating a geometry object in place cannot preserve stale
224
+ // hit-test coordinates. Registered geometry never aliases caller-owned values.
225
+ const geometryKey = cells
226
+ ? JSON.stringify([
227
+ geometry.mode,
228
+ geometry.rowGap,
229
+ geometry.columnGap,
230
+ geometry.padding.top,
231
+ geometry.padding.right,
232
+ geometry.padding.bottom,
233
+ geometry.padding.left,
234
+ cells.cellWidth,
235
+ cells.cellHeight,
236
+ pixelRatio,
237
+ ])
238
+ : null;
239
+ const measured = useMemo(
240
+ () =>
241
+ cells
242
+ ? {
243
+ cells,
244
+ geometry: {
245
+ ...(geometry.mode === 'fixed'
246
+ ? {
247
+ mode: 'fixed' as const,
248
+ cellWidth: geometry.cellWidth,
249
+ cellHeight: geometry.cellHeight,
250
+ }
251
+ : { mode: 'fit' as const }),
252
+ rowGap: geometry.rowGap,
253
+ columnGap: geometry.columnGap,
254
+ padding: {
255
+ top: geometry.padding.top,
256
+ right: geometry.padding.right,
257
+ bottom: geometry.padding.bottom,
258
+ left: geometry.padding.left,
259
+ },
260
+ },
261
+ pixelRatio,
262
+ }
263
+ : null, // eslint-disable-next-line react-hooks/exhaustive-deps
264
+ [geometryKey],
265
+ );
266
+ const data = useMemo(
267
+ () => new Map(snapshot.items?.map(item => [item.id, item]) ?? []),
268
+ [snapshot.items],
269
+ );
270
+ useLayoutEffect(() => {
271
+ const invalid = zone?.kind !== 'grid' || (size !== null && !measured);
272
+ reportIssues(
273
+ `grid:${zoneId}`,
274
+ invalid
275
+ ? [
276
+ {
277
+ code:
278
+ zone?.kind !== 'grid'
279
+ ? 'invalid-configuration'
280
+ : 'invalid-geometry',
281
+ zoneId,
282
+ message:
283
+ 'SortableGrid requires an existing grid zone and geometry that fits its measured viewport.',
284
+ },
285
+ ]
286
+ : [],
287
+ );
288
+ if (zone?.kind !== 'grid' || !measured) {
289
+ unregisterZone(zoneId, identity);
290
+ return;
291
+ }
292
+ registerZone(
293
+ {
294
+ kind: 'grid',
295
+ zoneId,
296
+ revision,
297
+ ref,
298
+ layout: zone,
299
+ ...measured,
300
+ renderItem: args => {
301
+ const placement = zone.placements.find(
302
+ entry => entry.itemId === args.item.id,
303
+ );
304
+ if (!placement) return null;
305
+ const rect = itemRect(
306
+ placement.position,
307
+ placement.span,
308
+ measured.geometry,
309
+ measured.cells,
310
+ );
311
+ return renderItem({
312
+ ...args,
313
+ item: args.item as DndItem<T>,
314
+ position: placement.position,
315
+ span: placement.span,
316
+ placement: placement.placement,
317
+ width: rect.width,
318
+ height: rect.height,
319
+ });
320
+ },
321
+ },
322
+ identity,
323
+ );
324
+ }, [
325
+ zone,
326
+ zoneId,
327
+ revision,
328
+ ref,
329
+ measured,
330
+ size,
331
+ registerZone,
332
+ unregisterZone,
333
+ reportIssues,
334
+ identity,
335
+ renderItem,
336
+ ]);
337
+ useLayoutEffect(
338
+ () => () => {
339
+ unregisterZone(zoneId, identity);
340
+ reportIssues(`grid:${zoneId}`, []);
341
+ },
342
+ [zoneId, identity, unregisterZone, reportIssues],
343
+ );
344
+ return (
345
+ <Animated.View
346
+ {...viewProps}
347
+ ref={ref}
348
+ collapsable={false}
349
+ style={[styles.zone, style]}
350
+ onLayout={event => {
351
+ if (!mounted.current) return;
352
+ const { width, height } = event.nativeEvent.layout;
353
+ setSize(current =>
354
+ current?.width === width && current.height === height
355
+ ? current
356
+ : { width, height },
357
+ );
358
+ onLayout?.(event);
359
+ }}
360
+ >
361
+ {children}
362
+ {measured && presentation && (
363
+ <Animated.View
364
+ pointerEvents="none"
365
+ style={[styles.indicator, dropIndicatorStyle, indicator]}
366
+ />
367
+ )}
368
+ {!presentation &&
369
+ measured &&
370
+ display?.kind === 'grid' &&
371
+ runtime.snapshot.validity === 'valid' &&
372
+ runtime.snapshot.targetZoneId === zoneId &&
373
+ (() => {
374
+ const active = display.placements.find(
375
+ entry => entry.itemId === snapshot.activeItemId,
376
+ );
377
+ if (!active) return null;
378
+ const rect = itemRect(
379
+ active.position,
380
+ active.span,
381
+ measured.geometry,
382
+ measured.cells,
383
+ );
384
+ return (
385
+ <Animated.View
386
+ pointerEvents="none"
387
+ style={[
388
+ styles.indicator,
389
+ {
390
+ left: rect.x,
391
+ top: rect.y,
392
+ width: rect.width,
393
+ height: rect.height,
394
+ },
395
+ dropIndicatorStyle,
396
+ ]}
397
+ />
398
+ );
399
+ })()}
400
+ {measured &&
401
+ display?.kind === 'grid' &&
402
+ display.placements.map((placement, index) => {
403
+ const item = data.get(placement.itemId);
404
+ if (!item) return null;
405
+ const rect = itemRect(
406
+ placement.position,
407
+ placement.span,
408
+ measured.geometry,
409
+ measured.cells,
410
+ );
411
+ return (
412
+ <GridCell
413
+ key={item.id}
414
+ item={item as DndItem<T>}
415
+ placement={placement.placement}
416
+ row={placement.position.row}
417
+ col={placement.position.col}
418
+ rows={placement.span.rows}
419
+ cols={placement.span.cols}
420
+ index={index}
421
+ zoneId={zoneId}
422
+ revision={revision}
423
+ committedRevision={runtime.committedRevision}
424
+ x={rect.x}
425
+ y={rect.y}
426
+ width={rect.width}
427
+ height={rect.height}
428
+ renderItem={renderItem}
429
+ hiddenItemId={hiddenItemId}
430
+ animation={runtime.animation}
431
+ presentation={runtime.presentation}
432
+ isDragging={snapshot.activeItemId === item.id}
433
+ />
434
+ );
435
+ })}
436
+ </Animated.View>
437
+ );
438
+ }
439
+
440
+ const styles = StyleSheet.create({
441
+ zone: { position: 'relative' },
442
+ cell: { position: 'absolute', left: 0, top: 0 },
443
+ indicator: {
444
+ position: 'absolute',
445
+ borderWidth: 1,
446
+ borderColor: '#64748B',
447
+ backgroundColor: 'rgba(100, 116, 139, 0.12)',
448
+ },
449
+ });