diff --git a/VDS.xcodeproj/project.pbxproj b/VDS.xcodeproj/project.pbxproj index d686322f..1648be01 100644 --- a/VDS.xcodeproj/project.pbxproj +++ b/VDS.xcodeproj/project.pbxproj @@ -51,10 +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 */; }; - EA985BE429688F3300F2FF2E /* TiletTypographicalStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA985BE329688F3300F2FF2E /* TiletTypographicalStyle.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 */; }; @@ -155,10 +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 = ""; }; - EA985BE329688F3300F2FF2E /* TiletTypographicalStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TiletTypographicalStyle.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 = ""; }; @@ -465,6 +471,10 @@ isa = PBXGroup; children = ( EA5E30522950DDA60082B959 /* TitleLockup.swift */, + EA985BEF2968A93600F2FF2E /* TitleLockupEyebrowModel.swift */, + EA985BED2968A92400F2FF2E /* TitleLockupSubTitleModel.swift */, + EA985BEB2968A91200F2FF2E /* TitleLockupTitleModel.swift */, + EA985BF12968B5BB00F2FF2E /* TitleLockupTypography.swift */, ); path = TitleLockup; sourceTree = ""; @@ -473,10 +483,9 @@ isa = PBXGroup; children = ( EA5E3057295105A40082B959 /* Tilet.swift */, - EA985BE329688F3300F2FF2E /* TiletTypographicalStyle.swift */, EA985BE529688F6A00F2FF2E /* TiletBadgeModel.swift */, - EA985BE72968951C00F2FF2E /* TiletTitleModel.swift */, EA985BE929689B6D00F2FF2E /* TiletSubTitleModel.swift */, + EA985BE72968951C00F2FF2E /* TiletTitleModel.swift */, ); path = Tilet; sourceTree = ""; @@ -723,6 +732,8 @@ 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 */, @@ -738,7 +749,6 @@ EAB1D2EA28AE84AA00DAE764 /* UIControlPublisher.swift in Sources */, EAF7F13328A2A16500B287F5 /* AttachmentLabelAttributeModel.swift in Sources */, EA0FC2C62914222900DF80B4 /* ButtonGroup.swift in Sources */, - EA985BE429688F3300F2FF2E /* TiletTypographicalStyle.swift in Sources */, EA89200628B526D6006B9984 /* CheckboxGroup.swift in Sources */, EAD8D2C128BFDE8B006EB6A6 /* UIGestureRecognizer+Publisher.swift in Sources */, EAF7F0B9289C139800B287F5 /* ColorConfiguration.swift in Sources */, @@ -759,6 +769,7 @@ 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 */, @@ -778,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/TitleLockup/TitleLockup.swift b/VDS/Components/TitleLockup/TitleLockup.swift index 958d7a81..74865ac3 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,48 +242,56 @@ 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 + 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 + } - titleLabel.textPosition = allLabelsTextPosition - titleLabel.typograpicalStyle = titleTypograpicalStyle.value - titleLabel.text = titleText - titleLabel.attributes = titleTextAttributes - titleLabel.surface = surface + 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 + } + + 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 + } - subTitleLabel.textPosition = allLabelsTextPosition - subTitleLabel.typograpicalStyle = otherTypograpicalStyle.value - subTitleLabel.text = subTitleText - subTitleLabel.attributes = subTitleTextAttributes - subTitleLabel.surface = surface - subTitleLabel.disabled = subTitleColor == .secondary - //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) - } } extension TypographicalStyle { 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 } +}