Skip to content

Commit 4837205

Browse files
add docs
1 parent 84ed5e8 commit 4837205

File tree

5 files changed

+145
-9
lines changed

5 files changed

+145
-9
lines changed

Sources/ComponentsKit/Shared/ComponentColor.swift

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,26 @@
11
import Foundation
22

3+
/// A structure that defines a color set for components.
34
public struct ComponentColor: Hashable {
4-
// MARK: Properties
5+
// MARK: - Properties
56

7+
/// The primary color used for the component.
68
public let main: UniversalColor
9+
10+
/// The contrast color, typically used for text or elements displayed on top of the `main` color.
711
public let contrast: UniversalColor
12+
13+
/// The background color for the component.
814
public let background: UniversalColor
915

10-
// MARK: Initialization
16+
// MARK: - Initialization
1117

18+
/// Initializer.
19+
///
20+
/// - Parameters:
21+
/// - main: The primary color for the component.
22+
/// - contrast: The color that contrasts with the `main` color, typically used for text or icons.
23+
/// - background: The background color for the component. Defaults to `main` color with 15% opacity if `nil`.
1224
public init(
1325
main: UniversalColor,
1426
contrast: UniversalColor,
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
import Foundation
22

3+
/// An enumeration that defines size options for a component.
34
public enum ComponentSize: Hashable {
5+
/// A small-sized component.
46
case small
7+
/// A medium-sized component.
58
case medium
9+
/// A large-sized component.
610
case large
711
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,21 @@
11
import UIKit
22

3+
/// A protocol that defines a UIKit component with a configurable model.
4+
///
5+
/// Types conforming to `UKComponent` are responsible for updating their appearance
6+
/// based on changes to their associated model.
37
public protocol UKComponent: UIView {
8+
/// A type of the model that defines the appearance properties.
49
associatedtype Model
510

11+
/// A model that defines the appearance properties.
612
var model: Model { get set }
713

14+
/// Updates the component when the model changes.
15+
///
16+
/// This method is called when the `model` property changes, providing an opportunity
17+
/// to compare the new and old models and update the component's appearance.
18+
///
19+
/// - Parameter oldModel: The previous model before the update.
820
func update(_ oldModel: Model)
921
}

Sources/ComponentsKit/Shared/UniversalColor.swift

Lines changed: 61 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,34 @@
11
import SwiftUI
22
import UIKit
33

4+
/// A structure that represents an universal color that can be used in both UIKit and SwiftUI,
5+
/// with light and dark theme variants.
46
public struct UniversalColor: Hashable {
5-
// MARK: ColorRepresentable
7+
// MARK: - ColorRepresentable
68

9+
/// An enumeration that defines the possible representations of a color.
710
public enum ColorRepresentable: Hashable {
11+
/// A color defined by its RGBA components.
12+
///
13+
/// - Parameters:
14+
/// - r: The red component (0–255).
15+
/// - g: The green component (0–255).
16+
/// - b: The blue component (0–255).
17+
/// - a: The alpha (opacity) component (0.0–1.0).
818
case rgba(r: CGFloat, g: CGFloat, b: CGFloat, a: CGFloat)
19+
20+
/// A color represented by a `UIColor` instance.
921
case uiColor(UIColor)
22+
23+
/// A color represented by a SwiftUI `Color` instance.
1024
case color(Color)
1125

26+
/// Creates a `ColorRepresentable` instance from a hexadecimal string.
27+
///
28+
/// - Parameter value: A hex string representing the color (e.g., `"#FFFFFF"` or `"FFFFFF"`).
29+
/// - Returns: A `ColorRepresentable` instance with the corresponding RGBA values.
30+
/// - Note: This method assumes the input string has exactly six hexadecimal characters.
31+
/// - Warning: This method will trigger an assertion failure if the input is invalid.
1232
public static func hex(_ value: String) -> Self {
1333
let start: String.Index
1434
if value.hasPrefix("#") {
@@ -28,10 +48,17 @@ public struct UniversalColor: Hashable {
2848

2949
return .rgba(r: r, g: g, b: b, a: 1.0)
3050
} else {
31-
fatalError("Unable to initialize color from the provided hex value: \(value)")
51+
assertionFailure(
52+
"Unable to initialize color from the provided hex value: \(value)"
53+
)
54+
return .rgba(r: 0, g: 0, b: 0, a: 1.0)
3255
}
3356
}
3457

58+
/// Returns a new `ColorRepresentable` with the specified opacity.
59+
///
60+
/// - Parameter alpha: The desired opacity (0.0–1.0).
61+
/// - Returns: A `ColorRepresentable` instance with the adjusted opacity.
3562
fileprivate func withOpacity(_ alpha: CGFloat) -> Self {
3663
switch self {
3764
case .rgba(let r, let g, let b, _):
@@ -43,6 +70,7 @@ public struct UniversalColor: Hashable {
4370
}
4471
}
4572

73+
/// Converts the `ColorRepresentable` to a `UIColor` instance.
4674
fileprivate var uiColor: UIColor {
4775
switch self {
4876
case .rgba(let red, let green, let blue, let alpha):
@@ -59,6 +87,7 @@ public struct UniversalColor: Hashable {
5987
}
6088
}
6189

90+
/// Converts the `ColorRepresentable` to a SwiftUI `Color` instance.
6291
fileprivate var color: Color {
6392
switch self {
6493
case .rgba(let r, let g, let b, let a):
@@ -76,41 +105,63 @@ public struct UniversalColor: Hashable {
76105
}
77106
}
78107

79-
// MARK: Properties
108+
// MARK: - Properties
80109

110+
/// The color used in light mode.
81111
let light: ColorRepresentable
112+
113+
/// The color used in dark mode.
82114
let dark: ColorRepresentable
83115

84-
// MARK: Initialization
116+
// MARK: - Initialization
85117

118+
/// Creates a `UniversalColor` with distinct light and dark mode colors.
119+
///
120+
/// - Parameters:
121+
/// - light: The color to use in light mode.
122+
/// - dark: The color to use in dark mode.
123+
/// - Returns: A new `UniversalColor` instance.
86124
public static func themed(
87125
light: ColorRepresentable,
88126
dark: ColorRepresentable
89127
) -> Self {
90128
return Self(light: light, dark: dark)
91129
}
92130

131+
/// Creates a `UniversalColor` with a single color used for both light and dark modes.
132+
///
133+
/// - Parameter universal: The universal color to use.
134+
/// - Returns: A new `UniversalColor` instance.
93135
public static func universal(_ universal: ColorRepresentable) -> Self {
94136
return Self(light: universal, dark: universal)
95137
}
96138

97-
// MARK: Methods
139+
// MARK: - Methods
98140

141+
/// Returns a new `UniversalColor` with the specified opacity.
142+
///
143+
/// - Parameter alpha: The desired opacity (0.0–1.0).
144+
/// - Returns: A new `UniversalColor` instance with the adjusted opacity.
99145
public func withOpacity(_ alpha: CGFloat) -> Self {
100146
return .init(
101147
light: self.light.withOpacity(alpha),
102148
dark: self.dark.withOpacity(alpha)
103149
)
104150
}
105151

152+
/// Returns a disabled version of the color based on a global opacity configuration.
153+
///
154+
/// - Parameter isEnabled: A Boolean value indicating whether the color should be enabled.
155+
/// - Returns: A new `UniversalColor` instance with reduced opacity if `isEnabled` is `false`.
106156
public func enabled(_ isEnabled: Bool) -> Self {
107157
return isEnabled
108158
? self
109159
: self.withOpacity(ComponentsKitConfig.shared.layout.disabledOpacity)
110160
}
111161

112-
// MARK: Colors
162+
// MARK: - Colors
113163

164+
/// Returns the `UIColor` representation of the color, adapting to the current system theme.
114165
public var uiColor: UIColor {
115166
return UIColor { trait in
116167
switch trait.userInterfaceStyle {
@@ -124,6 +175,10 @@ public struct UniversalColor: Hashable {
124175
}
125176
}
126177

178+
/// Returns the `Color` representation of the color for a given SwiftUI `ColorScheme`.
179+
///
180+
/// - Parameter colorScheme: The current color scheme (`.light` or `.dark`).
181+
/// - Returns: The corresponding `Color` instance.
127182
public func color(for colorScheme: ColorScheme) -> Color {
128183
switch colorScheme {
129184
case .light:

Sources/ComponentsKit/Shared/UniversalFont.swift

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,66 @@
11
import SwiftUI
22
import UIKit
33

4+
/// A structure that represents an universal font that can be used in both UIKit and SwiftUI,
5+
/// with support for custom and system fonts.
46
public enum UniversalFont: Hashable {
7+
/// An enumeration that defines the weight of a font.
58
public enum Weight: Hashable {
9+
/// Ultra-light font weight.
610
case ultraLight
11+
/// Thin font weight.
712
case thin
13+
/// Light font weight.
814
case light
15+
/// Regular font weight.
916
case regular
17+
/// Medium font weight.
1018
case medium
19+
/// Semi-bold font weight.
1120
case semibold
21+
/// Bold font weight.
1222
case bold
23+
/// Heavy font weight.
1324
case heavy
25+
/// Black (extra-bold) font weight.
1426
case black
1527
}
28+
29+
/// A custom font with a specific name and size.
30+
///
31+
/// - Parameters:
32+
/// - name: The name of the font.
33+
/// - size: The size of the font.
1634
case custom(name: String, size: CGFloat)
35+
36+
/// A system font with a specific size and weight.
37+
///
38+
/// - Parameters:
39+
/// - size: The size of the font.
40+
/// - weight: The weight of the font, defined by `UniversalFont.Weight`.
1741
case system(size: CGFloat, weight: Weight)
1842

1943
// MARK: Fonts
2044

45+
/// Converts the `UniversalFont` to a `UIFont` instance.
46+
///
47+
/// - Returns: A `UIFont` representation of the `UniversalFont`.
2148
public var uiFont: UIFont {
2249
switch self {
2350
case .custom(let name, let size):
2451
guard let font = UIFont(name: name, size: size) else {
25-
fatalError("Unable to initialize font '\(name)'")
52+
assertionFailure("Unable to initialize font '\(name)'")
53+
return UIFont.systemFont(ofSize: size)
2654
}
2755
return font
2856
case let .system(size, weight):
2957
return UIFont.systemFont(ofSize: size, weight: weight.uiFontWeight)
3058
}
3159
}
3260

61+
/// Converts the `UniversalFont` to a SwiftUI `Font` instance.
62+
///
63+
/// - Returns: A `Font` representation of the `UniversalFont`.
3364
public var font: Font {
3465
switch self {
3566
case .custom(let name, let size):
@@ -41,6 +72,10 @@ public enum UniversalFont: Hashable {
4172

4273
// MARK: Helpers
4374

75+
/// Returns a new `UniversalFont` with the specified size.
76+
///
77+
/// - Parameter size: The new size for the font.
78+
/// - Returns: A new `UniversalFont` instance with the updated size.
4479
public func withSize(_ size: CGFloat) -> Self {
4580
switch self {
4681
case .custom(let name, _):
@@ -50,6 +85,10 @@ public enum UniversalFont: Hashable {
5085
}
5186
}
5287

88+
/// Returns a new `UniversalFont` with a size adjusted by a relative value.
89+
///
90+
/// - Parameter shift: The amount to adjust the font size by.
91+
/// - Returns: A new `UniversalFont` instance with the adjusted size.
5392
public func withRelativeSize(_ shift: CGFloat) -> Self {
5493
switch self {
5594
case .custom(let name, let size):
@@ -63,6 +102,7 @@ public enum UniversalFont: Hashable {
63102
// MARK: Helpers
64103

65104
extension UniversalFont.Weight {
105+
/// Converts `UniversalFont.Weight` to `UIFont.Weight`.
66106
var uiFontWeight: UIFont.Weight {
67107
switch self {
68108
case .ultraLight:
@@ -88,6 +128,7 @@ extension UniversalFont.Weight {
88128
}
89129

90130
extension UniversalFont.Weight {
131+
/// Converts `UniversalFont.Weight` to SwiftUI `Font.Weight`.
91132
var swiftUIFontWeight: Font.Weight {
92133
switch self {
93134
case .ultraLight:
@@ -115,42 +156,54 @@ extension UniversalFont.Weight {
115156
// MARK: - UniversalFont + Config
116157

117158
extension UniversalFont {
159+
/// Small headline font.
118160
public static var smHeadline: UniversalFont {
119161
return ComponentsKitConfig.shared.layout.typography.headline.small
120162
}
163+
/// Medium headline font.
121164
public static var mdHeadline: UniversalFont {
122165
return ComponentsKitConfig.shared.layout.typography.headline.medium
123166
}
167+
/// Large headline font.
124168
public static var lgHeadline: UniversalFont {
125169
return ComponentsKitConfig.shared.layout.typography.headline.large
126170
}
127171

172+
/// Small body font.
128173
public static var smBody: UniversalFont {
129174
return ComponentsKitConfig.shared.layout.typography.body.small
130175
}
176+
/// Medium body font.
131177
public static var mdBody: UniversalFont {
132178
return ComponentsKitConfig.shared.layout.typography.body.medium
133179
}
180+
/// Large body font.
134181
public static var lgBody: UniversalFont {
135182
return ComponentsKitConfig.shared.layout.typography.body.large
136183
}
137184

185+
/// Small button font.
138186
public static var smButton: UniversalFont {
139187
return ComponentsKitConfig.shared.layout.typography.button.small
140188
}
189+
/// Medium button font.
141190
public static var mdButton: UniversalFont {
142191
return ComponentsKitConfig.shared.layout.typography.button.medium
143192
}
193+
/// Large button font.
144194
public static var lgButton: UniversalFont {
145195
return ComponentsKitConfig.shared.layout.typography.button.large
146196
}
147197

198+
/// Small caption font.
148199
public static var smCaption: UniversalFont {
149200
return ComponentsKitConfig.shared.layout.typography.caption.small
150201
}
202+
/// Medium caption font.
151203
public static var mdCaption: UniversalFont {
152204
return ComponentsKitConfig.shared.layout.typography.caption.medium
153205
}
206+
/// Large caption font.
154207
public static var lgCaption: UniversalFont {
155208
return ComponentsKitConfig.shared.layout.typography.caption.large
156209
}

0 commit comments

Comments
 (0)