66 lines
2.0 KiB
Swift
66 lines
2.0 KiB
Swift
import SwiftUI
|
|
|
|
struct MeasurementColumn: Identifiable {
|
|
let id = UUID()
|
|
let header: String
|
|
let width: CGFloat
|
|
let alignment: Alignment
|
|
}
|
|
|
|
struct MeasurementTable<Row: Identifiable>: View {
|
|
let columns: [MeasurementColumn]
|
|
let rows: [Row]
|
|
let cellText: (Row, Int) -> String
|
|
|
|
var body: some View {
|
|
VStack(spacing: 0) {
|
|
headerRow
|
|
Divider().background(Color.gray.opacity(0.4))
|
|
ScrollView {
|
|
LazyVStack(spacing: 0) {
|
|
ForEach(Array(rows.enumerated()), id: \.element.id) { idx, row in
|
|
dataRow(row, even: idx % 2 == 0)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
.font(.system(.caption, design: .monospaced))
|
|
#if os(iOS)
|
|
.background(Color(.systemBackground).opacity(0.05))
|
|
#else
|
|
.background(Color(white: 0.1).opacity(0.05))
|
|
#endif
|
|
}
|
|
|
|
private var headerRow: some View {
|
|
HStack(spacing: 0) {
|
|
ForEach(Array(columns.enumerated()), id: \.element.id) { idx, col in
|
|
Text(col.header)
|
|
.fontWeight(.semibold)
|
|
.frame(width: col.width, alignment: col.alignment)
|
|
.foregroundStyle(.secondary)
|
|
if idx < columns.count - 1 {
|
|
Spacer(minLength: 4)
|
|
}
|
|
}
|
|
}
|
|
.padding(.vertical, 6)
|
|
.padding(.horizontal, 8)
|
|
}
|
|
|
|
private func dataRow(_ row: Row, even: Bool) -> some View {
|
|
HStack(spacing: 0) {
|
|
ForEach(Array(columns.enumerated()), id: \.element.id) { idx, col in
|
|
Text(cellText(row, idx))
|
|
.frame(width: col.width, alignment: col.alignment)
|
|
if idx < columns.count - 1 {
|
|
Spacer(minLength: 4)
|
|
}
|
|
}
|
|
}
|
|
.padding(.vertical, 3)
|
|
.padding(.horizontal, 8)
|
|
.background(even ? Color.clear : Color.white.opacity(0.03))
|
|
}
|
|
}
|