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 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,136 @@
1
+ {
2
+ "name": "react-native-layout-dnd",
3
+ "version": "0.1.0-alpha.0",
4
+ "description": "Drag and drop for React Native grids and lists: mixed spans, optional FlatList virtualization, and atomic moves between zones.",
5
+ "main": "./lib/module/index.js",
6
+ "types": "./lib/typescript/src/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "react-native-layout-dnd-source": "./src/index.ts",
10
+ "types": "./lib/typescript/src/index.d.ts",
11
+ "default": "./lib/module/index.js"
12
+ },
13
+ "./engine": {
14
+ "react-native-layout-dnd-source": "./src/engine/index.ts",
15
+ "types": "./lib/typescript/src/engine/index.d.ts",
16
+ "default": "./lib/module/engine/index.js"
17
+ },
18
+ "./package.json": "./package.json"
19
+ },
20
+ "files": [
21
+ "src",
22
+ "lib",
23
+ "!**/__tests__",
24
+ "!**/__fixtures__",
25
+ "!**/__mocks__",
26
+ "!**/.*"
27
+ ],
28
+ "scripts": {
29
+ "example": "yarn workspace react-native-layout-dnd-example",
30
+ "clean": "del-cli android/build example/android/build example/android/app/build example/ios/build lib",
31
+ "build": "bob build",
32
+ "prepack": "bob build",
33
+ "test": "jest --runInBand --watchman=false",
34
+ "typecheck": "tsc",
35
+ "lint": "eslint \"**/*.{js,ts,tsx}\"",
36
+ "check:package": "node scripts/check-package.mjs",
37
+ "test:perf-tools": "node --test scripts/perf/metrics.test.mjs"
38
+ },
39
+ "keywords": [
40
+ "react-native",
41
+ "drag-and-drop",
42
+ "dnd",
43
+ "drag",
44
+ "drop",
45
+ "draggable",
46
+ "sortable",
47
+ "reorderable",
48
+ "grid",
49
+ "list",
50
+ "flatlist",
51
+ "reanimated",
52
+ "gesture-handler",
53
+ "ios",
54
+ "android"
55
+ ],
56
+ "repository": {
57
+ "type": "git",
58
+ "url": "git+https://github.com/baesumin/react-native-layout-dnd.git"
59
+ },
60
+ "author": {
61
+ "name": "baesumin",
62
+ "url": "https://github.com/baesumin"
63
+ },
64
+ "license": "MIT",
65
+ "bugs": {
66
+ "url": "https://github.com/baesumin/react-native-layout-dnd/issues"
67
+ },
68
+ "homepage": "https://github.com/baesumin/react-native-layout-dnd#readme",
69
+ "publishConfig": {
70
+ "registry": "https://registry.npmjs.org/",
71
+ "access": "public"
72
+ },
73
+ "devDependencies": {
74
+ "@babel/core": "7.29.7",
75
+ "@eslint/compat": "^2.1.0",
76
+ "@eslint/eslintrc": "^3.3.6",
77
+ "@eslint/js": "^9.39.5",
78
+ "@react-native/babel-preset": "0.87.1",
79
+ "@react-native/eslint-config": "0.87.1",
80
+ "@react-native/jest-preset": "0.87.1",
81
+ "@react-native/metro-config": "0.87.1",
82
+ "@react-native/typescript-config": "0.87.1",
83
+ "@types/jest": "29.5.14",
84
+ "@types/react": "^19.2.0",
85
+ "del-cli": "^7.0.0",
86
+ "eslint": "^9.39.5",
87
+ "eslint-config-prettier": "^10.1.8",
88
+ "eslint-plugin-prettier": "^5.5.6",
89
+ "jest": "29.7.0",
90
+ "prettier": "^3.9.6",
91
+ "react": "19.2.3",
92
+ "react-native": "0.87.1",
93
+ "react-native-builder-bob": "^0.43.1",
94
+ "react-native-gesture-handler": "3.3.0",
95
+ "react-native-reanimated": "4.6.0",
96
+ "react-native-worklets": "0.12.2",
97
+ "typescript": "^6.0.3"
98
+ },
99
+ "peerDependencies": {
100
+ "react": ">=19.0.0",
101
+ "react-native": ">=0.78.0",
102
+ "react-native-gesture-handler": ">=3.0.0 <4.0.0",
103
+ "react-native-reanimated": ">=4.0.0 <5.0.0",
104
+ "react-native-worklets": ">=0.5.0 <1.0.0"
105
+ },
106
+ "workspaces": [
107
+ "example"
108
+ ],
109
+ "packageManager": "yarn@4.11.0",
110
+ "react-native-builder-bob": {
111
+ "source": "src",
112
+ "output": "lib",
113
+ "targets": [
114
+ [
115
+ "module",
116
+ {
117
+ "esm": true
118
+ }
119
+ ],
120
+ [
121
+ "typescript",
122
+ {
123
+ "project": "tsconfig.build.json"
124
+ }
125
+ ]
126
+ ]
127
+ },
128
+ "prettier": {
129
+ "arrowParens": "avoid",
130
+ "quoteProps": "consistent",
131
+ "singleQuote": true,
132
+ "tabWidth": 2,
133
+ "trailingComma": "all",
134
+ "useTabs": false
135
+ }
136
+ }
@@ -0,0 +1,181 @@
1
+ import type {
2
+ CoordinateResult,
3
+ LayoutPoint,
4
+ LayoutRect,
5
+ MeasurementFreshness,
6
+ RectMeasurement,
7
+ ZoneCoordinateContext,
8
+ } from '../contracts';
9
+
10
+ import { isRecord } from '../engine/validation';
11
+
12
+ function isPoint(value: unknown): value is LayoutPoint {
13
+ return (
14
+ isRecord(value) &&
15
+ typeof value.x === 'number' &&
16
+ Number.isFinite(value.x) &&
17
+ typeof value.y === 'number' &&
18
+ Number.isFinite(value.y)
19
+ );
20
+ }
21
+
22
+ function isRect(value: unknown): value is LayoutRect {
23
+ return (
24
+ isPoint(value) &&
25
+ 'width' in value &&
26
+ typeof value.width === 'number' &&
27
+ Number.isFinite(value.width) &&
28
+ value.width > 0 &&
29
+ 'height' in value &&
30
+ typeof value.height === 'number' &&
31
+ Number.isFinite(value.height) &&
32
+ value.height > 0
33
+ );
34
+ }
35
+
36
+ function isNonnegativeFinite(value: unknown): value is number {
37
+ return typeof value === 'number' && Number.isFinite(value) && value >= 0;
38
+ }
39
+
40
+ /** Estimates remain estimates after validation; callers must inspect source. */
41
+ export function validateRectMeasurement<Measurement extends RectMeasurement>(
42
+ measurement: Measurement,
43
+ freshness: MeasurementFreshness,
44
+ ): CoordinateResult<Measurement> {
45
+ if (
46
+ !isRecord(freshness) ||
47
+ !Number.isSafeInteger(freshness.revision) ||
48
+ freshness.revision < 0 ||
49
+ (freshness.nowMs === undefined) !== (freshness.maxAgeMs === undefined) ||
50
+ (freshness.nowMs !== undefined &&
51
+ (!isNonnegativeFinite(freshness.nowMs) ||
52
+ !isNonnegativeFinite(freshness.maxAgeMs)))
53
+ ) {
54
+ return { valid: false, reason: 'invalid-freshness' };
55
+ }
56
+ if (
57
+ !isRecord(measurement) ||
58
+ (measurement.source !== 'measured' && measurement.source !== 'estimated') ||
59
+ (measurement.space !== 'screen' && measurement.space !== 'content') ||
60
+ !isRect(measurement.rect) ||
61
+ !Number.isSafeInteger(measurement.revision) ||
62
+ measurement.revision < 0 ||
63
+ !isNonnegativeFinite(measurement.timestampMs)
64
+ ) {
65
+ return { valid: false, reason: 'invalid-measurement' };
66
+ }
67
+ if (
68
+ measurement.revision !== freshness.revision ||
69
+ (freshness.nowMs !== undefined &&
70
+ (measurement.timestampMs > freshness.nowMs ||
71
+ freshness.nowMs - measurement.timestampMs > freshness.maxAgeMs!))
72
+ ) {
73
+ return { valid: false, reason: 'stale-measurement' };
74
+ }
75
+ return { valid: true, value: measurement };
76
+ }
77
+
78
+ function validateContext(
79
+ context: ZoneCoordinateContext,
80
+ freshness: MeasurementFreshness,
81
+ ): CoordinateResult<ZoneCoordinateContext> {
82
+ if (!isRecord(context) || !isPoint(context.scrollOffset)) {
83
+ return { valid: false, reason: 'invalid-context' };
84
+ }
85
+ const measurement = validateRectMeasurement(context.viewport, freshness);
86
+ if (!measurement.valid) return measurement;
87
+ if (
88
+ measurement.value.source !== 'measured' ||
89
+ measurement.value.space !== 'screen'
90
+ ) {
91
+ return { valid: false, reason: 'invalid-context' };
92
+ }
93
+ return { valid: true, value: context };
94
+ }
95
+
96
+ function convertPoint(
97
+ point: LayoutPoint,
98
+ context: ZoneCoordinateContext,
99
+ freshness: MeasurementFreshness,
100
+ direction: 'to-content' | 'to-screen',
101
+ ): CoordinateResult<LayoutPoint> {
102
+ if (!isPoint(point)) return { valid: false, reason: 'invalid-coordinate' };
103
+ const validation = validateContext(context, freshness);
104
+ if (!validation.valid) return validation;
105
+ const { rect } = context.viewport;
106
+ const { scrollOffset } = context;
107
+ const value =
108
+ direction === 'to-content'
109
+ ? {
110
+ x: point.x - rect.x + scrollOffset.x,
111
+ y: point.y - rect.y + scrollOffset.y,
112
+ }
113
+ : {
114
+ x: point.x - scrollOffset.x + rect.x,
115
+ y: point.y - scrollOffset.y + rect.y,
116
+ };
117
+ return isPoint(value)
118
+ ? { valid: true, value }
119
+ : { valid: false, reason: 'invalid-coordinate' };
120
+ }
121
+
122
+ /** Convert absolute screen pixels to zone content pixels using the current offset. */
123
+ export function screenToContent(
124
+ point: LayoutPoint,
125
+ context: ZoneCoordinateContext,
126
+ freshness: MeasurementFreshness,
127
+ ): CoordinateResult<LayoutPoint> {
128
+ return convertPoint(point, context, freshness, 'to-content');
129
+ }
130
+
131
+ export function contentToScreen(
132
+ point: LayoutPoint,
133
+ context: ZoneCoordinateContext,
134
+ freshness: MeasurementFreshness,
135
+ ): CoordinateResult<LayoutPoint> {
136
+ return convertPoint(point, context, freshness, 'to-screen');
137
+ }
138
+
139
+ export function screenRectToContent(
140
+ measurement: RectMeasurement<'screen'>,
141
+ context: ZoneCoordinateContext,
142
+ freshness: MeasurementFreshness,
143
+ ): CoordinateResult<RectMeasurement<'content'>> {
144
+ const validation = validateRectMeasurement(measurement, freshness);
145
+ if (!validation.valid) return validation;
146
+ if (measurement.space !== 'screen')
147
+ return { valid: false, reason: 'invalid-measurement' };
148
+ const converted = screenToContent(measurement.rect, context, freshness);
149
+ return converted.valid
150
+ ? {
151
+ valid: true,
152
+ value: {
153
+ ...measurement,
154
+ space: 'content',
155
+ rect: { ...measurement.rect, ...converted.value },
156
+ },
157
+ }
158
+ : converted;
159
+ }
160
+
161
+ export function contentRectToScreen(
162
+ measurement: RectMeasurement<'content'>,
163
+ context: ZoneCoordinateContext,
164
+ freshness: MeasurementFreshness,
165
+ ): CoordinateResult<RectMeasurement<'screen'>> {
166
+ const validation = validateRectMeasurement(measurement, freshness);
167
+ if (!validation.valid) return validation;
168
+ if (measurement.space !== 'content')
169
+ return { valid: false, reason: 'invalid-measurement' };
170
+ const converted = contentToScreen(measurement.rect, context, freshness);
171
+ return converted.valid
172
+ ? {
173
+ valid: true,
174
+ value: {
175
+ ...measurement,
176
+ space: 'screen',
177
+ rect: { ...measurement.rect, ...converted.value },
178
+ },
179
+ }
180
+ : converted;
181
+ }
@@ -0,0 +1,147 @@
1
+ import type { LayoutPoint } from '../contracts';
2
+
3
+ /** The permitted drag direction is independent of a list's orientation. */
4
+ export type DragAxis = 'x' | 'y' | 'both';
5
+
6
+ export type AutoScrollOptions = {
7
+ enabled?: boolean;
8
+ /** Edge activation distance in logical pixels. Defaults to 48. */
9
+ edgeThreshold?: number;
10
+ /** Maximum speed in logical pixels per second. Defaults to 600. */
11
+ maxSpeed?: number;
12
+ };
13
+
14
+ /** One axis of a measured scroll viewport, using logical pixels throughout. */
15
+ export type AutoScrollInput = {
16
+ /** Absolute screen coordinate on the scrolling axis. */
17
+ pointer: number;
18
+ viewportStart: number;
19
+ viewportSize: number;
20
+ /** Current native scroll offset; temporary bounce offsets are accepted. */
21
+ offset: number;
22
+ contentSize: number;
23
+ deltaTimeMs: number;
24
+ options?: AutoScrollOptions;
25
+ };
26
+
27
+ export type AutoScrollResult =
28
+ | {
29
+ valid: true;
30
+ /** Bounded native scroll target, including when velocity is zero. */
31
+ offset: number;
32
+ /** Actual speed after clamping, in logical pixels per second. */
33
+ velocity: number;
34
+ }
35
+ | { valid: false; reason: 'invalid-input' | 'invalid-options' };
36
+
37
+ export type AutoScrollOptionsValidationResult =
38
+ { valid: true } | { valid: false; reason: 'invalid-options' };
39
+
40
+ /** Validate public options before activating a gesture or executing a frame. */
41
+ export function validateAutoScrollOptions(
42
+ options?: AutoScrollOptions,
43
+ ): AutoScrollOptionsValidationResult {
44
+ 'worklet';
45
+ if (
46
+ options !== undefined &&
47
+ (!options ||
48
+ typeof options !== 'object' ||
49
+ Array.isArray(options) ||
50
+ (options.enabled !== undefined && typeof options.enabled !== 'boolean') ||
51
+ (options.edgeThreshold !== undefined &&
52
+ (!Number.isFinite(options.edgeThreshold) ||
53
+ options.edgeThreshold <= 0)) ||
54
+ (options.maxSpeed !== undefined &&
55
+ (!Number.isFinite(options.maxSpeed) || options.maxSpeed < 0)))
56
+ )
57
+ return { valid: false, reason: 'invalid-options' };
58
+ return { valid: true };
59
+ }
60
+
61
+ /**
62
+ * Compute one frame of edge scrolling for either orientation. Adapters should
63
+ * call scrollTo only for nonzero velocity, preserving native bounce while idle.
64
+ * Call only during an active drag, and re-read its candidate after scrolling.
65
+ */
66
+ export function computeAutoScroll(input: AutoScrollInput): AutoScrollResult {
67
+ 'worklet';
68
+ if (
69
+ !input ||
70
+ typeof input !== 'object' ||
71
+ Array.isArray(input) ||
72
+ !Number.isFinite(input.pointer) ||
73
+ !Number.isFinite(input.viewportStart) ||
74
+ !Number.isFinite(input.viewportSize) ||
75
+ input.viewportSize <= 0 ||
76
+ !Number.isFinite(input.offset) ||
77
+ !Number.isFinite(input.contentSize) ||
78
+ input.contentSize < 0 ||
79
+ !Number.isFinite(input.deltaTimeMs) ||
80
+ input.deltaTimeMs < 0
81
+ )
82
+ return { valid: false, reason: 'invalid-input' };
83
+
84
+ const { options } = input;
85
+ const validation = validateAutoScrollOptions(options);
86
+ if (!validation.valid) return validation;
87
+
88
+ const maximum = Math.max(0, input.contentSize - input.viewportSize);
89
+ const offset = Math.max(0, Math.min(maximum, input.offset));
90
+ const idle: AutoScrollResult = { valid: true, offset, velocity: 0 };
91
+ const pointer = input.pointer - input.viewportStart;
92
+ if (!Number.isFinite(pointer))
93
+ return { valid: false, reason: 'invalid-input' };
94
+
95
+ if (
96
+ options?.enabled === false ||
97
+ pointer < 0 ||
98
+ pointer > input.viewportSize ||
99
+ maximum === 0 ||
100
+ input.deltaTimeMs === 0
101
+ )
102
+ return idle;
103
+
104
+ // Cap overlapping edge bands at the midpoint so tiny viewports do not bias
105
+ // toward the first edge. The exact midpoint has no preferred direction.
106
+ const threshold = Math.min(
107
+ options?.edgeThreshold ?? 48,
108
+ input.viewportSize / 2,
109
+ );
110
+ if (threshold === 0) return idle;
111
+ const trailingDistance = input.viewportSize - pointer;
112
+ const direction =
113
+ pointer < threshold ? -1 : trailingDistance < threshold ? 1 : 0;
114
+ if (direction === 0) return idle;
115
+
116
+ const distance = direction < 0 ? pointer : trailingDistance;
117
+ const speed = (options?.maxSpeed ?? 600) * (1 - distance / threshold);
118
+ // A paused/resumed frame must not skip a large portion of the list.
119
+ const seconds = Math.min(input.deltaTimeMs, 64) / 1000;
120
+ if (seconds === 0 || speed === 0) return idle;
121
+ const nextOffset = Math.max(
122
+ 0,
123
+ Math.min(maximum, offset + direction * speed * seconds),
124
+ );
125
+ const movement = nextOffset - offset;
126
+ return {
127
+ valid: true,
128
+ offset: nextOffset,
129
+ velocity:
130
+ movement === 0
131
+ ? 0
132
+ : direction * Math.min(speed, Math.abs(movement / seconds)),
133
+ };
134
+ }
135
+
136
+ /** Project a validated screen point onto the configured axis through origin. */
137
+ export function constrainDragPoint(
138
+ point: LayoutPoint,
139
+ origin: LayoutPoint,
140
+ axis: DragAxis,
141
+ ): LayoutPoint {
142
+ 'worklet';
143
+ return {
144
+ x: axis === 'y' ? origin.x : point.x,
145
+ y: axis === 'x' ? origin.y : point.y,
146
+ };
147
+ }
@@ -0,0 +1,112 @@
1
+ import type { LayoutValidationIssue } from '../contracts';
2
+ import { isPositiveInteger, isRecord } from '../engine/validation';
3
+
4
+ /** FlatList rendering limits; enabling virtualization preserves the layout API. */
5
+ export type ListVirtualizationOptions = {
6
+ /** Cells rendered initially. Defaults to 12. */
7
+ initialNumToRender?: number;
8
+ /** Maximum cells rendered in each batch. Defaults to 12. */
9
+ maxToRenderPerBatch?: number;
10
+ /** Render window in viewport lengths; must exceed 1. Defaults to 7. */
11
+ windowSize?: number;
12
+ /** Delay between render batches in milliseconds. Defaults to 50. */
13
+ updateCellsBatchingPeriod?: number;
14
+ };
15
+
16
+ export type ListVirtualizationResult =
17
+ | { valid: true; options: Required<ListVirtualizationOptions> | null }
18
+ | { valid: false; issues: LayoutValidationIssue[] };
19
+
20
+ const DEFAULT_OPTIONS: Readonly<Required<ListVirtualizationOptions>> =
21
+ Object.freeze({
22
+ initialNumToRender: 12,
23
+ maxToRenderPerBatch: 12,
24
+ windowSize: 7,
25
+ updateCellsBatchingPeriod: 50,
26
+ });
27
+
28
+ function invalid(message: string): ListVirtualizationResult {
29
+ return {
30
+ valid: false,
31
+ issues: [{ code: 'invalid-configuration', message }],
32
+ };
33
+ }
34
+
35
+ /** Undefined/false selects ScrollView; true or an options object selects FlatList. */
36
+ export function resolveListVirtualization(
37
+ value: unknown,
38
+ ): ListVirtualizationResult {
39
+ if (value === undefined || value === false) {
40
+ return { valid: true, options: null };
41
+ }
42
+ if (value === true) return { valid: true, options: { ...DEFAULT_OPTIONS } };
43
+ if (!isRecord(value)) {
44
+ return invalid('virtualization must be a boolean or an options object.');
45
+ }
46
+ if (
47
+ Object.keys(value).some(
48
+ key =>
49
+ key !== 'initialNumToRender' &&
50
+ key !== 'maxToRenderPerBatch' &&
51
+ key !== 'windowSize' &&
52
+ key !== 'updateCellsBatchingPeriod',
53
+ )
54
+ ) {
55
+ return invalid(
56
+ 'virtualization supports only initialNumToRender, maxToRenderPerBatch, windowSize and updateCellsBatchingPeriod.',
57
+ );
58
+ }
59
+ const initialNumToRender =
60
+ value.initialNumToRender === undefined
61
+ ? DEFAULT_OPTIONS.initialNumToRender
62
+ : value.initialNumToRender;
63
+ const maxToRenderPerBatch =
64
+ value.maxToRenderPerBatch === undefined
65
+ ? DEFAULT_OPTIONS.maxToRenderPerBatch
66
+ : value.maxToRenderPerBatch;
67
+ const windowSize =
68
+ value.windowSize === undefined
69
+ ? DEFAULT_OPTIONS.windowSize
70
+ : value.windowSize;
71
+ const updateCellsBatchingPeriod =
72
+ value.updateCellsBatchingPeriod === undefined
73
+ ? DEFAULT_OPTIONS.updateCellsBatchingPeriod
74
+ : value.updateCellsBatchingPeriod;
75
+ if (!isPositiveInteger(initialNumToRender)) {
76
+ return invalid(
77
+ 'virtualization.initialNumToRender must be a positive safe integer.',
78
+ );
79
+ }
80
+ if (!isPositiveInteger(maxToRenderPerBatch)) {
81
+ return invalid(
82
+ 'virtualization.maxToRenderPerBatch must be a positive safe integer.',
83
+ );
84
+ }
85
+ if (
86
+ typeof windowSize !== 'number' ||
87
+ !Number.isFinite(windowSize) ||
88
+ windowSize <= 1
89
+ ) {
90
+ return invalid(
91
+ 'virtualization.windowSize must be finite and greater than 1.',
92
+ );
93
+ }
94
+ if (
95
+ typeof updateCellsBatchingPeriod !== 'number' ||
96
+ !Number.isFinite(updateCellsBatchingPeriod) ||
97
+ updateCellsBatchingPeriod < 0
98
+ ) {
99
+ return invalid(
100
+ 'virtualization.updateCellsBatchingPeriod must be finite and nonnegative.',
101
+ );
102
+ }
103
+ return {
104
+ valid: true,
105
+ options: {
106
+ initialNumToRender,
107
+ maxToRenderPerBatch,
108
+ windowSize,
109
+ updateCellsBatchingPeriod,
110
+ },
111
+ };
112
+ }