197 lines
6.1 KiB
Swift
197 lines
6.1 KiB
Swift
import SwiftUI
|
|
|
|
/// 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 button style, used to style buttons in a namespace.
|
|
//@MainActor
|
|
//public struct AnyButtonStyle<ButtonType>: ButtonStyle, Sendable {
|
|
// private let _makeBody: @Sendable (Configuration) -> AnyView
|
|
//
|
|
// public init<S: ButtonStyle>(_ style: S) where S: Sendable, S.Body: Sendable {
|
|
// self._makeBody = { configuration in
|
|
// AnyView(style.makeBody(configuration: configuration))
|
|
// }
|
|
// }
|
|
//
|
|
// public func makeBody(configuration: Configuration) -> some View {
|
|
// self._makeBody(configuration)
|
|
// }
|
|
//}
|
|
|
|
/// A type erased primitive button style, used to style buttons in a namespace.
|
|
@MainActor
|
|
public struct AnyPrimitiveButtonStyle<ButtonType>: PrimitiveButtonStyle {
|
|
private let _makeBody: (Configuration) -> AnyView
|
|
|
|
public init<S: PrimitiveButtonStyle>(_ 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<Style: LabelStyle>: 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)
|
|
}
|
|
// configuration.label
|
|
// .font(font)
|
|
// .foregroundStyle(color.opacity(configuration.isPressed ? 0.5 : 1))
|
|
// .labelStyle(labelStyle)
|
|
// .scaleEffect(configuration.isPressed ? 0.8 : 1)
|
|
}
|
|
}
|
|
|
|
public struct DefaultNextButtonStyle<ButtonStyle: PrimitiveButtonStyle, Label: LabelStyle>: 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<NextButtonType> {
|
|
public static var toolbar: Self { .init(ToolbarNextButtonStyle()) }
|
|
}
|
|
|
|
//extension AnyButtonStyle where ButtonType == InfoButtonType {
|
|
// public static var `default`: Self {
|
|
// .init(DefaultInfoButtonStyle<IconOnlyLabelStyle>(labelStyle: .iconOnly))
|
|
// }
|
|
//
|
|
// public static func `default`<S: LabelStyle>(color: Color, font: Font, labelStyle: S) -> Self {
|
|
// .init(DefaultInfoButtonStyle<S>(color: color, font: font, labelStyle: labelStyle))
|
|
// }
|
|
//}
|
|
|
|
private struct InfoButtonStyleKey: @preconcurrency EnvironmentKey {
|
|
@MainActor
|
|
static var defaultValue: AnyPrimitiveButtonStyle<InfoButtonType> {
|
|
AnyPrimitiveButtonStyle<InfoButtonType>(DefaultInfoButtonStyle(labelStyle: .iconOnly))
|
|
}
|
|
}
|
|
|
|
private struct NextButtonStyleKey: EnvironmentKey {
|
|
@MainActor
|
|
static var defaultValue: AnyPrimitiveButtonStyle<NextButtonType> {
|
|
AnyPrimitiveButtonStyle<NextButtonType>(
|
|
DefaultNextButtonStyle<BorderedProminentButtonStyle, NextLabelStyle>()
|
|
)
|
|
}
|
|
}
|
|
|
|
private struct ResetButtonStyleKey: EnvironmentKey {
|
|
static let defaultValue = AnyPrimitiveButtonStyle<ResetButtonType>(.borderedProminent)
|
|
}
|
|
|
|
extension EnvironmentValues {
|
|
// @Entry var infoButtonStyle: AnyButtonStyle<InfoButtonType> = AnyButtonStyle.default
|
|
|
|
var infoButtonStyle: AnyPrimitiveButtonStyle<InfoButtonType> {
|
|
get { self[InfoButtonStyleKey.self] }
|
|
set { self[InfoButtonStyleKey.self] = newValue }
|
|
}
|
|
|
|
var nextButtonStyle: AnyPrimitiveButtonStyle<NextButtonType> {
|
|
get { self[NextButtonStyleKey.self] }
|
|
set { self[NextButtonStyleKey.self] = newValue }
|
|
}
|
|
|
|
var resetButtonStyle: AnyPrimitiveButtonStyle<ResetButtonType> {
|
|
get { self[ResetButtonStyleKey.self] }
|
|
set { self[ResetButtonStyleKey.self] = newValue }
|
|
}
|
|
}
|
|
|
|
extension View {
|
|
|
|
/// Sets the button style for the ``InfoButton`` type.
|
|
public func infoButtonStyle(_ style: AnyPrimitiveButtonStyle<InfoButtonType>) -> some View {
|
|
environment(\.infoButtonStyle, style)
|
|
}
|
|
|
|
/// Sets the button style for the ``InfoButton`` type.
|
|
public func infoButtonStyle<S: PrimitiveButtonStyle>(_ style: S) -> some View {
|
|
infoButtonStyle(AnyPrimitiveButtonStyle(style))
|
|
}
|
|
|
|
/// Sets the button style for the ``NextButton`` type.
|
|
public func nextButtonStyle(_ style: AnyPrimitiveButtonStyle<NextButtonType>) -> some View {
|
|
environment(\.nextButtonStyle, style)
|
|
}
|
|
|
|
/// Sets the button style for the ``NextButton`` type.
|
|
public func nextButtonStyle<S: PrimitiveButtonStyle>(_ style: S) -> some View {
|
|
nextButtonStyle(AnyPrimitiveButtonStyle(style))
|
|
}
|
|
|
|
/// Sets the button style for the ``ResetButton`` type.
|
|
public func resetButtonStyle(_ style: AnyPrimitiveButtonStyle<ResetButtonType>) -> some View {
|
|
environment(\.resetButtonStyle, style)
|
|
}
|
|
|
|
/// Sets the button style for the ``ResetButton`` type.
|
|
public func resetButtonStyle<S: PrimitiveButtonStyle>(_ style: S) -> some View {
|
|
resetButtonStyle(AnyPrimitiveButtonStyle(style))
|
|
}
|
|
}
|