1+ import SwiftUI
2+
3+ // MARK: - Color <-> Hex helpers
4+ extension Color {
5+ init ? ( hex: String ) {
6+ var hex = hex
7+ if hex. hasPrefix ( " # " ) { hex. removeFirst ( ) }
8+ guard hex. count == 6 , let intVal = Int ( hex, radix: 16 ) else { return nil }
9+ let r = Double ( ( intVal >> 16 ) & 0xFF ) / 255.0
10+ let g = Double ( ( intVal >> 8 ) & 0xFF ) / 255.0
11+ let b = Double ( intVal & 0xFF ) / 255.0
12+ self . init ( red: r, green: g, blue: b)
13+ }
14+
15+ func toHexString( ) -> String ? {
16+ let uiColor = NSColor ( self )
17+ guard let rgb = uiColor. usingColorSpace ( . deviceRGB) else { return nil }
18+ let r = Int ( rgb. redComponent * 255 )
19+ let g = Int ( rgb. greenComponent * 255 )
20+ let b = Int ( rgb. blueComponent * 255 )
21+ return String ( format: " #%02X%02X%02X " , r, g, b)
22+ }
23+
24+ // Returns a lighter version of the color by blending with white
25+ func lighter( by amount: CGFloat = 0.6 ) -> Color {
26+ let uiColor = NSColor ( self )
27+ guard let rgb = uiColor. usingColorSpace ( . deviceRGB) else { return self }
28+ let r = rgb. redComponent + ( 1.0 - rgb. redComponent) * amount
29+ let g = rgb. greenComponent + ( 1.0 - rgb. greenComponent) * amount
30+ let b = rgb. blueComponent + ( 1.0 - rgb. blueComponent) * amount
31+ return Color ( red: r, green: g, blue: b)
32+ }
33+
34+ // Returns a darker version of the color by blending with black
35+ func darker( by amount: CGFloat = 0.3 ) -> Color {
36+ let uiColor = NSColor ( self )
37+ guard let rgb = uiColor. usingColorSpace ( . deviceRGB) else { return self }
38+ let r = rgb. redComponent * ( 1.0 - amount)
39+ let g = rgb. greenComponent * ( 1.0 - amount)
40+ let b = rgb. blueComponent * ( 1.0 - amount)
41+ return Color ( red: r, green: g, blue: b)
42+ }
43+
44+ // Returns the contrast ratio between self and another color (WCAG 2.0)
45+ func contrastRatio( with other: Color ) -> CGFloat {
46+ let c1 = NSColor ( self ) . usingColorSpace ( . deviceRGB) ?? . black
47+ let c2 = NSColor ( other) . usingColorSpace ( . deviceRGB) ?? . white
48+ func luminance( _ c: NSColor ) -> CGFloat {
49+ func channel( _ v: CGFloat ) -> CGFloat {
50+ return v <= 0.03928 ? v / 12.92 : pow ( ( v + 0.055 ) / 1.055 , 2.4 )
51+ }
52+ return 0.2126 * channel( c. redComponent) + 0.7152 * channel( c. greenComponent) + 0.0722 * channel( c. blueComponent)
53+ }
54+ let l1 = luminance ( c1)
55+ let l2 = luminance ( c2)
56+ return ( max ( l1, l2) + 0.05 ) / ( min ( l1, l2) + 0.05 )
57+ }
58+ }
0 commit comments