VDS Button to atomic beginning/

This commit is contained in:
Scott Pfeil 2023-09-14 10:37:42 -04:00
parent 022319c186
commit 4c2214d7d4
4 changed files with 79 additions and 172 deletions

View File

@ -8,10 +8,10 @@
import UIKit
import VDSColorTokens
import VDS
public typealias FacadeElements = (fill: UIColor?, text: UIColor?, border: UIColor?)
open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWatcherFieldProtocol {
//--------------------------------------------------
// MARK: - Properties
@ -26,13 +26,13 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat
public var action: ActionModelProtocol
public var enabled: Bool = true
public var width: CGFloat?
public var style: Styler.Button.Style? {
public var style: Use? {
didSet {
guard let style = style else { return }
setFacade(by: style)
}
}
public var size: Styler.Button.Size? = .standard
public var size: ButtonSize = .large
public var groupName: String = ""
public var inverted: Bool = false
@ -160,14 +160,14 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat
disabledBorderColor_inverted = Color(uiColor: VDSColor.interactiveDisabledOndark)
}
public func setFacade(by style: Styler.Button.Style) {
public func setFacade(by style: VDS.Use) {
switch style {
case .primary:
setPrimaryFacade()
case .secondary:
setSecondaryFacade()
@unknown default:
setPrimaryFacade()
}
}
@ -211,17 +211,17 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat
action = try typeContainer.decodeModel(codingKey: .action)
///Style captured from the JSON
if let style = try typeContainer.decodeIfPresent(Styler.Button.Style.self, forKey: .style){
if let style = try typeContainer.decodeIfPresent(Use.self, forKey: .style) {
self.style = style
setFacade(by: style)
} else if let style = decoder.context?.value(forKey: CodingKeys.style.stringValue) as? Styler.Button.Style { ///Reading the style param from context which is set is molecules, ex: TwoButtonView
} else if let style = decoder.context?.value(forKey: CodingKeys.style.stringValue) as? Use { ///Reading the style param from context which is set is molecules, ex: TwoButtonView
self.style = style
setFacade(by: style)
} else { ///Default style
setFacade(by: .primary)
}
if let size = try typeContainer.decodeIfPresent(Styler.Button.Size.self, forKey: .size) {
if let size = try typeContainer.decodeIfPresent(VDS.ButtonSize.self, forKey: .size) {
self.size = size
}

View File

@ -8,35 +8,19 @@
import UIKit
import VDSColorTokens
import VDS
open class PillButton: Button, MVMCoreUIViewConstrainingProtocol {
open class PillButton: VDS.Button, MVMCoreUIViewConstrainingProtocol, MoleculeViewProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
/// Used to size the button.
var size = MVMCoreUIUtility.getWidth()
var model: MoleculeModelProtocol?
var buttonModel: ButtonModel? {
get { model as? ButtonModel }
}
/// Need to re-style on set.
open override var isEnabled: Bool {
didSet { style(with: buttonModel) }
}
open var buttonSize: Styler.Button.Size = .standard {
didSet { buttonModel?.size = buttonSize }
}
//--------------------------------------------------
// MARK: - Constraints
//--------------------------------------------------
public var widthConstraint: NSLayoutConstraint?
public var minimumWidthConstraint: NSLayoutConstraint?
//--------------------------------------------------
// MARK: - Initializers
//--------------------------------------------------
@ -44,127 +28,29 @@ open class PillButton: Button, MVMCoreUIViewConstrainingProtocol {
@objc public convenience init(asPrimaryButton isPrimary: Bool, makeTiny istiny: Bool) {
let model = ButtonModel(with: "", action: ActionNoopModel())
model.style = isPrimary ? .primary : .secondary
model.size = istiny ? .tiny : .standard
model.size = istiny ? .small : .large
self.init(model: model, nil, nil)
}
//--------------------------------------------------
// MARK: - Computed Properties
//--------------------------------------------------
public var enabledTitleColor: UIColor? {
get { titleColor(for: .normal) }
set { setTitleColor(newValue, for: .normal) }
}
public var disabledTitleColor: UIColor? {
get { titleColor(for: .disabled) }
set { setTitleColor(newValue, for: .disabled) }
}
public var borderColor: UIColor? {
get {
guard let currentColor = layer.borderColor else { return nil }
return UIColor(cgColor: currentColor)
}
set { layer.borderColor = newValue?.cgColor }
}
//--------------------------------------------------
// MARK: - Methods
//--------------------------------------------------
/// The primary styling for a button. Should be used for main buttons
public func stylePrimary() {
let buttonModel = ButtonModel(primaryButtonWith: "", action: ActionNoopModel())
style(with: buttonModel)
}
/// The secondary styling for a button. Should be used for secondary buttons
public func styleSecondary() {
let buttonModel = ButtonModel(secondaryButtonWith: "", action: ActionNoopModel())
style(with: buttonModel)
}
/// Styles the button based on the model style
private func style(with model: ButtonModel?) {
layer.borderWidth = model?.style == .secondary ? 1 : 0
if let titleColor = model?.enabledColors.text {
enabledTitleColor = titleColor
}
if let disabledTitleColor = model?.disabledColors.text {
self.disabledTitleColor = disabledTitleColor
}
#if DEBUG
// Useful to detect with isHittable when performing UI testing.
isAccessibilityElement = isEnabled
#endif
if isEnabled {
if let fillColor = model?.enabledColors.fill {
backgroundColor = fillColor
}
if let borderColor = model?.enabledColors.border {
self.borderColor = borderColor
}
} else {
if let fillColor = model?.disabledColors.fill {
backgroundColor = fillColor
}
if let borderColor = model?.disabledColors.border {
self.borderColor = borderColor
}
}
}
private func getInnerPadding() -> CGFloat {
buttonSize.getHeight() / 2.0
}
private func getContentEdgeInsets() -> UIEdgeInsets {
var verticalPadding = 0.0
var horizontalPadding = 0.0
switch buttonSize {
case .standard:
verticalPadding = Padding.Three
horizontalPadding = Padding.Five
break
case .small:
verticalPadding = Padding.Two
horizontalPadding = Padding.Four
break
case .tiny:
verticalPadding = Padding.One
horizontalPadding = Padding.Two
break
}
return UIEdgeInsets(top: verticalPadding, left: horizontalPadding, bottom: verticalPadding, right: horizontalPadding)
}
//--------------------------------------------------
// MARK: - MVMCoreViewProtocol
//--------------------------------------------------
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
// The button will get styled in the enable check in super.
super.set(with: model, delegateObject, additionalData)
open func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
guard let model = model as? ButtonModel else { return }
self.model = model
if let accessibilityIdentifier = model.accessibilityIdentifier {
self.accessibilityIdentifier = accessibilityIdentifier
}
setTitle(model.title, for: .normal)
if let accessibilityText = model.accessibilityText {
accessibilityLabel = accessibilityText
}
if let size = model.size {
buttonSize = size
}
isEnabled = model.enabled
size = model.size
model.updateUI = { [weak self] in
MVMCoreDispatchUtility.performBlock(onMainThread: {
@ -173,7 +59,62 @@ open class PillButton: Button, MVMCoreUIViewConstrainingProtocol {
}
FormValidator.setupValidation(for: model, delegate: delegateObject?.formHolderDelegate)
guard let model = model as? ButtonModelProtocol else { return }
//set(with: model.action, delegateObject: delegateObject, additionalData: additionalData)
}
}
open func reset() {
backgroundColor = .clear
}
// MARK: Overridables
// Base classes need to implement these functions otherwise swift won't respect the subclass functions and use the ones in the protocol extension instead.
open class func nameForReuse(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> String? {
model.moleculeName
}
open class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { nil }
open class func requiredModules(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject?>?) -> [String]? { nil }
//--------------------------------------------------
// MARK: - Accessibility
//--------------------------------------------------
open override func accessibilityActivate() -> Bool {
guard isEnabled else { return false }
buttonAction?(self)
return buttonAction != nil
}
}
// MARK: - MVMCoreViewProtocol
extension Button: MVMCoreViewProtocol {
open func updateView(_ size: CGFloat) { }
/// Will be called only once.
open func setupView() {
isAccessibilityElement = true
accessibilityTraits = .button
translatesAutoresizingMaskIntoConstraints = false
insetsLayoutMarginsFromSafeArea = false
titleLabel?.numberOfLines = 0
titleLabel?.lineBreakMode = .byWordWrapping
}
}
// MARK: AppleGuidelinesProtocol
extension Button: AppleGuidelinesProtocol {
override open func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
Self.acceptablyOutsideBounds(point: point, bounds: bounds)
}
}
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return (model as? ButtonModel)?.size?.getHeight()

View File

@ -16,3 +16,5 @@ extension Icon.Size: Codable {}
extension TileContainer.BackgroundColor: Codable {}
extension TileContainer.Padding: Codable {}
extension TileContainer.AspectRatio: Codable {}
extension ButtonSize: Codable {}
extension Use: Codable {}

View File

@ -159,42 +159,6 @@ open class Styler {
}
}
public enum Button {
public enum Style: String, Codable {
case primary
case secondary
}
///MVA 3.0 - Button sizes are standard(default size), small, Tiny. Tiny button has been depricated as of Rebranding 3.0.
public enum Size: String, Codable {
case standard
case small
case tiny
func getHeight() -> CGFloat {
switch self {
case .standard:
return 44
case .small:
return 32
case .tiny:
return 20
}
}
func minimumWidth() -> CGFloat {
switch self {
case .standard:
return 76
case .small:
return 0
case .tiny:
return 49
}
}
}
}
//--------------------------------------------------
// MARK: - Functions
//--------------------------------------------------