import SwiftUI #warning("Remove button types and just make styles stand-alone") /// A name space for edit button styles. public enum EditButtonType { } /// A name space for info button styles. public enum InfoButtonType { } /// A name space for info button styles. public enum NextButtonType { } /// A name space for info button styles. public enum ResetButtonType { } /// A type erased primitive button style, used to style buttons in a namespace. @MainActor public struct AnyPrimitiveButtonStyle: PrimitiveButtonStyle { private let _makeBody: (Configuration) -> AnyView public init(_ style: S) { self._makeBody = { configuration in AnyView(style.makeBody(configuration: configuration)) } } public func makeBody(configuration: Configuration) -> some View { self._makeBody(configuration) } } /// The default info button style. @MainActor public struct DefaultInfoButtonStyle: PrimitiveButtonStyle { let color: Color let font: Font let labelStyle: Style init( color: Color = .accentColor, font: Font = .title2, labelStyle: Style ) { self.color = color self.font = font self.labelStyle = labelStyle } public func makeBody(configuration: Configuration) -> some View { Button(role: configuration.role, action: configuration.trigger) { configuration.label .font(font) .foregroundStyle(color) .labelStyle(labelStyle) } .buttonStyle(.plain) } } public struct DefaultNextButtonStyle: PrimitiveButtonStyle { let buttonStyle: ButtonStyle let labelStyle: Label public init(buttonStyle: ButtonStyle, labelStyle: Label) { self.buttonStyle = buttonStyle self.labelStyle = labelStyle } public func makeBody(configuration: Configuration) -> some View { Button(role: configuration.role, action: configuration.trigger) { configuration.label } .labelStyle(labelStyle) .buttonStyle(buttonStyle) } } extension DefaultNextButtonStyle where ButtonStyle == BorderedProminentButtonStyle, Label == NextLabelStyle { init() { self.init(buttonStyle: .borderedProminent, labelStyle: .nextLabel()) } } public struct ToolbarNextButtonStyle: PrimitiveButtonStyle { public func makeBody(configuration: Configuration) -> some View { Button(role: configuration.role, action: configuration.trigger) { configuration.label .foregroundStyle(Color.accentColor) } .labelStyle(NextLabelStyle()) .buttonStyle(.plain) } } extension AnyPrimitiveButtonStyle { public static var toolbar: Self { .init(ToolbarNextButtonStyle()) } } private struct InfoButtonStyleKey: @preconcurrency EnvironmentKey { @MainActor static var defaultValue: AnyPrimitiveButtonStyle { AnyPrimitiveButtonStyle(DefaultInfoButtonStyle(labelStyle: .iconOnly)) } } private struct NextButtonStyleKey: EnvironmentKey { static var defaultValue: AnyPrimitiveButtonStyle { MainActor.assumeIsolated { AnyPrimitiveButtonStyle( DefaultNextButtonStyle() ) } } } private struct ResetButtonStyleKey: EnvironmentKey { static let defaultValue = MainActor.assumeIsolated { AnyPrimitiveButtonStyle(.borderedProminent) } } extension EnvironmentValues { // @Entry var infoButtonStyle: AnyButtonStyle = AnyButtonStyle.default @Entry var editButtonStyle = MainActor.assumeIsolated { AnyPrimitiveButtonStyle(DefaultInfoButtonStyle(labelStyle: .automatic)) } var infoButtonStyle: AnyPrimitiveButtonStyle { get { self[InfoButtonStyleKey.self] } set { self[InfoButtonStyleKey.self] = newValue } } var nextButtonStyle: AnyPrimitiveButtonStyle { get { self[NextButtonStyleKey.self] } set { self[NextButtonStyleKey.self] = newValue } } var resetButtonStyle: AnyPrimitiveButtonStyle { get { self[ResetButtonStyleKey.self] } set { self[ResetButtonStyleKey.self] = newValue } } } extension View { /// Sets the button style for the ``EditButton`` type. public func editButtonStyle(_ style: AnyPrimitiveButtonStyle) -> some View { environment(\.editButtonStyle, style) } /// Sets the button style for the ``EditButton`` type. public func editButtonStyle(_ style: S) -> some View { editButtonStyle(AnyPrimitiveButtonStyle(style)) } /// Sets the button style for the ``InfoButton`` type. public func infoButtonStyle(_ style: AnyPrimitiveButtonStyle) -> some View { environment(\.infoButtonStyle, style) } /// Sets the button style for the ``InfoButton`` type. public func infoButtonStyle(_ style: S) -> some View { infoButtonStyle(AnyPrimitiveButtonStyle(style)) } /// Sets the button style for the ``NextButton`` type. public func nextButtonStyle(_ style: AnyPrimitiveButtonStyle) -> some View { environment(\.nextButtonStyle, style) } /// Sets the button style for the ``NextButton`` type. public func nextButtonStyle(_ style: S) -> some View { nextButtonStyle(AnyPrimitiveButtonStyle(style)) } /// Sets the button style for the ``ResetButton`` type. public func resetButtonStyle(_ style: AnyPrimitiveButtonStyle) -> some View { environment(\.resetButtonStyle, style) } /// Sets the button style for the ``ResetButton`` type. public func resetButtonStyle(_ style: S) -> some View { resetButtonStyle(AnyPrimitiveButtonStyle(style)) } }