81 lines
2.4 KiB
Swift
81 lines
2.4 KiB
Swift
//
|
|
// List.swift
|
|
// MacBackend
|
|
//
|
|
// Created by david-swift on 23.11.2024.
|
|
//
|
|
|
|
import SwiftUI
|
|
|
|
/// A list widget.
|
|
public struct List<Element>: SwiftUIWidget where Element: Identifiable {
|
|
|
|
/// The elements.
|
|
var elements: [Element]
|
|
/// The selected element.
|
|
var selection: Meta.Binding<Element.ID?>
|
|
/// The content for an element.
|
|
var content: (Element) -> Body
|
|
/// The action at the bottom.
|
|
var bottomAction: ((String, Icon), () -> Void)?
|
|
|
|
/// The wrapped views.
|
|
public var wrappedViews: [String: any Meta.AnyView] {
|
|
elements.reduce(into: [:]) { partialResult, element in
|
|
partialResult["\(element.id)"] = content(element)
|
|
}
|
|
}
|
|
|
|
/// Initialize a list widget.
|
|
/// - Parameters:
|
|
/// - elements: The elements.
|
|
/// - selection: The selected element.
|
|
/// - content: The content for an element.
|
|
public init(
|
|
_ elements: [Element],
|
|
selection: Meta.Binding<Element.ID?>,
|
|
@Meta.ViewBuilder content: @escaping (Element) -> Body
|
|
) {
|
|
self.elements = elements
|
|
self.content = content
|
|
self.selection = selection
|
|
}
|
|
|
|
/// Get the SwiftUI view.
|
|
/// - Parameter properties: The widget data.
|
|
/// - Returns: The SwiftUI view.
|
|
public static func view(properties: Self) -> some SwiftUI.View {
|
|
SwiftUI.List(properties.elements, selection: properties.selection.swiftUI) { element in
|
|
MacBackendView("\(element.id)")
|
|
}
|
|
.safeAreaInset(edge: .bottom, alignment: .leading) {
|
|
if let action = properties.bottomAction {
|
|
SwiftUI.Button {
|
|
action.1()
|
|
} label: {
|
|
SwiftUI.Label {
|
|
SwiftUI.Text(action.0.0)
|
|
} icon: {
|
|
action.0.1.image
|
|
}
|
|
}
|
|
.buttonStyle(.plain)
|
|
.foregroundStyle(.secondary)
|
|
.symbolVariant(.circle)
|
|
.padding([.bottom, .leading], 7)
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Add a button to the bottom of the list.
|
|
/// - Parameters:
|
|
/// - label: The button's label.
|
|
/// - icon: The button's icon.
|
|
/// - handler: The handler.
|
|
/// - Returns: The list.
|
|
public func bottomAction(_ label: String, icon: Icon, handler: @escaping () -> Void) -> Self {
|
|
modify { $0.bottomAction = ((label, icon), handler) }
|
|
}
|
|
|
|
}
|