11import SwiftUI
22import 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.
46public 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:
0 commit comments