(layout, widgets, bp)
| 113 | } |
| 114 | |
| 115 | export function tidyLayout(layout, widgets, bp) { |
| 116 | const bpCols = cols[bp] || 12; |
| 117 | const items = Array.isArray(layout) ? layout : []; |
| 118 | // Force single column on mobile breakpoints |
| 119 | if (bp === "xs" || bp === "xxs") { |
| 120 | // Stack items vertically full width, preserving item heights |
| 121 | const ordered = cloneItems(items).sort((a, b) => (a.y - b.y) || (a.x - b.x) || `${a.i}`.localeCompare(`${b.i}`)); |
| 122 | let cursorY = 0; |
| 123 | const stacked = ordered.map((it) => { |
| 124 | const h = Math.max(1, it.h || 1); |
| 125 | const placed = { ...it, x: 0, y: cursorY, w: bpCols, h }; |
| 126 | cursorY += h; |
| 127 | return placed; |
| 128 | }); |
| 129 | return stacked; |
| 130 | } |
| 131 | // MVP: simple normalize + compact pass left-to-right and up. |
| 132 | // Future: implement gap-row scanning, stretching, equalization per spec. |
| 133 | return normalizeAndCompact(items, bpCols); |
| 134 | } |
| 135 | |
| 136 | export function placeNewWidget(existingLayout, widget, bp) { |
| 137 | const bpCols = cols[bp] || 12; |
no test coverage detected