@@ -86,6 +86,47 @@ public struct UniversalColor: Hashable {
8686 return UIColor ( color)
8787 }
8888 }
89+
90+ /// Returns a tuple containing the red, green, blue, and alpha components of the color.
91+ private var rgba : ( r: CGFloat , g: CGFloat , b: CGFloat , a: CGFloat ) {
92+ switch self {
93+ case let . rgba( r, g, b, a) :
94+ return ( r, g, b, a)
95+ case . uiColor, . color:
96+ var red : CGFloat = 0
97+ var green : CGFloat = 0
98+ var blue : CGFloat = 0
99+ var alpha : CGFloat = 0
100+
101+ self . uiColor. getRed ( & red, green: & green, blue: & blue, alpha: & alpha)
102+
103+ return ( red, green, blue, alpha)
104+ }
105+ }
106+
107+ /// Returns a new `ColorRepresentable` by blending the current color with another color.
108+ ///
109+ /// The blending is performed using the alpha value of the current color,
110+ /// where the second color is treated as fully opaque (alpha = `1.0 - self.alpha`).
111+ ///
112+ /// The resulting color's RGBA components are calculated as:
113+ /// - `red = self.red * self.alpha + other.red * (1.0 - self.alpha)`
114+ /// - `green = self.green * self.alpha + other.green * (1.0 - self.alpha)`
115+ /// - `blue = self.blue * self.alpha + other.blue * (1.0 - self.alpha)`
116+ /// - The resulting color's alpha will always be `1.0`.
117+ ///
118+ /// - Parameter other: The `ColorRepresentable` to blend with the current color.
119+ /// - Returns: A new `ColorRepresentable` instance representing the blended color.
120+ fileprivate func blended( with other: Self ) -> Self {
121+ let rgba = self . rgba
122+ let otherRgba = other. rgba
123+
124+ let red = rgba. r * rgba. a + otherRgba. r * ( 1.0 - rgba. a)
125+ let green = rgba. g * rgba. a + otherRgba. g * ( 1.0 - rgba. a)
126+ let blue = rgba. b * rgba. a + otherRgba. b * ( 1.0 - rgba. a)
127+
128+ return . rgba( r: red, g: green, b: blue, a: 1.0 )
129+ }
89130 }
90131
91132 // MARK: - Properties
@@ -119,29 +160,6 @@ public struct UniversalColor: Hashable {
119160 return Self ( light: universal, dark: universal)
120161 }
121162
122- // MARK: - Methods
123-
124- /// Returns a new `UniversalColor` with the specified opacity.
125- ///
126- /// - Parameter alpha: The desired opacity (0.0–1.0).
127- /// - Returns: A new `UniversalColor` instance with the adjusted opacity.
128- public func withOpacity( _ alpha: CGFloat ) -> Self {
129- return . init(
130- light: self . light. withOpacity ( alpha) ,
131- dark: self . dark. withOpacity ( alpha)
132- )
133- }
134-
135- /// Returns a disabled version of the color based on a global opacity configuration.
136- ///
137- /// - Parameter isEnabled: A Boolean value indicating whether the color should be enabled.
138- /// - Returns: A new `UniversalColor` instance with reduced opacity if `isEnabled` is `false`.
139- public func enabled( _ isEnabled: Bool ) -> Self {
140- return isEnabled
141- ? self
142- : self . withOpacity ( ComponentsKitConfig . shared. layout. disabledOpacity)
143- }
144-
145163 // MARK: - Colors
146164
147165 /// Returns the `UIColor` representation of the color.
@@ -167,4 +185,47 @@ public struct UniversalColor: Hashable {
167185 public var cgColor : CGColor {
168186 return self . uiColor. cgColor
169187 }
188+
189+ // MARK: - Methods
190+
191+ /// Returns a new `UniversalColor` with the specified opacity.
192+ ///
193+ /// - Parameter alpha: The desired opacity (0.0–1.0).
194+ /// - Returns: A new `UniversalColor` instance with the adjusted opacity.
195+ public func withOpacity( _ alpha: CGFloat ) -> Self {
196+ return . init(
197+ light: self . light. withOpacity ( alpha) ,
198+ dark: self . dark. withOpacity ( alpha)
199+ )
200+ }
201+
202+ /// Returns a disabled version of the color based on a global opacity configuration.
203+ ///
204+ /// - Parameter isEnabled: A Boolean value indicating whether the color should be enabled.
205+ /// - Returns: A new `UniversalColor` instance with reduced opacity if `isEnabled` is `false`.
206+ public func enabled( _ isEnabled: Bool ) -> Self {
207+ return isEnabled
208+ ? self
209+ : self . withOpacity ( ComponentsKitConfig . shared. layout. disabledOpacity)
210+ }
211+
212+ /// Returns a new `UniversalColor` by blending the current color with another color.
213+ ///
214+ /// The blending is performed using the alpha value of the current color,
215+ /// where the second color is treated as fully opaque (alpha = `1.0 - self.alpha`).
216+ ///
217+ /// The resulting color's RGBA components are calculated as:
218+ /// - `red = self.red * self.alpha + other.red * (1.0 - self.alpha)`
219+ /// - `green = self.green * self.alpha + other.green * (1.0 - self.alpha)`
220+ /// - `blue = self.blue * self.alpha + other.blue * (1.0 - self.alpha)`
221+ /// - The resulting color's alpha will always be `1.0`.
222+ ///
223+ /// - Parameter other: The `UniversalColor` to blend with the current color.
224+ /// - Returns: A new `UniversalColor` instance representing the blended color.
225+ public func blended( with other: Self ) -> Self {
226+ return . init(
227+ light: self . light. blended ( with: other. light) ,
228+ dark: self . dark. blended ( with: other. dark)
229+ )
230+ }
170231}
0 commit comments