david-swift e989bea14e
All checks were successful
Deploy Docs / publish (push) Successful in 2m38s
Initial commit
2024-12-02 22:14:13 +01:00

165 lines
4.8 KiB
Swift

//
// Alert.swift
// MacBackend
//
// Created by david-swift on 01.12.2024.
//
import SwiftUI
/// The alert view.
public struct Alert: SwiftUIWidget {
/// The alert's title.
var title: String
/// The alert's description.
var description: String
/// Whether the alert is presented.
var isPresented: Meta.Binding<Bool>
/// The alert's actions.
var actions: [Action] = []
/// The wrapped view.
var child: Meta.AnyView
/// The wrapped views.
public var wrappedViews: [String: Meta.AnyView] {
[.mainContent: child]
}
/// An alert action.
enum Action {
/// A regular button.
case button(button: Button)
/// A cancel button.
case cancel(button: Button)
/// A destructive button.
case destructive(button: Button)
/// Get the SwiftUI button.
@SwiftUI.ViewBuilder var button: some SwiftUI.View {
switch self {
case let .button(button):
button.button()
case let .cancel(button):
button.button(cancel: true)
case let .destructive(button):
button.button(destructive: true)
}
}
}
/// The button.
struct Button {
/// The button's label.
var label: String
/// The button's action.
var action: () -> Void
/// Whether it is the default action.
var defaultAction: Bool
/// Get the SwiftUI button.
/// - Parameters:
/// - cancel: Whether it is the cancel action.
/// - destructive: Whether it is a destructive action.
/// - Returns: The SwiftUI view.
@SwiftUI.ViewBuilder
func button(cancel: Bool = false, destructive: Bool = false) -> some SwiftUI.View {
let button = SwiftUI.Button(
label,
role: cancel ? .cancel : (destructive ? .destructive : nil),
action: action
)
if defaultAction {
button
.keyboardShortcut(.defaultAction)
} else {
button
}
}
}
/// Get the SwiftUI view.
/// - Parameter properties: The widget data.
/// - Returns: The SwiftUI view.
public static func view(properties: Self) -> some SwiftUI.View {
MacBackendView(.mainContent)
.alert(properties.title, isPresented: properties.isPresented.swiftUI) {
ForEach(Array(properties.actions.enumerated()), id: \.offset) { action in
action.element.button
}
} message: {
SwiftUI.Text(properties.description)
}
}
/// Add a button to the alert.
/// - Parameters:
/// - label: The button's label.
/// - defaultAction: Whether it is a default action.
/// - action: The handler.
/// - Returns: The alert.
public func button(
_ label: String,
default defaultAction: Bool = false,
action: @escaping () -> Void
) -> Self {
modify { alert in
alert.actions.append(.button(button: .init(label: label, action: action, defaultAction: defaultAction)))
}
}
/// Add a cancel button to the alert.
/// - Parameters:
/// - label: The button's label.
/// - defaultAction: Whether it is a default action.
/// - action: The handler.
/// - Returns: The alert.
public func cancelButton(
_ label: String,
default defaultAction: Bool = false,
action: @escaping () -> Void
) -> Self {
modify { alert in
alert.actions.append(.cancel(button: .init(label: label, action: action, defaultAction: defaultAction)))
}
}
/// Add a destructive button to the alert.
/// - Parameters:
/// - label: The button's label.
/// - defaultAction: Whether it is a default action.
/// - action: The handler.
/// - Returns: The alert.
public func destructiveButton(
_ label: String,
default defaultAction: Bool = false,
action: @escaping () -> Void
) -> Self {
modify { alert in
alert.actions
.append(.destructive(button: .init(label: label, action: action, defaultAction: defaultAction)))
}
}
}
extension Meta.AnyView {
// swiftlint:disable function_default_parameter_at_end
/// Add an alert to a view.
/// - Parameters:
/// - title: The title.
/// - description: The description.
/// - isPresented: Whether the alert is visible.
/// - Returns: The alert.
public func alert(_ title: String, description: String = "", isPresented: Meta.Binding<Bool>) -> Alert {
.init(title: title, description: description, isPresented: isPresented, child: self)
}
// swiftlint:enable function_default_parameter_at_end
}