import SwiftUI /// All card positions are calculated in the same transaction as the bookmark flight. struct LeadCardGrid: Layout { let columnCount: Int var spacing: CGFloat = 16 func sizeThatFits(proposal: ProposedViewSize, subviews: Subviews, cache: inout ()) -> CGSize { let width = proposal.width ?? 310 let frames = frames(width: width, subviews: subviews) return CGSize(width: width, height: frames.map(\.maxY).max() ?? 0) } func placeSubviews(in bounds: CGRect, proposal: ProposedViewSize, subviews: Subviews, cache: inout ()) { let frames = frames(width: bounds.width, subviews: subviews) for (index, subview) in subviews.enumerated() { let frame = frames[index] subview.place(at: CGPoint(x: bounds.minX + frame.minX, y: bounds.minY + frame.minY), anchor: .topLeading, proposal: ProposedViewSize(width: frame.width, height: frame.height)) } } private func frames(width: CGFloat, subviews: Subviews) -> [CGRect] { let columns = max(1, columnCount) let cardWidth = max(0, (width - CGFloat(columns - 1) * spacing) / CGFloat(columns)) var frames: [CGRect] = [] var rowY: CGFloat = 0 var rowHeight: CGFloat = 0 for (index, subview) in subviews.enumerated() { let column = index % columns if column == 0 && index > 0 { rowY += rowHeight + spacing rowHeight = 0 } let size = subview.sizeThatFits(ProposedViewSize(width: cardWidth, height: nil)) frames.append(CGRect(x: CGFloat(column) * (cardWidth + spacing), y: rowY, width: cardWidth, height: size.height)) rowHeight = max(rowHeight, size.height) } return frames } }