* Compact items in wrap order, filling gaps from left-to-right, top-to-bottom. * All items are assumed to be 1x1 for wrap mode to work correctly.
(layout: Layout, cols: number)
| 57 | * All items are assumed to be 1x1 for wrap mode to work correctly. |
| 58 | */ |
| 59 | function compactWrap(layout: Layout, cols: number): LayoutItem[] { |
| 60 | if (layout.length === 0) return []; |
| 61 | |
| 62 | const sorted = sortByWrapOrder(layout); |
| 63 | const out: LayoutItem[] = new Array(layout.length); |
| 64 | const statics = sorted.filter(item => item.static); |
| 65 | |
| 66 | // Track which positions are occupied by static items |
| 67 | const staticPositions = new Set<number>(); |
| 68 | for (const s of statics) { |
| 69 | // For static items, mark all cells they occupy |
| 70 | for (let dy = 0; dy < s.h; dy++) { |
| 71 | for (let dx = 0; dx < s.w; dx++) { |
| 72 | staticPositions.add((s.y + dy) * cols + (s.x + dx)); |
| 73 | } |
| 74 | } |
| 75 | } |
| 76 | |
| 77 | let nextPos = 0; |
| 78 | |
| 79 | for (let i = 0; i < sorted.length; i++) { |
| 80 | const sortedItem = sorted[i]; |
| 81 | if (sortedItem === undefined) continue; |
| 82 | |
| 83 | const l = cloneLayoutItem(sortedItem); |
| 84 | |
| 85 | if (l.static) { |
| 86 | // Static items stay in place |
| 87 | const originalIndex = layout.indexOf(sortedItem); |
| 88 | out[originalIndex] = l; |
| 89 | l.moved = false; |
| 90 | continue; |
| 91 | } |
| 92 | |
| 93 | // Find next available position that doesn't conflict with statics |
| 94 | while (staticPositions.has(nextPos)) { |
| 95 | nextPos++; |
| 96 | } |
| 97 | |
| 98 | // For items larger than 1x1, we need to check if the full item fits |
| 99 | const { x, y } = fromWrapPosition(nextPos, cols); |
| 100 | |
| 101 | // Check if item would overflow the row |
| 102 | if (x + l.w > cols) { |
| 103 | // Move to start of next row |
| 104 | nextPos = (y + 1) * cols; |
| 105 | // Skip any static positions on the new row |
| 106 | while (staticPositions.has(nextPos)) { |
| 107 | nextPos++; |
| 108 | } |
| 109 | } |
| 110 | |
| 111 | const newCoords = fromWrapPosition(nextPos, cols); |
| 112 | (l as Mutable<LayoutItem>).x = newCoords.x; |
| 113 | (l as Mutable<LayoutItem>).y = newCoords.y; |
| 114 | |
| 115 | // Advance past this item |
| 116 | nextPos += l.w; |
no test coverage detected
searching dependent graphs…