Merge branch 'feature/tilet' into 'develop'

refactored to use tokens instead of hardcoded values

See merge request BPHV_MIPS/vds_ios!23
This commit is contained in:
Bruce, Matt R 2023-01-06 21:31:23 +00:00
commit 2b164f9f25
19 changed files with 515 additions and 199 deletions

View File

@ -51,6 +51,13 @@
EA89201328B568D8006B9984 /* RadioBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA89201228B568D8006B9984 /* RadioBox.swift */; };
EA89201528B56CF4006B9984 /* RadioBoxGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA89201428B56CF4006B9984 /* RadioBoxGroup.swift */; };
EA978EC5291D6AFE00ACC883 /* AnyLabelAttribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA978EC4291D6AFE00ACC883 /* AnyLabelAttribute.swift */; };
EA985BE629688F6A00F2FF2E /* TiletBadgeModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA985BE529688F6A00F2FF2E /* TiletBadgeModel.swift */; };
EA985BE82968951C00F2FF2E /* TiletTitleModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA985BE72968951C00F2FF2E /* TiletTitleModel.swift */; };
EA985BEA29689B6D00F2FF2E /* TiletSubTitleModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA985BE929689B6D00F2FF2E /* TiletSubTitleModel.swift */; };
EA985BEC2968A91200F2FF2E /* TitleLockupTitleModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA985BEB2968A91200F2FF2E /* TitleLockupTitleModel.swift */; };
EA985BEE2968A92400F2FF2E /* TitleLockupSubTitleModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA985BED2968A92400F2FF2E /* TitleLockupSubTitleModel.swift */; };
EA985BF02968A93600F2FF2E /* TitleLockupEyebrowModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA985BEF2968A93600F2FF2E /* TitleLockupEyebrowModel.swift */; };
EA985BF22968B5BB00F2FF2E /* TitleLockupTypography.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA985BF12968B5BB00F2FF2E /* TitleLockupTypography.swift */; };
EAA5EEB528ECBFB4003B3210 /* ImageLabelAttribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAA5EEB428ECBFB4003B3210 /* ImageLabelAttribute.swift */; };
EAA5EEB728ECC03A003B3210 /* ToolTipLabelAttribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAA5EEB628ECC03A003B3210 /* ToolTipLabelAttribute.swift */; };
EAA5EEB928ECD24B003B3210 /* Icons.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = EAA5EEB828ECD24B003B3210 /* Icons.xcassets */; };
@ -151,6 +158,13 @@
EA89201228B568D8006B9984 /* RadioBox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioBox.swift; sourceTree = "<group>"; };
EA89201428B56CF4006B9984 /* RadioBoxGroup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioBoxGroup.swift; sourceTree = "<group>"; };
EA978EC4291D6AFE00ACC883 /* AnyLabelAttribute.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnyLabelAttribute.swift; sourceTree = "<group>"; };
EA985BE529688F6A00F2FF2E /* TiletBadgeModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TiletBadgeModel.swift; sourceTree = "<group>"; };
EA985BE72968951C00F2FF2E /* TiletTitleModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TiletTitleModel.swift; sourceTree = "<group>"; };
EA985BE929689B6D00F2FF2E /* TiletSubTitleModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TiletSubTitleModel.swift; sourceTree = "<group>"; };
EA985BEB2968A91200F2FF2E /* TitleLockupTitleModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TitleLockupTitleModel.swift; sourceTree = "<group>"; };
EA985BED2968A92400F2FF2E /* TitleLockupSubTitleModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TitleLockupSubTitleModel.swift; sourceTree = "<group>"; };
EA985BEF2968A93600F2FF2E /* TitleLockupEyebrowModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TitleLockupEyebrowModel.swift; sourceTree = "<group>"; };
EA985BF12968B5BB00F2FF2E /* TitleLockupTypography.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TitleLockupTypography.swift; sourceTree = "<group>"; };
EAA5EEB428ECBFB4003B3210 /* ImageLabelAttribute.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageLabelAttribute.swift; sourceTree = "<group>"; };
EAA5EEB628ECC03A003B3210 /* ToolTipLabelAttribute.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToolTipLabelAttribute.swift; sourceTree = "<group>"; };
EAA5EEB828ECD24B003B3210 /* Icons.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Icons.xcassets; sourceTree = "<group>"; };
@ -457,6 +471,10 @@
isa = PBXGroup;
children = (
EA5E30522950DDA60082B959 /* TitleLockup.swift */,
EA985BEF2968A93600F2FF2E /* TitleLockupEyebrowModel.swift */,
EA985BED2968A92400F2FF2E /* TitleLockupSubTitleModel.swift */,
EA985BEB2968A91200F2FF2E /* TitleLockupTitleModel.swift */,
EA985BF12968B5BB00F2FF2E /* TitleLockupTypography.swift */,
);
path = TitleLockup;
sourceTree = "<group>";
@ -465,6 +483,9 @@
isa = PBXGroup;
children = (
EA5E3057295105A40082B959 /* Tilet.swift */,
EA985BE529688F6A00F2FF2E /* TiletBadgeModel.swift */,
EA985BE929689B6D00F2FF2E /* TiletSubTitleModel.swift */,
EA985BE72968951C00F2FF2E /* TiletTitleModel.swift */,
);
path = Tilet;
sourceTree = "<group>";
@ -711,9 +732,13 @@
EA978EC5291D6AFE00ACC883 /* AnyLabelAttribute.swift in Sources */,
EA33622C2891E73B0071C351 /* FontProtocol.swift in Sources */,
EAF7F11728A1475A00B287F5 /* RadioButton.swift in Sources */,
EA985BEE2968A92400F2FF2E /* TitleLockupSubTitleModel.swift in Sources */,
EA985BF22968B5BB00F2FF2E /* TitleLockupTypography.swift in Sources */,
EAB1D2CD28ABE76100DAE764 /* Withable.swift in Sources */,
EAC846F3294B95CE00F685BA /* ButtonGroupCollectionViewCell.swift in Sources */,
EAF7F0952899861000B287F5 /* Checkbox.swift in Sources */,
EA985BE82968951C00F2FF2E /* TiletTitleModel.swift in Sources */,
EA985BEA29689B6D00F2FF2E /* TiletSubTitleModel.swift in Sources */,
EA3361C9289054C50071C351 /* Surfaceable.swift in Sources */,
EAB5FEED2927E1B200998C17 /* ButtonGroupPositionLayout.swift in Sources */,
EA4DB30228DCBCA500103EE3 /* Badge.swift in Sources */,
@ -742,7 +767,9 @@
EA89200228AECF2A006B9984 /* UIButton+Publisher.swift in Sources */,
EAF7F0AB289B13FD00B287F5 /* TypographicalStyleLabelAttribute.swift in Sources */,
EAB1D29C28A5618900DAE764 /* RadioButtonGroup.swift in Sources */,
EA985BE629688F6A00F2FF2E /* TiletBadgeModel.swift in Sources */,
EA336171288B19200071C351 /* VDS.docc in Sources */,
EA985BF02968A93600F2FF2E /* TitleLockupEyebrowModel.swift in Sources */,
EA5E30532950DDA60082B959 /* TitleLockup.swift in Sources */,
EAA5EEB528ECBFB4003B3210 /* ImageLabelAttribute.swift in Sources */,
EAB5FF0129424ACB00998C17 /* UIControl.swift in Sources */,
@ -762,6 +789,7 @@
EA3361A8288B23300071C351 /* UIColor.swift in Sources */,
EAC9257D29119B5400091998 /* TextLink.swift in Sources */,
EA1F266628B945070033E859 /* RadioSwatchGroup.swift in Sources */,
EA985BEC2968A91200F2FF2E /* TitleLockupTitleModel.swift in Sources */,
5FC35BE328D51405004EBEAC /* Button.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;

View File

@ -67,7 +67,7 @@ public class Badge: View, Accessable {
isAccessibilityElement = true
accessibilityTraits = .staticText
layer.cornerRadius = 2
layer.cornerRadius = VDSFormControls.borderradius
addSubview(label)
label.pinToSuperView(.init(top: 2, left: 4, bottom: 2, right: 4))

View File

@ -146,7 +146,7 @@ open class Button: ButtonBase, Useable {
super.updateView()
let bgColor = backgroundColorConfiguration.getColor(self)
let borderColor = borderColorConfiguration.getColor(self)
let borderWidth = use == .secondary ? 1.0 : 0.0
let borderWidth = use == .secondary ? VDSFormControls.widthBorder : 0.0
let buttonHeight = size.height
let cornerRadius = size.cornerRadius
let minWidth = size.minimumWidth

View File

@ -371,8 +371,8 @@ open class CheckboxBase: Control, Accessable, DataTrackable, Errorable {
selectorView.backgroundColor = backgroundColor
selectorView.layer.borderColor = borderColor.cgColor
selectorView.layer.cornerRadius = 2.0
selectorView.layer.borderWidth = 1.0
selectorView.layer.cornerRadius = VDSFormControls.borderradius
selectorView.layer.borderWidth = VDSFormControls.widthBorder
if shapeLayer == nil {
let bounds = selectorView.bounds

View File

@ -281,10 +281,10 @@ open class RadioBoxBase: Control, Accessable, DataTrackable{
//--------------------------------------------------
// MARK: - Configuration Properties
//--------------------------------------------------
private var strikeThroughLineThickness: CGFloat = 1.0
private var selectorCornerRadius: CGFloat = 4.0
private var selectorBorderWidthSelected: CGFloat = 2.0
private var selectorBorderWidth: CGFloat = 1.0
private var strikeThroughLineThickness: CGFloat = VDSFormControls.widthBorder
private var selectorCornerRadius: CGFloat = VDSFormControls.borderradius
private var selectorBorderWidthSelected: CGFloat = VDSFormControls.widthBorder + VDSFormControls.widthBorder
private var selectorBorderWidth: CGFloat = VDSFormControls.widthBorder
private var backgroundColorConfiguration = ControlColorConfiguration().with {
$0.setSurfaceColors(VDSFormControlsColor.backgroundOnlight, VDSFormControlsColor.backgroundOndark, forState: .normal)
@ -311,7 +311,7 @@ open class RadioBoxBase: Control, Accessable, DataTrackable{
//get the colors
let backgroundColor = backgroundColorConfiguration.getColor(self)
let borderColor = borderColorConfiguration.getColor(self)
let borderWidth = isSelected || isHighlighted ? selectorBorderWidthSelected : selectorBorderWidth
let borderWidth = isSelected ? selectorBorderWidthSelected : selectorBorderWidth
selectorView.backgroundColor = backgroundColor
selectorView.layer.borderColor = borderColor.cgColor

View File

@ -373,7 +373,7 @@ open class RadioButtonBase: Control, Accessable, DataTrackable, Errorable {
selectorView.backgroundColor = backgroundColor
selectorView.layer.borderColor = borderColor.cgColor
selectorView.layer.cornerRadius = selectorView.bounds.width * 0.5
selectorView.layer.borderWidth = 1.0
selectorView.layer.borderWidth = VDSFormControls.widthBorder
if shapeLayer == nil {
let selectedBounds = radioButtonSelectedSize

View File

@ -162,8 +162,8 @@ open class RadioSwatchBase: Control, Accessable, DataTrackable {
//--------------------------------------------------
// MARK: - Configuration Properties
//--------------------------------------------------
private var strikeThroughLineThickness: CGFloat = 1.0
private var selectorBorderWidth: CGFloat = 1.0
private var strikeThroughLineThickness: CGFloat = VDSFormControls.widthBorder
private var selectorBorderWidth: CGFloat = VDSFormControls.widthBorder
public let swatchSize = CGSize(width: 48, height: 48)
public let fillSize = CGSize(width: 36, height: 36)
public let disabledAlpha = 0.5

View File

@ -285,8 +285,8 @@ open class EntryField: Control, Accessable {
containerView.backgroundColor = backgroundColorConfiguration.getColor(self)
containerView.layer.borderColor = borderColorConfiguration.getColor(self).cgColor
containerView.layer.borderWidth = 1
containerView.layer.cornerRadius = 4
containerView.layer.borderWidth = VDSFormControls.widthBorder
containerView.layer.cornerRadius = VDSFormControls.borderradius
updateTitleLabel()
updateErrorLabel()

View File

@ -7,6 +7,7 @@
import Foundation
import VDSColorTokens
import VDSFormControlsTokens
import UIKit
@objc(VDSTileContainer)
@ -81,8 +82,10 @@ open class TileContainer: Control {
set {
if newValue > 100 {
_width = newValue
didChange()
} else {
_width = 100
}
didChange()
}
}
@ -181,8 +184,8 @@ open class TileContainer: Control {
//corner radius
layer.cornerRadius = cornerRadius
backgroundImageView.layer.cornerRadius = 8
highlightView.layer.cornerRadius = 8
backgroundImageView.layer.cornerRadius = cornerRadius
highlightView.layer.cornerRadius = cornerRadius
}
@ -194,7 +197,7 @@ open class TileContainer: Control {
//--------------------------------------------------
// MARK: - Configuration
//--------------------------------------------------
private let cornerRadius = 8.0
private let cornerRadius = VDSFormControls.borderradius * 2
private var backgroundColorConfig = BackgroundColorConfiguration()
@ -262,14 +265,14 @@ open class TileContainer: Control {
}
layer.borderColor = borderColorConfig.getColor(self).cgColor
layer.borderWidth = showBorder ? 1 : 0
layer.borderWidth = showBorder ? VDSFormControls.widthBorder : 0
containerTopConstraint?.constant = padding
containerLeadingConstraint?.constant = padding
containerBottomConstraint?.constant = -padding
containerTrailingConstraint?.constant = -padding
if aspectRatio == .none {
if aspectRatio == .none && height == nil{
widthConstraint?.constant = width
heightConstraint?.isActive = false
heightGreaterThanConstraint?.isActive = true

View File

@ -10,33 +10,8 @@ import Foundation
import VDSColorTokens
import UIKit
public enum TiletTitleTypographicalStyle: String, Codable, EnumSubset {
case TitleXLarge
case BoldTitleXLarge
case TitleLarge
case BoldTitleLarge
case TitleMedium
case BoldTitleMedium
case TitleSmall
case BoldTitleSmall
public var defaultValue: TitleLockupTitleTypographicalStyle { .BoldTitleSmall }
}
public enum TiletOtherTypographicalStyle: String, Codable, EnumSubset {
case BodyLarge
case BoldBodyLarge
case BodyMedium
case BoldBodyMedium
case BodySmall
case BoldBodySmall
public var defaultValue: TitleLockupOtherTypographicalStyle { .BodySmall }
}
@objc(VDSTilet)
open class Tilet: View {
open class Tilet: TileContainer {
//--------------------------------------------------
// MARK: - Initializers
@ -58,22 +33,91 @@ open class Tilet: View {
//--------------------------------------------------
// MARK: - Private Properties
//--------------------------------------------------
private var tileContainer = TileContainer().with {
$0.aspectRatio = .none
$0.surface = .light
private var stackView = UIStackView().with {
$0.translatesAutoresizingMaskIntoConstraints = false
$0.axis = .vertical
$0.distribution = .fill
$0.spacing = 5
}
private var titleLockup = TitleLockup()
private var titleLockupContainerView = UIView().with {
$0.translatesAutoresizingMaskIntoConstraints = false
}
private var titleLockup = TitleLockup().with {
let configs = [
TypographicalStyleDeviceSpacingConfig([.TitleSmall, .BoldTitleSmall],
neighboring: [
.BodySmall, .BoldBodySmall,
.BodyMedium, .BoldBodyMedium
],
spacing: 8.0,
deviceType: .iPhone),
TypographicalStyleDeviceSpacingConfig([.TitleMedium, .BoldTitleMedium,
.TitleLarge, .BoldTitleLarge],
neighboring: [
.BodySmall, .BoldBodySmall,
.BodyMedium, .BoldBodyMedium,
.BodyLarge, .BoldBodyLarge],
spacing: 8.0,
deviceType: .iPhone),
TypographicalStyleDeviceSpacingConfig([.TitleXLarge, .BoldTitleXLarge],
neighboring: [
.BodySmall, .BoldBodySmall,
.BodyMedium, .BoldBodyMedium,
.BodyLarge, .BoldBodyLarge,
.TitleMedium, .BoldTitleMedium
],
spacing: 12.0,
deviceType: .iPhone),
TypographicalStyleDeviceSpacingConfig([.TitleSmall, .BoldTitleSmall,
.TitleMedium, .BoldTitleMedium],
neighboring: [
.BodySmall, .BoldBodySmall,
.BodyMedium, .BoldBodyMedium,
.BodyLarge, .BoldBodyLarge
],
spacing: 8.0,
deviceType: .iPad),
TypographicalStyleDeviceSpacingConfig([.TitleLarge, .BoldTitleLarge],
neighboring: [
.BodySmall, .BoldBodySmall,
.BodyMedium, .BoldBodyMedium,
.BodyLarge, .BoldBodyLarge,
.TitleSmall, .BoldTitleSmall
],
spacing: 12.0,
deviceType: .iPad),
TypographicalStyleDeviceSpacingConfig([.TitleXLarge, .BoldTitleXLarge],
neighboring: [
.BodyLarge, .BoldBodyLarge,
.TitleMedium, .BoldTitleMedium
],
spacing: 16.0,
deviceType: .iPad)
]
$0.bottomTypographicalStyleSpacingConfig = TypographicalStyleSpacingConfig(configs: configs)
}
private var badgeContainerView = UIView().with {
$0.translatesAutoresizingMaskIntoConstraints = false
}
private var badge = Badge().with {
$0.fillColor = .red
}
//--------------------------------------------------
// MARK: - Public Properties
//--------------------------------------------------
//style
open var titleTypograpicalStyle: TiletTitleTypographicalStyle = .BoldTitleSmall { didSet { didChange() }}
open var otherTypograpicalStyle: TiletOtherTypographicalStyle = .BodySmall { didSet { didChange() }}
open var width: CGFloat = 100 { didSet { didChange() }}
private var _textWidth: CGFloat?
open var textWidth: CGFloat? {
get { _textWidth }
@ -107,15 +151,14 @@ open class Tilet: View {
}
}
//text
open var titleText: String = "" { didSet { didChange() }}
open var titleTextAttributes: [any LabelAttributeModel]? { didSet { didChange() }}
//models
public var badgeModel: TiletBadgeModel? { didSet { didChange() }}
public var titleModel: TiletTitleModel? { didSet { didChange() }}
public var subTitleModel: TiletSubTitleModel? { didSet { didChange() }}
//icons
open var subTitleText: String = "" { didSet { didChange() }}
open var subTitleTextAttributes: [any LabelAttributeModel]? { didSet { didChange() }}
open var subTitleColor: Use = .primary { didSet { didChange() }}
//--------------------------------------------------
// MARK: - Constraints
//--------------------------------------------------
@ -128,81 +171,128 @@ open class Tilet: View {
open override func setup() {
super.setup()
addSubview(tileContainer)
tileContainer.pinToSuperView()
tileContainer.addContentView(titleLockup, shouldPin: false)
titleLockup.pinTop()
titleLockup.pinLeading()
titleLockup.pinBottom()
width = 100
aspectRatio = .none
containerBackgroundColor = .black
//either you are 100% width of the tileContainer.contentView
titleLockupTrailingConstraint = titleLockup.trailingAnchor.constraint(equalTo: tileContainer.containerView.trailingAnchor)
addContentView(stackView)
//badge
badgeContainerView.addSubview(badge)
badge
.pinTop()
.pinLeading()
.pinBottom()
badge.trailingAnchor.constraint(lessThanOrEqualTo: badgeContainerView.trailingAnchor).isActive = true
titleLockupContainerView.addSubview(titleLockup)
titleLockup
.pinTop()
.pinLeading()
.pinBottom()
titleLockupTrailingConstraint = titleLockup.trailingAnchor.constraint(equalTo: titleLockupContainerView.trailingAnchor)
titleLockupTrailingConstraint?.isActive = true
//stackView.addArrangedSubview(badgeContainerView)
//stackView.addArrangedSubview(titleLockupContainerView)
}
public override func reset() {
super.reset()
tileContainer.reset()
tileContainer.aspectRatio = .none
tileContainer.surface = .light
titleLockup.reset()
aspectRatio = .none
surface = .light
containerBackgroundColor = .black
titleText = ""
titleTextAttributes = nil
subTitleText = ""
subTitleTextAttributes = nil
subTitleColor = .primary
//badge
badge.reset()
badgeModel = nil
//titleLockup
titleLockup.reset()
titleModel = nil
subTitleModel = nil
}
//--------------------------------------------------
// MARK: - State
//--------------------------------------------------
open override func updateView() {
super.updateView()
//flip the color
let flippedColor:TileContainer.ContainerBackgroundColor = surface == .dark ? .white : .black
tileContainer.containerBackgroundColor = flippedColor
tileContainer.width = width
//flip the surface for the titleLockup
let flippedSurface: Surface = surface == .dark ? .light : .dark
titleLockup.surface = flippedSurface
let titleLockupSurface: Surface = containerBackgroundColor == .black ? .dark : .light
titleLockup.surface = titleLockupSurface
//either use textWidth
if let textWidth {
titleLockupTrailingConstraint?.isActive = false
titleLockupWidthConstraint?.isActive = false
titleLockupWidthConstraint = titleLockup.widthAnchor.constraint(equalToConstant: textWidth)
titleLockupWidthConstraint?.isActive = true
} else if let textPercentage {
titleLockupTrailingConstraint?.isActive = false
titleLockupWidthConstraint?.isActive = false
titleLockupWidthConstraint = NSLayoutConstraint(item: titleLockup,
attribute: .width,
relatedBy: .equal,
toItem: tileContainer.containerView,
attribute: .width,
multiplier: textPercentage / 100,
constant: 0.0)
titleLockupWidthConstraint?.isActive = true
//update constraints
//badge
if let badgeModel {
if badgeContainerView.superview == nil {
stackView.insertArrangedSubview(badgeContainerView, at: 0)
}
badge.text = badgeModel.text
badge.fillColor = badgeModel.fillColor
badge.numberOfLines = badgeModel.numberOfLines
badge.surface = badgeModel.surface
badge.maxWidth = badgeModel.maxWidth
} else {
titleLockupWidthConstraint?.isActive = false
titleLockupTrailingConstraint?.isActive = true
badge.reset()
badgeContainerView.removeFromSuperview()
}
titleLockup.titleText = titleText
titleLockup.titleTypograpicalStyle = titleTypograpicalStyle.value
titleLockup.titleTextAttributes = titleTextAttributes
var showTitleLockup = false
titleLockup.subTitleText = subTitleText
titleLockup.otherTypograpicalStyle = otherTypograpicalStyle.value
titleLockup.subTitleTextAttributes = titleTextAttributes
titleLockup.subTitleColor = subTitleColor
if let titleModel, !titleModel.text.isEmpty {
showTitleLockup = true
}
if let subTitleModel, !subTitleModel.text.isEmpty {
showTitleLockup = true
}
if showTitleLockup {
if titleLockupContainerView.superview == nil {
stackView.insertArrangedSubview(titleLockupContainerView, at: badgeContainerView.superview == nil ? 0 : 1)
}
//titleLockup
if let textWidth {
titleLockupTrailingConstraint?.isActive = false
titleLockupWidthConstraint?.isActive = false
titleLockupWidthConstraint = titleLockup.widthAnchor.constraint(equalToConstant: textWidth)
titleLockupWidthConstraint?.isActive = true
} else if let textPercentage {
titleLockupTrailingConstraint?.isActive = false
titleLockupWidthConstraint?.isActive = false
titleLockupWidthConstraint = NSLayoutConstraint(item: titleLockup,
attribute: .width,
relatedBy: .equal,
toItem: containerView,
attribute: .width,
multiplier: textPercentage / 100,
constant: 0.0)
titleLockupWidthConstraint?.isActive = true
} else {
titleLockupWidthConstraint?.isActive = false
titleLockupTrailingConstraint?.isActive = true
}
//set models
titleLockup.titleModel = titleModel?.toTitleLockupTitleModel()
titleLockup.subTitleModel = subTitleModel?.toTitleLockupSubTitleModel()
if let style = subTitleModel?.typographicalStyle.value {
titleLockup.otherTypograpicalStyle = style
}
} else {
titleLockupContainerView.removeFromSuperview()
}
}
}

View File

@ -0,0 +1,23 @@
//
// TiletBadgeModel.swift
// VDS
//
// Created by Matt Bruce on 1/6/23.
//
import Foundation
public struct TiletBadgeModel {
public var text: String = ""
public var fillColor: BadgeFillColor
public var surface: Surface
public var numberOfLines: Int
public var maxWidth: CGFloat?
public init(text: String, fillColor: BadgeFillColor = .red, surface: Surface = .light, numberOfLines: Int = 0, maxWidth: CGFloat? = nil) {
self.text = text
self.fillColor = fillColor
self.surface = surface
self.numberOfLines = numberOfLines
self.maxWidth = maxWidth
}
}

View File

@ -0,0 +1,42 @@
//
// TiletSubTitleModel.swift
// VDS
//
// Created by Matt Bruce on 1/6/23.
//
import Foundation
public struct TiletSubTitleModel {
public enum SubTitleTypographicalStyle: String, Codable, EnumSubset {
case BodyLarge
case BoldBodyLarge
case BodyMedium
case BoldBodyMedium
case BodySmall
case BoldBodySmall
public var defaultValue: TitleLockupOtherTypographicalStyle { .BodySmall }
}
public var text: String = ""
public var textAttributes: [any LabelAttributeModel]?
public var typographicalStyle: SubTitleTypographicalStyle
public var textColor: Use
public init(text: String,
textColor: Use = .primary,
textAttributes: [any LabelAttributeModel]? = nil,
typographicalStyle: SubTitleTypographicalStyle = .BodySmall) {
self.text = text
self.textColor = textColor
self.textAttributes = textAttributes
self.typographicalStyle = typographicalStyle
}
public func toTitleLockupSubTitleModel() -> TitleLockupSubTitleModel {
TitleLockupSubTitleModel(text: text,
textColor: textColor,
textAttributes: textAttributes)
}
}

View File

@ -0,0 +1,39 @@
//
// TiletTitleModel.swift
// VDS
//
// Created by Matt Bruce on 1/6/23.
//
import Foundation
public struct TiletTitleModel {
public enum TitleTypographicalStyle: String, EnumSubset {
case TitleXLarge
case BoldTitleXLarge
case TitleLarge
case BoldTitleLarge
case TitleMedium
case BoldTitleMedium
case TitleSmall
case BoldTitleSmall
public var defaultValue: TitleLockupTitleTypographicalStyle { .BoldTitleSmall }
}
public var text: String = ""
public var textAttributes: [any LabelAttributeModel]?
public var typographicalStyle: TitleTypographicalStyle
public init(text: String,
textAttributes: [any LabelAttributeModel]? = nil,
typographicalStyle: TitleTypographicalStyle = .BoldTitleSmall) {
self.text = text
self.textAttributes = textAttributes
self.typographicalStyle = typographicalStyle
}
public func toTitleLockupTitleModel() -> TitleLockupTitleModel {
TitleLockupTitleModel(text: text, textAttributes: textAttributes, typographicalStyle: typographicalStyle.value)
}
}

View File

@ -23,40 +23,6 @@ public enum TitleLockupTextPosition: String, Codable, CaseIterable {
}
}
public enum TitleLockupTitleTypographicalStyle: String, Codable, EnumSubset {
case FeatureMedium
case BoldFeatureMedium
case FeatureSmall
case BoldFeatureSmall
case FeatureXSmall
case BoldFeatureXSmall
case Title2XLarge
case BoldTitle2XLarge
case TitleXLarge
case BoldTitleXLarge
case TitleLarge
case BoldTitleLarge
case TitleMedium
case BoldTitleMedium
case TitleSmall
case BoldTitleSmall
public var defaultValue: TypographicalStyle {.BoldFeatureXSmall }
}
public enum TitleLockupOtherTypographicalStyle: String, Codable, EnumSubset {
case BodyLarge
case BoldBodyLarge
case BodyMedium
case BoldBodyMedium
case BodySmall
case BoldBodySmall
public var defaultValue: TypographicalStyle {.BodyLarge }
}
@objc(VDSTitleLockup)
open class TitleLockup: View {
@ -214,30 +180,26 @@ open class TitleLockup: View {
open var textPosition: TitleLockupTextPosition = .left { didSet { didChange() }}
//style
open var titleTypograpicalStyle: TitleLockupTitleTypographicalStyle = .BoldFeatureXSmall { didSet { didChange() }}
open var otherTypograpicalStyle: TitleLockupOtherTypographicalStyle = UIDevice.isIPad ? .BodyLarge : .BodyMedium { didSet { didChange() }}
//first row
open var eyebrowLabel = Label().with {
$0.setContentCompressionResistancePriority(.required, for: .vertical)
}
open var eyebrowText: String = "" { didSet { didChange() }}
open var eyebrowTextAttributes: [any LabelAttributeModel]? { didSet { didChange() }}
open var eyebrowModel: TitleLockupEyebrowModel? { didSet { didChange() }}
//second row
open var titleLabel = Label().with {
$0.setContentCompressionResistancePriority(.required, for: .vertical)
}
open var titleText: String = "" { didSet { didChange() }}
open var titleTextAttributes: [any LabelAttributeModel]? { didSet { didChange() }}
open var titleModel: TitleLockupTitleModel? { didSet { didChange() }}
//third row
open var subTitleLabel = Label().with {
$0.setContentCompressionResistancePriority(.required, for: .vertical)
}
open var subTitleText: String = "" { didSet { didChange() }}
open var subTitleTextAttributes: [any LabelAttributeModel]? { didSet { didChange() }}
open var subTitleColor: Use = .primary { didSet { didChange() }}
open var subTitleModel: TitleLockupSubTitleModel? { didSet { didChange() }}
//--------------------------------------------------
// MARK: - Lifecycle
//--------------------------------------------------
@ -266,14 +228,9 @@ open class TitleLockup: View {
textPosition = .left
eyebrowText = ""
eyebrowTextAttributes = nil
titleText = ""
titleTextAttributes = nil
subTitleText = ""
subTitleTextAttributes = nil
titleTextAttributes = nil
titleTypograpicalStyle = .BoldFeatureXSmall
eyebrowModel = nil
titleModel = nil
subTitleModel = nil
otherTypograpicalStyle = .BodyLarge
}
@ -285,47 +242,66 @@ open class TitleLockup: View {
super.updateView()
let allLabelsTextPosition = textPosition.labelTextPosition
var eyebrowTextIsEmpty = true
var titleTextIsEmpty = true
var subTitleTextIsEmpty = true
eyebrowLabel.textPosition = allLabelsTextPosition
eyebrowLabel.typograpicalStyle = otherTypograpicalStyle.value
eyebrowLabel.text = eyebrowText
eyebrowLabel.attributes = eyebrowTextAttributes
eyebrowLabel.surface = surface
titleLabel.textPosition = allLabelsTextPosition
titleLabel.typograpicalStyle = titleTypograpicalStyle.value
titleLabel.text = titleText
titleLabel.attributes = titleTextAttributes
titleLabel.surface = surface
subTitleLabel.textPosition = allLabelsTextPosition
subTitleLabel.typograpicalStyle = otherTypograpicalStyle.value
subTitleLabel.text = subTitleText
subTitleLabel.attributes = subTitleTextAttributes
subTitleLabel.surface = surface
subTitleLabel.disabled = subTitleColor == .secondary
if let eyebrowModel, !eyebrowModel.text.isEmpty {
eyebrowTextIsEmpty = false
eyebrowLabel.textPosition = allLabelsTextPosition
eyebrowLabel.typograpicalStyle = otherTypograpicalStyle.value
eyebrowLabel.text = eyebrowModel.text
eyebrowLabel.attributes = eyebrowModel.textAttributes
eyebrowLabel.numberOfLines = eyebrowModel.numberOfLines
eyebrowLabel.surface = surface
} else {
eyebrowLabel.reset()
}
if let titleModel, !titleModel.text.isEmpty {
titleTextIsEmpty = false
titleLabel.textPosition = allLabelsTextPosition
titleLabel.typograpicalStyle = titleModel.typographicalStyle.value
titleLabel.text = titleModel.text
titleLabel.attributes = titleModel.textAttributes
titleLabel.numberOfLines = titleModel.numberOfLines
titleLabel.surface = surface
} else {
titleLabel.reset()
}
if let subTitleModel, !subTitleModel.text.isEmpty {
subTitleTextIsEmpty = false
subTitleLabel.textPosition = allLabelsTextPosition
subTitleLabel.typograpicalStyle = otherTypograpicalStyle.value
subTitleLabel.text = subTitleModel.text
subTitleLabel.attributes = subTitleModel.textAttributes
subTitleLabel.numberOfLines = subTitleModel.numberOfLines
subTitleLabel.surface = surface
subTitleLabel.disabled = subTitleModel.textColor == .secondary
} else {
subTitleLabel.reset()
}
//if both first 2 rows not empty set spacing
if !eyebrowText.isEmpty && !titleText.isEmpty {
stackView.spacing = getTopSpacing()
if let eyebrowModel, let titleModel, !eyebrowModel.text.isEmpty, !titleModel.text.isEmpty {
stackView.spacing = topTypographicalStyleSpacingConfig.spacing(for: titleModel.typographicalStyle.value, neighboring: otherTypograpicalStyle.value)
} else {
stackView.spacing = 0.0
}
//if either first 2 rows not empty and subtile not empty, create space else collapse
if (!eyebrowText.isEmpty || !titleText.isEmpty) && !subTitleText.isEmpty {
stackView.setCustomSpacing(getBottomSpacing(), after: titleLabel)
} else if (!eyebrowText.isEmpty || !titleText.isEmpty) && subTitleText.isEmpty {
if let titleModel, (!eyebrowTextIsEmpty || !titleTextIsEmpty) && !subTitleTextIsEmpty {
let bottomSpace = bottomTypographicalStyleSpacingConfig.spacing(for: titleModel.typographicalStyle.value, neighboring: otherTypograpicalStyle.value)
stackView.setCustomSpacing(bottomSpace, after: titleLabel)
} else if (!eyebrowTextIsEmpty || !titleTextIsEmpty) && subTitleTextIsEmpty {
stackView.setCustomSpacing(0.0, after: titleLabel)
}
}
open func getTopSpacing() -> CGFloat {
topTypographicalStyleSpacingConfig.spacing(for: titleTypograpicalStyle.value, neighboring: otherTypograpicalStyle.value)
}
open func getBottomSpacing() -> CGFloat {
bottomTypographicalStyleSpacingConfig.spacing(for: titleTypograpicalStyle.value, neighboring: otherTypograpicalStyle.value)
//hide/show
eyebrowLabel.isHidden = eyebrowTextIsEmpty
titleLabel.isHidden = titleTextIsEmpty
subTitleLabel.isHidden = subTitleTextIsEmpty
}
}

View File

@ -0,0 +1,22 @@
//
// TitleLockupEyebrowModel.swift
// VDS
//
// Created by Matt Bruce on 1/6/23.
//
import Foundation
public struct TitleLockupEyebrowModel {
public var text: String
public var textAttributes: [any LabelAttributeModel]?
public var numberOfLines: Int
public init(text: String,
textAttributes: [any LabelAttributeModel]? = nil,
numberOfLines: Int = 0) {
self.text = text
self.textAttributes = textAttributes
self.numberOfLines = numberOfLines
}
}

View File

@ -0,0 +1,25 @@
//
// TitleLockupSubTitleModel.swift
// VDS
//
// Created by Matt Bruce on 1/6/23.
//
import Foundation
public struct TitleLockupSubTitleModel {
public var text: String
public var textColor: Use
public var textAttributes: [any LabelAttributeModel]?
public var numberOfLines: Int
public init(text: String,
textColor: Use = .primary,
textAttributes: [any LabelAttributeModel]? = nil,
numberOfLines: Int = 0) {
self.text = text
self.textColor = textColor
self.textAttributes = textAttributes
self.numberOfLines = numberOfLines
}
}

View File

@ -0,0 +1,25 @@
//
// TitleLockupTitleModel.swift
// VDS
//
// Created by Matt Bruce on 1/6/23.
//
import Foundation
public struct TitleLockupTitleModel {
public var text: String
public var textAttributes: [any LabelAttributeModel]?
public var typographicalStyle: TitleLockupTitleTypographicalStyle
public var numberOfLines: Int
public init(text: String,
textAttributes: [any LabelAttributeModel]? = nil,
typographicalStyle: TitleLockupTitleTypographicalStyle = .BoldFeatureXSmall,
numberOfLines: Int = 0) {
self.text = text
self.textAttributes = textAttributes
self.typographicalStyle = typographicalStyle
self.numberOfLines = numberOfLines
}
}

View File

@ -0,0 +1,42 @@
//
// TitleLockupTypography.swift
// VDS
//
// Created by Matt Bruce on 1/6/23.
//
import Foundation
public enum TitleLockupTitleTypographicalStyle: String, Codable, EnumSubset {
case FeatureMedium
case BoldFeatureMedium
case FeatureSmall
case BoldFeatureSmall
case FeatureXSmall
case BoldFeatureXSmall
case Title2XLarge
case BoldTitle2XLarge
case TitleXLarge
case BoldTitleXLarge
case TitleLarge
case BoldTitleLarge
case TitleMedium
case BoldTitleMedium
case TitleSmall
case BoldTitleSmall
public var defaultValue: TypographicalStyle {.BoldFeatureXSmall }
}
public enum TitleLockupOtherTypographicalStyle: String, Codable, EnumSubset {
case BodyLarge
case BoldBodyLarge
case BodyMedium
case BoldBodyMedium
case BodySmall
case BoldBodySmall
public var defaultValue: TypographicalStyle {.BodyLarge }
}

View File

@ -7,6 +7,7 @@
import Foundation
import UIKit
import VDSFormControlsTokens
extension UIView {
public func pin(_ view: UIView, with edges: UIEdgeInsets = UIEdgeInsets.zero) {
@ -122,7 +123,7 @@ extension UIView {
public func debugBorder(show shouldShow: Bool = true, color: UIColor = .red) {
if shouldShow {
layer.borderColor = color.cgColor
layer.borderWidth = 1
layer.borderWidth = VDSFormControls.widthBorder
} else {
layer.borderColor = UIColor.clear.cgColor
layer.borderWidth = 0