diff --git a/VDS.xcodeproj/project.pbxproj b/VDS.xcodeproj/project.pbxproj index 7ef890b9..1648be01 100644 --- a/VDS.xcodeproj/project.pbxproj +++ b/VDS.xcodeproj/project.pbxproj @@ -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 = ""; }; EA89201428B56CF4006B9984 /* RadioBoxGroup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioBoxGroup.swift; sourceTree = ""; }; EA978EC4291D6AFE00ACC883 /* AnyLabelAttribute.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnyLabelAttribute.swift; sourceTree = ""; }; + EA985BE529688F6A00F2FF2E /* TiletBadgeModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TiletBadgeModel.swift; sourceTree = ""; }; + EA985BE72968951C00F2FF2E /* TiletTitleModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TiletTitleModel.swift; sourceTree = ""; }; + EA985BE929689B6D00F2FF2E /* TiletSubTitleModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TiletSubTitleModel.swift; sourceTree = ""; }; + EA985BEB2968A91200F2FF2E /* TitleLockupTitleModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TitleLockupTitleModel.swift; sourceTree = ""; }; + EA985BED2968A92400F2FF2E /* TitleLockupSubTitleModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TitleLockupSubTitleModel.swift; sourceTree = ""; }; + EA985BEF2968A93600F2FF2E /* TitleLockupEyebrowModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TitleLockupEyebrowModel.swift; sourceTree = ""; }; + EA985BF12968B5BB00F2FF2E /* TitleLockupTypography.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TitleLockupTypography.swift; sourceTree = ""; }; EAA5EEB428ECBFB4003B3210 /* ImageLabelAttribute.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageLabelAttribute.swift; sourceTree = ""; }; EAA5EEB628ECC03A003B3210 /* ToolTipLabelAttribute.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToolTipLabelAttribute.swift; sourceTree = ""; }; EAA5EEB828ECD24B003B3210 /* Icons.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Icons.xcassets; sourceTree = ""; }; @@ -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 = ""; @@ -465,6 +483,9 @@ isa = PBXGroup; children = ( EA5E3057295105A40082B959 /* Tilet.swift */, + EA985BE529688F6A00F2FF2E /* TiletBadgeModel.swift */, + EA985BE929689B6D00F2FF2E /* TiletSubTitleModel.swift */, + EA985BE72968951C00F2FF2E /* TiletTitleModel.swift */, ); path = Tilet; sourceTree = ""; @@ -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; diff --git a/VDS/Components/Badge/Badge.swift b/VDS/Components/Badge/Badge.swift index b3ffb2bd..40c1139b 100644 --- a/VDS/Components/Badge/Badge.swift +++ b/VDS/Components/Badge/Badge.swift @@ -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)) diff --git a/VDS/Components/Buttons/Button/Button.swift b/VDS/Components/Buttons/Button/Button.swift index ee2c0ab5..43682d96 100644 --- a/VDS/Components/Buttons/Button/Button.swift +++ b/VDS/Components/Buttons/Button/Button.swift @@ -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 diff --git a/VDS/Components/Checkbox/Checkbox.swift b/VDS/Components/Checkbox/Checkbox.swift index 91c08aab..d16c12f4 100644 --- a/VDS/Components/Checkbox/Checkbox.swift +++ b/VDS/Components/Checkbox/Checkbox.swift @@ -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 diff --git a/VDS/Components/RadioBox/RadioBox.swift b/VDS/Components/RadioBox/RadioBox.swift index 7951c4cd..d9398259 100644 --- a/VDS/Components/RadioBox/RadioBox.swift +++ b/VDS/Components/RadioBox/RadioBox.swift @@ -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 diff --git a/VDS/Components/RadioButton/RadioButton.swift b/VDS/Components/RadioButton/RadioButton.swift index 674a0a6f..3972fcf7 100644 --- a/VDS/Components/RadioButton/RadioButton.swift +++ b/VDS/Components/RadioButton/RadioButton.swift @@ -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 diff --git a/VDS/Components/RadioSwatch/RadioSwatch.swift b/VDS/Components/RadioSwatch/RadioSwatch.swift index 5c36c575..e17eef28 100644 --- a/VDS/Components/RadioSwatch/RadioSwatch.swift +++ b/VDS/Components/RadioSwatch/RadioSwatch.swift @@ -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 diff --git a/VDS/Components/TextFields/EntryField/EntryField.swift b/VDS/Components/TextFields/EntryField/EntryField.swift index 851fb0e5..ab9c0a98 100644 --- a/VDS/Components/TextFields/EntryField/EntryField.swift +++ b/VDS/Components/TextFields/EntryField/EntryField.swift @@ -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() diff --git a/VDS/Components/TileContainer/TileContainer.swift b/VDS/Components/TileContainer/TileContainer.swift index 1f676421..40efde6d 100644 --- a/VDS/Components/TileContainer/TileContainer.swift +++ b/VDS/Components/TileContainer/TileContainer.swift @@ -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 diff --git a/VDS/Components/Tilet/Tilet.swift b/VDS/Components/Tilet/Tilet.swift index 417a7f08..5c44503a 100644 --- a/VDS/Components/Tilet/Tilet.swift +++ b/VDS/Components/Tilet/Tilet.swift @@ -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() + } } } + + diff --git a/VDS/Components/Tilet/TiletBadgeModel.swift b/VDS/Components/Tilet/TiletBadgeModel.swift new file mode 100644 index 00000000..fbad4d5f --- /dev/null +++ b/VDS/Components/Tilet/TiletBadgeModel.swift @@ -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 + } +} diff --git a/VDS/Components/Tilet/TiletSubTitleModel.swift b/VDS/Components/Tilet/TiletSubTitleModel.swift new file mode 100644 index 00000000..10161008 --- /dev/null +++ b/VDS/Components/Tilet/TiletSubTitleModel.swift @@ -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) + } +} diff --git a/VDS/Components/Tilet/TiletTitleModel.swift b/VDS/Components/Tilet/TiletTitleModel.swift new file mode 100644 index 00000000..179c543a --- /dev/null +++ b/VDS/Components/Tilet/TiletTitleModel.swift @@ -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) + } +} diff --git a/VDS/Components/TitleLockup/TitleLockup.swift b/VDS/Components/TitleLockup/TitleLockup.swift index 958d7a81..33633723 100644 --- a/VDS/Components/TitleLockup/TitleLockup.swift +++ b/VDS/Components/TitleLockup/TitleLockup.swift @@ -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 } } diff --git a/VDS/Components/TitleLockup/TitleLockupEyebrowModel.swift b/VDS/Components/TitleLockup/TitleLockupEyebrowModel.swift new file mode 100644 index 00000000..786d3b09 --- /dev/null +++ b/VDS/Components/TitleLockup/TitleLockupEyebrowModel.swift @@ -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 + } +} diff --git a/VDS/Components/TitleLockup/TitleLockupSubTitleModel.swift b/VDS/Components/TitleLockup/TitleLockupSubTitleModel.swift new file mode 100644 index 00000000..f5b1380b --- /dev/null +++ b/VDS/Components/TitleLockup/TitleLockupSubTitleModel.swift @@ -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 + } +} diff --git a/VDS/Components/TitleLockup/TitleLockupTitleModel.swift b/VDS/Components/TitleLockup/TitleLockupTitleModel.swift new file mode 100644 index 00000000..c351206c --- /dev/null +++ b/VDS/Components/TitleLockup/TitleLockupTitleModel.swift @@ -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 + } +} diff --git a/VDS/Components/TitleLockup/TitleLockupTypography.swift b/VDS/Components/TitleLockup/TitleLockupTypography.swift new file mode 100644 index 00000000..0e67d58a --- /dev/null +++ b/VDS/Components/TitleLockup/TitleLockupTypography.swift @@ -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 } +} diff --git a/VDS/Extensions/UIView.swift b/VDS/Extensions/UIView.swift index 6db07dd2..951cbbf5 100644 --- a/VDS/Extensions/UIView.swift +++ b/VDS/Extensions/UIView.swift @@ -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