jellyflood/Swiftfin/Components/ListRow.swift

74 lines
2.0 KiB
Swift

//
// Swiftfin is subject to the terms of the Mozilla Public
// License, v2.0. If a copy of the MPL was not distributed with this
// file, you can obtain one at https://mozilla.org/MPL/2.0/.
//
// Copyright (c) 2025 Jellyfin & Jellyfin Contributors
//
import SwiftUI
// TODO: come up with better name along with `ListRowButton`
// Meant to be used when making a custom list without `List` or `Form`
struct ListRow<Leading: View, Content: View>: View {
@State
private var contentSize: CGSize = .zero
private let leading: Leading
private let content: Content
private var action: () -> Void
private var insets: EdgeInsets
private var isSeparatorVisible: Bool
var body: some View {
ZStack(alignment: .bottomTrailing) {
Button(action: action) {
HStack(alignment: .center, spacing: EdgeInsets.edgePadding) {
leading
content
.frame(maxHeight: .infinity)
.trackingSize($contentSize)
}
.padding(insets)
}
.foregroundStyle(.primary, .secondary)
.contentShape(.contextMenuPreview, Rectangle())
Color.secondarySystemFill
.frame(width: contentSize.width, height: 1)
.padding(.trailing, insets.trailing)
.isVisible(isSeparatorVisible)
}
}
}
extension ListRow {
init(
insets: EdgeInsets = .zero,
@ViewBuilder leading: @escaping () -> Leading,
@ViewBuilder content: @escaping () -> Content
) {
self.init(
leading: leading(),
content: content(),
action: {},
insets: insets,
isSeparatorVisible: true
)
}
func isSeparatorVisible(_ isVisible: Bool) -> Self {
copy(modifying: \.isSeparatorVisible, with: isVisible)
}
func onSelect(perform action: @escaping () -> Void) -> Self {
copy(modifying: \.action, with: action)
}
}