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,326 @@
1
+ "use strict";
2
+
3
+ import { DEFAULT_SEARCH_BUDGET } from "../defaults.js";
4
+ import { orderedSlots, packOrderedPlacements, samePlacement, slotIndex, slotPosition } from "./gridPlacements.js";
5
+ import { validateLayoutState } from "./layoutState.js";
6
+ import { validateGridMovementPolicy } from "./movementPolicy.js";
7
+ import { resolveSpatialMove } from "./spatial.js";
8
+ import { isCellPosition, isCellSpan, isPositiveInteger, isRecord } from "./validation.js";
9
+
10
+ /** Caller-owned target grid geometry; list membership never stores a grid span. */
11
+
12
+ function invalid(code, message, context = {}) {
13
+ return {
14
+ status: 'invalid',
15
+ issues: [{
16
+ code,
17
+ message,
18
+ ...context
19
+ }]
20
+ };
21
+ }
22
+ function positioned(placement) {
23
+ return {
24
+ id: placement.itemId,
25
+ span: placement.span,
26
+ position: placement.position,
27
+ ...(placement.placement === undefined ? {} : {
28
+ placement: placement.placement
29
+ }),
30
+ data: undefined
31
+ };
32
+ }
33
+
34
+ /** Remove an item; an ordered grid closes the gap it leaves. */
35
+ function withoutItem(zone, itemId) {
36
+ if (zone.kind === 'list') return {
37
+ ...zone,
38
+ itemIds: zone.itemIds.filter(id => id !== itemId)
39
+ };
40
+ const remaining = zone.placements.filter(item => item.itemId !== itemId);
41
+ if (!zone.itemSpan) return {
42
+ ...zone,
43
+ placements: remaining
44
+ };
45
+ const slots = orderedSlots(zone, zone.itemSpan);
46
+ return {
47
+ ...zone,
48
+ placements: packOrderedPlacements(remaining, zone.itemSpan, slots.perRow, zone.placements)
49
+ };
50
+ }
51
+
52
+ /**
53
+ * Compute an atomic move from one complete baseline. The existing spatial
54
+ * solver owns grid movement policy and bounded search; list membership drops
55
+ * grid geometry. Opaque data is never read, copied, or passed to the solver.
56
+ */
57
+ export function computeLayoutMove(input) {
58
+ if (!isRecord(input)) {
59
+ return invalid('invalid-structure', 'Expected a layout move input object.');
60
+ }
61
+ const validation = validateLayoutState(input.value);
62
+ if (!validation.valid) return {
63
+ status: 'invalid',
64
+ issues: validation.issues
65
+ };
66
+ return computeValidatedLayoutMove(input);
67
+ }
68
+
69
+ /**
70
+ * Internal entry for a caller that has already passed `input.value` through
71
+ * `validateLayoutState` and holds it immutably since (the session keeps its
72
+ * committed value). Only that baseline pass is skipped; the complete candidate
73
+ * is still validated before it is returned.
74
+ */
75
+ export function computeValidatedLayoutMove(input) {
76
+ const policyValidation = validateGridMovementPolicy(input.movementPolicy);
77
+ if (!policyValidation.valid) return {
78
+ status: 'invalid',
79
+ issues: policyValidation.issues
80
+ };
81
+ const searchBudget = input.searchBudget === undefined ? DEFAULT_SEARCH_BUDGET : input.searchBudget;
82
+ if (!isPositiveInteger(searchBudget)) {
83
+ return invalid('invalid-budget', 'searchBudget must be a positive safe integer.');
84
+ }
85
+ if (input.gridItem !== undefined) {
86
+ if (!isRecord(input.gridItem) || !isCellSpan(input.gridItem.span)) {
87
+ return invalid('invalid-span', 'gridItem.span must contain positive safe integer rows and cols.');
88
+ }
89
+ if (input.gridItem.placement !== undefined && input.gridItem.placement !== 'insert' && input.gridItem.placement !== 'exchange') {
90
+ return invalid('invalid-placement', 'gridItem.placement must be insert or exchange when supplied.');
91
+ }
92
+ }
93
+ if (typeof input.itemId !== 'string') {
94
+ return invalid('invalid-structure', 'The moving item ID must be a string.');
95
+ }
96
+ if (!isRecord(input.to) || typeof input.to.zoneId !== 'string') {
97
+ return invalid('invalid-structure', 'A target zone is required.');
98
+ }
99
+ const {
100
+ value,
101
+ itemId,
102
+ to
103
+ } = input;
104
+ const source = value.zones.find(zone => zone.kind === 'list' ? zone.itemIds.includes(itemId) : zone.placements.some(placement => placement.itemId === itemId));
105
+ const target = value.zones.find(zone => zone.id === to.zoneId);
106
+ if (!source || !target) {
107
+ return invalid('invalid-structure', 'The item and target zone must exist.', {
108
+ itemId,
109
+ zoneId: to.zoneId
110
+ });
111
+ }
112
+ if (to.kind !== target.kind) {
113
+ return invalid('invalid-structure', 'Target kind must match its zone.', {
114
+ itemId,
115
+ zoneId: target.id
116
+ });
117
+ }
118
+ const original = source.kind === 'grid' ? source.placements.find(item => item.itemId === itemId) : undefined;
119
+ const from = source.kind === 'list' ? {
120
+ kind: 'list',
121
+ zoneId: source.id,
122
+ index: source.itemIds.indexOf(itemId)
123
+ } : {
124
+ kind: 'grid',
125
+ zoneId: source.id,
126
+ position: {
127
+ ...original.position
128
+ }
129
+ };
130
+ const sameZone = source.id === target.id;
131
+ let nextTarget;
132
+ let resolvedTo;
133
+ let changed;
134
+ let attempts = 0;
135
+ if (target.kind === 'list' && to.kind === 'list') {
136
+ const remaining = target.itemIds.filter(id => id !== itemId);
137
+ if (!Number.isSafeInteger(to.index) || to.index < 0 || to.index > remaining.length) {
138
+ return invalid('invalid-position', 'Insertion index must address the array after removal.', {
139
+ itemId,
140
+ zoneId: target.id
141
+ });
142
+ }
143
+ remaining.splice(to.index, 0, itemId);
144
+ nextTarget = {
145
+ ...target,
146
+ itemIds: remaining
147
+ };
148
+ resolvedTo = {
149
+ kind: 'list',
150
+ zoneId: target.id,
151
+ index: to.index
152
+ };
153
+ changed = !sameZone || from.kind !== 'list' || from.index !== to.index;
154
+ } else if (target.kind === 'grid' && to.kind === 'grid') {
155
+ if (!isCellPosition(to.position)) {
156
+ return invalid('invalid-position', 'A grid target requires safe integer row and col coordinates.', {
157
+ itemId,
158
+ zoneId: target.id
159
+ });
160
+ }
161
+ const descriptor = input.gridItem ?? original;
162
+ if (!descriptor) {
163
+ return invalid('missing-item-span', 'A list-to-grid move requires an explicit gridItem descriptor.', {
164
+ itemId,
165
+ zoneId: target.id
166
+ });
167
+ }
168
+ if (sameZone && original && (descriptor.span.rows !== original.span.rows || descriptor.span.cols !== original.span.cols)) {
169
+ return invalid('span-mismatch', 'An in-grid move cannot change the item footprint.', {
170
+ itemId,
171
+ zoneId: target.id
172
+ });
173
+ }
174
+ if (to.position.row < 0 || to.position.col < 0 || to.position.row > target.rows - descriptor.span.rows || to.position.col > target.columns - descriptor.span.cols) {
175
+ return {
176
+ status: 'impossible',
177
+ attempts
178
+ };
179
+ }
180
+ if (target.itemSpan) {
181
+ // Ordered grid: the target position names a slot after removal; the
182
+ // zone re-packs in reading order and its capacity is the slot count.
183
+ const {
184
+ itemSpan
185
+ } = target;
186
+ if (descriptor.span.rows !== itemSpan.rows || descriptor.span.cols !== itemSpan.cols) return {
187
+ status: 'impossible',
188
+ attempts
189
+ };
190
+ const slots = orderedSlots(target, itemSpan);
191
+ const remaining = target.placements.filter(item => item.itemId !== itemId);
192
+ if (slots.perRow === 0 || slots.rows === 0 || Math.ceil((remaining.length + 1) / slots.perRow) > slots.rows) return {
193
+ status: 'impossible',
194
+ attempts
195
+ };
196
+ const index = slotIndex(to.position, itemSpan, slots.perRow);
197
+ if (index === null || index > remaining.length) return invalid('invalid-position', 'An ordered target must address a slot after removal.', {
198
+ itemId,
199
+ zoneId: target.id
200
+ });
201
+ remaining.splice(index, 0, {
202
+ itemId,
203
+ position: slotPosition(index, itemSpan, slots.perRow),
204
+ span: {
205
+ rows: itemSpan.rows,
206
+ cols: itemSpan.cols
207
+ },
208
+ ...(descriptor.placement === undefined ? {} : {
209
+ placement: descriptor.placement
210
+ })
211
+ });
212
+ const placements = packOrderedPlacements(remaining, itemSpan, slots.perRow, target.placements);
213
+ nextTarget = {
214
+ ...target,
215
+ placements
216
+ };
217
+ resolvedTo = {
218
+ kind: 'grid',
219
+ zoneId: target.id,
220
+ position: slotPosition(index, itemSpan, slots.perRow)
221
+ };
222
+ changed = !sameZone || placements.length !== target.placements.length || placements.some((placement, position) => !samePlacement(placement, target.placements[position]));
223
+ } else {
224
+ const active = {
225
+ id: itemId,
226
+ data: undefined,
227
+ position: {
228
+ ...to.position
229
+ },
230
+ span: {
231
+ ...descriptor.span
232
+ },
233
+ ...(descriptor.placement === undefined ? {} : {
234
+ placement: descriptor.placement
235
+ })
236
+ };
237
+ const result = resolveSpatialMove({
238
+ items: target.placements.filter(item => item.itemId !== itemId).map(positioned),
239
+ active,
240
+ origin: sameZone && original ? positioned(original) : undefined,
241
+ rows: target.rows,
242
+ columns: target.columns,
243
+ searchBudget,
244
+ movementPolicy: input.movementPolicy
245
+ });
246
+ if (result.status !== 'ok') return result;
247
+ attempts = result.attempts;
248
+ const computed = new Map(result.placements.map(item => [item.id, item]));
249
+ const targetIds = target.placements.map(item => item.itemId);
250
+ if (!sameZone) targetIds.push(itemId);
251
+ const existing = new Map(target.placements.map(item => [item.itemId, item]));
252
+ const placements = targetIds.map(id => {
253
+ const item = computed.get(id);
254
+ const placement = {
255
+ itemId: item.id,
256
+ position: {
257
+ ...item.position
258
+ },
259
+ span: {
260
+ ...item.span
261
+ },
262
+ ...(item.placement === undefined ? {} : {
263
+ placement: item.placement
264
+ })
265
+ };
266
+ const previous = existing.get(id);
267
+ return previous && samePlacement(previous, placement) ? previous : placement;
268
+ });
269
+ nextTarget = {
270
+ ...target,
271
+ placements
272
+ };
273
+ resolvedTo = {
274
+ kind: 'grid',
275
+ zoneId: target.id,
276
+ position: {
277
+ ...computed.get(itemId).position
278
+ }
279
+ };
280
+ changed = !sameZone || placements.some((placement, index) => !samePlacement(placement, target.placements[index]));
281
+ }
282
+ } else {
283
+ return invalid('invalid-structure', 'Unsupported target kind.', {
284
+ itemId,
285
+ zoneId: target.id
286
+ });
287
+ }
288
+ if (!changed) {
289
+ return {
290
+ status: 'ok',
291
+ value,
292
+ from,
293
+ to: resolvedTo,
294
+ changed,
295
+ attempts
296
+ };
297
+ }
298
+ if (value.revision === Number.MAX_SAFE_INTEGER) {
299
+ return invalid('invalid-revision', 'The layout revision cannot exceed a safe integer.');
300
+ }
301
+ const candidate = {
302
+ revision: value.revision + 1,
303
+ items: value.items,
304
+ zones: value.zones.map(zone => {
305
+ if (zone.id === target.id) return nextTarget;
306
+ if (zone.id === source.id) return withoutItem(source, itemId);
307
+ return zone;
308
+ })
309
+ };
310
+ const candidateValidation = validateLayoutState(candidate);
311
+ if (!candidateValidation.valid) {
312
+ return {
313
+ status: 'invalid',
314
+ issues: candidateValidation.issues
315
+ };
316
+ }
317
+ return {
318
+ status: 'ok',
319
+ value: candidate,
320
+ from,
321
+ to: resolvedTo,
322
+ changed,
323
+ attempts
324
+ };
325
+ }
326
+ //# sourceMappingURL=layoutMove.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["DEFAULT_SEARCH_BUDGET","orderedSlots","packOrderedPlacements","samePlacement","slotIndex","slotPosition","validateLayoutState","validateGridMovementPolicy","resolveSpatialMove","isCellPosition","isCellSpan","isPositiveInteger","isRecord","invalid","code","message","context","status","issues","positioned","placement","id","itemId","span","position","undefined","data","withoutItem","zone","kind","itemIds","filter","remaining","placements","item","itemSpan","slots","perRow","computeLayoutMove","input","validation","value","valid","computeValidatedLayoutMove","policyValidation","movementPolicy","searchBudget","gridItem","to","zoneId","source","zones","find","includes","some","target","original","from","index","indexOf","sameZone","nextTarget","resolvedTo","changed","attempts","Number","isSafeInteger","length","splice","descriptor","rows","cols","row","col","columns","Math","ceil","active","result","items","map","origin","computed","Map","targetIds","push","existing","get","previous","revision","MAX_SAFE_INTEGER","candidate","candidateValidation"],"sourceRoot":"../../../src","sources":["engine/layoutMove.ts"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,344 @@
1
+ "use strict";
2
+
3
+ import { orderedSlots, slotPosition } from "./gridPlacements.js";
4
+ import { computeZoneLayout } from "./layout.js";
5
+ import { rectanglesOverlap } from "./rectangles.js";
6
+ import { isCellPosition, isCellSpan, isPositiveInteger, isRecord, validateValue } from "./validation.js";
7
+ function addIssue(issues, code, message, context = {}) {
8
+ issues.push({
9
+ code,
10
+ ...context,
11
+ message
12
+ });
13
+ }
14
+ function isRevision(value) {
15
+ return typeof value === 'number' && Number.isSafeInteger(value) && value >= 0;
16
+ }
17
+ function collectReference(itemId, itemIds, references, issues, context) {
18
+ if (typeof itemId !== 'string') {
19
+ addIssue(issues, 'invalid-structure', 'Item reference must be a string.', context);
20
+ return;
21
+ }
22
+ const itemContext = {
23
+ ...context,
24
+ itemId
25
+ };
26
+ if (!itemIds.has(itemId)) {
27
+ addIssue(issues, 'unknown-item', 'Item reference must resolve to a declared item.', itemContext);
28
+ }
29
+ if (references.has(itemId)) {
30
+ addIssue(issues, 'duplicate-reference', 'An item must appear in exactly one placement or list position.', itemContext);
31
+ }
32
+ references.add(itemId);
33
+ }
34
+ function collectGridIssues(zone, itemIds, references, issues, context) {
35
+ const dimensionsValid = isPositiveInteger(zone.rows) && isPositiveInteger(zone.columns);
36
+ if (!dimensionsValid) {
37
+ addIssue(issues, 'invalid-dimension', 'Rows and columns must be positive safe integers.', context);
38
+ }
39
+ if (!Array.isArray(zone.placements)) {
40
+ addIssue(issues, 'invalid-structure', 'Grid placements must be an array.', context);
41
+ return;
42
+ }
43
+ const rectangles = [];
44
+ for (const placement of zone.placements) {
45
+ if (!isRecord(placement)) {
46
+ addIssue(issues, 'invalid-structure', 'Each grid placement must be an object.', context);
47
+ continue;
48
+ }
49
+ collectReference(placement.itemId, itemIds, references, issues, context);
50
+ const itemContext = {
51
+ ...context,
52
+ ...(typeof placement.itemId === 'string' ? {
53
+ itemId: placement.itemId
54
+ } : {})
55
+ };
56
+ if (placement.placement !== undefined && placement.placement !== 'insert' && placement.placement !== 'exchange') {
57
+ addIssue(issues, 'invalid-placement', 'Placement must be insert or exchange when provided.', itemContext);
58
+ }
59
+ const spanValid = isCellSpan(placement.span);
60
+ const positionValid = isCellPosition(placement.position);
61
+ if (!spanValid) {
62
+ addIssue(issues, 'invalid-span', 'Span must contain positive safe integer rows and cols.', itemContext);
63
+ }
64
+ if (!positionValid) {
65
+ addIssue(issues, 'invalid-position', 'Position must contain safe integer row and col.', itemContext);
66
+ }
67
+ if (!spanValid || !positionValid || !dimensionsValid) continue;
68
+ const rectangle = placement;
69
+ if (rectangle.position.row < 0 || rectangle.position.col < 0 || rectangle.position.row > zone.rows - rectangle.span.rows || rectangle.position.col > zone.columns - rectangle.span.cols) {
70
+ addIssue(issues, 'out-of-bounds', 'Grid placement must fit inside its zone.', itemContext);
71
+ continue;
72
+ }
73
+ for (const previous of rectangles) {
74
+ if (rectanglesOverlap(previous, rectangle)) {
75
+ addIssue(issues, 'overlap', `Grid placement overlaps an earlier item (${previous.itemId}).`, itemContext);
76
+ }
77
+ }
78
+ rectangles.push(rectangle);
79
+ }
80
+ if (zone.itemSpan !== undefined) collectOrderedIssues(zone, dimensionsValid, issues, context);
81
+ }
82
+
83
+ /** An ordered grid keeps one span per item, reading-order slots and its capacity. */
84
+ function collectOrderedIssues(zone, dimensionsValid, issues, context) {
85
+ const itemSpan = zone.itemSpan;
86
+ if (!isCellSpan(itemSpan)) {
87
+ addIssue(issues, 'invalid-span', 'Ordered itemSpan must contain positive safe integer rows and cols.', context);
88
+ return;
89
+ }
90
+ const placements = zone.placements;
91
+ for (const placement of placements) {
92
+ if (!isRecord(placement) || !isCellSpan(placement.span)) continue;
93
+ if (placement.span.rows !== itemSpan.rows || placement.span.cols !== itemSpan.cols) addIssue(issues, 'span-mismatch', 'Every ordered item span must equal the zone itemSpan.', {
94
+ ...context,
95
+ ...(typeof placement.itemId === 'string' ? {
96
+ itemId: placement.itemId
97
+ } : {})
98
+ });
99
+ }
100
+ if (!dimensionsValid) return;
101
+ const slots = orderedSlots({
102
+ rows: zone.rows,
103
+ columns: zone.columns
104
+ }, itemSpan);
105
+ // Avoid multiplying dimensions: their product can overflow despite valid inputs.
106
+ if (placements.length > 0 && (slots.perRow === 0 || Math.ceil(placements.length / slots.perRow) > slots.rows)) {
107
+ addIssue(issues, 'capacity-exceeded', 'Ordered item count exceeds the available slots.', context);
108
+ return;
109
+ }
110
+ placements.forEach((placement, index) => {
111
+ if (!isRecord(placement) || !isCellPosition(placement.position)) return;
112
+ const expected = slotPosition(index, itemSpan, slots.perRow);
113
+ if (placement.position.row !== expected.row || placement.position.col !== expected.col) addIssue(issues, 'invalid-position', 'Ordered placements must occupy reading-order slots.', {
114
+ ...context,
115
+ ...(typeof placement.itemId === 'string' ? {
116
+ itemId: placement.itemId
117
+ } : {})
118
+ });
119
+ });
120
+ }
121
+
122
+ /** Validates the complete candidate without inspecting data or modifying inputs. */
123
+ export function validateLayoutState(state) {
124
+ const issues = [];
125
+ if (!isRecord(state)) {
126
+ return {
127
+ valid: false,
128
+ issues: [{
129
+ code: 'invalid-structure',
130
+ message: 'Layout state must be an object.'
131
+ }]
132
+ };
133
+ }
134
+ if (!isRevision(state.revision)) {
135
+ addIssue(issues, 'invalid-revision', 'Layout revision must be a nonnegative safe integer.');
136
+ }
137
+ const itemIds = new Set();
138
+ if (!Array.isArray(state.items)) {
139
+ addIssue(issues, 'invalid-structure', 'Layout items must be an array.');
140
+ } else {
141
+ for (const item of state.items) {
142
+ if (!isRecord(item) || typeof item.id !== 'string') {
143
+ addIssue(issues, 'invalid-structure', 'Each item must be an object with a string ID.');
144
+ } else if (itemIds.has(item.id)) {
145
+ addIssue(issues, 'duplicate-id', 'Item ID must be globally unique.', {
146
+ itemId: item.id
147
+ });
148
+ } else {
149
+ itemIds.add(item.id);
150
+ }
151
+ // Do not read item.data, including getters or serialization hooks.
152
+ }
153
+ }
154
+ const zoneIds = new Set();
155
+ const references = new Set();
156
+ if (!Array.isArray(state.zones)) {
157
+ addIssue(issues, 'invalid-structure', 'Layout zones must be an array.');
158
+ } else {
159
+ for (const zone of state.zones) {
160
+ if (!isRecord(zone)) {
161
+ addIssue(issues, 'invalid-structure', 'Each zone must be an object.');
162
+ continue;
163
+ }
164
+ const context = typeof zone.id === 'string' ? {
165
+ zoneId: zone.id
166
+ } : {};
167
+ if (typeof zone.id !== 'string') {
168
+ addIssue(issues, 'invalid-structure', 'Zone ID must be a string.');
169
+ } else if (zoneIds.has(zone.id)) {
170
+ addIssue(issues, 'duplicate-id', 'Zone ID must be globally unique.', context);
171
+ } else {
172
+ zoneIds.add(zone.id);
173
+ }
174
+ if (zone.kind === 'grid') {
175
+ collectGridIssues(zone, itemIds, references, issues, context);
176
+ } else if (zone.kind === 'list') {
177
+ if (zone.orientation !== 'vertical' && zone.orientation !== 'horizontal') {
178
+ addIssue(issues, 'invalid-orientation', 'List orientation must be vertical or horizontal.', context);
179
+ }
180
+ if (!Array.isArray(zone.itemIds)) {
181
+ addIssue(issues, 'invalid-structure', 'List item IDs must be an array.', context);
182
+ } else {
183
+ for (const itemId of zone.itemIds) {
184
+ collectReference(itemId, itemIds, references, issues, context);
185
+ }
186
+ }
187
+ } else {
188
+ addIssue(issues, 'invalid-structure', 'Zone kind must be grid or list.', context);
189
+ }
190
+ }
191
+ }
192
+ for (const itemId of itemIds) {
193
+ if (!references.has(itemId)) {
194
+ addIssue(issues, 'unplaced-item', 'Every declared item must belong to a zone.', {
195
+ itemId
196
+ });
197
+ }
198
+ }
199
+ return issues.length === 0 ? {
200
+ valid: true
201
+ } : {
202
+ valid: false,
203
+ issues
204
+ };
205
+ }
206
+
207
+ /**
208
+ * Imports existing spatial/ordered grids into explicit cell placements. Ordered
209
+ * grids keep their rendered positions and their `itemSpan`, so `toGridValue`
210
+ * restores the ordered strategy; they do not become one-dimensional lists.
211
+ * Proposal responses are session metadata and are not copied into layout state.
212
+ */
213
+ export function fromGridValue(value, revision) {
214
+ const validation = validateValue(value);
215
+ if (!validation.valid) return validation;
216
+ const nextRevision = revision ?? value.revision ?? 0;
217
+ if (!isRevision(nextRevision)) {
218
+ return {
219
+ valid: false,
220
+ issues: [{
221
+ code: 'invalid-revision',
222
+ message: 'Layout revision must be a nonnegative safe integer.'
223
+ }]
224
+ };
225
+ }
226
+ const items = [];
227
+ const zones = [];
228
+ for (const zone of value.zones) {
229
+ const layout = computeZoneLayout(zone);
230
+ if (!layout.valid) return layout;
231
+ zones.push({
232
+ id: zone.id,
233
+ kind: 'grid',
234
+ rows: zone.rows,
235
+ columns: zone.columns,
236
+ ...(zone.strategy === 'ordered' ? {
237
+ itemSpan: {
238
+ rows: zone.itemSpan.rows,
239
+ cols: zone.itemSpan.cols
240
+ }
241
+ } : {}),
242
+ placements: layout.items.map(item => {
243
+ items.push({
244
+ id: item.id,
245
+ data: item.data
246
+ });
247
+ return {
248
+ itemId: item.id,
249
+ position: {
250
+ ...item.position
251
+ },
252
+ span: {
253
+ ...item.span
254
+ },
255
+ ...(item.placement === undefined ? {} : {
256
+ placement: item.placement
257
+ })
258
+ };
259
+ })
260
+ });
261
+ }
262
+ return {
263
+ valid: true,
264
+ value: {
265
+ revision: nextRevision,
266
+ items,
267
+ zones
268
+ }
269
+ };
270
+ }
271
+
272
+ /**
273
+ * Exports all-grid state: zones with `itemSpan` become ordered grids again and
274
+ * the rest spatial grids; list zones require the future list adapter.
275
+ */
276
+ export function toGridValue(state) {
277
+ const validation = validateLayoutState(state);
278
+ if (!validation.valid) return validation;
279
+ const unsupported = state.zones.filter(zone => zone.kind !== 'grid');
280
+ if (unsupported.length > 0) {
281
+ return {
282
+ valid: false,
283
+ issues: unsupported.map(zone => ({
284
+ code: 'unsupported-zone',
285
+ zoneId: zone.id,
286
+ message: 'The grid adapter cannot convert list zones.'
287
+ }))
288
+ };
289
+ }
290
+ return {
291
+ valid: true,
292
+ value: layoutToGridValue(state)
293
+ };
294
+ }
295
+
296
+ /**
297
+ * Internal unchecked export for a state that only contains grid zones and was
298
+ * validated on the way in (the controller adapter converts every candidate).
299
+ */
300
+ export function layoutToGridValue(state) {
301
+ const items = new Map(state.items.map(item => [item.id, item]));
302
+ return {
303
+ revision: state.revision,
304
+ zones: state.zones.map(zone => zone.itemSpan ? {
305
+ id: zone.id,
306
+ strategy: 'ordered',
307
+ rows: zone.rows,
308
+ columns: zone.columns,
309
+ itemSpan: {
310
+ rows: zone.itemSpan.rows,
311
+ cols: zone.itemSpan.cols
312
+ },
313
+ items: zone.placements.map(placement => ({
314
+ id: placement.itemId,
315
+ data: items.get(placement.itemId).data,
316
+ span: {
317
+ ...placement.span
318
+ },
319
+ ...(placement.placement === undefined ? {} : {
320
+ placement: placement.placement
321
+ })
322
+ }))
323
+ } : {
324
+ id: zone.id,
325
+ strategy: 'spatial',
326
+ rows: zone.rows,
327
+ columns: zone.columns,
328
+ items: zone.placements.map(placement => ({
329
+ id: placement.itemId,
330
+ data: items.get(placement.itemId).data,
331
+ position: {
332
+ ...placement.position
333
+ },
334
+ span: {
335
+ ...placement.span
336
+ },
337
+ ...(placement.placement === undefined ? {} : {
338
+ placement: placement.placement
339
+ })
340
+ }))
341
+ })
342
+ };
343
+ }
344
+ //# sourceMappingURL=layoutState.js.map