Feat: Working on pressure estimations feature
This commit is contained in:
90
Sources/Styleguide/Styles/ButtonStyles.swift
Normal file
90
Sources/Styleguide/Styles/ButtonStyles.swift
Normal file
@@ -0,0 +1,90 @@
|
||||
import SwiftUI
|
||||
|
||||
/// A name space for info button styles.
|
||||
public enum InfoButtonType { }
|
||||
|
||||
/// A name space for info button styles.
|
||||
public enum ResetButtonType { }
|
||||
|
||||
|
||||
public struct AnyButtonStyle<ButtonType>: ButtonStyle {
|
||||
private let _makeBody: (Configuration) -> AnyView
|
||||
|
||||
public init<S: ButtonStyle>(_ style: S) {
|
||||
self._makeBody = { configuration in
|
||||
AnyView(style.makeBody(configuration: configuration))
|
||||
}
|
||||
}
|
||||
|
||||
public func makeBody(configuration: Configuration) -> some View {
|
||||
self._makeBody(configuration)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public struct DefaultInfoButtonStyle: ButtonStyle {
|
||||
public func makeBody(configuration: Configuration) -> some View {
|
||||
configuration.label
|
||||
.buttonStyle(.plain)
|
||||
.foregroundStyle(Color.accentColor)
|
||||
.labelStyle(.iconOnly)
|
||||
}
|
||||
}
|
||||
|
||||
extension AnyButtonStyle where ButtonType == InfoButtonType {
|
||||
public static var `default`: Self {
|
||||
.init(DefaultInfoButtonStyle())
|
||||
}
|
||||
}
|
||||
|
||||
public struct DefaultResetButtonStyle: ButtonStyle {
|
||||
public func makeBody(configuration: Configuration) -> some View {
|
||||
configuration.label
|
||||
.buttonStyle(.borderedProminent)
|
||||
}
|
||||
}
|
||||
|
||||
extension AnyButtonStyle where ButtonType == ResetButtonType {
|
||||
public static var `default`: Self {
|
||||
.init(DefaultResetButtonStyle())
|
||||
}
|
||||
}
|
||||
|
||||
private struct InfoButtonStyleKey: EnvironmentKey {
|
||||
static var defaultValue = AnyButtonStyle<InfoButtonType>.default
|
||||
}
|
||||
|
||||
private struct ResetButtonStyleKey: EnvironmentKey {
|
||||
static var defaultValue = AnyButtonStyle<ResetButtonType>.default
|
||||
}
|
||||
|
||||
extension EnvironmentValues {
|
||||
public var infoButtonStyle: AnyButtonStyle<InfoButtonType> {
|
||||
get { self[InfoButtonStyleKey.self] }
|
||||
set { self[InfoButtonStyleKey.self] = newValue }
|
||||
}
|
||||
|
||||
public var resetButtonStyle: AnyButtonStyle<ResetButtonType> {
|
||||
get { self[ResetButtonStyleKey.self] }
|
||||
set { self[ResetButtonStyleKey.self] = newValue }
|
||||
}
|
||||
}
|
||||
|
||||
extension View {
|
||||
|
||||
public func infoButtonStyle(_ style: AnyButtonStyle<InfoButtonType>) -> some View {
|
||||
environment(\.infoButtonStyle, AnyButtonStyle(style))
|
||||
}
|
||||
|
||||
public func infoButtonStyle<S: ButtonStyle>(_ style: S) -> some View {
|
||||
infoButtonStyle(AnyButtonStyle(style))
|
||||
}
|
||||
|
||||
public func resetButtonStyle(_ style: AnyButtonStyle<ResetButtonType>) -> some View {
|
||||
environment(\.resetButtonStyle, AnyButtonStyle(style))
|
||||
}
|
||||
|
||||
public func resetButtonStyle<S: ButtonStyle>(_ style: S) -> some View {
|
||||
resetButtonStyle(AnyButtonStyle(style))
|
||||
}
|
||||
}
|
||||
176
Sources/Styleguide/Styles/FlaggedViewStyle.swift
Normal file
176
Sources/Styleguide/Styles/FlaggedViewStyle.swift
Normal file
@@ -0,0 +1,176 @@
|
||||
import SharedModels
|
||||
import SwiftUI
|
||||
|
||||
public protocol FlaggedViewStyle {
|
||||
associatedtype Body: View
|
||||
typealias Configuration = FlaggedViewStyleConfiguration
|
||||
|
||||
@ViewBuilder
|
||||
func makeBody(configuration: Self.Configuration) -> Self.Body
|
||||
}
|
||||
|
||||
public struct FlaggedViewStyleConfiguration {
|
||||
public let flagged: Flagged
|
||||
public let label: Label
|
||||
|
||||
/// A type erased label for a flagged view.
|
||||
public struct Label: View {
|
||||
public let body: AnyView
|
||||
|
||||
public init<Content: View>(_ content: Content) {
|
||||
self.body = AnyView(content)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public struct AnyFlaggedViewStyle: FlaggedViewStyle {
|
||||
private var _makeBody: (Configuration) -> AnyView
|
||||
|
||||
internal init(makeBody: @escaping (Configuration) -> AnyView) {
|
||||
self._makeBody = makeBody
|
||||
}
|
||||
|
||||
public init<S: FlaggedViewStyle>(style: S) {
|
||||
self.init { configuration in
|
||||
AnyView(style.makeBody(configuration: configuration))
|
||||
}
|
||||
}
|
||||
|
||||
public func makeBody(configuration: Configuration) -> some View {
|
||||
_makeBody(configuration)
|
||||
}
|
||||
}
|
||||
|
||||
public struct DefaultFlagViewStyle: FlaggedViewStyle {
|
||||
|
||||
let alignment: HorizontalAlignment
|
||||
let fractionLength: Int
|
||||
let spacing: CGFloat
|
||||
|
||||
init(
|
||||
alignment: HorizontalAlignment = .leading,
|
||||
fractionLength: Int = 2,
|
||||
spacing: CGFloat = 8
|
||||
) {
|
||||
self.alignment = alignment
|
||||
self.fractionLength = fractionLength
|
||||
self.spacing = spacing
|
||||
}
|
||||
|
||||
public func makeBody(configuration: Configuration) -> some View {
|
||||
VStack(alignment: alignment, spacing: spacing) {
|
||||
HStack {
|
||||
configuration.label
|
||||
Spacer()
|
||||
Text(
|
||||
configuration.flagged.wrappedValue,
|
||||
format: .number.precision(.fractionLength(fractionLength))
|
||||
)
|
||||
configuration.flagged.flagImage
|
||||
}
|
||||
flaggedMessageView(flagged: configuration.flagged)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public struct FlagAndMessageOnlyStyle: FlaggedViewStyle {
|
||||
|
||||
public enum StackStyle {
|
||||
case horizontal
|
||||
case vertical
|
||||
}
|
||||
|
||||
let stackStyle: StackStyle
|
||||
|
||||
@ViewBuilder
|
||||
public func makeBody(configuration: Configuration) -> some View {
|
||||
switch stackStyle {
|
||||
case .horizontal:
|
||||
HStack {
|
||||
flaggedMessageView(flagged: configuration.flagged)
|
||||
configuration.flagged.flagImage
|
||||
}
|
||||
case .vertical:
|
||||
VStack {
|
||||
configuration.flagged.flagImage
|
||||
flaggedMessageView(flagged: configuration.flagged)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension FlaggedViewStyle where Self == FlagAndMessageOnlyStyle {
|
||||
public static func flagAndMessageOnly(_ stackStyle: FlagAndMessageOnlyStyle.StackStyle = .vertical) -> Self {
|
||||
.init(stackStyle: stackStyle)
|
||||
}
|
||||
}
|
||||
|
||||
private struct FlaggedViewStyleKey: EnvironmentKey {
|
||||
static let defaultValue = AnyFlaggedViewStyle(style: DefaultFlagViewStyle())
|
||||
}
|
||||
|
||||
extension EnvironmentValues {
|
||||
public var flaggedViewStyle: AnyFlaggedViewStyle {
|
||||
get { self[FlaggedViewStyleKey.self] }
|
||||
set { self[FlaggedViewStyleKey.self] = newValue }
|
||||
}
|
||||
}
|
||||
|
||||
extension FlaggedViewStyle where Self == DefaultFlagViewStyle {
|
||||
public static func `default`(alignment: HorizontalAlignment = .leading, fractionLength: Int = 2, spacing: CGFloat = 8) -> Self {
|
||||
.init(alignment: alignment, fractionLength: fractionLength, spacing: spacing)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extension Flagged.CheckResult.Key {
|
||||
|
||||
public var flagColor: Color {
|
||||
switch self {
|
||||
case .good:
|
||||
return .green
|
||||
case .warning:
|
||||
return .yellow
|
||||
case .error:
|
||||
return .red
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extension Flagged {
|
||||
public var flagColor: Color { projectedValue.key.flagColor }
|
||||
|
||||
public var flagImage: some View {
|
||||
Image(systemName: "flag.fill")
|
||||
.foregroundStyle(flagColor)
|
||||
}
|
||||
|
||||
public var messageView: some View { flaggedMessageView(flagged: self) }
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private func flaggedMessageView(flagged: Flagged) -> some View {
|
||||
if let message = flagged.message {
|
||||
HStack {
|
||||
Text(flagged.projectedValue.key.title)
|
||||
.bold()
|
||||
.foregroundStyle(flagged.projectedValue.key.flagColor)
|
||||
TextLabel(message)
|
||||
}
|
||||
.font(.caption)
|
||||
}
|
||||
}
|
||||
|
||||
extension View {
|
||||
public func flaggedViewStyle(_ style: AnyFlaggedViewStyle) -> some View {
|
||||
environment(\.flaggedViewStyle, style)
|
||||
}
|
||||
|
||||
public func flaggedViewStyle<S: FlaggedViewStyle>(
|
||||
_ style: S
|
||||
) -> some View {
|
||||
environment(\.flaggedViewStyle, AnyFlaggedViewStyle(style: style))
|
||||
}
|
||||
}
|
||||
175
Sources/Styleguide/Styles/TextLabelStyle.swift
Normal file
175
Sources/Styleguide/Styles/TextLabelStyle.swift
Normal file
@@ -0,0 +1,175 @@
|
||||
import SwiftUI
|
||||
|
||||
public protocol TextLabelStyle {
|
||||
|
||||
associatedtype Body: View
|
||||
typealias Configuration = TextLabelConfiguration
|
||||
|
||||
func makeBody(configuration: Self.Configuration) -> Self.Body
|
||||
}
|
||||
|
||||
extension TextLabelStyle {
|
||||
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
|
||||
}
|
||||
|
||||
public struct AnyTextLabelStyle: TextLabelStyle {
|
||||
private var _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 {
|
||||
public func makeBody(configuration: Configuration) -> some View {
|
||||
configuration.label
|
||||
}
|
||||
}
|
||||
|
||||
private struct TextLabelStyleKey: EnvironmentKey {
|
||||
static let defaultValue = AnyTextLabelStyle(style: AutomaticTextLabelStyle())
|
||||
}
|
||||
|
||||
private struct SectionHeaderLabelStyleKey: EnvironmentKey {
|
||||
static let defaultValue = 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)
|
||||
}
|
||||
}
|
||||
|
||||
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))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension View {
|
||||
|
||||
public func textLabelStyle(_ style: AnyTextLabelStyle) -> some View {
|
||||
environment(\.textLabelStyle, style)
|
||||
}
|
||||
|
||||
public func textLabelStyle<S: TextLabelStyle>(_ style: S) -> some View {
|
||||
environment(\.textLabelStyle, AnyTextLabelStyle(style: style))
|
||||
}
|
||||
|
||||
public func sectionHeaderLabelStyle<S: TextLabelStyle>(_ style: S) -> some View {
|
||||
environment(\.sectionHeaderLabelStyle, AnyTextLabelStyle(style: style))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user