// // UIColor.swift // VDS // // Created by Matt Bruce on 7/22/22. // import Foundation import UIKit import VDSColorTokens extension UIColor { //-------------------------------------------------- // MARK: - Functions //-------------------------------------------------- /// Convenience to get a grayscale UIColor where the same value is used for red, green, and blue. public class func grayscale(rgb: Int, alpha: CGFloat = 1.0) -> UIColor { let grayscale = CGFloat(rgb) / 255.0 return UIColor(red: grayscale, green: grayscale, blue: grayscale, alpha: alpha) } /// Convenience to get a UIColor. public class func color8Bits(red: Int, green: Int, blue: Int, alpha: CGFloat = 1.0) -> UIColor { return UIColor(red: CGFloat(red) / 255.0, green: CGFloat(green) / 255.0, blue: CGFloat(blue) / 255.0, alpha: alpha) } /// Convenience to get a UIColor. public class func color8Bits(red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat = 1.0) -> UIColor { return UIColor(red: red / 255.0, green: green / 255.0, blue: blue / 255.0, alpha: alpha) } /// Gets UIColor via an 8 digit hex string. public class func getColorBy(hex: String) -> UIColor { var hexint: UInt64 = 0 let scanner = Scanner(string: hex) scanner.charactersToBeSkipped = CharacterSet(charactersIn: "#") scanner.scanHexInt64(&hexint) return UIColor(red: (CGFloat((hexint & 0xFF0000) >> 16)) / 255, green: (CGFloat((hexint & 0xFF00) >> 8)) / 255, blue: (CGFloat(hexint & 0xFF)) / 255, alpha: 1) } /// Gets UIColor via an 8 digit hex string. The last two being the alpha channel. public class func getColorWithTransparencyBy(hex: String) -> UIColor { var hexint: UInt64 = 0 let scanner = Scanner(string: hex) scanner.charactersToBeSkipped = CharacterSet(charactersIn: "#") scanner.scanHexInt64(&hexint) return UIColor(red: (CGFloat((hexint & 0xFF000000) >> 24)) / 255, green: (CGFloat((hexint & 0xFF0000) >> 16)) / 255, blue: (CGFloat((hexint & 0xFF00) >> 8)) / 255, alpha: (CGFloat(hexint & 0xFF)) / 255) } public class func gradientColor(_ color: UIColor?) -> UIColor { var h: CGFloat = 0 var s: CGFloat = 0 var b: CGFloat = 0 var a: CGFloat = 0 if color?.getHue(&h, saturation: &s, brightness: &b, alpha: &a) ?? false { return UIColor(hue: h, saturation: max(s - 0.17, 0.0), brightness: min(b - 0.03, 1.0), alpha: a) } return .white } /// - parameter color: The UIColor intended to retrieve its hex value. public class func hexString(for color: UIColor) -> String? { guard let components = color.cgColor.components else { return nil } let numberOfComponents = color.cgColor.numberOfComponents if numberOfComponents >= 3 { // RGB color space let r = Int(CGFloat(components[0]) * 255) let g = Int(CGFloat(components[1]) * 255) let b = Int(CGFloat(components[2]) * 255) // If alpha of color is less than 1.0 then alpha hex is relevant. if color.cgColor.numberOfComponents == 4 && components[3] < 1.0 { let a = Int(CGFloat(components[3]) * 255) return String(format: "%02X%02X%02X%02X", r, g, b, a) } return String(format: "%02X%02X%02X", r, g, b) } else if numberOfComponents == 2 { // Monochromatic color space let value = Int(CGFloat(components[0]) * 255) // If alpha of color is less than 1.0 then alpha hex is relevant. if components[1] < 1.0 { let alpha = Int(CGFloat(components[1]) * 255) return String(format: "%02X%02X%02X%02X", value, value, value, alpha) } return String(format: "%02X%02X%02X", value, value, value) } return nil } /// - parameter color: The UIColor intended to retrieve its hex value. public var hexString: String? { guard let components = cgColor.components else { return nil } let numberOfComponents = cgColor.numberOfComponents if numberOfComponents >= 3 { // RGB color space let r = Int(CGFloat(components[0]) * 255) let g = Int(CGFloat(components[1]) * 255) let b = Int(CGFloat(components[2]) * 255) // If alpha of color is less than 1.0 then alpha hex is relevant. if cgColor.numberOfComponents == 4 && components[3] < 1.0 { let a = Int(CGFloat(components[3]) * 255) return String(format: "%02X%02X%02X%02X", r, g, b, a) } return String(format: "%02X%02X%02X", r, g, b) } else if numberOfComponents == 2 { // Monochromatic color space let value = Int(CGFloat(components[0]) * 255) // If alpha of color is less than 1.0 then alpha hex is relevant. if components[1] < 1.0 { let alpha = Int(CGFloat(components[1]) * 255) return String(format: "%02X%02X%02X%02X", value, value, value, alpha) } return String(format: "%02X%02X%02X", value, value, value) } return nil } public convenience init(hexString: String) { let hex = hexString.trimmingCharacters(in: CharacterSet.alphanumerics.inverted) var int = UInt64() Scanner(string: hex).scanHexInt64(&int) let a, r, g, b: UInt64 switch hex.count { case 3: // RGB (12-bit) (a, r, g, b) = (255, (int >> 8) * 17, (int >> 4 & 0xF) * 17, (int & 0xF) * 17) case 6: // RGB (24-bit) (a, r, g, b) = (255, int >> 16, int >> 8 & 0xFF, int & 0xFF) case 8: // ARGB (32-bit) (a, r, g, b) = (int >> 24, int >> 16 & 0xFF, int >> 8 & 0xFF, int & 0xFF) default: (a, r, g, b) = (255, 0, 0, 0) } self.init(red: CGFloat(r) / 255, green: CGFloat(g) / 255, blue: CGFloat(b) / 255, alpha: CGFloat(a) / 255) } } extension UIColor { convenience init( light lightModeColor: @escaping @autoclosure () -> UIColor, dark darkModeColor: @escaping @autoclosure () -> UIColor ) { self.init { traitCollection in switch traitCollection.userInterfaceStyle { case .light: return lightModeColor() case .dark: return darkModeColor() case .unspecified: return lightModeColor() @unknown default: return lightModeColor() } } } }