Something went wrong. Try again.
A library for helping build high quality forms in SwiftUI and TCA
Something went wrong. Try again.
3.4 kB · 119 lines
Swift
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120#if canImport(SwiftUI)import SwiftUI
public struct FormFieldStyleConfiguration { fileprivate init( content: AnyView, validation: FieldValidationState? ) { self.content = content self.validation = validation }
public let content: AnyView public let validation: FieldValidationState?}
public protocol FormFieldStyle: Sendable { associatedtype Body: View
@MainActor @ViewBuilder func makeBody(configuration: FormFieldStyleConfiguration) -> Body}
public struct AutomaticFormFieldStyle: FormFieldStyle { public init() {}
public func makeBody(configuration: FormFieldStyleConfiguration) -> some View { VStack(alignment: .leading) { configuration.content FormFieldValidationStatus(validation: configuration.validation) } }}
extension FormFieldStyle where Self == AutomaticFormFieldStyle { public static var automatic: Self { Self() }}
public struct FormFieldValidationStatus: View { public init(validation: FieldValidationState?) { self.validation = validation }
let validation: FieldValidationState?
public var body: some View { if self.validation?.isValidating == true { HStack(spacing: 6) { ProgressView() #if !os(Android) .controlSize(.small) #endif Text("Checking") .font(.footnote) .foregroundStyle(.secondary) } }
ForEach(Array((self.validation?.errors ?? []).enumerated()), id: \.offset) { _, error in Text(error.message) .font(.footnote) .foregroundStyle(.red) } }}
extension View { public func formFieldStyle<Style: FormFieldStyle>(_ style: Style) -> some View { self.environment(\.formFieldStyle, AnyFormFieldStyle(style)) }}
struct FormFieldContent<Root, FieldValue, Content: View>: View { @Environment(\.formFieldStyle) private var formFieldStyle
let fieldID: AnyHashable let keyPath: WritableKeyPath<Root, FieldValue> let submit: (AnyHashable) -> Void let validation: FieldValidationState? @Binding var value: Root let content: @MainActor (Binding<FieldValue>) -> Content
var body: some View { self.formFieldStyle.makeBody( FormFieldStyleConfiguration( content: AnyView( self.content(self.$value[dynamicMember: self.keyPath]) .onSubmit { self.submit(self.fieldID) } ), validation: self.validation ) ) }}
private struct AnyFormFieldStyle { init<Style: FormFieldStyle>(_ style: Style) { self.makeBody = { configuration in AnyView(style.makeBody(configuration: configuration)) } }
var makeBody: @MainActor (FormFieldStyleConfiguration) -> AnyView}
private enum FormFieldStyleKey: EnvironmentKey { static let defaultValue = AnyFormFieldStyle(AutomaticFormFieldStyle())}
private extension EnvironmentValues { var formFieldStyle: AnyFormFieldStyle { get { self[FormFieldStyleKey.self] } set { self[FormFieldStyleKey.self] = newValue } }}#endif