Files
swift-estimated-pressures-core/Sources/Styleguide/Styles/TextLabelStyle.swift

211 lines
5.3 KiB
Swift

import SwiftUI
public protocol TextLabelStyle {
associatedtype Body: View
typealias Configuration = TextLabelConfiguration
@MainActor
func makeBody(configuration: Self.Configuration) -> Self.Body
}
extension TextLabelStyle {
@MainActor
public func combining<Other: TextLabelStyle>(_ style: Other) -> AnyTextLabelStyle {
AnyTextLabelStyle(style: self).combining(style)
}
}
public struct TextLabelConfiguration {
/// A type erased label for a text label.
public struct Label: View {
public var body: AnyView
public init<Content: View>(content: Content) {
body = AnyView(content)
}
}
public let label: TextLabelConfiguration.Label
}
@MainActor
public struct AnyTextLabelStyle: TextLabelStyle {
private let _makeBody: (Configuration) -> AnyView
internal init(makeBody: @escaping (Configuration) -> AnyView) {
self._makeBody = makeBody
}
public init<S: TextLabelStyle>(style: S) {
self._makeBody = { configuration in
AnyView(style.makeBody(configuration: configuration))
}
}
public func makeBody(configuration: Configuration) -> some View {
_makeBody(configuration)
}
public func combining<S: TextLabelStyle>(_ style: S) -> Self {
Self.init { configuration in
AnyView(
self.makeBody(
configuration: TextLabelConfiguration(
label: .init(content: style.makeBody(configuration: configuration))
)
))
}
}
}
public struct AutomaticTextLabelStyle: TextLabelStyle {
@MainActor
public func makeBody(configuration: Configuration) -> some View {
configuration.label
}
}
private struct TextLabelStyleKey: EnvironmentKey {
static let defaultValue = MainActor.assumeIsolated {
AnyTextLabelStyle(style: AutomaticTextLabelStyle())
}
}
private struct SectionHeaderLabelStyleKey: EnvironmentKey {
static let defaultValue = MainActor.assumeIsolated {
AnyTextLabelStyle(style: AutomaticTextLabelStyle())
}
}
extension EnvironmentValues {
public var textLabelStyle: AnyTextLabelStyle {
get { self[TextLabelStyleKey.self] }
set { self[TextLabelStyleKey.self] = newValue }
}
public var sectionHeaderLabelStyle: AnyTextLabelStyle {
get { self[SectionHeaderLabelStyleKey.self] }
set { self[SectionHeaderLabelStyleKey.self] = newValue }
}
}
public struct FontTextLabelStyle: TextLabelStyle {
let font: Font?
let fontWeight: Font.Weight?
public func makeBody(configuration: Configuration) -> some View {
configuration.label
.font(font)
.fontWeight(fontWeight)
}
}
public struct ColoredTextLabelStyle: TextLabelStyle {
let primary: Color
let secondary: Color?
let tertiary: Color?
@ViewBuilder
public func makeBody(configuration: Configuration) -> some View {
switch (secondary, tertiary) {
case let (.some(secondary), .some(tertiary)):
configuration.label.foregroundStyle(primary, secondary, tertiary)
case let (.some(secondary), .none):
configuration.label.foregroundStyle(primary, secondary)
case let (.none, .some(tertiary)):
configuration.label.foregroundStyle(primary, tertiary)
case (.none, .none):
configuration.label.foregroundStyle(primary)
}
}
@MainActor
public func font(_ font: Font? = nil, fontWeight: Font.Weight? = nil) -> AnyTextLabelStyle {
self.combining(.font(font, fontWeight: fontWeight))
}
}
extension TextLabelStyle where Self == AutomaticTextLabelStyle {
public static var automatic: Self {
.init()
}
}
extension TextLabelStyle where Self == FontTextLabelStyle {
public static func font(_ font: Font? = nil, fontWeight: Font.Weight? = nil) -> Self {
.init(font: font, fontWeight: fontWeight)
}
public static var heavyTitle2: Self {
.font(.title2, fontWeight: .heavy)
}
}
extension TextLabelStyle where Self == ColoredTextLabelStyle {
public static func colored(_ color: Color) -> Self {
.init(primary: color, secondary: nil, tertiary: nil)
}
public static func colored(_ primary: Color, _ secondary: Color, _ tertiary: Color? = nil) -> Self {
.init(primary: primary, secondary: secondary, tertiary: tertiary)
}
public static var secondary: Self {
self.colored(.secondary)
}
}
extension AnyTextLabelStyle {
public static var boldSecondary: AnyTextLabelStyle {
ColoredTextLabelStyle(primary: .secondary, secondary: nil, tertiary: nil)
.combining(.font(fontWeight: .bold))
}
}
public struct PillViewTextLabelStyle: TextLabelStyle {
let labelColor: Color?
let pillColor: Color
public func makeBody(configuration: Configuration) -> some View {
configuration.label
.foregroundStyle(labelColor ?? .primary)
.background {
Capsule()
.foregroundStyle(pillColor)
}
}
}
extension TextLabelStyle where Self == PillViewTextLabelStyle {
public static func pill(
pillColor: Color,
labelColor: Color? = nil
) -> Self {
.init(labelColor: labelColor, pillColor: pillColor)
}
}
extension View {
public func textLabelStyle(_ style: AnyTextLabelStyle) -> some View {
environment(\.textLabelStyle, style)
}
public func textLabelStyle<S: TextLabelStyle>(_ style: S) -> some View {
textLabelStyle(AnyTextLabelStyle(style: style))
}
public func sectionHeaderLabelStyle<S: TextLabelStyle>(_ style: S) -> some View {
environment(\.sectionHeaderLabelStyle, AnyTextLabelStyle(style: style))
}
}