From 581bb415dfb22abdb3d2ce94f4af65ebddad0247 Mon Sep 17 00:00:00 2001 From: Alexandr Romanov Date: Thu, 21 Jul 2022 21:59:06 +0300 Subject: [PATCH] Refactor Row and ControlPadding --- Package.swift | 8 +- Sources/OversizeUI/Controls/Row/Row.swift | 260 ++++++++++-------- .../SegmentedControl/SegmentedControl.swift | 16 +- .../Controls/Surface/MaterialSurface.swift | 8 +- .../OversizeUI/Controls/Surface/Surface.swift | 5 +- .../Controls/Surface/View+Surface.swift | 26 ++ Sources/OversizeUI/Core/Typography.swift | 140 +++------- .../ControlPaddingEnvironment.swift | 42 +++ .../EnvironmentKey/PaddingEnvironment.swift | 23 -- 9 files changed, 279 insertions(+), 249 deletions(-) create mode 100644 Sources/OversizeUI/Extensions/EnvironmentKey/ControlPaddingEnvironment.swift delete mode 100644 Sources/OversizeUI/Extensions/EnvironmentKey/PaddingEnvironment.swift diff --git a/Package.swift b/Package.swift index 332681c..bdf8f8d 100644 --- a/Package.swift +++ b/Package.swift @@ -14,19 +14,13 @@ let package = Package( .watchOS(.v8), ], products: [ - // Products define the executables and libraries a package produces, and make them visible to other packages. .library( name: "OversizeUI", targets: ["OversizeUI"] ), ], - dependencies: [ - // Dependencies declare other packages that this package depends on. - // .package(url: /* package url */, from: "1.0.0"), - ], + dependencies: [], targets: [ - // Targets are the basic building blocks of a package. A target can define a module or a test suite. - // Targets can depend on other targets in this package, and on products in packages this package depends on. .target( name: "OversizeUI", dependencies: [] diff --git a/Sources/OversizeUI/Controls/Row/Row.swift b/Sources/OversizeUI/Controls/Row/Row.swift index 8b87e0b..5214363 100644 --- a/Sources/OversizeUI/Controls/Row/Row.swift +++ b/Sources/OversizeUI/Controls/Row/Row.swift @@ -6,19 +6,17 @@ import SwiftUI public enum RowTrailingType { - case none case radio(isOn: Binding) case checkbox(isOn: Binding) case toggle(isOn: Binding) case toggleWithArrowButton(isOn: Binding, action: (() -> Void)? = nil) - // case timePicker(date: Binding) + case timePicker(date: Binding) case arrowIcon case text(_ text: String) case button(_ text: String, action: () -> Void) } public enum RowLeadingType { - case none case icon(_ name: IconsNames) case iconOnSurface(_ name: IconsNames) case image(_ image: Image) @@ -28,122 +26,99 @@ public enum RowLeadingType { } public struct Row: View { + @Environment(\.elevation) private var elevation: Elevation + @Environment(\.controlRadius) var controlRadius: Radius + @Environment(\.controlPadding) var controlPadding: ControlPadding @Environment(\.multilineTextAlignment) var multilineTextAlignment @Environment(\.isPremium) var premiumStatus private enum Constants { /// Spacing - static var spacingIconAndText: CGFloat { Space.xxSmall.rawValue } + static var spacingIconAndText: Space { Space.xxSmall } } private let title: String - private let subtitle: String + private let subtitle: String? - private let paddingVertical: Space - private let paddingHorizontal: Space - - private let leadingType: RowLeadingType - private let trallingType: RowTrailingType + private var leadingType: RowLeadingType? + private var trallingType: RowTrailingType? private let action: (() -> Void)? private var isPremiumOption: Bool = false public init(_ title: String, - subtitle: String = "", - leadingType: RowLeadingType = .none, - trallingType: RowTrailingType = .none, - paddingHorizontal: Space = .medium, - paddingVertical: Space = .small, + subtitle: String? = nil, + action: (() -> Void)? = nil) + { + self.title = title + self.subtitle = subtitle + self.action = action + } + + @available(*, deprecated, message: "Use row modificators") + public init(_ title: String, + subtitle: String? = nil, + leadingType: RowLeadingType? = nil, + trallingType: RowTrailingType? = nil, + paddingHorizontal _: Space = .medium, + paddingVertical _: Space = .small, action: (() -> Void)? = nil) { self.title = title self.subtitle = subtitle self.leadingType = leadingType self.trallingType = trallingType - self.paddingVertical = paddingVertical - self.paddingHorizontal = paddingHorizontal self.action = action } public var body: some View { - actionableRow() - } - - @ViewBuilder - private func actionableRow() -> some View { if action != nil { Button { if isPremiumOption == false || (isPremiumOption && premiumStatus) { action?() } - } label: { - contentAlignment(multilineTextAlignment) + content(multilineTextAlignment) } - .buttonStyle(RowActionButtonStyle()) + .buttonStyle(.row) } else { - contentAlignment(multilineTextAlignment) + content(multilineTextAlignment) } } @ViewBuilder - private func contentAlignment(_ textAlignment: TextAlignment) -> some View { - switch textAlignment { - case .leading: - VStack(alignment: .leading) { - HStack(spacing: .xSmall) { - leading() - - text - - premiumLabel() + private func content(_ textAlignment: TextAlignment) -> some View { + VStack(alignment: .leading) { + HStack(spacing: .xSmall) { + if let leadingType = leadingType { + leading(leadingType) + } + if textAlignment == .trailing || textAlignment == .center { Spacer() - - tralling() } - } - .padding(.vertical, paddingVertical.rawValue) - .padding(.horizontal, paddingHorizontal.rawValue) - case .center: - VStack(alignment: .leading) { - HStack(spacing: .xSmall) { - leading() - Spacer() + text - text + premiumLabel() + if textAlignment == .leading || textAlignment == .center { Spacer() - - tralling() } - } - .padding(.vertical, paddingVertical.rawValue) - .padding(.horizontal, paddingHorizontal.rawValue) - case .trailing: - VStack(alignment: .leading) { - HStack(spacing: .xSmall) { - leading() - - Spacer() - - text - tralling() + if let trallingType = trallingType { + tralling(trallingType) } } - .padding(.vertical, paddingVertical.rawValue) - .padding(.horizontal, paddingHorizontal.rawValue) } + .padding(.vertical, verticalPadding) + .padding(.horizontal, controlPadding.horizontal) } @ViewBuilder - private func leading() -> some View { + private func leading(_ leadingType: RowLeadingType) -> some View { switch leadingType { - case .none: - EmptyView() case let .icon(icon): Icon(icon) .padding(.trailing, Constants.spacingIconAndText) @@ -157,6 +132,7 @@ public struct Row: View { case let .avatar(avatar): avatar + case let .iconOnSurface(icon): Surface { Icon(icon) @@ -164,12 +140,14 @@ public struct Row: View { .surfaceStyle(.secondary) .padding(.trailing, Constants.spacingIconAndText) .controlPadding(.xxSmall) + case let .systemImage(systemImage): Image(systemName: systemImage) .foregroundColor(Color.onBackgroundHighEmphasis) .font(.system(size: 24)) .frame(width: 24, height: 24, alignment: .center) .padding(.trailing, Constants.spacingIconAndText) + case let .view(view): view } @@ -177,51 +155,49 @@ public struct Row: View { // swiftlint:disable function_body_length @ViewBuilder - private func tralling() -> some View { + private func tralling(_ trallingType: RowTrailingType) -> some View { switch trallingType { - case .none: - EmptyView() case let .toggle(isOn): Toggle(isOn: isOn) {} .labelsHidden() .disabled(isPremiumOption && premiumStatus == false) case let .radio(isOn: isOn): - - if isOn.wrappedValue { - ZStack { - Circle().fill(Color.accent).frame(width: 24, height: 24) - .cornerRadius(12) - - Circle().fill(Color.white).frame(width: 8, height: 8) - .cornerRadius(4) - } - - } else { + ZStack { Circle() .stroke(Color.onSurfaceDisabled, lineWidth: 4) .frame(width: 24, height: 24) .cornerRadius(12) - } - case let .checkbox(isOn: isOn): + .opacity(isOn.wrappedValue ? 0 : 1) - if isOn.wrappedValue { - ZStack { - Circle().fill(Color.accent).frame(width: 24, height: 24) - .cornerRadius(12) + Circle().fill(Color.accent) + .frame(width: 24, height: 24) + .cornerRadius(12) + .opacity(isOn.wrappedValue ? 1 : 0) - Circle().fill(Color.white).frame(width: 8, height: 8) - .cornerRadius(4) - } + Circle().fill(Color.white).frame(width: 8, height: 8) + .cornerRadius(4) + .opacity(isOn.wrappedValue ? 1 : 0) + } - } else { - Circle() + case let .checkbox(isOn: isOn): + ZStack { + RoundedRectangle(cornerRadius: Radius.small.rawValue, style: .continuous) .stroke(Color.onSurfaceDisabled, lineWidth: 4) .frame(width: 24, height: 24) - .cornerRadius(12) + .opacity(isOn.wrappedValue ? 0 : 1) + + RoundedRectangle(cornerRadius: Radius.small.rawValue, style: .continuous).fill(Color.accent) + .frame(width: 24, height: 24) + .opacity(isOn.wrappedValue ? 1 : 0) + + Image(systemName: "checkmark") + .font(.caption.weight(.black)) + .foregroundColor(.onPrimaryHighEmphasis) + .opacity(isOn.wrappedValue ? 1 : 0) } - case let .toggleWithArrowButton(isOn: isOn, action: action): + case let .toggleWithArrowButton(isOn: isOn, action: action): HStack { Toggle(isOn: isOn) {} .labelsHidden() @@ -231,12 +207,13 @@ public struct Row: View { }) } .disabled(isPremiumOption && premiumStatus == false) - case .arrowIcon: + case .arrowIcon: Icon(.chevronRight, color: .onSurfaceDisabled) -// case let .timePicker(date: date): -// DatePicker("", selection: date, displayedComponents: .hourAndMinute) -// .labelsHidden() + + case let .timePicker(date: date): + DatePicker("", selection: date, displayedComponents: .hourAndMinute) + .labelsHidden() case let .text(text): Text(text) @@ -245,24 +222,26 @@ public struct Row: View { case let .button(text, action: action): Button(text, action: action) - .buttonStyle(.tertiary) + .buttonStyle(.secondary) + .controlBorderShape(.capsule) .controlSize(.small) + .elevation(.z2) .disabled(isPremiumOption && premiumStatus == false) } } - var text: some View { - VStack(alignment: .leading) { + private var text: some View { + VStack(alignment: textAlignment) { Text(title) .headline() .foregroundColor(.onSurfaceHighEmphasis) - - if subtitle != "" { + if let subtitle = subtitle { Text(subtitle) - .fontStyle(.subheadline) + .subheadline() .foregroundColor(.onSurfaceMediumEmphasis) } } + .multilineTextAlignment(multilineTextAlignment) } @ViewBuilder @@ -274,11 +253,55 @@ public struct Row: View { } } + private var verticalPadding: CGFloat { + switch controlPadding.vertical { + case .zero: + return .zero + case .xxSmall: + return .zero + default: + return controlPadding.vertical.rawValue - Space.xxSmall.rawValue + } + } + + private var textAlignment: HorizontalAlignment { + switch multilineTextAlignment { + case .leading: + return .leading + case .center: + return .center + case .trailing: + return .trailing + } + } + + // Modificators public func premium(_ premium: Bool = true) -> Row { var control = self control.isPremiumOption = premium return control } + + public func rowLeading(_ leading: RowLeadingType) -> Row { + var control = self + control.leadingType = leading + return control + } + + public func rowTrailing(_ trailing: RowTrailingType) -> Row { + var control = self + control.trallingType = trailing + return control + } +} + +public extension View { + func rowOnSurface(_ elevation: Elevation = .z4) -> some View { + Surface { + self.controlPadding(.zero) + } + .elevation(elevation) + } } public struct RowActionButtonStyle: ButtonStyle { @@ -303,20 +326,37 @@ struct ListRow_Previews: PreviewProvider { Row("Title", subtitle: "Subtitle") - Row("Title", subtitle: "Subtitle", leadingType: .icon(.calendar), trallingType: .radio(isOn: .constant(true)), paddingVertical: .medium) + Row("Title", subtitle: "Subtitle") + .rowLeading(.icon(.calendar)) + .rowTrailing(.radio(isOn: .constant(true))) + + Row("Title", subtitle: "Subtitle") + .rowLeading(.iconOnSurface(.calendar)) + .rowTrailing(.toggle(isOn: .constant(true))) - Row("Title", subtitle: "Subtitle", leadingType: .icon(.calendar), trallingType: .toggle(isOn: .constant(true)), paddingVertical: .medium) + Row("Title", subtitle: "Subtitle") + .rowLeading(.icon(.calendar)) + .rowTrailing(.checkbox(isOn: .constant(true))) + .rowOnSurface() + .padding() + .previewLayout(.fixed(width: 375, height: 120)) - Row("Title", subtitle: "Subtitle", leadingType: .icon(.calendar), trallingType: .radio(isOn: .constant(false)), paddingVertical: .small) + Row("Title", subtitle: "Subtitle") + .rowLeading(.avatar(AvatarView(firstName: "Name"))) + .rowTrailing(.text("Text")) - Row("Title", subtitle: "Subtitle", leadingType: .avatar(AvatarView(firstName: "Name")), trallingType: .radio(isOn: .constant(false)), paddingVertical: .small) + Row("Title") + .rowTrailing(.toggleWithArrowButton(isOn: .constant(true), action: nil)) - Row("Title", trallingType: .toggleWithArrowButton(isOn: .constant(true), action: nil)) + Row("Title", subtitle: "Subtitle") + .rowTrailing(.button("Button", action: {})) Row("Title") + .rowTrailing(.timePicker(date: .constant(Date()))) + + Row("Title", subtitle: "Red") .premium() } - // .padding() - .previewLayout(.fixed(width: 375, height: 60)) + .previewLayout(.fixed(width: 375, height: 70)) } } diff --git a/Sources/OversizeUI/Controls/SegmentedControl/SegmentedControl.swift b/Sources/OversizeUI/Controls/SegmentedControl/SegmentedControl.swift index f154c84..4c28222 100644 --- a/Sources/OversizeUI/Controls/SegmentedControl/SegmentedControl.swift +++ b/Sources/OversizeUI/Controls/SegmentedControl/SegmentedControl.swift @@ -13,7 +13,7 @@ public struct SegmentedPickerSelector: V @Environment(\.theme) private var theme: ThemeSettings @Environment(\.segmentedControlStyle) private var style @Environment(\.controlRadius) var controlRadius: Radius - @Environment(\.controlPadding) var controlPadding: Space + @Environment(\.controlPadding) var controlPadding: ControlPadding public typealias Data = [Element] @@ -107,8 +107,11 @@ public struct SegmentedPickerSelector: V .multilineTextAlignment(.center) Spacer() } - - .padding(.vertical, controlPadding.rawValue - Space.xxSmall.rawValue) + .padding(.horizontal, controlPadding.horizontal) + .padding(.vertical, + controlPadding.vertical != Space.zero || controlPadding.vertical != Space.xxSmall + ? controlPadding.vertical.rawValue - Space.xxSmall.rawValue + : Space.zero.rawValue) .background(selectedIndex != index ? getUnselection(unselectionStyle: style.unseletionStyle) : nil) @@ -156,8 +159,11 @@ public struct SegmentedPickerSelector: V .foregroundColor(.onSurfaceHighEmphasis) .multilineTextAlignment(.center) - .padding(.vertical, controlPadding.rawValue - Space.xxSmall.rawValue) - .padding(.horizontal, controlPadding) + .padding(.horizontal, controlPadding.horizontal) + .padding(.vertical, + controlPadding.vertical != Space.zero || controlPadding.vertical != Space.xxSmall + ? controlPadding.vertical.rawValue - Space.xxSmall.rawValue + : Space.zero.rawValue) .background(selectedIndex != index ? getUnselection(unselectionStyle: style.unseletionStyle) : nil) diff --git a/Sources/OversizeUI/Controls/Surface/MaterialSurface.swift b/Sources/OversizeUI/Controls/Surface/MaterialSurface.swift index ab4cd67..2deb1db 100644 --- a/Sources/OversizeUI/Controls/Surface/MaterialSurface.swift +++ b/Sources/OversizeUI/Controls/Surface/MaterialSurface.swift @@ -23,7 +23,7 @@ import SwiftUI @Environment(\.elevation) private var elevation: Elevation @Environment(\.theme) private var theme: ThemeSettings @Environment(\.controlRadius) var controlRadius: Radius - @Environment(\.controlPadding) var controlPadding: Space + @Environment(\.controlPadding) var controlPadding: ControlPadding private let label: Label private let action: (() -> Void)? @@ -58,14 +58,16 @@ import SwiftUI private var surface: some View { if #available(iOS 15.0, macOS 12.0, tvOS 15.0, *) { label - .padding(.all, controlPadding.rawValue) + .padding(.horizontal, controlPadding.horizontal) + .padding(.vertical, controlPadding.vertical) .background(backgroundMaterial, in: RoundedRectangle(cornerRadius: controlRadius.rawValue, style: .continuous)) .overlay(overlayView) .shadowElevaton(elevation) } else { label - .padding(.all, controlPadding.rawValue) + .padding(.horizontal, controlPadding.horizontal) + .padding(.vertical, controlPadding.vertical) .background(legacyBackgroundView) .overlay(overlayView) .shadowElevaton(elevation) diff --git a/Sources/OversizeUI/Controls/Surface/Surface.swift b/Sources/OversizeUI/Controls/Surface/Surface.swift index 82d21f8..a45db24 100644 --- a/Sources/OversizeUI/Controls/Surface/Surface.swift +++ b/Sources/OversizeUI/Controls/Surface/Surface.swift @@ -17,7 +17,7 @@ public struct Surface: View { @Environment(\.elevation) private var elevation: Elevation @Environment(\.theme) private var theme: ThemeSettings @Environment(\.controlRadius) var controlRadius: Radius - @Environment(\.controlPadding) var controlPadding: Space + @Environment(\.controlPadding) var controlPadding: ControlPadding private enum Constants { /// Colors @@ -57,7 +57,8 @@ public struct Surface: View { private var surface: some View { label - .padding(.all, controlPadding.rawValue) + .padding(.horizontal, controlPadding.horizontal) + .padding(.vertical, controlPadding.vertical) .background( RoundedRectangle(cornerRadius: controlRadius.rawValue, style: .circular) diff --git a/Sources/OversizeUI/Controls/Surface/View+Surface.swift b/Sources/OversizeUI/Controls/Surface/View+Surface.swift index 9d3da10..0b76d96 100644 --- a/Sources/OversizeUI/Controls/Surface/View+Surface.swift +++ b/Sources/OversizeUI/Controls/Surface/View+Surface.swift @@ -11,17 +11,43 @@ public extension View { Surface { self } } + func surface(_ elevation: Elevation) -> some View { + Surface { self } + .elevation(elevation) + } + + func surface(_ elevation: Elevation, background: SurfaceStyle) -> some View { + Surface { self } + .surfaceStyle(background) + .elevation(elevation) + } + +// func surface(_ elevation: Elevation = .z0, +// background: SurfaceStyle = .primary, +// padding: Space = .medium, +// radius: Radius = .medium) -> some View +// { +// Surface { self } +// .surfaceStyle(background) +// .controlPadding(padding) +// .controlRadius(radius) +// .elevation(elevation) +// } + + @available(*, deprecated, message: "Use without elevation") func surface(elevation: Elevation) -> some View { Surface { self } .elevation(elevation) } + @available(*, deprecated, message: "Use without elevation") func surface(elevation: Elevation, background: SurfaceStyle) -> some View { Surface { self } .surfaceStyle(background) .elevation(elevation) } + @available(*, deprecated, message: "Use without elevation") func surface(elevation: Elevation = .z0, background: SurfaceStyle = .primary, padding: Space = .medium, diff --git a/Sources/OversizeUI/Core/Typography.swift b/Sources/OversizeUI/Core/Typography.swift index c7cf610..e6cee94 100644 --- a/Sources/OversizeUI/Core/Typography.swift +++ b/Sources/OversizeUI/Core/Typography.swift @@ -26,156 +26,98 @@ public struct Typography: ViewModifier { @Environment(\.theme) private var theme: ThemeSettings @Environment(\.isLoading) var isLoading - private var designTitle: Font.Design { - theme.fontTitle.system - } + public let fontStyle: Font.TextStyle + public let isBold: Bool? - private var designParagraph: Font.Design { - theme.fontParagraph.system + private var fontDesign: Font.Design { + switch fontStyle { + case .largeTitle, .title, .title2, .title3, .headline, .subheadline: + return theme.fontTitle.system + case .body: + return theme.fontParagraph.system + case .caption, .caption2, .footnote, .callout: + return theme.fontOverline.system + @unknown default: + return .default + } } - private var designOverline: Font.Design { - theme.fontOverline.system + private var fontWeight: Font.Weight { + switch fontStyle { + case .largeTitle, .title: + return isBold ?? true ? .heavy : .regular + case .headline: + return isBold ?? true ? .bold : .semibold + default: + return isBold ?? false ? .bold : .regular + } } - private var designButton: Font.Design { - theme.fontButton.system + public init(fontStyle: Font.TextStyle, isBold: Bool? = nil) { + self.fontStyle = fontStyle + self.isBold = isBold } - public var style: Font.TextStyle - - public var isBold: Bool = false - - // swiftlint:disable cyclomatic_complexity - @ViewBuilder public func body(content: Content) -> some View { - switch style { - /// The font style for large titles. - case .largeTitle: - content - .font(.system(.largeTitle, design: designTitle).weight(isBold ? .heavy : .regular)) - .redacted(reason: isLoading ? .placeholder : .init()) - - /// The font used for first level hierarchical headings. - case .title: - content - .font(.system(.title, design: designTitle).weight(isBold ? .heavy : .regular)) - .redacted(reason: isLoading ? .placeholder : .init()) - - /// The font used for second level hierarchical headings. - case .title2: - content - .font(.system(.title2, design: designTitle).weight(isBold ? .bold : .regular)) - .redacted(reason: isLoading ? .placeholder : .init()) - - /// The font used for third level hierarchical headings. - case .title3: - content - .font(.system(.title3, design: designTitle).weight(isBold ? .bold : .regular)) - .redacted(reason: isLoading ? .placeholder : .init()) - - /// The font used for headings. - case .headline: - content - .font(.system(.headline, design: designTitle).weight(isBold ? .bold : .semibold)) - .redacted(reason: isLoading ? .placeholder : .init()) - - /// The font used for subheadings. - case .subheadline: - content - .font(.system(.subheadline, design: designTitle).weight(isBold ? .bold : .regular)) - .redacted(reason: isLoading ? .placeholder : .init()) - - /// The font used for body text. - case .body: - content - .font(.system(.body, design: designParagraph).weight(isBold ? .bold : .regular)) - .redacted(reason: isLoading ? .placeholder : .init()) - - /// The font used for callouts. - case .callout: - content - .font(.system(.callout, design: designOverline).weight(isBold ? .bold : .regular)) - .redacted(reason: isLoading ? .placeholder : .init()) - - /// The font used in footnotes. - case .footnote: - content - .font(.system(.footnote, design: designOverline).weight(isBold ? .bold : .regular)) - .redacted(reason: isLoading ? .placeholder : .init()) - - /// The font used for standard captions. - case .caption: - content - .font(.system(.caption, design: designOverline).weight(isBold ? .bold : .regular)) - .redacted(reason: isLoading ? .placeholder : .init()) - - /// The font used for alternate captions. - case .caption2: - content - .font(.system(.caption2, design: designOverline).weight(isBold ? .bold : .regular)) - .redacted(reason: isLoading ? .placeholder : .init()) - - default: - content - } + content + .font(.system(fontStyle, design: fontDesign).weight(fontWeight)) } } public extension View { func largeTitle(_ bold: Bool = true) -> some View { - modifier(Typography(style: .largeTitle, isBold: bold)) + modifier(Typography(fontStyle: .largeTitle, isBold: bold)) } func title(_ bold: Bool = true) -> some View { - modifier(Typography(style: .title, isBold: bold)) + modifier(Typography(fontStyle: .title, isBold: bold)) } func title2(_ bold: Bool = true) -> some View { - modifier(Typography(style: .title2, isBold: bold)) + modifier(Typography(fontStyle: .title2, isBold: bold)) } func title3(_ bold: Bool = true) -> some View { - modifier(Typography(style: .title3, isBold: bold)) + modifier(Typography(fontStyle: .title3, isBold: bold)) } func headline(_ bold: Bool = true) -> some View { - modifier(Typography(style: .headline, isBold: bold)) + modifier(Typography(fontStyle: .headline, isBold: bold)) } - func subheadline(_ bold: Bool = true) -> some View { - modifier(Typography(style: .subheadline, isBold: bold)) + func subheadline(_ bold: Bool = false) -> some View { + modifier(Typography(fontStyle: .subheadline, isBold: bold)) } func body(_ bold: Bool = false) -> some View { - modifier(Typography(style: .body, isBold: bold)) + modifier(Typography(fontStyle: .body, isBold: bold)) } func callout(_ bold: Bool = false) -> some View { - modifier(Typography(style: .callout, isBold: bold)) + modifier(Typography(fontStyle: .callout, isBold: bold)) } func footnote(_ bold: Bool = false) -> some View { - modifier(Typography(style: .footnote, isBold: bold)) + modifier(Typography(fontStyle: .footnote, isBold: bold)) } func caption(_ bold: Bool = false) -> some View { - modifier(Typography(style: .caption, isBold: bold)) + modifier(Typography(fontStyle: .caption, isBold: bold)) } func caption2(_ bold: Bool = false) -> some View { - modifier(Typography(style: .caption2, isBold: bold)) + modifier(Typography(fontStyle: .caption2, isBold: bold)) } } public extension View { func fontStyle(_ style: Font.TextStyle) -> some View { - modifier(Typography(style: style)) + modifier(Typography(fontStyle: style)) } @available(*, deprecated, message: "Use native color modificator") func fontStyle(_ style: Font.TextStyle, color: Color) -> some View { - modifier(Typography(style: style)) + modifier(Typography(fontStyle: style)) .foregroundColor(color) } } diff --git a/Sources/OversizeUI/Extensions/EnvironmentKey/ControlPaddingEnvironment.swift b/Sources/OversizeUI/Extensions/EnvironmentKey/ControlPaddingEnvironment.swift new file mode 100644 index 0000000..339bcf0 --- /dev/null +++ b/Sources/OversizeUI/Extensions/EnvironmentKey/ControlPaddingEnvironment.swift @@ -0,0 +1,42 @@ +// +// Copyright © 2022 Alexander Romanov +// ControlPaddingEnvironment.swift +// + +import SwiftUI + +public struct ControlPadding { + public let horizontal: Space + public let vertical: Space + + public init(_ all: Space) { + horizontal = all + vertical = all + } + + public init(horizontal: Space, vertical: Space) { + self.horizontal = horizontal + self.vertical = vertical + } +} + +private struct ControlPaddingKey: EnvironmentKey { + public static var defaultValue: ControlPadding = .init(.medium) +} + +public extension EnvironmentValues { + var controlPadding: ControlPadding { + get { self[ControlPaddingKey.self] } + set { self[ControlPaddingKey.self] = newValue } + } +} + +public extension View { + func controlPadding(_ all: Space) -> some View { + environment(\.controlPadding, ControlPadding(all)) + } + + func controlPadding(horizontal: Space, vertical: Space) -> some View { + environment(\.controlPadding, ControlPadding(horizontal: horizontal, vertical: vertical)) + } +} diff --git a/Sources/OversizeUI/Extensions/EnvironmentKey/PaddingEnvironment.swift b/Sources/OversizeUI/Extensions/EnvironmentKey/PaddingEnvironment.swift deleted file mode 100644 index 525ae54..0000000 --- a/Sources/OversizeUI/Extensions/EnvironmentKey/PaddingEnvironment.swift +++ /dev/null @@ -1,23 +0,0 @@ -// -// Copyright © 2022 Alexander Romanov -// PaddingEnvironment.swift -// - -import SwiftUI - -private struct ControlPaddingKey: EnvironmentKey { - public static var defaultValue: Space = .medium -} - -public extension EnvironmentValues { - var controlPadding: Space { - get { self[ControlPaddingKey.self] } - set { self[ControlPaddingKey.self] = newValue } - } -} - -public extension View { - func controlPadding(_ space: Space) -> some View { - environment(\.controlPadding, space) - } -}