diff --git a/Examples/DemosApp/DemosApp/ComponentsPreview/Helpers/ModalPreview+Helpers.swift b/Examples/DemosApp/DemosApp/ComponentsPreview/Helpers/ModalPreview+Helpers.swift index bc195431..2b27dd5c 100644 --- a/Examples/DemosApp/DemosApp/ComponentsPreview/Helpers/ModalPreview+Helpers.swift +++ b/Examples/DemosApp/DemosApp/ComponentsPreview/Helpers/ModalPreview+Helpers.swift @@ -60,10 +60,10 @@ struct ModalPreviewHelpers { Section("Properties") { Picker("Background Color", selection: self.$model.backgroundColor) { Text("Default").tag(Optional.none) - Text("Accent Background").tag(ComponentColor.accent.background) - Text("Success Background").tag(ComponentColor.success.background) - Text("Warning Background").tag(ComponentColor.warning.background) - Text("Danger Background").tag(ComponentColor.danger.background) + Text("Accent Background").tag(UniversalColor.accentBackground) + Text("Success Background").tag(UniversalColor.successBackground) + Text("Warning Background").tag(UniversalColor.warningBackground) + Text("Danger Background").tag(UniversalColor.dangerBackground) } BorderWidthPicker(selection: self.$model.borderWidth) Toggle("Closes On Overlay Tap", isOn: self.$model.closesOnOverlayTap) diff --git a/Examples/DemosApp/DemosApp/ComponentsPreview/PreviewPages/AlertPreview.swift b/Examples/DemosApp/DemosApp/ComponentsPreview/PreviewPages/AlertPreview.swift index e791b250..93e3b098 100644 --- a/Examples/DemosApp/DemosApp/ComponentsPreview/PreviewPages/AlertPreview.swift +++ b/Examples/DemosApp/DemosApp/ComponentsPreview/PreviewPages/AlertPreview.swift @@ -84,10 +84,10 @@ struct AlertPreview: View { Section("Main Properties") { Picker("Background Color", selection: self.$model.backgroundColor) { Text("Default").tag(Optional.none) - Text("Accent Background").tag(ComponentColor.accent.background) - Text("Success Background").tag(ComponentColor.success.background) - Text("Warning Background").tag(ComponentColor.warning.background) - Text("Danger Background").tag(ComponentColor.danger.background) + Text("Accent Background").tag(UniversalColor.accentBackground) + Text("Success Background").tag(UniversalColor.successBackground) + Text("Warning Background").tag(UniversalColor.warningBackground) + Text("Danger Background").tag(UniversalColor.dangerBackground) } BorderWidthPicker(selection: self.$model.borderWidth) Toggle("Closes On Overlay Tap", isOn: self.$model.closesOnOverlayTap) @@ -154,7 +154,7 @@ Enim habitant laoreet inceptos scelerisque senectus, tellus molestie ut. Eros ri } static let initialSecondaryButton = AlertButtonVM { $0.title = SecondaryButtonText.short.rawValue - $0.style = .light + $0.style = .plain } var primaryButtonVMOrDefault: Binding { diff --git a/Examples/DemosApp/DemosApp/ComponentsPreview/PreviewPages/BadgePreview.swift b/Examples/DemosApp/DemosApp/ComponentsPreview/PreviewPages/BadgePreview.swift index be023fbc..55b06b51 100644 --- a/Examples/DemosApp/DemosApp/ComponentsPreview/PreviewPages/BadgePreview.swift +++ b/Examples/DemosApp/DemosApp/ComponentsPreview/PreviewPages/BadgePreview.swift @@ -17,21 +17,17 @@ struct BadgePreview: View { SUBadge(model: self.model) } Form { + ComponentOptionalColorPicker(selection: self.$model.color) + ComponentRadiusPicker(selection: self.$model.cornerRadius) { + Text("Custom: 4px").tag(ComponentRadius.custom(4)) + } + Toggle("Enabled", isOn: self.$model.isEnabled) Picker("Font", selection: self.$model.font) { - Text("Default").tag(Optional.none) Text("Small").tag(UniversalFont.smButton) Text("Medium").tag(UniversalFont.mdButton) Text("Large").tag(UniversalFont.lgButton) Text("Custom: system bold of size 16").tag(UniversalFont.system(size: 16, weight: .bold)) } - ComponentOptionalColorPicker(selection: self.$model.color) - ComponentRadiusPicker(selection: self.$model.cornerRadius) { - Text("Custom: 4px").tag(ComponentRadius.custom(4)) - } - Picker("Style", selection: self.$model.style) { - Text("Filled").tag(BadgeVM.Style.filled) - Text("Light").tag(BadgeVM.Style.light) - } Picker("Paddings", selection: self.$model.paddings) { Text("8px; 6px") .tag(Paddings(top: 6, leading: 8, bottom: 6, trailing: 8)) @@ -40,6 +36,10 @@ struct BadgePreview: View { Text("12px; 10px") .tag(Paddings(top: 10, leading: 12, bottom: 10, trailing: 12)) } + Picker("Style", selection: self.$model.style) { + Text("Filled").tag(BadgeVM.Style.filled) + Text("Light").tag(BadgeVM.Style.light) + } } } } diff --git a/Examples/DemosApp/DemosApp/ComponentsPreview/PreviewPages/CardPreview.swift b/Examples/DemosApp/DemosApp/ComponentsPreview/PreviewPages/CardPreview.swift index c64ae340..1543e844 100644 --- a/Examples/DemosApp/DemosApp/ComponentsPreview/PreviewPages/CardPreview.swift +++ b/Examples/DemosApp/DemosApp/ComponentsPreview/PreviewPages/CardPreview.swift @@ -18,10 +18,10 @@ struct CardPreview: View { Picker("Background Color", selection: self.$model.backgroundColor) { Text("Default").tag(Optional.none) Text("Secondary Background").tag(UniversalColor.secondaryBackground) - Text("Accent Background").tag(ComponentColor.accent.background) - Text("Success Background").tag(ComponentColor.success.background) - Text("Warning Background").tag(ComponentColor.warning.background) - Text("Danger Background").tag(ComponentColor.danger.background) + Text("Accent Background").tag(UniversalColor.accentBackground) + Text("Success Background").tag(UniversalColor.successBackground) + Text("Warning Background").tag(UniversalColor.warningBackground) + Text("Danger Background").tag(UniversalColor.dangerBackground) } BorderWidthPicker(selection: self.$model.borderWidth) Picker("Content Paddings", selection: self.$model.contentPaddings) { @@ -37,7 +37,7 @@ struct CardPreview: View { Text("Small").tag(Shadow.small) Text("Medium").tag(Shadow.medium) Text("Large").tag(Shadow.large) - Text("Custom").tag(Shadow.custom(20.0, .zero, ComponentColor.accent.background)) + Text("Custom").tag(Shadow.custom(20.0, .zero, UniversalColor.accentBackground)) } } } diff --git a/README.md b/README.md index 6fa036ec..5dcd4c8d 100644 --- a/README.md +++ b/README.md @@ -88,12 +88,12 @@ inputField.resignFirstResponder() ### Styling -**Config** +**Theme** -The library comes with predefined fonts, sizes and colors, but you can change these values to customize the appearance of your app. To do this, alter the config: +The library comes with predefined fonts, sizes and colors, but you can change these values to customize the appearance of your app. To do this, alter the current theme: ```swift -ComponentsKitConfig.shared.update { +Theme.current.update { // Update colors $0.colors.primary = ... @@ -103,12 +103,12 @@ ComponentsKitConfig.shared.update { ``` > [!Note] -> The best place to set up the initial config is in the `func application(_:, didFinishLaunchingWithOptions:) -> Bool` method in your `AppDelegate` or a similar method in `SceneDelegate`. +> The best place to set up the initial theme is in the `func application(_:, didFinishLaunchingWithOptions:) -> Bool` method in your `AppDelegate` or a similar method in `SceneDelegate`. -By altering the config, you can also create *custom themes* for your app. To do this, first create a new instance of a config: +By altering the theme, you can also create *custom themes* for your app. To do this, first create a new instance of a `Theme`: ```swift -let halloweenTheme = ComponentsKitConfig { +let halloweenTheme = Theme { $0.colors.background = .themed( light: .hex("#e38f36"), dark: .hex("#ba5421") @@ -117,25 +117,26 @@ let halloweenTheme = ComponentsKitConfig { } ``` -When the user switches the theme, apply it by assigning it to the `shared` instance: +When the user switches the theme, apply it by assigning it to the `current` instance: ```swift -ComponentsKitConfig.shared = halloweenTheme +Theme.current = halloweenTheme ``` **Extend Colors** -All colors from the config can be used within the app. For example: +All colors from the theme can be used within the app. For example: ```swift // in UIKit view.backgroundColor = UniversalColor.background.uiColor // in SwiftUI -UniversalColor.background.color +SomeView() + .background(UniversalColor.background.color) ``` -If you want to use additional colors that are not included in the config, you can extend `UniversalColor`: +If you want to use additional colors that are not included in the theme, you can extend `UniversalColor`: ```swift extension UniversalColor { @@ -155,7 +156,7 @@ view.backgroundColor = UniversalColor.special.uiColor **Extend Fonts** -If you want to use additional fonts that are not included in the config, you can extend `UniversalFont`: +If you want to use additional fonts that are not included in the theme, you can extend `UniversalFont`: ```swift extension UniversalFont { diff --git a/Sources/ComponentsKit/Components/Badge/Models/BadgeVM.swift b/Sources/ComponentsKit/Components/Badge/Models/BadgeVM.swift index 4232dff6..8e61d7d9 100644 --- a/Sources/ComponentsKit/Components/Badge/Models/BadgeVM.swift +++ b/Sources/ComponentsKit/Components/Badge/Models/BadgeVM.swift @@ -8,24 +8,29 @@ public struct BadgeVM: ComponentVM { /// The color of the badge. public var color: ComponentColor? - /// The visual style of the badge. + /// The corner radius of the badge. /// - /// Defaults to `.filled`. - public var style: Style = .filled + /// Defaults to `.medium`. + public var cornerRadius: ComponentRadius = .medium /// The font used for the badge's text. /// /// Defaults to `.smButton`. public var font: UniversalFont = .smButton - /// The corner radius of the badge. + /// A Boolean value indicating whether the button is enabled or disabled. /// - /// Defaults to `.medium`. - public var cornerRadius: ComponentRadius = .medium + /// Defaults to `true`. + public var isEnabled: Bool = true /// Paddings for the badge. public var paddings: Paddings = .init(horizontal: 10, vertical: 8) + /// The visual style of the badge. + /// + /// Defaults to `.filled`. + public var style: Style = .filled + /// Initializes a new instance of `BadgeVM` with default values. public init() {} } @@ -35,22 +40,24 @@ public struct BadgeVM: ComponentVM { extension BadgeVM { /// Returns the background color of the badge based on its style. var backgroundColor: UniversalColor { - switch self.style { + let color = switch self.style { case .filled: - return self.color?.main ?? .content2 + self.color?.main ?? .content2 case .light: - return self.color?.background ?? .content1 + self.color?.background ?? .content1 } + return color.enabled(self.isEnabled) } /// Returns the foreground color of the badge based on its style. var foregroundColor: UniversalColor { - switch self.style { + let color = switch self.style { case .filled: - return self.color?.contrast ?? .foreground + self.color?.contrast ?? .foreground case .light: - return self.color?.main ?? .foreground + self.color?.main ?? .foreground } + return color.enabled(self.isEnabled) } } diff --git a/Sources/ComponentsKit/Components/Button/SUButton.swift b/Sources/ComponentsKit/Components/Button/SUButton.swift index f9e4ed73..d415a8ae 100644 --- a/Sources/ComponentsKit/Components/Button/SUButton.swift +++ b/Sources/ComponentsKit/Components/Button/SUButton.swift @@ -56,8 +56,7 @@ private struct CustomButtonStyle: SwiftUI.ButtonStyle { configuration.label .font(self.model.preferredFont.font) .lineLimit(1) - .padding(.leading, self.model.horizontalPadding) - .padding(.trailing, self.model.horizontalPadding) + .padding(.horizontal, self.model.horizontalPadding) .frame(maxWidth: self.model.width) .frame(height: self.model.height) .foregroundStyle(self.model.foregroundColor.color) diff --git a/Sources/ComponentsKit/Components/Button/UKButton.swift b/Sources/ComponentsKit/Components/Button/UKButton.swift index c7f573ce..058c1609 100644 --- a/Sources/ComponentsKit/Components/Button/UKButton.swift +++ b/Sources/ComponentsKit/Components/Button/UKButton.swift @@ -27,8 +27,6 @@ open class UKButton: UIView, UKComponent { } } - private var titleLabelConstraints: LayoutConstraints = .init() - // MARK: Subviews /// A label that displays the title from the model. @@ -85,11 +83,7 @@ open class UKButton: UIView, UKComponent { // MARK: Layout private func layout() { - self.titleLabelConstraints = self.titleLabel.horizontally(self.model.horizontalPadding) self.titleLabel.center() - - self.titleLabelConstraints.leading?.priority = .defaultHigh - self.titleLabelConstraints.trailing?.priority = .defaultHigh } open override func layoutSubviews() { @@ -106,10 +100,7 @@ open class UKButton: UIView, UKComponent { self.style() if self.model.shouldUpdateSize(oldModel) { - self.titleLabelConstraints.leading?.constant = self.model.horizontalPadding - self.titleLabelConstraints.trailing?.constant = -self.model.horizontalPadding self.invalidateIntrinsicContentSize() - self.setNeedsLayout() } } diff --git a/Sources/ComponentsKit/Configuration/Config.swift b/Sources/ComponentsKit/Configuration/Config.swift deleted file mode 100644 index c31c807a..00000000 --- a/Sources/ComponentsKit/Configuration/Config.swift +++ /dev/null @@ -1,24 +0,0 @@ -import Foundation - -/// A configuration structure for customizing colors and layout attributes of the components. -public struct ComponentsKitConfig: Initializable, Updatable { - // MARK: - Properties - - /// The palette of colors. - public var colors: Palette = .init() - - /// The layout configuration. - public var layout: Layout = .init() - - // MARK: - Initialization - - /// Initializes a new `ComponentsKitConfig` instance with default values. - public init() {} -} - -// MARK: - ComponentsKitConfig + Shared - -extension ComponentsKitConfig { - /// A shared instance of `ComponentsKitConfig` for global use. - public static var shared: Self = .init() -} diff --git a/Sources/ComponentsKit/Shared/Colors/UniversalColor.swift b/Sources/ComponentsKit/Shared/Colors/UniversalColor.swift index 24be0319..28c240a5 100644 --- a/Sources/ComponentsKit/Shared/Colors/UniversalColor.swift +++ b/Sources/ComponentsKit/Shared/Colors/UniversalColor.swift @@ -206,7 +206,7 @@ public struct UniversalColor: Hashable { public func enabled(_ isEnabled: Bool) -> Self { return isEnabled ? self - : self.withOpacity(ComponentsKitConfig.shared.layout.disabledOpacity) + : self.withOpacity(Theme.current.layout.disabledOpacity) } /// Returns a new `UniversalColor` by blending the current color with another color. diff --git a/Sources/ComponentsKit/Shared/Fonts/UniversalFont.swift b/Sources/ComponentsKit/Shared/Fonts/UniversalFont.swift index cd1ec1f0..ccc6cd29 100644 --- a/Sources/ComponentsKit/Shared/Fonts/UniversalFont.swift +++ b/Sources/ComponentsKit/Shared/Fonts/UniversalFont.swift @@ -158,53 +158,53 @@ extension UniversalFont.Weight { extension UniversalFont { /// Small headline font. public static var smHeadline: UniversalFont { - return ComponentsKitConfig.shared.layout.typography.headline.small + return Theme.current.layout.typography.headline.small } /// Medium headline font. public static var mdHeadline: UniversalFont { - return ComponentsKitConfig.shared.layout.typography.headline.medium + return Theme.current.layout.typography.headline.medium } /// Large headline font. public static var lgHeadline: UniversalFont { - return ComponentsKitConfig.shared.layout.typography.headline.large + return Theme.current.layout.typography.headline.large } /// Small body font. public static var smBody: UniversalFont { - return ComponentsKitConfig.shared.layout.typography.body.small + return Theme.current.layout.typography.body.small } /// Medium body font. public static var mdBody: UniversalFont { - return ComponentsKitConfig.shared.layout.typography.body.medium + return Theme.current.layout.typography.body.medium } /// Large body font. public static var lgBody: UniversalFont { - return ComponentsKitConfig.shared.layout.typography.body.large + return Theme.current.layout.typography.body.large } /// Small button font. public static var smButton: UniversalFont { - return ComponentsKitConfig.shared.layout.typography.button.small + return Theme.current.layout.typography.button.small } /// Medium button font. public static var mdButton: UniversalFont { - return ComponentsKitConfig.shared.layout.typography.button.medium + return Theme.current.layout.typography.button.medium } /// Large button font. public static var lgButton: UniversalFont { - return ComponentsKitConfig.shared.layout.typography.button.large + return Theme.current.layout.typography.button.large } /// Small caption font. public static var smCaption: UniversalFont { - return ComponentsKitConfig.shared.layout.typography.caption.small + return Theme.current.layout.typography.caption.small } /// Medium caption font. public static var mdCaption: UniversalFont { - return ComponentsKitConfig.shared.layout.typography.caption.medium + return Theme.current.layout.typography.caption.medium } /// Large caption font. public static var lgCaption: UniversalFont { - return ComponentsKitConfig.shared.layout.typography.caption.large + return Theme.current.layout.typography.caption.large } } diff --git a/Sources/ComponentsKit/Shared/Types/AnimationScale.swift b/Sources/ComponentsKit/Shared/Types/AnimationScale.swift index 9a6f0695..7d423ee5 100644 --- a/Sources/ComponentsKit/Shared/Types/AnimationScale.swift +++ b/Sources/ComponentsKit/Shared/Types/AnimationScale.swift @@ -21,7 +21,7 @@ extension AnimationScale { /// /// - Returns: /// - `1.0` for `.none` (no scaling). - /// - Predefined values from `ComponentsKitConfig` for `.small`, `.medium`, and `.large`. + /// - Predefined values from `Theme` for `.small`, `.medium`, and `.large`. /// - The custom value provided for `.custom`, constrained between `0.0` and `1.0`. /// - Note: If the custom value is outside the range `0.0–1.0`, an assertion failure occurs, /// and a default value of `1.0` is returned. @@ -30,11 +30,11 @@ extension AnimationScale { case .none: return 1.0 case .small: - return ComponentsKitConfig.shared.layout.animationScale.small + return Theme.current.layout.animationScale.small case .medium: - return ComponentsKitConfig.shared.layout.animationScale.medium + return Theme.current.layout.animationScale.medium case .large: - return ComponentsKitConfig.shared.layout.animationScale.large + return Theme.current.layout.animationScale.large case .custom(let value): guard value >= 0 && value <= 1.0 else { assertionFailure("Animation scale value should be between 0 and 1") diff --git a/Sources/ComponentsKit/Shared/Types/BorderWidth.swift b/Sources/ComponentsKit/Shared/Types/BorderWidth.swift index 2ebb7082..6110b233 100644 --- a/Sources/ComponentsKit/Shared/Types/BorderWidth.swift +++ b/Sources/ComponentsKit/Shared/Types/BorderWidth.swift @@ -19,11 +19,11 @@ extension BorderWidth { case .none: return 0.0 case .small: - return ComponentsKitConfig.shared.layout.borderWidth.small + return Theme.current.layout.borderWidth.small case .medium: - return ComponentsKitConfig.shared.layout.borderWidth.medium + return Theme.current.layout.borderWidth.medium case .large: - return ComponentsKitConfig.shared.layout.borderWidth.large + return Theme.current.layout.borderWidth.large } } } diff --git a/Sources/ComponentsKit/Shared/Types/ComponentRadius.swift b/Sources/ComponentsKit/Shared/Types/ComponentRadius.swift index f8af07c3..f62dad6a 100644 --- a/Sources/ComponentsKit/Shared/Types/ComponentRadius.swift +++ b/Sources/ComponentsKit/Shared/Types/ComponentRadius.swift @@ -24,13 +24,13 @@ extension ComponentRadius { /// /// - Parameter height: The height of the component. Defaults to a large number (10,000) for unrestricted calculations. /// - Returns: The calculated corner radius as a `CGFloat`, capped at half of the height for `full` rounding or custom values. - func value(for height: CGFloat = 10_000) -> CGFloat { + public func value(for height: CGFloat = 10_000) -> CGFloat { let maxValue = height / 2 let value = switch self { case .none: CGFloat(0) - case .small: ComponentsKitConfig.shared.layout.componentRadius.small - case .medium: ComponentsKitConfig.shared.layout.componentRadius.medium - case .large: ComponentsKitConfig.shared.layout.componentRadius.large + case .small: Theme.current.layout.componentRadius.small + case .medium: Theme.current.layout.componentRadius.medium + case .large: Theme.current.layout.componentRadius.large case .full: height / 2 case .custom(let value): value } diff --git a/Sources/ComponentsKit/Shared/Types/ContainerRadius.swift b/Sources/ComponentsKit/Shared/Types/ContainerRadius.swift index 419b988a..ca62838b 100644 --- a/Sources/ComponentsKit/Shared/Types/ContainerRadius.swift +++ b/Sources/ComponentsKit/Shared/Types/ContainerRadius.swift @@ -17,12 +17,12 @@ public enum ContainerRadius: Hashable { } extension ContainerRadius { - var value: CGFloat { + public var value: CGFloat { return switch self { case .none: CGFloat(0) - case .small: ComponentsKitConfig.shared.layout.containerRadius.small - case .medium: ComponentsKitConfig.shared.layout.containerRadius.medium - case .large: ComponentsKitConfig.shared.layout.containerRadius.large + case .small: Theme.current.layout.containerRadius.small + case .medium: Theme.current.layout.containerRadius.medium + case .large: Theme.current.layout.containerRadius.large case .custom(let value): value } } diff --git a/Sources/ComponentsKit/Shared/Types/Paddings.swift b/Sources/ComponentsKit/Shared/Types/Paddings.swift index f6674901..641fbf3c 100644 --- a/Sources/ComponentsKit/Shared/Types/Paddings.swift +++ b/Sources/ComponentsKit/Shared/Types/Paddings.swift @@ -1,4 +1,5 @@ import SwiftUI +import UIKit /// Defines padding values for each edge. public struct Paddings: Hashable { @@ -54,7 +55,7 @@ public struct Paddings: Hashable { // MARK: - SwiftUI Helpers extension Paddings { - var edgeInsets: EdgeInsets { + public var edgeInsets: EdgeInsets { return EdgeInsets( top: self.top, leading: self.leading, @@ -63,3 +64,16 @@ extension Paddings { ) } } + +// MARK: - UIKit Helpers + +extension Paddings { + public var uiEdgeInsets: UIEdgeInsets { + return UIEdgeInsets( + top: self.top, + left: self.leading, + bottom: self.bottom, + right: self.trailing + ) + } +} diff --git a/Sources/ComponentsKit/Shared/Types/Shadow.swift b/Sources/ComponentsKit/Shared/Types/Shadow.swift index 2be6dd37..ed873a18 100644 --- a/Sources/ComponentsKit/Shared/Types/Shadow.swift +++ b/Sources/ComponentsKit/Shared/Types/Shadow.swift @@ -21,32 +21,32 @@ public enum Shadow: Hashable { } extension Shadow { - var radius: CGFloat { + public var radius: CGFloat { return switch self { case .none: CGFloat(0) - case .small: ComponentsKitConfig.shared.layout.shadow.small.radius - case .medium: ComponentsKitConfig.shared.layout.shadow.medium.radius - case .large: ComponentsKitConfig.shared.layout.shadow.large.radius + case .small: Theme.current.layout.shadow.small.radius + case .medium: Theme.current.layout.shadow.medium.radius + case .large: Theme.current.layout.shadow.large.radius case .custom(let radius, _, _): radius } } - var offset: CGSize { + public var offset: CGSize { return switch self { case .none: .zero - case .small: ComponentsKitConfig.shared.layout.shadow.small.offset - case .medium: ComponentsKitConfig.shared.layout.shadow.medium.offset - case .large: ComponentsKitConfig.shared.layout.shadow.large.offset + case .small: Theme.current.layout.shadow.small.offset + case .medium: Theme.current.layout.shadow.medium.offset + case .large: Theme.current.layout.shadow.large.offset case .custom(_, let offset, _): offset } } - var color: UniversalColor { + public var color: UniversalColor { return switch self { case .none: .clear - case .small: ComponentsKitConfig.shared.layout.shadow.small.color - case .medium: ComponentsKitConfig.shared.layout.shadow.medium.color - case .large: ComponentsKitConfig.shared.layout.shadow.large.color + case .small: Theme.current.layout.shadow.small.color + case .medium: Theme.current.layout.shadow.medium.color + case .large: Theme.current.layout.shadow.large.color case .custom(_, _, let color): color } } @@ -55,7 +55,7 @@ extension Shadow { // MARK: - UIKit + Shadow extension UIView { - func shadow(_ shadow: Shadow) { + public func shadow(_ shadow: Shadow) { self.layer.shadowRadius = shadow.radius self.layer.shadowOffset = shadow.offset self.layer.shadowColor = shadow.color.cgColor @@ -66,7 +66,7 @@ extension UIView { // MARK: - SwiftUI + Shadow extension View { - func shadow(_ shadow: Shadow) -> some View { + public func shadow(_ shadow: Shadow) -> some View { self.shadow( color: shadow.color.color, radius: shadow.radius, diff --git a/Sources/ComponentsKit/Shared/Types/SubmitType.swift b/Sources/ComponentsKit/Shared/Types/SubmitType.swift index 5169f4bb..aab22ce7 100644 --- a/Sources/ComponentsKit/Shared/Types/SubmitType.swift +++ b/Sources/ComponentsKit/Shared/Types/SubmitType.swift @@ -26,7 +26,7 @@ public enum SubmitType { // MARK: - UIKit Helpers extension SubmitType { - var returnKeyType: UIReturnKeyType { + public var returnKeyType: UIReturnKeyType { switch self { case .done: return .done @@ -53,7 +53,7 @@ extension SubmitType { // MARK: - SwiftUI Helpers extension SubmitType { - var submitLabel: SubmitLabel { + public var submitLabel: SubmitLabel { switch self { case .done: return .done diff --git a/Sources/ComponentsKit/Shared/Types/TextAutocapitalization.swift b/Sources/ComponentsKit/Shared/Types/TextAutocapitalization.swift index c8159e67..cedc6c77 100644 --- a/Sources/ComponentsKit/Shared/Types/TextAutocapitalization.swift +++ b/Sources/ComponentsKit/Shared/Types/TextAutocapitalization.swift @@ -14,7 +14,7 @@ public enum TextAutocapitalization { } extension TextAutocapitalization { - var textAutocapitalizationType: UITextAutocapitalizationType { + public var textAutocapitalizationType: UITextAutocapitalizationType { switch self { case .never: return .none @@ -29,7 +29,7 @@ extension TextAutocapitalization { } extension TextAutocapitalization { - var textInputAutocapitalization: TextInputAutocapitalization { + public var textInputAutocapitalization: TextInputAutocapitalization { switch self { case .never: return .never diff --git a/Sources/ComponentsKit/Configuration/Layout.swift b/Sources/ComponentsKit/Theme/Layout.swift similarity index 95% rename from Sources/ComponentsKit/Configuration/Layout.swift rename to Sources/ComponentsKit/Theme/Layout.swift index 24c83a28..c79f51a2 100644 --- a/Sources/ComponentsKit/Configuration/Layout.swift +++ b/Sources/ComponentsKit/Theme/Layout.swift @@ -1,12 +1,12 @@ import Foundation -extension ComponentsKitConfig { +extension Theme { /// A structure that defines the layout-related configurations for components in the framework. - public struct Layout: Initializable, Updatable { + public struct Layout: Initializable, Updatable, Equatable { // MARK: - Radius /// A structure representing radius values for components. - public struct Radius { + public struct Radius: Equatable { /// The small radius size. public var small: CGFloat /// The medium radius size. @@ -30,7 +30,7 @@ extension ComponentsKitConfig { // MARK: - BorderWidth /// A structure representing border width values for components. - public struct BorderWidth { + public struct BorderWidth: Equatable { /// The small border width. public var small: CGFloat /// The medium border width. @@ -56,7 +56,7 @@ extension ComponentsKitConfig { /// A structure representing animation scale values for components. /// /// The values must be between `0.0` and `1.0`. - public struct AnimationScale { + public struct AnimationScale: Equatable { /// The small animation scale. public var small: CGFloat /// The medium animation scale. @@ -88,7 +88,7 @@ extension ComponentsKitConfig { // MARK: - Shadow /// A structure that defines the parameters for a shadow effect. - public struct ShadowParams { + public struct ShadowParams: Equatable { /// The blur radius of the shadow. /// /// A larger radius results in a more diffuse shadow. @@ -119,7 +119,7 @@ extension ComponentsKitConfig { } /// A structure that defines shadow presets for small, medium, and large shadows. - public struct Shadow { + public struct Shadow: Equatable { /// The shadow parameters for a small shadow. public var small: ShadowParams @@ -147,7 +147,7 @@ extension ComponentsKitConfig { // MARK: - Typography /// A structure representing a set of fonts for different component sizes. - public struct FontSet { + public struct FontSet: Equatable { /// The small font. public var small: UniversalFont /// The medium font. @@ -169,7 +169,7 @@ extension ComponentsKitConfig { } /// A structure representing typography settings for various components. - public struct Typography { + public struct Typography: Equatable { /// The font set for headlines. public var headline: FontSet /// The font set for body text. @@ -260,7 +260,7 @@ extension ComponentsKitConfig { headline: .init( small: .system(size: 14, weight: .semibold), medium: .system(size: 20, weight: .semibold), - large: .system(size: 28, weight: .semibold) + large: .system(size: 24, weight: .semibold) ), body: .init( small: .system(size: 14, weight: .regular), diff --git a/Sources/ComponentsKit/Configuration/Palette.swift b/Sources/ComponentsKit/Theme/Palette.swift similarity index 80% rename from Sources/ComponentsKit/Configuration/Palette.swift rename to Sources/ComponentsKit/Theme/Palette.swift index 0d0bb5e1..5def595c 100644 --- a/Sources/ComponentsKit/Configuration/Palette.swift +++ b/Sources/ComponentsKit/Theme/Palette.swift @@ -1,8 +1,8 @@ import Foundation -extension ComponentsKitConfig { +extension Theme { /// Defines a set of colors that are used for styling components and interfaces. - public struct Palette: Initializable, Updatable { + public struct Palette: Initializable, Updatable, Equatable { /// The color for the main background of the interface. public var background: UniversalColor = .themed( light: .hex("#FFFFFF"), @@ -122,23 +122,23 @@ extension ComponentsKitConfig { extension ComponentColor { /// The primary color. public static var primary: Self { - return ComponentsKitConfig.shared.colors.primary + return Theme.current.colors.primary } /// The accent color. public static var accent: Self { - return ComponentsKitConfig.shared.colors.accent + return Theme.current.colors.accent } /// The success state color, used for indicating positive actions or statuses. public static var success: Self { - return ComponentsKitConfig.shared.colors.success + return Theme.current.colors.success } /// The warning state color, used for indicating caution or non-critical alerts. public static var warning: Self { - return ComponentsKitConfig.shared.colors.warning + return Theme.current.colors.warning } /// The danger state color, used for indicating errors, destructive actions, or critical alerts. public static var danger: Self { - return ComponentsKitConfig.shared.colors.danger + return Theme.current.colors.danger } } @@ -161,58 +161,74 @@ extension UniversalColor { extension UniversalColor { /// The color for the main background of the interface. public static var background: Self { - return ComponentsKitConfig.shared.colors.background + return Theme.current.colors.background } /// The color for the secondary background of the interface. public static var secondaryBackground: Self { - return ComponentsKitConfig.shared.colors.secondaryBackground + return Theme.current.colors.secondaryBackground } /// The color for text labels that contain primary content. public static var foreground: Self { - return ComponentsKitConfig.shared.colors.foreground + return Theme.current.colors.foreground } /// The color for text labels that contain secondary content. public static var secondaryForeground: Self { - return ComponentsKitConfig.shared.colors.secondaryForeground + return Theme.current.colors.secondaryForeground } /// The color for thin borders or divider lines. public static var divider: Self { - return ComponentsKitConfig.shared.colors.divider + return Theme.current.colors.divider } /// The first content color. public static var content1: Self { - return ComponentsKitConfig.shared.colors.content1 + return Theme.current.colors.content1 } /// The second content color. public static var content2: Self { - return ComponentsKitConfig.shared.colors.content2 + return Theme.current.colors.content2 } /// The third content color. public static var content3: Self { - return ComponentsKitConfig.shared.colors.content3 + return Theme.current.colors.content3 } /// The forth content color. public static var content4: Self { - return ComponentsKitConfig.shared.colors.content4 + return Theme.current.colors.content4 } /// The primary color. public static var primary: Self { - return ComponentsKitConfig.shared.colors.primary.main + return Theme.current.colors.primary.main } /// The accent color. public static var accent: Self { - return ComponentsKitConfig.shared.colors.accent.main + return Theme.current.colors.accent.main + } + /// The accent background color. + public static var accentBackground: Self { + return Theme.current.colors.accent.background } /// The success state color, used for indicating positive actions or statuses. public static var success: Self { - return ComponentsKitConfig.shared.colors.success.main + return Theme.current.colors.success.main + } + /// The success background color. + public static var successBackground: Self { + return Theme.current.colors.success.background } /// The warning state color, used for indicating caution or non-critical alerts. public static var warning: Self { - return ComponentsKitConfig.shared.colors.warning.main + return Theme.current.colors.warning.main + } + /// The warning background color. + public static var warningBackground: Self { + return Theme.current.colors.warning.background } /// The danger state color, used for indicating errors, destructive actions, or critical alerts. public static var danger: Self { - return ComponentsKitConfig.shared.colors.danger.main + return Theme.current.colors.danger.main + } + /// The danger background color. + public static var dangerBackground: Self { + return Theme.current.colors.danger.background } } diff --git a/Sources/ComponentsKit/Theme/Theme.swift b/Sources/ComponentsKit/Theme/Theme.swift new file mode 100644 index 00000000..d65e0665 --- /dev/null +++ b/Sources/ComponentsKit/Theme/Theme.swift @@ -0,0 +1,25 @@ +import Foundation + +/// A predefined set of colors and layout attributes that ensure visual consistency across the +/// application. +public struct Theme: Initializable, Updatable, Equatable { + // MARK: - Properties + + /// The palette of colors. + public var colors: Palette = .init() + + /// The layout configuration. + public var layout: Layout = .init() + + // MARK: - Initialization + + /// Initializes a new `Theme` instance with default values. + public init() {} +} + +// MARK: - Theme + Shared + +extension Theme { + /// A current instance of `Theme` for global use. + public static var current: Self = .init() +}