diff --git a/VDS.xcodeproj/project.pbxproj b/VDS.xcodeproj/project.pbxproj index 2b35121d..472f2040 100644 --- a/VDS.xcodeproj/project.pbxproj +++ b/VDS.xcodeproj/project.pbxproj @@ -57,7 +57,7 @@ EAF7F0B3289B1ADC00B287F5 /* LabelAttributeAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF7F0B2289B1ADC00B287F5 /* LabelAttributeAction.swift */; }; EAF7F0B5289C126F00B287F5 /* UILabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF7F0B4289C126F00B287F5 /* UILabel.swift */; }; EAF7F0B7289C12A600B287F5 /* UITapGestureRecognizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF7F0B6289C12A600B287F5 /* UITapGestureRecognizer.swift */; }; - EAF7F0B9289C139800B287F5 /* ModelColorHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF7F0B8289C139800B287F5 /* ModelColorHelpers.swift */; }; + EAF7F0B9289C139800B287F5 /* ColorConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF7F0B8289C139800B287F5 /* ColorConfiguration.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -122,7 +122,7 @@ EAF7F0B2289B1ADC00B287F5 /* LabelAttributeAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelAttributeAction.swift; sourceTree = ""; }; EAF7F0B4289C126F00B287F5 /* UILabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UILabel.swift; sourceTree = ""; }; EAF7F0B6289C12A600B287F5 /* UITapGestureRecognizer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITapGestureRecognizer.swift; sourceTree = ""; }; - EAF7F0B8289C139800B287F5 /* ModelColorHelpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModelColorHelpers.swift; sourceTree = ""; }; + EAF7F0B8289C139800B287F5 /* ColorConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorConfiguration.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -256,9 +256,9 @@ isa = PBXGroup; children = ( EA3C3B4B2894823E000CA526 /* AnyProxy-PropertyWrapper.swift */, + EAF7F0B8289C139800B287F5 /* ColorConfiguration.swift */, EAF7F09D289AAEC000B287F5 /* Constants.swift */, EA3361B5288B2A410071C351 /* Control.swift */, - EAF7F0B8289C139800B287F5 /* ModelColorHelpers.swift */, EAF7F09F289AB7EC00B287F5 /* View.swift */, ); path = Classes; @@ -464,7 +464,7 @@ EA33624728931B050071C351 /* Initable.swift in Sources */, EAF7F0A4289B017C00B287F5 /* LabelAttributeModel.swift in Sources */, EAF7F0B1289B177F00B287F5 /* LabelAttributeColor.swift in Sources */, - EAF7F0B9289C139800B287F5 /* ModelColorHelpers.swift in Sources */, + EAF7F0B9289C139800B287F5 /* ColorConfiguration.swift in Sources */, EA3361BD288B2C760071C351 /* TypeAlias.swift in Sources */, EAF7F09A2899B17200B287F5 /* CATransaction.swift in Sources */, EAF7F0A2289AFB3900B287F5 /* Errorable.swift in Sources */, diff --git a/VDS/Classes/ColorConfiguration.swift b/VDS/Classes/ColorConfiguration.swift new file mode 100644 index 00000000..18d02d4a --- /dev/null +++ b/VDS/Classes/ColorConfiguration.swift @@ -0,0 +1,131 @@ +// +// ModelColorConfiguration.swift +// VDS +// +// Created by Matt Bruce on 8/4/22. +// + +import Foundation +import UIKit + +public protocol Colorable { + associatedtype ModelType + func getColor(_ viewModel: ModelType) -> UIColor +} + +public protocol BinaryColorable{ + var userTrueColor: Bool { get } +} + +/// Meant to be used in a Object that implements the following interfaces for 2 possible color combinations +/// - Surfaceable (var surface: Surface) +/// +/// let model = TestModel() +/// model.surface = .light +/// +/// let config = SurfaceColorConfiguration() +/// +/// config.lightColor = .black +/// config.darkColor = .white +/// +/// let textColor = config.getColor(model) //returns .black +open class SurfaceColorConfiguration: Colorable { + public var lightColor: UIColor = .clear + public var darkColor: UIColor = .clear + + public func getColor(_ viewModel: ModelType) -> UIColor { + return viewModel.surface == .light ? lightColor : darkColor + } +} + +/// Meant to be used in a Object that implements the following interfaces for 4 possible color combinations +/// - Disabling (var disabled: Bool) +/// - Surfaceable (var surface: Surface) +/// +/// let model = TestModel() +/// model.surface = .dark +/// model.disabled = false +/// +/// let config = DisabledSurfaceColorConfiguration() +/// +/// //disabled == false +/// config.enabled.lightColor = .black +/// config.enabled.darkColor = .white +/// +/// //disabled == true +/// config.disabled.lightColor = .gray +/// config.disabled.darkColor = .lightGray +/// +/// let textColor = config.getColor(model) //returns .white +/// +/// +open class DisabledSurfaceColorConfiguration: Colorable { + public var disabled = SurfaceColorConfiguration() + public var enabled = SurfaceColorConfiguration() + + public func getColor(_ viewModel: ModelType) -> UIColor { + return viewModel.disabled ? disabled.getColor(viewModel) : enabled.getColor(viewModel) + } +} + +/// Meant to be used in a Object that implements the following interfaces for 4 possible color combinations +/// - BinaryColorable (var userTrueColor: Bool) +/// - Surfaceable (var surface: Surface) +/// +/// let model = TestModel() +/// model.surface = .dark +/// model.on = true //this is read in the extension var userTrueColor +/// let config = BinarySurfaceColorConfiguration() +/// +/// //True from BinaryColorable.userTrueColor +/// config.isTrue.lightColor = .black +/// config.isTrue.darkColor = .white +/// +/// //False from BinaryColorable.userTrueColor +/// config.isFalse.lightColor = .red +/// config.isFalse.darkColor = .red +/// +/// let textColor = config.getColor(model) //returns .white +/// +/// +open class BinarySurfaceColorConfiguration: Colorable{ + public var isTrue = SurfaceColorConfiguration() + public var isFalse = SurfaceColorConfiguration() + + public func getColor(_ viewModel: ModelType) -> UIColor { + return viewModel.userTrueColor ? isTrue.getColor(viewModel) : isFalse.getColor(viewModel) + } +} + +/// Meant to be used in a Object that implements the following interfaces for 8 possible color combinations +/// - BinaryColorable (var userTrueColor: Bool) +/// - Disabling (var disabled: Bool) +/// - Surfaceable (var surface: Surface) +/// +/// let model = TestModel() +/// model. +/// let config = BinaryDisabledSurfaceColorConfiguration() +/// +/// //True +/// config.isTrue.enabled.lightColor = .black +/// config.isTrue.enabled.darkColor = .white +/// config.isTrue.disabled.lightColor = .darkGray +/// config.isTrue.disabled.darkColor = .lightGray +/// +/// //False +/// config.isFalse.enabled.lightColor = .red +/// config.isFalse.enabled.darkColor = .red +/// config.isFalse.disabled.lightColor =.darkGray +/// config.isFalse.disabled.darkColor = .lightGray +/// +/// let textColor = config.getColor(model) +/// +/// +open class BinaryDisabledSurfaceColorConfiguration: Colorable { + public var isTrue = DisabledSurfaceColorConfiguration() + public var isFalse = DisabledSurfaceColorConfiguration() + + public func getColor(_ viewModel: ModelType) -> UIColor { + return viewModel.userTrueColor ? isTrue.getColor(viewModel) : isFalse.getColor(viewModel) + } +} diff --git a/VDS/Classes/ModelColorHelpers.swift b/VDS/Classes/ModelColorHelpers.swift deleted file mode 100644 index ebb72a47..00000000 --- a/VDS/Classes/ModelColorHelpers.swift +++ /dev/null @@ -1,68 +0,0 @@ -// -// ModelColorHelper.swift -// VDS -// -// Created by Matt Bruce on 8/4/22. -// - -import Foundation -import UIKit - -public protocol Colorable { - associatedtype ModelType - func getColor(_ viewModel: ModelType) -> UIColor -} - -open class ModelSurfaceColorHelper: Colorable { - public var lightColor: UIColor = .clear - public var darkColor: UIColor = .clear - - public func getColor(_ viewModel: ModelType) -> UIColor { - return viewModel.surface == .light ? lightColor : darkColor - } -} - -open class ModelSingleColorHelper: Colorable { - public var disabled = ModelSurfaceColorHelper() - public var enabled = ModelSurfaceColorHelper() - - public func getColor(_ viewModel: ModelType) -> UIColor { - return viewModel.disabled ? disabled.getColor(viewModel) : enabled.getColor(viewModel) - } -} - -public protocol BinaryColorable{ - var userTrueColor: Bool { get } -} - -open class BinaryColorHelper { - public var trueColor: UIColor = .clear - public var falseColor: UIColor = .clear - - public func getColor(_ viewModel: ModelType) -> UIColor { - return viewModel.userTrueColor ? trueColor : falseColor - } -} - -open class BinarySurfaceColorHelper: Colorable{ - public var light = BinaryColorHelper() - public var dark = BinaryColorHelper() - - public func getColor(_ viewModel: ModelType) -> UIColor { - if viewModel.surface == .light { - return light.getColor(viewModel) - } else { - return dark.getColor(viewModel) - } - } -} - -open class BinaryModelColorHelper: Colorable { - public var disabled = BinarySurfaceColorHelper() - public var enabled = BinarySurfaceColorHelper() - - public func getColor(_ viewModel: ModelType) -> UIColor { - return viewModel.disabled ? disabled.getColor(viewModel) : enabled.getColor(viewModel) - } -} - diff --git a/VDS/Components/Checkbox/Checkbox.swift b/VDS/Components/Checkbox/Checkbox.swift index b7032516..a1f3b110 100644 --- a/VDS/Components/Checkbox/Checkbox.swift +++ b/VDS/Components/Checkbox/Checkbox.swift @@ -271,48 +271,48 @@ open class CheckboxBase: Control, Changable /// Manages the appearance of the checkbox. private var shapeLayer: CAShapeLayer? - private var checkboxBackgroundColor: CheckboxErrorColorHelper = { - let helper = CheckboxErrorColorHelper() - helper.disabled.light.trueColor = VDSColor.interactiveDisabledOnlight - helper.disabled.dark.trueColor = VDSColor.interactiveDisabledOndark - helper.error.light.trueColor = VDSColor.elementsPrimaryOnlight - helper.error.light.falseColor = VDSColor.feedbackErrorBackgroundOnlight - helper.error.dark.trueColor = VDSColor.elementsPrimaryOndark - helper.error.dark.falseColor = VDSColor.feedbackErrorBackgroundOndark - helper.enabled.light.trueColor = VDSColor.elementsPrimaryOnlight - helper.enabled.dark.trueColor = VDSColor.elementsPrimaryOndark - return helper + private var checkboxBackgroundColorConfiguration: CheckboxErrorColorConfiguration = { + let config = CheckboxErrorColorConfiguration() + config.isTrue.enabled.lightColor = VDSColor.elementsPrimaryOnlight + config.isTrue.enabled.darkColor = VDSColor.elementsPrimaryOndark + config.isTrue.disabled.lightColor = VDSColor.interactiveDisabledOnlight + config.isTrue.disabled.darkColor = VDSColor.interactiveDisabledOndark + config.error.isTrue.enabled.lightColor = VDSColor.elementsPrimaryOnlight + config.error.isTrue.enabled.darkColor = VDSColor.elementsPrimaryOndark + config.error.isFalse.enabled.lightColor = VDSColor.feedbackErrorBackgroundOnlight + config.error.isFalse.enabled.darkColor = VDSColor.feedbackErrorBackgroundOndark + return config }() - private var checkboxBorderColor: CheckboxErrorColorHelper = { - let helper = CheckboxErrorColorHelper() - helper.disabled.light.trueColor = VDSColor.interactiveDisabledOnlight - helper.disabled.light.falseColor = VDSColor.interactiveDisabledOnlight - helper.disabled.dark.trueColor = VDSColor.interactiveDisabledOndark - helper.disabled.dark.falseColor = VDSColor.interactiveDisabledOndark - helper.error.light.trueColor = VDSColor.elementsPrimaryOnlight - helper.error.light.falseColor = VDSColor.feedbackErrorOnlight - helper.error.dark.trueColor = VDSColor.elementsPrimaryOndark - helper.error.dark.falseColor = VDSColor.feedbackErrorOndark - helper.enabled.light.trueColor = VDSColor.elementsPrimaryOnlight - helper.enabled.light.falseColor = VDSFormControlsColor.borderOnlight - helper.enabled.dark.trueColor = VDSColor.elementsPrimaryOndark - helper.enabled.dark.falseColor = VDSFormControlsColor.borderOndark - return helper + private var checkboxBorderColorConfiguration: CheckboxErrorColorConfiguration = { + let config = CheckboxErrorColorConfiguration() + config.isTrue.enabled.lightColor = VDSColor.elementsPrimaryOnlight + config.isTrue.enabled.darkColor = VDSColor.elementsPrimaryOndark + config.isFalse.enabled.lightColor = VDSFormControlsColor.borderOnlight + config.isFalse.enabled.darkColor = VDSFormControlsColor.borderOndark + config.isTrue.disabled.lightColor = VDSColor.interactiveDisabledOnlight + config.isTrue.disabled.darkColor = VDSColor.interactiveDisabledOndark + config.isFalse.disabled.lightColor = VDSColor.interactiveDisabledOnlight + config.isFalse.disabled.darkColor = VDSColor.interactiveDisabledOndark + config.error.isTrue.enabled.lightColor = VDSColor.elementsPrimaryOnlight + config.error.isTrue.enabled.darkColor = VDSColor.elementsPrimaryOndark + config.error.isFalse.enabled.lightColor = VDSColor.feedbackErrorOnlight + config.error.isFalse.enabled.darkColor = VDSColor.feedbackErrorOndark + return config }() - private var checkboxCheckColor: BinarySurfaceColorHelper = { - let helper = BinarySurfaceColorHelper() - helper.light.trueColor = VDSColor.elementsPrimaryOndark - helper.dark.trueColor = VDSColor.elementsPrimaryOnlight - return helper + private var checkboxCheckColorConfiguration: BinarySurfaceColorConfiguration = { + let config = BinarySurfaceColorConfiguration() + config.isTrue.lightColor = VDSColor.elementsPrimaryOndark + config.isTrue.darkColor = VDSColor.elementsPrimaryOnlight + return config }() private func updateCheckbox(_ viewModel: ModelType) { //get the colors - let backgroundColor = checkboxBackgroundColor.getColor(viewModel) - let borderColor = checkboxBorderColor.getColor(viewModel) - let checkColor = checkboxCheckColor.getColor(viewModel) + let backgroundColor = checkboxBackgroundColorConfiguration.getColor(viewModel) + let borderColor = checkboxBorderColorConfiguration.getColor(viewModel) + let checkColor = checkboxCheckColorConfiguration.getColor(viewModel) if let shapeLayer = shapeLayer, let sublayers = layer.sublayers, sublayers.contains(shapeLayer) { shapeLayer.removeFromSuperlayer() @@ -413,10 +413,10 @@ open class CheckboxBase: Control, Changable } //-------------------------------------------------- - // MARK: - Color Class Helpers + // MARK: - Color Class Configurations //-------------------------------------------------- - private class CheckboxErrorColorHelper: BinaryModelColorHelper { - public let error = BinarySurfaceColorHelper() + private class CheckboxErrorColorConfiguration: BinaryDisabledSurfaceColorConfiguration { + public let error = BinaryDisabledSurfaceColorConfiguration() override func getColor(_ viewModel: ModelType) -> UIColor { //only show error is enabled and showError == true diff --git a/VDS/Components/Label/Label.swift b/VDS/Components/Label/Label.swift index cf53996b..895b72f7 100644 --- a/VDS/Components/Label/Label.swift +++ b/VDS/Components/Label/Label.swift @@ -117,9 +117,9 @@ open class LabelBase: UILabel, ModelHandlerable, Initable /// - Parameter viewModel: state open func onStateChange(viewModel: ModelType) { textAlignment = viewModel.textPosition.textAlignment - textColor = textColorHelper.getColor(viewModel) + textColor = textColorConfiguration.getColor(viewModel) - if let vdsFont = self.font { + if let vdsFont = viewModel.font { font = vdsFont } else { font = FontStyle.defaultStyle.font @@ -163,8 +163,8 @@ open class LabelBase: UILabel, ModelHandlerable, Initable //-------------------------------------------------- // MARK: - Private Functions //-------------------------------------------------- - private var textColorHelper: ModelSingleColorHelper = { - let helper = ModelSingleColorHelper() + private var textColorConfiguration: DisabledSurfaceColorConfiguration = { + let helper = DisabledSurfaceColorConfiguration() helper.disabled.lightColor = VDSColor.elementsSecondaryOnlight helper.disabled.darkColor = VDSColor.elementsSecondaryOndark helper.enabled.lightColor = VDSColor.elementsPrimaryOnlight diff --git a/VDS/Components/Toggle/Toggle.swift b/VDS/Components/Toggle/Toggle.swift index 0f874154..2bddbe25 100644 --- a/VDS/Components/Toggle/Toggle.swift +++ b/VDS/Components/Toggle/Toggle.swift @@ -179,31 +179,30 @@ open class ToggleBase: Control, Changable { //-------------------------------------------------- // MARK: - Toggle //-------------------------------------------------- - private var toggleColor: BinaryModelColorHelper = { - let helper = BinaryModelColorHelper() - helper.disabled.light.trueColor = VDSColor.interactiveDisabledOnlight - helper.disabled.light.falseColor = VDSColor.interactiveDisabledOnlight - helper.disabled.dark.trueColor = VDSColor.interactiveDisabledOndark - helper.disabled.dark.falseColor = VDSColor.interactiveDisabledOndark - helper.enabled.light.trueColor = VDSColor.paletteGreen26 - helper.enabled.light.falseColor = VDSColor.elementsSecondaryOnlight - helper.enabled.dark.trueColor = VDSColor.paletteGreen34 - helper.enabled.dark.falseColor = VDSColor.paletteGray44 - return helper + private var toggleColorConfiguration: BinaryDisabledSurfaceColorConfiguration = { + let config = BinaryDisabledSurfaceColorConfiguration() + config.isTrue.enabled.lightColor = VDSColor.paletteGreen26 + config.isTrue.enabled.darkColor = VDSColor.paletteGreen34 + config.isTrue.disabled.lightColor = VDSColor.interactiveDisabledOnlight + config.isTrue.disabled.darkColor = VDSColor.interactiveDisabledOndark + config.isFalse.enabled.lightColor = VDSColor.elementsSecondaryOnlight + config.isFalse.enabled.darkColor = VDSColor.paletteGray44 + config.isFalse.disabled.lightColor = VDSColor.interactiveDisabledOnlight + config.isFalse.disabled.darkColor = VDSColor.interactiveDisabledOndark + return config } () - private var knobColor: BinaryModelColorHelper = { - let helper = BinaryModelColorHelper() - helper.disabled.light.trueColor = VDSColor.paletteGray95 - helper.disabled.light.falseColor = VDSColor.paletteGray95 - helper.disabled.dark.trueColor = VDSColor.paletteGray44 - helper.disabled.dark.falseColor = VDSColor.paletteGray44 - - helper.enabled.light.trueColor = VDSColor.elementsPrimaryOndark - helper.enabled.light.falseColor = VDSColor.elementsPrimaryOndark - helper.enabled.dark.trueColor = VDSColor.elementsPrimaryOndark - helper.enabled.dark.falseColor = VDSColor.elementsPrimaryOndark - return helper + private var knobColorConfiguration: BinaryDisabledSurfaceColorConfiguration = { + let config = BinaryDisabledSurfaceColorConfiguration() + config.isTrue.enabled.lightColor = VDSColor.elementsPrimaryOndark + config.isTrue.enabled.darkColor = VDSColor.elementsPrimaryOndark + config.isTrue.disabled.lightColor = VDSColor.paletteGray95 + config.isTrue.disabled.darkColor = VDSColor.paletteGray44 + config.isFalse.enabled.lightColor = VDSColor.elementsPrimaryOndark + config.isFalse.enabled.darkColor = VDSColor.elementsPrimaryOndark + config.isFalse.disabled.lightColor = VDSColor.paletteGray95 + config.isFalse.disabled.darkColor = VDSColor.paletteGray44 + return config } () private func updateToggle(_ viewModel: ModelType) { @@ -224,8 +223,8 @@ open class ToggleBase: Control, Changable { self.layoutIfNeeded() } - let toggleColor = toggleColor.getColor(viewModel) - let knobColor = knobColor.getColor(viewModel) + let toggleColor = toggleColorConfiguration.getColor(viewModel) + let knobColor = knobColorConfiguration.getColor(viewModel) if viewModel.disabled { toggleView.backgroundColor = toggleColor @@ -282,7 +281,7 @@ open class ToggleBase: Control, Changable { toggleView.layer.cornerRadius = toggleSize.height / 2.0 knobView.layer.cornerRadius = knobSize.height / 2.0 - toggleView.backgroundColor = toggleColor.getColor(model) + toggleView.backgroundColor = toggleColorConfiguration.getColor(model) toggleView.addSubview(knobView) @@ -305,8 +304,8 @@ open class ToggleBase: Control, Changable { public override func reset() { super.reset() - toggleView.backgroundColor = toggleColor.getColor(model) - knobView.backgroundColor = knobColor.getColor(model) + toggleView.backgroundColor = toggleColorConfiguration.getColor(model) + knobView.backgroundColor = knobColorConfiguration.getColor(model) setAccessibilityLabel() onChange = nil } diff --git a/VDS/Extensions/UIColor.swift b/VDS/Extensions/UIColor.swift index 0da704d6..84100106 100644 --- a/VDS/Extensions/UIColor.swift +++ b/VDS/Extensions/UIColor.swift @@ -163,3 +163,23 @@ extension UIColor { 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() + } + } + } +} diff --git a/VDS/Protocols/Accessable.swift b/VDS/Protocols/Accessable.swift index 469602ca..35afd6e6 100644 --- a/VDS/Protocols/Accessable.swift +++ b/VDS/Protocols/Accessable.swift @@ -17,7 +17,7 @@ public protocol Accessable { var accessibilityLabelDisabled: String? { get set } } -//Helpers to set within the UIControl +//Configurations to set within the UIControl extension ModelHandlerable where Self: UIView { private var accessableModel: Accessable? { guard let model = self.model as? Accessable else {