Merge branch 'develop' into generic-class
# Conflicts: # VDS/Classes/VDSControl.swift # VDS/Components/Toggle/VDSToggle.swift Signed-off-by: Matt Bruce <matt.bruce@verizon.com>
This commit is contained in:
commit
2c4b0a578a
@ -9,7 +9,7 @@ import Foundation
|
||||
import UIKit
|
||||
import Combine
|
||||
|
||||
open class VDSControl<ModelType>: UIControl, Modelable, ViewProtocol {
|
||||
open class VDSControl<ModelType: Initable>: UIControl, Modelable, ViewProtocol {
|
||||
|
||||
@Published public var model: ModelType
|
||||
private var cancellable: AnyCancellable?
|
||||
@ -39,7 +39,9 @@ open class VDSControl<ModelType>: UIControl, Modelable, ViewProtocol {
|
||||
}
|
||||
|
||||
public required init?(coder: NSCoder) {
|
||||
fatalError("Control does not support xib.")
|
||||
self.model = ModelType.init()
|
||||
super.init(coder: coder)
|
||||
initialSetup()
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
|
||||
@ -57,10 +57,26 @@ open class VDSLabel: UILabel, Modelable, Initable {
|
||||
}
|
||||
}
|
||||
|
||||
private func getTextColor(for disabled: Bool, surface: Surface) -> UIColor {
|
||||
if disabled {
|
||||
if surface == .light {
|
||||
return VDSColor.elementsSecondaryOnlight
|
||||
} else {
|
||||
return VDSColor.elementsSecondaryOndark
|
||||
}
|
||||
} else {
|
||||
if surface == .light {
|
||||
return VDSColor.elementsPrimaryOnlight
|
||||
} else {
|
||||
return VDSColor.elementsPrimaryOndark
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//functions
|
||||
private func onStateChange(viewModel: VDSLabelModel) {
|
||||
textAlignment = viewModel.textPosition.textAlignment
|
||||
textColor = viewModel.surface == .dark ? VDSColor.elementsPrimaryOndark : VDSColor.elementsPrimaryOnlight
|
||||
textColor = getTextColor(for: viewModel.disabled, surface: viewModel.surface)
|
||||
|
||||
guard let vdsFont = try? VDSFontStyle.font(for: viewModel.fontCategory, fontWeight: viewModel.fontWeight, fontSize: viewModel.fontSize) else {
|
||||
font = VDSFontStyle.RegularBodyLarge.font
|
||||
|
||||
@ -8,14 +8,15 @@
|
||||
import Foundation
|
||||
import UIKit
|
||||
|
||||
public protocol VDSLabelModel: Labelable, Surfaceable {
|
||||
public protocol VDSLabelModel: Labelable, Surfaceable, Disabling {
|
||||
}
|
||||
|
||||
open class DefaultLabelModel: VDSLabelModel {
|
||||
public var fontCategory: VDSFontCategory = .body
|
||||
public var fontSize: VDSFontSize = .large
|
||||
public var fontSize: VDSFontSize = .small
|
||||
public var fontWeight: VDSFontWeight = .regular
|
||||
public var textPosition: VDSTextPosition = .left
|
||||
public var surface: Surface = .light
|
||||
public var disabled: Bool = false
|
||||
required public init(){}
|
||||
}
|
||||
|
||||
@ -18,7 +18,7 @@ import Combine
|
||||
Knob: The circular indicator that slides on the container.
|
||||
*/
|
||||
|
||||
final public class VDSToggle: VDSToggleBase<DefaultToggleModel>{
|
||||
@objcMembers public class VDSToggle: VDSToggleBase<DefaultToggleModel>{
|
||||
public convenience init() {
|
||||
self.init(with: DefaultToggleModel())
|
||||
}
|
||||
@ -37,15 +37,46 @@ final public class VDSToggle: VDSToggleBase<DefaultToggleModel>{
|
||||
//--------------------------------------------------
|
||||
// MARK: - Private Properties
|
||||
//--------------------------------------------------
|
||||
/// Holds the on and off colors for the container.
|
||||
private var containerTintColor: (on: UIColor, off: UIColor) = (on: VDSColor.paletteGreen26, off: VDSColor.paletteGray44)
|
||||
private var toggleTintColor: (on: UIColor, off: UIColor) {
|
||||
return getToggleColor(for: disabled, surface: surface)
|
||||
}
|
||||
|
||||
/// Holds the on and off colors for the knob.
|
||||
private var knobTintColor: (on: UIColor, off: UIColor) = (on: VDSColor.paletteWhite, off: VDSColor.paletteWhite)
|
||||
private var knobTintColor: (on: UIColor, off: UIColor) {
|
||||
return getKnobColor(for: disabled, surface: surface)
|
||||
}
|
||||
|
||||
private func getToggleColor(for disabled: Bool, surface: Surface) -> (on: UIColor, off: UIColor) {
|
||||
if disabled {
|
||||
if surface == .light {
|
||||
return (on: VDSColor.elementsDisabledOnlight, off: VDSColor.elementsDisabledOnlight)
|
||||
} else {
|
||||
return (on: VDSColor.elementsDisabledOnDark, off: VDSColor.elementsDisabledOnDark)
|
||||
}
|
||||
} else {
|
||||
if surface == .light {
|
||||
return (on: VDSColor.paletteGreen26, off: VDSColor.elementsSecondaryOnlight)
|
||||
} else {
|
||||
return (on: VDSColor.paletteGreen34, off: VDSColor.paletteGray44)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func getKnobColor(for disabled: Bool, surface: Surface) -> (on: UIColor, off: UIColor) {
|
||||
if disabled {
|
||||
if surface == .light {
|
||||
return (on: VDSColor.paletteGray95, off: VDSColor.paletteGray95)
|
||||
} else {
|
||||
return (on: VDSColor.paletteGray44, off: VDSColor.paletteGray44)
|
||||
}
|
||||
} else {
|
||||
if surface == .light {
|
||||
return (on: VDSColor.elementsPrimaryOndark, off: VDSColor.elementsPrimaryOndark)
|
||||
} else {
|
||||
return (on: VDSColor.elementsPrimaryOndark, off: VDSColor.elementsPrimaryOndark)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Holds the on and off colors for the disabled state..
|
||||
private var disabledTintColor: (container: UIColor, knob: UIColor) = (container: VDSColor.paletteGray11, knob: VDSColor.paletteWhite)
|
||||
|
||||
private var showTextSpacing: CGFloat {
|
||||
showText ? 12 : 0
|
||||
}
|
||||
@ -94,7 +125,13 @@ final public class VDSToggle: VDSToggleBase<DefaultToggleModel>{
|
||||
// MARK: - Computed Properties
|
||||
//--------------------------------------------------
|
||||
@Proxy(\.model.showText)
|
||||
public var showText: Bool
|
||||
public var showText: Bool {
|
||||
didSet {
|
||||
if oldValue != showText {
|
||||
ensureLabel()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Proxy(\.model.onText)
|
||||
public var onText: String
|
||||
@ -103,7 +140,13 @@ final public class VDSToggle: VDSToggleBase<DefaultToggleModel>{
|
||||
public var offText: String
|
||||
|
||||
@Proxy(\.model.textPosition)
|
||||
public var textPosition: VDSTextPosition
|
||||
public var textPosition: VDSTextPosition {
|
||||
didSet {
|
||||
if oldValue != textPosition {
|
||||
ensureLabel()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Proxy(\.model.fontSize)
|
||||
public var fontSize: VDSFontSize
|
||||
@ -117,6 +160,9 @@ final public class VDSToggle: VDSToggleBase<DefaultToggleModel>{
|
||||
@Proxy(\.model.on)
|
||||
open var isOn: Bool
|
||||
|
||||
@Proxy(\.model.disabled)
|
||||
open var disabled: Bool
|
||||
|
||||
open override var isEnabled: Bool {
|
||||
get { !model.disabled }
|
||||
set {
|
||||
@ -164,10 +210,7 @@ final public class VDSToggle: VDSToggleBase<DefaultToggleModel>{
|
||||
super.setupView()
|
||||
|
||||
isAccessibilityElement = true
|
||||
setAccessibilityHint()
|
||||
setAccessibilityLabel()
|
||||
accessibilityTraits = .button
|
||||
|
||||
addSubview(stackView)
|
||||
|
||||
toggleHeightConstraint = toggleView.heightAnchor.constraint(equalToConstant: toggleSize.height)
|
||||
@ -179,7 +222,7 @@ final public class VDSToggle: VDSToggleBase<DefaultToggleModel>{
|
||||
toggleView.layer.cornerRadius = toggleSize.height / 2.0
|
||||
knobView.layer.cornerRadius = knobSize.height / 2.0
|
||||
|
||||
toggleView.backgroundColor = containerTintColor.off
|
||||
toggleView.backgroundColor = toggleTintColor.off
|
||||
|
||||
toggleView.addSubview(knobView)
|
||||
|
||||
@ -216,7 +259,7 @@ final public class VDSToggle: VDSToggleBase<DefaultToggleModel>{
|
||||
public override func reset() {
|
||||
super.reset()
|
||||
|
||||
toggleView.backgroundColor = containerTintColor.off
|
||||
toggleView.backgroundColor = toggleTintColor.off
|
||||
knobView.backgroundColor = knobTintColor.off
|
||||
setAccessibilityLabel()
|
||||
onChange = nil
|
||||
@ -262,22 +305,16 @@ final public class VDSToggle: VDSToggleBase<DefaultToggleModel>{
|
||||
}
|
||||
|
||||
public override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
|
||||
|
||||
knobReformAnimation()
|
||||
|
||||
// Action only occurs of the user lifts up from withing acceptable region of the toggle.
|
||||
guard let coordinates = touches.first?.location(in: self),
|
||||
coordinates.x > -20,
|
||||
coordinates.x < bounds.width + 20,
|
||||
coordinates.y > -20,
|
||||
coordinates.y < bounds.height + 20
|
||||
else { return }
|
||||
let value = 20.0
|
||||
guard let coordinates = touches.first?.location(in: self) else { return }
|
||||
guard coordinates.x > -value else { return }
|
||||
|
||||
sendActions(for: .touchUpInside)
|
||||
}
|
||||
|
||||
public func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent) {
|
||||
|
||||
open override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
|
||||
knobReformAnimation()
|
||||
sendActions(for: .touchCancel)
|
||||
}
|
||||
@ -297,7 +334,7 @@ final public class VDSToggle: VDSToggleBase<DefaultToggleModel>{
|
||||
/// - Parameter viewModel: state
|
||||
open override func onStateChange(viewModel: ModelType) {
|
||||
let enabled = !viewModel.disabled
|
||||
|
||||
|
||||
label.set(with: viewModel)
|
||||
label.text = viewModel.on ? viewModel.onText : viewModel.offText
|
||||
|
||||
@ -321,33 +358,30 @@ final public class VDSToggle: VDSToggleBase<DefaultToggleModel>{
|
||||
self.layoutIfNeeded()
|
||||
}
|
||||
|
||||
let toggleColor = getToggleColor(for: viewModel.disabled, surface: viewModel.surface)
|
||||
let knobColor = getKnobColor(for: viewModel.disabled, surface: viewModel.surface)
|
||||
|
||||
if viewModel.disabled {
|
||||
toggleView.backgroundColor = enabled ? viewModel.on ? containerTintColor.on : containerTintColor.off : disabledTintColor.container
|
||||
knobView.backgroundColor = enabled ? viewModel.on ? knobTintColor.on : knobTintColor.off : disabledTintColor.knob
|
||||
toggleView.backgroundColor = viewModel.on ? toggleColor.on : toggleColor.off
|
||||
knobView.backgroundColor = viewModel.on ? knobColor.on : knobColor.off
|
||||
constrainKnob()
|
||||
} else {
|
||||
UIView.animate(withDuration: 0.2, delay: 0.0, options: .curveEaseIn, animations: {
|
||||
if viewModel.on {
|
||||
self.knobView.backgroundColor = self.knobTintColor.on
|
||||
self.toggleView.backgroundColor = self.containerTintColor.on
|
||||
|
||||
} else {
|
||||
self.knobView.backgroundColor = self.knobTintColor.off
|
||||
self.toggleView.backgroundColor = self.containerTintColor.off
|
||||
}
|
||||
self.toggleView.backgroundColor = viewModel.on ? toggleColor.on : toggleColor.off
|
||||
self.knobView.backgroundColor = viewModel.on ? knobColor.on : knobColor.off
|
||||
}, completion: nil)
|
||||
|
||||
UIView.animate(withDuration: 0.33, delay: 0, usingSpringWithDamping: 0.6, initialSpringVelocity: 0.2, options: [], animations: {
|
||||
UIView.animate(withDuration: 0.33, delay: 0, usingSpringWithDamping: 0.7, initialSpringVelocity: 0.5, options: [], animations: {
|
||||
constrainKnob()
|
||||
}, completion: nil)
|
||||
}
|
||||
|
||||
backgroundColor = viewModel.surface == .dark ? VDSColor.backgroundPrimaryDark : .clear
|
||||
backgroundColor = viewModel.surface.color
|
||||
isUserInteractionEnabled = !viewModel.disabled
|
||||
|
||||
accessibilityHint = enabled ? viewModel.accessibilityHintEnabled :viewModel.accessibilityHintDisabled
|
||||
accessibilityValue = viewModel.on ? viewModel.accessibilityValueEnabled : viewModel.accessibilityValueDisabled
|
||||
accessibilityLabel = viewModel.on ? viewModel.accessibilityLabelEnabled : viewModel.accessibilityLabelDisabled
|
||||
setAccessibilityHint(enabled)
|
||||
setAccessibilityValue(viewModel.on)
|
||||
setAccessibilityLabel(viewModel.on)
|
||||
|
||||
setNeedsLayout()
|
||||
layoutIfNeeded()
|
||||
|
||||
@ -14,7 +14,7 @@ extension VDSToggle {
|
||||
}
|
||||
}
|
||||
|
||||
public protocol VDSToggleModel: VDSLabelModel, FormFieldable, DataTrackable, Disabling, Accessable {
|
||||
public protocol VDSToggleModel: VDSLabelModel, FormFieldable, DataTrackable, Accessable, Initable {
|
||||
var id: String? { get set }
|
||||
var showText: Bool { get set }
|
||||
var on: Bool { get set }
|
||||
@ -32,7 +32,6 @@ extension VDSToggleModel {
|
||||
public class DefaultToggleModel: DefaultLabelModel, VDSToggleModel {
|
||||
public var id: String?
|
||||
public var inputId: String?
|
||||
public var disabled: Bool = false
|
||||
public var showText: Bool = false
|
||||
public var on: Bool = false
|
||||
public var offText: String = "Off"
|
||||
|
||||
@ -7,6 +7,12 @@
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
import VDSColorTokens
|
||||
|
||||
extension VDSColor {
|
||||
public static let elementsDisabledOnlight: UIColor = .init(hexString: "#D8DADA")
|
||||
public static let elementsDisabledOnDark: UIColor = .init(hexString: "#333333")
|
||||
}
|
||||
|
||||
extension UIColor {
|
||||
//--------------------------------------------------
|
||||
@ -143,5 +149,22 @@ extension UIColor {
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,7 +18,7 @@ public protocol Accessable {
|
||||
}
|
||||
|
||||
//Helpers to set within the UIControl
|
||||
extension Modelable where Self: UIControl {
|
||||
extension Modelable where Self: UIView {
|
||||
private var accessableModel: Accessable? {
|
||||
guard let model = self.model as? Accessable else {
|
||||
return nil
|
||||
|
||||
@ -6,9 +6,14 @@
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
import VDSColorTokens
|
||||
|
||||
public enum Surface: String, Codable {
|
||||
case light, dark
|
||||
public var color: UIColor {
|
||||
return self == .dark ? VDSColor.backgroundPrimaryDark : .clear
|
||||
}
|
||||
}
|
||||
|
||||
public protocol Surfaceable {
|
||||
|
||||
@ -14,9 +14,8 @@ public protocol FontProtocol: CaseIterable, RawRepresentable, Hashable {
|
||||
}
|
||||
|
||||
extension FontProtocol {
|
||||
|
||||
public func register() {
|
||||
guard let bundle = Bundle(identifier: "com.verizon.vega.metrics") else { return }
|
||||
guard let bundle = Bundle(identifier: "com.vzw.vds") else { return }
|
||||
Self.allCases.forEach{ font in
|
||||
if let url = bundle.url(forResource: font.fontName, withExtension: font.fontFileExtension){
|
||||
do{
|
||||
|
||||
@ -21,7 +21,7 @@ public enum VDSFontWeight: String, Codable {
|
||||
}
|
||||
}
|
||||
|
||||
public enum VDSTextPosition: String, Codable {
|
||||
public enum VDSTextPosition: String, Codable, CaseIterable {
|
||||
case left, right, center
|
||||
|
||||
var textAlignment: NSTextAlignment {
|
||||
@ -36,7 +36,7 @@ public enum VDSTextPosition: String, Codable {
|
||||
}
|
||||
}
|
||||
|
||||
public enum VDSFontCategory: String, Codable {
|
||||
public enum VDSFontCategory: String, Codable, CaseIterable {
|
||||
case feature
|
||||
case title
|
||||
case body
|
||||
@ -52,7 +52,7 @@ public enum VDSFontCategory: String, Codable {
|
||||
}
|
||||
}
|
||||
|
||||
public enum VDSFontSize: String, Codable {
|
||||
public enum VDSFontSize: String, Codable, CaseIterable {
|
||||
case xxlarge
|
||||
case xlarge
|
||||
case large
|
||||
@ -72,7 +72,7 @@ public enum VDSFontSize: String, Codable {
|
||||
}
|
||||
}
|
||||
|
||||
public enum VDSFontStyle: String, Codable {
|
||||
public enum VDSFontStyle: String, Codable, CaseIterable {
|
||||
public enum Error: Swift.Error {
|
||||
case fontNotFound
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user