// // Badge.swift // VDS // // Created by Matt Bruce on 9/22/22. // import Foundation import UIKit import VDSColorTokens import VDSFormControlsTokens import Combine public class Badge: BadgeBase{} open class BadgeBase: View { private var label = Label() //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- @Proxy(\.model.fillColor) open var fillColor: BadgeFillColor @Proxy(\.model.text) open var text: String @Proxy(\.model.maxWidth) open var maxWidth: CGFloat? @Proxy(\.model.numberOfLines) open var numberOfLines: Int @Proxy(\.model.accessibilityHintEnabled) open var accessibilityHintEnabled: String? @Proxy(\.model.accessibilityHintDisabled) open var accessibilityHintDisabled: String? @Proxy(\.model.accessibilityValueEnabled) open var accessibilityValueEnabled: String? @Proxy(\.model.accessibilityValueDisabled) open var accessibilityValueDisabled: String? @Proxy(\.model.accessibilityLabelEnabled) open var accessibilityLabelEnabled: String? @Proxy(\.model.accessibilityLabelDisabled) open var accessibilityLabelDisabled: String? //-------------------------------------------------- // MARK: - Constraints //-------------------------------------------------- private var maxWidthConstraint: NSLayoutConstraint? private var minWidthConstraint: NSLayoutConstraint? //functions //-------------------------------------------------- // MARK: - Lifecycle //-------------------------------------------------- open override func setup() { super.setup() isAccessibilityElement = true accessibilityTraits = .staticText addSubview(label) layer.cornerRadius = 2 label.adjustsFontSizeToFitWidth = false label.lineBreakMode = .byTruncatingTail label.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 4).isActive = true label.topAnchor.constraint(equalTo: topAnchor, constant: 2).isActive = true trailingAnchor.constraint(greaterThanOrEqualTo: label.trailingAnchor, constant: 4).isActive = true bottomAnchor.constraint(greaterThanOrEqualTo: label.bottomAnchor, constant: 2).isActive = true maxWidthConstraint = label.widthAnchor.constraint(lessThanOrEqualToConstant: 100) minWidthConstraint = label.widthAnchor.constraint(greaterThanOrEqualToConstant: 23) minWidthConstraint?.isActive = true } public override func reset() { super.reset() setAccessibilityLabel() } //-------------------------------------------------- // MARK: - Configuration //-------------------------------------------------- public func backgroundColor(for fillColor: BadgeFillColor) -> UIColor { var config: SurfaceColorConfiguration switch model.fillColor { case .red: config = SurfaceColorConfiguration().with { $0.lightColor = VDSColor.backgroundBrandhighlight $0.darkColor = VDSColor.backgroundBrandhighlight } case .yellow: config = SurfaceColorConfiguration().with { $0.lightColor = VDSColor.paletteYellow62 $0.darkColor = VDSColor.paletteYellow62 } case .green: config = SurfaceColorConfiguration().with { $0.lightColor = VDSColor.paletteGreen26 $0.darkColor = VDSColor.paletteGreen34 } case .orange: config = SurfaceColorConfiguration().with { $0.lightColor = VDSColor.paletteOrange39 $0.darkColor = VDSColor.paletteOrange46 } case .blue: config = SurfaceColorConfiguration().with { $0.lightColor = VDSColor.paletteBlue35 $0.darkColor = VDSColor.paletteBlue45 } case .black: config = SurfaceColorConfiguration().with { $0.lightColor = VDSColor.paletteBlack $0.darkColor = VDSColor.paletteBlack } case .white: config = SurfaceColorConfiguration().with { $0.lightColor = VDSColor.paletteWhite $0.darkColor = VDSColor.paletteWhite } } return config.getColor(model) } public func textColorConfiguration(for fillColor: BadgeFillColor) -> AnyColorable { switch fillColor { case .red, .black: return DisabledSurfaceColorConfiguration().with { $0.disabled.lightColor = VDSColor.elementsPrimaryOndark $0.disabled.darkColor = VDSColor.elementsPrimaryOndark $0.enabled.lightColor = VDSColor.elementsPrimaryOndark $0.enabled.darkColor = VDSColor.elementsPrimaryOndark }.eraseToAnyColorable() case .yellow, .white: return DisabledSurfaceColorConfiguration().with { $0.disabled.lightColor = VDSColor.elementsPrimaryOnlight $0.disabled.darkColor = VDSColor.elementsPrimaryOnlight $0.enabled.lightColor = VDSColor.elementsPrimaryOnlight $0.enabled.darkColor = VDSColor.elementsPrimaryOnlight }.eraseToAnyColorable() case .orange, .green, .blue: return DisabledSurfaceColorConfiguration().with { $0.disabled.lightColor = VDSColor.elementsPrimaryOndark $0.disabled.darkColor = VDSColor.elementsPrimaryOnlight $0.enabled.lightColor = VDSColor.elementsPrimaryOndark $0.enabled.darkColor = VDSColor.elementsPrimaryOnlight }.eraseToAnyColorable() } } //-------------------------------------------------- // MARK: - State //-------------------------------------------------- open override func updateView(viewModel: ModelType) { backgroundColor = backgroundColor(for: viewModel.fillColor) label.textColorConfiguration = textColorConfiguration(for: viewModel.fillColor) label.numberOfLines = viewModel.numberOfLines if let maxWidth = viewModel.maxWidth, let minWidth = minWidthConstraint?.constant, maxWidth > minWidth { maxWidthConstraint?.constant = maxWidth maxWidthConstraint?.isActive = true } else { maxWidthConstraint?.isActive = false } label.set(with: viewModel.label) setAccessibilityLabel() } }