added code comments

Signed-off-by: Matt Bruce <matt.bruce@verizon.com>
This commit is contained in:
Matt Bruce 2023-07-13 14:41:07 -05:00
parent a75e254064
commit 87ecc1e28a
9 changed files with 135 additions and 76 deletions

View File

@ -406,8 +406,8 @@
EA33619D288B1E330071C351 /* Components */ = { EA33619D288B1E330071C351 /* Components */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
EAD062AE2A3B87210015965D /* BadgeIndicator */,
EA4DB2FE28DCBC1900103EE3 /* Badge */, EA4DB2FE28DCBC1900103EE3 /* Badge */,
EAD062AE2A3B87210015965D /* BadgeIndicator */,
EA0FC2BE2912D18200DF80B4 /* Buttons */, EA0FC2BE2912D18200DF80B4 /* Buttons */,
EAF7F092289985E200B287F5 /* Checkbox */, EAF7F092289985E200B287F5 /* Checkbox */,
EA985BF3296C609E00F2FF2E /* Icon */, EA985BF3296C609E00F2FF2E /* Icon */,

View File

@ -23,7 +23,7 @@ public typealias ObjectColorable = Colorable & Initable & ObjectWithable
/// let textColor = config.getColor(model) //returns .black /// let textColor = config.getColor(model) //returns .black
/// ///
/// You can pass in a Surfaceable object and it will give you the color responding. /// You can pass in a Surfaceable object and this will return the corresponding Color based on the object's surface property.
open class SurfaceColorConfiguration: ObjectColorable { open class SurfaceColorConfiguration: ObjectColorable {
public typealias ObjectType = Surfaceable public typealias ObjectType = Surfaceable
public var lightColor: UIColor = .clear public var lightColor: UIColor = .clear

View File

@ -10,6 +10,7 @@ import UIKit
import Combine import Combine
@objc(VDSControl) @objc(VDSControl)
/// Base Class use to build Controls.
open class Control: UIControl, Handlerable, ViewProtocol, Resettable, UserInfoable, Clickable { open class Control: UIControl, Handlerable, ViewProtocol, Resettable, UserInfoable, Clickable {
//-------------------------------------------------- //--------------------------------------------------

View File

@ -11,6 +11,7 @@ import Combine
@objc(VDSView) @objc(VDSView)
/// Base Class used to build Views.
open class View: UIView, Handlerable, ViewProtocol, Resettable, UserInfoable { open class View: UIView, Handlerable, ViewProtocol, Resettable, UserInfoable {
//-------------------------------------------------- //--------------------------------------------------
@ -29,10 +30,10 @@ open class View: UIView, Handlerable, ViewProtocol, Resettable, UserInfoable {
/// Dictionary for keeping information for this Control use only Primitives /// Dictionary for keeping information for this Control use only Primitives
open var userInfo = [String: Primitive]() open var userInfo = [String: Primitive]()
/// Current Surface used within this Control and used to passdown to child views /// Current Surface and this is used to pass down to child objects that implement Surfacable
open var surface: Surface = .light { didSet { setNeedsUpdate() } } open var surface: Surface = .light { didSet { setNeedsUpdate() } }
/// Control is disabled or not /// Whether this object is disabled or not
open var disabled: Bool = false { didSet { setNeedsUpdate(); isUserInteractionEnabled = !disabled } } open var disabled: Bool = false { didSet { setNeedsUpdate(); isUserInteractionEnabled = !disabled } }
//-------------------------------------------------- //--------------------------------------------------

View File

@ -12,27 +12,32 @@ import VDSFormControlsTokens
import Combine import Combine
import VDSTypographyTokens import VDSTypographyTokens
/// Badges are visual labels used to convey status or highlight supplemental information. /// Badge Indicators are visual labels .
@objc(VDSBadgeIndicator) @objc(VDSBadgeIndicator)
open class BadgeIndicator: View { open class BadgeIndicator: View {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Enums // MARK: - Enums
//-------------------------------------------------- //--------------------------------------------------
/// Enum type for fill color
public enum FillColor: String, CaseIterable { public enum FillColor: String, CaseIterable {
case red, yellow, green, orange, blue, gray, grayLowContrast, black, white case red, yellow, green, orange, blue, gray, grayLowContrast, black, white
} }
/// Enum type for kind of BadgeIndicator
public enum Kind: String, CaseIterable { public enum Kind: String, CaseIterable {
case simple, numbered case simple, numbered
} }
public enum MaxDigits: String, CaseIterable { /// Enum type for maximum number of digits
public enum MaximumDigits: String, CaseIterable {
case one case one
case two case two
case three case three
case four case four
case five case five
case six case six
case none
public var value: Int { public var value: Int {
switch self { switch self {
@ -48,17 +53,21 @@ open class BadgeIndicator: View {
return 5 return 5
case .six: case .six:
return 6 return 6
case .none:
return 0
} }
} }
} }
/// Enum type describing size of Badge Indicator
public enum Size: String, CaseIterable { public enum Size: String, CaseIterable {
case xxlarge = "2XLarge" case xxlarge = "2XLarge"
case xlarge = "XLarge" case xlarge = "XLarge"
case large = "Large" case large = "Large"
case medium = "Medium" case medium = "Medium"
case small = "Small" case small = "Small"
/// Dynamic TextStyle for the size
public var textStyle: TextStyle { public var textStyle: TextStyle {
let style = TextStyle.bodySmall let style = TextStyle.bodySmall
var pointSize: CGFloat = VDSTypography.fontSizeBody12 var pointSize: CGFloat = VDSTypography.fontSizeBody12
@ -89,6 +98,7 @@ open class BadgeIndicator: View {
letterSpacing: letterSpacing) letterSpacing: letterSpacing)
} }
//EdgeInsets for the label
public var edgeInset: UIEdgeInsets { public var edgeInset: UIEdgeInsets {
var horizontalPadding: CGFloat = VDSLayout.Spacing.space1X.value var horizontalPadding: CGFloat = VDSLayout.Spacing.space1X.value
let verticalPadding: CGFloat = 0 let verticalPadding: CGFloat = 0
@ -109,6 +119,8 @@ open class BadgeIndicator: View {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Public Properties // MARK: - Public Properties
//-------------------------------------------------- //--------------------------------------------------
/// Label used for the numeric kind
open var label = Label().with { open var label = Label().with {
$0.setContentCompressionResistancePriority(.required, for: .vertical) $0.setContentCompressionResistancePriority(.required, for: .vertical)
$0.adjustsFontSizeToFitWidth = false $0.adjustsFontSizeToFitWidth = false
@ -117,6 +129,7 @@ open class BadgeIndicator: View {
$0.numberOfLines = 1 $0.numberOfLines = 1
} }
/// BorderColor for Surface.light
open var borderColorLight: UIColor? { open var borderColorLight: UIColor? {
didSet { didSet {
if let borderColorLight { if let borderColorLight {
@ -128,6 +141,7 @@ open class BadgeIndicator: View {
} }
} }
/// BorderColor for Surface.dark
open var borderColorDark: UIColor? { open var borderColorDark: UIColor? {
didSet { didSet {
if let borderColorDark { if let borderColorDark {
@ -139,46 +153,97 @@ open class BadgeIndicator: View {
} }
} }
/// This will render the badges fill color based on the available options.
/// When used in conjunction with the surface prop, this fill color will change its tint automatically based on a light or dark surface.
open var fillColor: FillColor = .red { didSet { setNeedsUpdate() }} open var fillColor: FillColor = .red { didSet { setNeedsUpdate() }}
/// Badge Number that will be shown if you are using Kind.numbered
open var number: Int? { didSet { setNeedsUpdate() }} open var number: Int? { didSet { setNeedsUpdate() }}
/// Type of Badge Indicator, simple is a dot, whereas numbered shows a number.
open var kind: Kind = .simple { didSet { setNeedsUpdate() }} open var kind: Kind = .simple { didSet { setNeedsUpdate() }}
/// Character that is always at the begging. Accepts any character and if unaffected by maximumDigits
open var leadingCharacter: String? { didSet { setNeedsUpdate() }} open var leadingCharacter: String? { didSet { setNeedsUpdate() }}
/// Determines the size of the Badge Indicator as well as the textStyle and padding used.
open var size: Size = .xxlarge { didSet { setNeedsUpdate() }} open var size: Size = .xxlarge { didSet { setNeedsUpdate() }}
/// Pixel size of the dot when the kind is set to simple
open var dotSize: CGFloat? { didSet { setNeedsUpdate() }} open var dotSize: CGFloat? { didSet { setNeedsUpdate() }}
/// Sets the padding at the top/bottom of the label
open var verticalPadding: CGFloat? { didSet { setNeedsUpdate() }} open var verticalPadding: CGFloat? { didSet { setNeedsUpdate() }}
/// Sets the padding at the left/right of the label
open var horitonalPadding: CGFloat? { didSet { setNeedsUpdate() }} open var horitonalPadding: CGFloat? { didSet { setNeedsUpdate() }}
/// Hides the dot when you are in Kind.simple mode.
open var hideDot: Bool = false { didSet { setNeedsUpdate() }} open var hideDot: Bool = false { didSet { setNeedsUpdate() }}
/// Will not show the border
open var hideBorder: Bool = false { didSet { setNeedsUpdate() }} open var hideBorder: Bool = false { didSet { setNeedsUpdate() }}
open var maxDigits: MaxDigits = .two { didSet { setNeedsUpdate() }} /// When in Kind.numbered this is the amount of digits that will show up when the user adds a number.
open var maximumDigits: MaximumDigits = .two { didSet { setNeedsUpdate() }}
/// The Container's width
open var width: CGFloat? { didSet { setNeedsUpdate() }} open var width: CGFloat? { didSet { setNeedsUpdate() }}
/// The Container's height
open var height: CGFloat? { didSet { setNeedsUpdate() }} open var height: CGFloat? { didSet { setNeedsUpdate() }}
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Private Properties // MARK: - Private Properties
//-------------------------------------------------- //--------------------------------------------------
private let borderWidth: CGFloat = 1.0 private let badgeView = View()
private var badgeSize: CGFloat { max(minSize, size.textStyle.font.lineHeight) }
private var labelEdgeInset: UIEdgeInsets {
var newInset = size.edgeInset
if let verticalPadding, let horitonalPadding {
newInset = .init(top: verticalPadding, left: horitonalPadding, bottom: verticalPadding, right: horitonalPadding)
} else if let verticalPadding {
newInset = .init(top: verticalPadding, left: newInset.left, bottom: verticalPadding, right: newInset.right)
} else if let horitonalPadding {
newInset = .init(top: newInset.top, left: horitonalPadding, bottom: newInset.bottom, right: horitonalPadding)
}
return newInset
}
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Constraints // MARK: - Constraints
//-------------------------------------------------- //--------------------------------------------------
private let badgeView = View()
private var badgeSize: CGFloat { max(16.0, size.textStyle.font.lineHeight) }
private var widthConstraint: NSLayoutConstraint? private var widthConstraint: NSLayoutConstraint?
private var heightConstraint: NSLayoutConstraint? private var heightConstraint: NSLayoutConstraint?
private var labelContraints = NSLayoutConstraint.Container() private var labelContraints = NSLayoutConstraint.Container()
//--------------------------------------------------
// MARK: - Configuration
//--------------------------------------------------
private let borderWidth: CGFloat = 1.0
private let minSize: CGFloat = 16.0
private let minDotSize: CGFloat = 4.0
private let dotRatio: CGFloat = 0.24
private var borderColorConfiguration = SurfaceColorConfiguration(VDSColor.paletteWhite, VDSColor.paletteBlack)
private var backgroundColorConfiguration: AnyColorable = {
let config = KeyedColorConfiguration<BadgeIndicator, FillColor>(keyPath: \.fillColor)
config.setSurfaceColors(VDSColor.backgroundBrandhighlight, VDSColor.backgroundBrandhighlight, forKey: .red)
config.setSurfaceColors(VDSColor.paletteYellow62, VDSColor.paletteYellow62, forKey: .yellow)
config.setSurfaceColors(VDSColor.paletteGreen26, VDSColor.paletteGreen36, forKey: .green)
config.setSurfaceColors(VDSColor.paletteOrange41, VDSColor.paletteOrange58, forKey: .orange)
config.setSurfaceColors(VDSColor.paletteBlue38, VDSColor.paletteBlue46, forKey: .blue)
config.setSurfaceColors(VDSColor.paletteGray44, VDSColor.paletteGray65, forKey: .gray)
config.setSurfaceColors(VDSColor.paletteGray85, VDSColor.paletteGray20, forKey: .grayLowContrast)
config.setSurfaceColors(VDSColor.backgroundPrimaryDark, VDSColor.backgroundPrimaryDark, forKey: .black)
config.setSurfaceColors(VDSColor.backgroundPrimaryLight, VDSColor.backgroundPrimaryLight, forKey: .white)
return config.eraseToAnyColorable()
}()
private var textColorConfiguration = ViewColorConfiguration()
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Lifecycle // MARK: - Lifecycle
//-------------------------------------------------- //--------------------------------------------------
@ -224,41 +289,7 @@ open class BadgeIndicator: View {
shouldUpdateView = true shouldUpdateView = true
setNeedsUpdate() setNeedsUpdate()
} }
private var labelEdgeInset: UIEdgeInsets {
var newInset = size.edgeInset
if let verticalPadding, let horitonalPadding {
newInset = .init(top: verticalPadding, left: horitonalPadding, bottom: verticalPadding, right: horitonalPadding)
} else if let verticalPadding {
newInset = .init(top: verticalPadding, left: newInset.left, bottom: verticalPadding, right: newInset.right)
} else if let horitonalPadding {
newInset = .init(top: newInset.top, left: horitonalPadding, bottom: newInset.bottom, right: horitonalPadding)
}
return newInset
}
//--------------------------------------------------
// MARK: - Configuration
//--------------------------------------------------
private var borderColorConfiguration = SurfaceColorConfiguration(VDSColor.paletteWhite, VDSColor.paletteBlack)
private var backgroundColorConfiguration: AnyColorable = {
let config = KeyedColorConfiguration<BadgeIndicator, FillColor>(keyPath: \.fillColor)
config.setSurfaceColors(VDSColor.backgroundBrandhighlight, VDSColor.backgroundBrandhighlight, forKey: .red)
config.setSurfaceColors(VDSColor.paletteYellow62, VDSColor.paletteYellow62, forKey: .yellow)
config.setSurfaceColors(VDSColor.paletteGreen26, VDSColor.paletteGreen36, forKey: .green)
config.setSurfaceColors(VDSColor.paletteOrange41, VDSColor.paletteOrange58, forKey: .orange)
config.setSurfaceColors(VDSColor.paletteBlue38, VDSColor.paletteBlue46, forKey: .blue)
config.setSurfaceColors(VDSColor.paletteGray44, VDSColor.paletteGray65, forKey: .gray)
config.setSurfaceColors(VDSColor.paletteGray85, VDSColor.paletteGray20, forKey: .grayLowContrast)
config.setSurfaceColors(VDSColor.backgroundPrimaryDark, VDSColor.backgroundPrimaryDark, forKey: .black)
config.setSurfaceColors(VDSColor.backgroundPrimaryLight, VDSColor.backgroundPrimaryLight, forKey: .white)
return config.eraseToAnyColorable()
}()
private var textColorConfiguration = ViewColorConfiguration()
public func updateTextColorConfig() { public func updateTextColorConfig() {
textColorConfiguration.reset() textColorConfiguration.reset()
@ -323,19 +354,13 @@ open class BadgeIndicator: View {
let badgeCount = number ?? 0 let badgeCount = number ?? 0
var text: String = "" var text: String = ""
if kind == .numbered && badgeCount >= 0 { if kind == .numbered && badgeCount >= 0 {
let maxBadgetCount = limitDigits(number: badgeCount, maxDigits: maxDigits.value) let maxBadgetCount = maximumDigits == .none ? badgeCount : limitDigits(number: badgeCount, maxDigits: maximumDigits.value)
let formatter = NumberFormatter() let formatter = NumberFormatter()
formatter.numberStyle = .decimal formatter.numberStyle = .decimal
text = formatter.string(from: .init(integerLiteral: maxBadgetCount))! text = formatter.string(from: .init(integerLiteral: maxBadgetCount))!
if maxDigits.value < "\(badgeCount)".count {
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
text = "\(text)+"
}
if let leadingCharacter { if let leadingCharacter {
text = "\(leadingCharacter)\(text)" text = "\(leadingCharacter)\(text)"
} else {
text = "\(text)"
} }
} }
return text return text
@ -368,7 +393,8 @@ open class BadgeIndicator: View {
let frame = badgeView.frame let frame = badgeView.frame
//default calculation if a dotSize isn't given //default calculation if a dotSize isn't given
var dot: CGFloat = frame.height * 0.1875 let dotSizeRatio = frame.height * dotRatio
var dot: CGFloat = dotSizeRatio < minDotSize ? minDotSize : dotSizeRatio
if let dotSize, dotSize < frame.width, dotSize < frame.height { if let dotSize, dotSize < frame.width, dotSize < frame.height {
dot = dotSize dot = dotSize
} }

View File

@ -8,12 +8,17 @@
import Foundation import Foundation
import UIKit import UIKit
/// Protocol used to be implemented on a object that can return a color for a Generic ObjectType.
public protocol Colorable<ObjectType> { public protocol Colorable<ObjectType> {
associatedtype ObjectType associatedtype ObjectType
/// Method used to get the current color needed for the Generic ObjectType passed into the method.
func getColor(_ object: ObjectType) -> UIColor func getColor(_ object: ObjectType) -> UIColor
} }
extension Colorable { extension Colorable {
/// Helper method used where you don't know the ObjectType to return the color.
/// - Parameter object: Any object, but this objectType will be checked against the registered Generic ObjectType for the Colorable
/// - Returns: UIColor for the rule of this Colorable implementation for the object passed into the function
fileprivate func getColor(_ object: Any) -> UIColor { fileprivate func getColor(_ object: Any) -> UIColor {
guard let model = object as? ObjectType else { guard let model = object as? ObjectType else {
assertionFailure("Invalid ObjectType, Expecting type \(ObjectType.self), received \(object) ") assertionFailure("Invalid ObjectType, Expecting type \(ObjectType.self), received \(object) ")
@ -22,21 +27,12 @@ extension Colorable {
return getColor(model) return getColor(model)
} }
/// TypeErasure for the Colorable to AnyColorable
/// - Returns: AnyColorable
public func eraseToAnyColorable() -> AnyColorable { AnyColorable(self) } public func eraseToAnyColorable() -> AnyColorable { AnyColorable(self) }
} }
public struct GenericColorable<ObjectType>: Colorable, Withable { /// TypeErased Struct of a Colorable Type. This type can be used anywhere as long as the ObjectType being passed into this method matches the wrapped Colorable ObjectType.
private var wrapped: any Colorable<ObjectType>
public init<C: Colorable>(colorable: C) where C.ObjectType == ObjectType {
wrapped = colorable
}
public func getColor(_ object: ObjectType) -> UIColor {
wrapped.getColor(object)
}
}
public struct AnyColorable: Colorable, Withable { public struct AnyColorable: Colorable, Withable {
private let wrapped: any Colorable private let wrapped: any Colorable

View File

@ -7,6 +7,8 @@
import Foundation import Foundation
/// Any object that can be disabled, which may change the appearance
public protocol Disabling { public protocol Disabling {
/// Whether this object is disabled or not
var disabled: Bool { get set } var disabled: Bool { get set }
} }

View File

@ -9,6 +9,7 @@ import Foundation
import UIKit import UIKit
import VDSColorTokens import VDSColorTokens
/// The background tint that the component will be placed on. This will automatically adjust other elements as needed and takes "light" or "dark"
public enum Surface: String, Equatable { public enum Surface: String, Equatable {
case light, dark case light, dark
public var color: UIColor { public var color: UIColor {
@ -17,5 +18,6 @@ public enum Surface: String, Equatable {
} }
public protocol Surfaceable { public protocol Surfaceable {
/// Current Surface and this is used to pass down to child objects that implement Surfacable
var surface: Surface { get set } var surface: Surface { get set }
} }

View File

@ -8,19 +8,50 @@ Using the system allows designers and developers to collaborate more easily and
## Topics ## Topics
### Components ### BaseComponents
- ``ButtonBase``
- ``Control``
- ``View``
- ``SelfSizingCollectionView``
- ``SelectorBase``
- ``SelectorItemBase``
- ``SelectorGroupHandlerBase``
- ``SelectorGroupSelectedHandlerBase``
### Components
- ``Badge`` - ``Badge``
- ``BadgeIndicator``
- ``Button`` - ``Button``
- ``TextLink`` - ``ButtonIcon``
- ``TextLinkCaret`` - ``ButtonGroup``
- ``CheckboxGroup``
- ``Checkbox`` - ``Checkbox``
- ``CheckboxItem``
- ``CheckboxGroup``
- ``Icon``
- ``Label`` - ``Label``
- ``Line``
- ``Loader``
- ``RadioBoxItem``
- ``RadioBoxGroup`` - ``RadioBoxGroup``
- ``RadioBox``
- ``RadioButtonGroup``
- ``RadioButton`` - ``RadioButton``
- ``RadioButtonItem``
- ``RadioButtonGroup``
- ``RadioSwatchGroup`` - ``RadioSwatchGroup``
- ``RadioSwatch`` - ``RadioSwatch``
- ``Tabs``
- ``TextLink``
- ``TextLinkCaret``
- ``TileContainer``
- ``Tilelet``
- ``TitleLockup``
- ``Toggle`` - ``Toggle``
- ``Tooltip``
### ColorConfiguration
- ``Colorable``
- ``AnyColorable``
- ``SurfaceColorConfiguration``
- ``KeyColorConfiguration``
- ``KeyedColorConfiguration``
- ``ControlColorConfiguration``
- ``ViewColorConfiguration``