refactored out top/bottom spacing config and created new one

updated models to use a StandardStyle
updated Tilelet/TitleLockup to use new features

Signed-off-by: Matt Bruce <matt.bruce@verizon.com>
This commit is contained in:
Matt Bruce 2023-06-29 12:06:28 -05:00
parent 3f6e450739
commit 98968bacbd
8 changed files with 299 additions and 242 deletions

View File

@ -70,65 +70,50 @@ open class Tilelet: TileContainer {
} }
open var titleLockup = TitleLockup().with { open var titleLockup = TitleLockup().with {
let configs = [ $0.standardStyleConfiguration = .init(styleConfigurations: [
TextStyle.DeviceSpacingConfig([.titleSmall, .boldTitleSmall], .init(deviceType: .iPhone,
neighboring: [ titleStandardStyles: [.titleSmall],
.bodySmall, .boldBodySmall, spacingConfigurations: [
.bodyMedium, .boldBodyMedium .init(otherStandardStyles: [.bodySmall, .bodyMedium],
], topSpacing: VDSLayout.Spacing.space2X.value,
spacing: 8.0, bottomSpacing: VDSLayout.Spacing.space2X.value)
deviceType: .iPhone), ]),
.init(deviceType: .iPhone,
TextStyle.DeviceSpacingConfig([.titleMedium, .boldTitleMedium, titleStandardStyles: [.titleMedium, .titleLarge],
.titleLarge, .boldTitleLarge], spacingConfigurations: [
neighboring: [ .init(otherStandardStyles: [.bodySmall, .bodyMedium, .bodyLarge],
.bodySmall, .boldBodySmall, topSpacing: VDSLayout.Spacing.space2X.value,
.bodyMedium, .boldBodyMedium, bottomSpacing: VDSLayout.Spacing.space2X.value)
.bodyLarge, .boldBodyLarge], ]),
spacing: 8.0, .init(deviceType: .iPhone,
deviceType: .iPhone), titleStandardStyles: [.titleXLarge],
spacingConfigurations: [
TextStyle.DeviceSpacingConfig([.titleXLarge, .boldTitleXLarge], .init(otherStandardStyles: [.bodyLarge, .bodySmall, .bodyMedium, .titleMedium],
neighboring: [ topSpacing: VDSLayout.Spacing.space3X.value,
.bodySmall, .boldBodySmall, bottomSpacing: VDSLayout.Spacing.space3X.value)
.bodyMedium, .boldBodyMedium, ]),
.bodyLarge, .boldBodyLarge, .init(deviceType: .iPad,
.titleMedium, .boldTitleMedium titleStandardStyles: [.titleSmall, .titleMedium],
], spacingConfigurations: [
spacing: 12.0, .init(otherStandardStyles: [.bodySmall, .bodyMedium, .bodyLarge],
deviceType: .iPhone), topSpacing: VDSLayout.Spacing.space2X.value,
bottomSpacing: VDSLayout.Spacing.space2X.value)
TextStyle.DeviceSpacingConfig([.titleSmall, .boldTitleSmall, ]),
.titleMedium, .boldTitleMedium], .init(deviceType: .iPad,
neighboring: [ titleStandardStyles: [.titleLarge],
.bodySmall, .boldBodySmall, spacingConfigurations: [
.bodyMedium, .boldBodyMedium, .init(otherStandardStyles: [.bodyLarge, .bodySmall, .bodyMedium, .titleSmall],
.bodyLarge, .boldBodyLarge topSpacing: VDSLayout.Spacing.space3X.value,
], bottomSpacing: VDSLayout.Spacing.space3X.value)
spacing: 8.0, ]),
deviceType: .iPad), .init(deviceType: .iPad,
titleStandardStyles: [.titleXLarge],
TextStyle.DeviceSpacingConfig([.titleLarge, .boldTitleLarge], spacingConfigurations: [
neighboring: [ .init(otherStandardStyles: [.titleMedium, .bodyLarge],
.bodySmall, .boldBodySmall, topSpacing: VDSLayout.Spacing.space3X.value,
.bodyMedium, .boldBodyMedium, bottomSpacing: VDSLayout.Spacing.space4X.value)
.bodyLarge, .boldBodyLarge, ])
.titleSmall, .boldTitleSmall ])
],
spacing: 12.0,
deviceType: .iPad),
TextStyle.DeviceSpacingConfig([.titleXLarge, .boldTitleXLarge],
neighboring: [
.bodyLarge, .boldBodyLarge,
.titleMedium, .boldTitleMedium
],
spacing: 16.0,
deviceType: .iPad)
]
$0.bottomTextStyleSpacingConfig = TextStyle.SpacingConfig(configs: configs)
} }
open var badge = Badge().with { open var badge = Badge().with {
@ -332,10 +317,6 @@ open class Tilelet: TileContainer {
titleLockup.titleModel = titleModel?.toTitleLockupTitleModel() titleLockup.titleModel = titleModel?.toTitleLockupTitleModel()
titleLockup.subTitleModel = subTitleModel?.toTitleLockupSubTitleModel() titleLockup.subTitleModel = subTitleModel?.toTitleLockupSubTitleModel()
if let style = subTitleModel?.textStyle.value {
titleLockup.otherTextStyle = style
}
if titleLockupContainerView.superview == nil { if titleLockupContainerView.superview == nil {
stackView.insertArrangedSubview(titleLockupContainerView, at: badgeContainerView.superview == nil ? 0 : 1) stackView.insertArrangedSubview(titleLockupContainerView, at: badgeContainerView.superview == nil ? 0 : 1)
setNeedsLayout() setNeedsLayout()

View File

@ -12,21 +12,18 @@ extension Tilelet {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Enums // MARK: - Enums
//-------------------------------------------------- //--------------------------------------------------
public enum TextStyle: String, EnumSubset { public enum StandardStyle: String, EnumSubset {
case bodyLarge case bodyLarge
case boldBodyLarge
case bodyMedium case bodyMedium
case boldBodyMedium
case bodySmall case bodySmall
case boldBodySmall
public var defaultValue: TitleLockup.OtherTextStyle { .bodySmall } public var defaultValue: TitleLockup.OtherStandardStyle { .bodySmall }
} }
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Public Properties // MARK: - Public Properties
//-------------------------------------------------- //--------------------------------------------------
public var text: String = "" public var text: String = ""
public var textStyle: TextStyle = .bodySmall public var standardStyle: StandardStyle = .bodySmall
public var textAttributes: [any LabelAttributeModel]? public var textAttributes: [any LabelAttributeModel]?
public var textColor: Use = .primary public var textColor: Use = .primary
@ -36,11 +33,11 @@ extension Tilelet {
public init(text: String, public init(text: String,
textColor: Use = .primary, textColor: Use = .primary,
textAttributes: [any LabelAttributeModel]? = nil, textAttributes: [any LabelAttributeModel]? = nil,
textStyle: TextStyle = .bodySmall) { standardStyle: StandardStyle = .bodySmall) {
self.text = text self.text = text
self.textAttributes = textAttributes self.textAttributes = textAttributes
self.textColor = textColor self.textColor = textColor
self.textStyle = textStyle self.standardStyle = standardStyle
} }
//-------------------------------------------------- //--------------------------------------------------
@ -48,6 +45,7 @@ extension Tilelet {
//-------------------------------------------------- //--------------------------------------------------
public func toTitleLockupSubTitleModel() -> TitleLockup.SubTitleModel { public func toTitleLockupSubTitleModel() -> TitleLockup.SubTitleModel {
TitleLockup.SubTitleModel(text: text, TitleLockup.SubTitleModel(text: text,
standardStyle: standardStyle.value,
textColor: textColor, textColor: textColor,
textAttributes: textAttributes) textAttributes: textAttributes)
} }

View File

@ -12,44 +12,39 @@ extension Tilelet {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Enums // MARK: - Enums
//-------------------------------------------------- //--------------------------------------------------
public enum TextStyle: String, EnumSubset { public enum StandardStyle: String, EnumSubset {
case titleXLarge case titleXLarge
case boldTitleXLarge
case titleLarge case titleLarge
case boldTitleLarge
case titleMedium case titleMedium
case boldTitleMedium
case titleSmall case titleSmall
case boldTitleSmall
public var defaultValue: TitleLockup.TitleTextStyle { .boldTitleSmall } public var defaultValue: TitleLockup.TitleStandardStyle { .titleSmall }
} }
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Public Properties // MARK: - Public Properties
//-------------------------------------------------- //--------------------------------------------------
public var text: String = "" public var text: String = ""
public var textAttributes: [any LabelAttributeModel]? public var textAttributes: [any LabelAttributeModel]?
public var textStyle: TextStyle = .boldTitleSmall public var standardStyle: StandardStyle = .titleSmall
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Initializers // MARK: - Initializers
//-------------------------------------------------- //--------------------------------------------------
public init(text: String, public init(text: String,
textAttributes: [any LabelAttributeModel]? = nil, textAttributes: [any LabelAttributeModel]? = nil,
textStyle: TextStyle = .boldTitleSmall) { standardStyle: StandardStyle = .titleSmall) {
self.text = text self.text = text
self.textAttributes = textAttributes self.textAttributes = textAttributes
self.textStyle = textStyle self.standardStyle = standardStyle
} }
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Public Functions // MARK: - Public Functions
//-------------------------------------------------- //--------------------------------------------------
public func toTitleLockupTitleModel() -> TitleLockup.TitleModel { public func toTitleLockupTitleModel() -> TitleLockup.TitleModel {
TitleLockup.TitleModel(text: text, TitleLockup.TitleModel(text: text,
textAttributes: textAttributes, textAttributes: textAttributes,
textStyle: textStyle.value) standardStyle: standardStyle.value)
} }
} }
} }

View File

@ -50,138 +50,114 @@ open class TitleLockup: View {
// MARK: - Configuration Properties // MARK: - Configuration Properties
//-------------------------------------------------- //--------------------------------------------------
// Sizes are from InVision design specs. // Sizes are from InVision design specs.
open var topTextStyleSpacingConfig: TextStyle.SpacingConfig = { open var standardStyleConfiguration: StandardStyleConfigurationProvider = StandardStyleConfigurationProvider(styleConfigurations: [
let configs = [
TextStyle.DeviceSpacingConfig([.boldTitleLarge, .titleLarge],
neighboring: [.bodySmall, .bodyMedium, .bodyLarge],
spacing: 12.0,
deviceType: .iPad),
TextStyle.DeviceSpacingConfig([.boldTitleXLarge, .titleXLarge], .init(deviceType: .iPad,
neighboring: [.titleMedium, .bodyLarge], titleStandardStyles: [.titleSmall, .titleMedium],
spacing: 12.0, spacingConfigurations: [
deviceType: .iPad), .init(otherStandardStyles: [.bodySmall, .bodyMedium, .bodyLarge],
topSpacing: VDSLayout.Spacing.space2X.value,
bottomSpacing: VDSLayout.Spacing.space2X.value)
]),
TextStyle.DeviceSpacingConfig([.boldTitle2XLarge, .title2XLarge, .boldFeatureXSmall, .featureXSmall], .init(deviceType: .iPad,
neighboring: [.titleMedium, .titleLarge], titleStandardStyles: [.titleLarge],
spacing: 16.0, spacingConfigurations: [
deviceType: .iPad), .init(otherStandardStyles: [.bodyLarge, .bodySmall, .bodyMedium, .titleSmall],
topSpacing: VDSLayout.Spacing.space3X.value,
bottomSpacing: VDSLayout.Spacing.space3X.value)
]),
TextStyle.DeviceSpacingConfig([.boldTitle2XLarge, .title2XLarge, .boldFeatureXSmall, .featureXSmall], .init(deviceType: .iPad,
neighboring: [.bodyLarge], titleStandardStyles: [.titleXLarge],
spacing: 12.0, spacingConfigurations: [
deviceType: .iPad), .init(otherStandardStyles: [.titleMedium, .bodyLarge],
topSpacing: VDSLayout.Spacing.space3X.value,
bottomSpacing: VDSLayout.Spacing.space4X.value)
]),
TextStyle.DeviceSpacingConfig([.boldFeatureSmall, .featureSmall, .boldFeatureMedium, .featureMedium], .init(deviceType: .iPad,
neighboring: [.titleMedium, .titleLarge], titleStandardStyles: [.title2XLarge, .featureXSmall],
spacing: 16.0, spacingConfigurations: [
deviceType: .iPad), .init(otherStandardStyles: [.bodyLarge],
topSpacing: VDSLayout.Spacing.space3X.value,
bottomSpacing: VDSLayout.Spacing.space6X.value),
TextStyle.DeviceSpacingConfig([.boldFeatureSmall, .featureSmall, .boldFeatureMedium, .featureMedium], .init(otherStandardStyles: [.titleMedium, .titleLarge],
neighboring: [.bodyLarge], topSpacing: VDSLayout.Spacing.space4X.value,
spacing: 12.0, bottomSpacing: VDSLayout.Spacing.space6X.value),
deviceType: .iPad), ]),
TextStyle.DeviceSpacingConfig([.boldTitleXLarge, .titleXLarge], .init(deviceType: .iPad,
neighboring: [.bodyLarge, .bodyMedium, .bodySmall, .titleMedium], titleStandardStyles: [.featureSmall, .featureMedium],
spacing: 12.0, spacingConfigurations: [
deviceType: .iPhone), .init(otherStandardStyles: [.titleLarge, .titleMedium],
topSpacing: VDSLayout.Spacing.space4X.value,
bottomSpacing: VDSLayout.Spacing.space6X.value),
TextStyle.DeviceSpacingConfig([.boldTitle2XLarge, .title2XLarge, .boldFeatureXSmall, .featureXSmall], .init(otherStandardStyles: [.bodyLarge],
neighboring: [.bodyLarge, .bodyMedium, .titleMedium], topSpacing: VDSLayout.Spacing.space3X.value,
spacing: 12.0, bottomSpacing: VDSLayout.Spacing.space6X.value),
deviceType: .iPhone), ]),
TextStyle.DeviceSpacingConfig([.boldFeatureSmall, .featureSmall], .init(deviceType: .iPhone,
neighboring: [.titleLarge, .bodyLarge], titleStandardStyles: [.titleSmall],
spacing: 12.0, spacingConfigurations: [
deviceType: .iPhone), .init(otherStandardStyles: [.bodySmall, .bodyMedium],
topSpacing: VDSLayout.Spacing.space2X.value,
bottomSpacing: VDSLayout.Spacing.space2X.value)
]),
TextStyle.DeviceSpacingConfig([.boldFeatureMedium, .featureMedium], .init(deviceType: .iPhone,
neighboring: [.titleLarge, .titleXLarge], titleStandardStyles: [.titleMedium, .titleLarge],
spacing: 16.0, spacingConfigurations: [
deviceType: .iPhone), .init(otherStandardStyles: [.bodySmall, .bodyMedium, .bodyLarge],
topSpacing: VDSLayout.Spacing.space2X.value,
bottomSpacing: VDSLayout.Spacing.space2X.value)
]),
TextStyle.DeviceSpacingConfig([.boldFeatureMedium, .featureMedium], .init(deviceType: .iPhone,
neighboring: [.bodyLarge], titleStandardStyles: [.titleXLarge],
spacing: 12.0, spacingConfigurations: [
deviceType: .iPhone) .init(otherStandardStyles: [.bodyLarge, .bodySmall, .bodyMedium, .titleMedium],
] topSpacing: VDSLayout.Spacing.space3X.value,
return TextStyle.SpacingConfig(configs: configs) bottomSpacing: VDSLayout.Spacing.space3X.value)
}() ]),
open var bottomTextStyleSpacingConfig: TextStyle.SpacingConfig = { .init(deviceType: .iPhone,
let configs = [ titleStandardStyles: [.title2XLarge, .featureXSmall],
TextStyle.DeviceSpacingConfig([.boldTitleLarge, .titleLarge], spacingConfigurations: [
neighboring: [.bodySmall, .bodyMedium, .bodyLarge], .init(otherStandardStyles: [.bodyLarge, .bodyMedium, .titleMedium],
spacing: 12.0, topSpacing: VDSLayout.Spacing.space3X.value,
deviceType: .iPad), bottomSpacing: VDSLayout.Spacing.space4X.value)
]),
TextStyle.DeviceSpacingConfig([.boldTitleXLarge, .titleXLarge], .init(deviceType: .iPhone,
neighboring: [.titleMedium, .bodyLarge], titleStandardStyles: [.featureSmall],
spacing: 16.0, spacingConfigurations: [
deviceType: .iPad), .init(otherStandardStyles: [.titleLarge, .bodyLarge],
topSpacing: VDSLayout.Spacing.space3X.value,
bottomSpacing: VDSLayout.Spacing.space4X.value)
]),
TextStyle.DeviceSpacingConfig([.boldTitle2XLarge, .title2XLarge, .boldFeatureXSmall, .featureXSmall], .init(deviceType: .iPhone,
neighboring: [.titleMedium, .titleLarge], titleStandardStyles: [.featureMedium],
spacing: 24.0, spacingConfigurations: [
deviceType: .iPad), .init(otherStandardStyles: [.titleLarge, .titleXLarge],
topSpacing: VDSLayout.Spacing.space4X.value,
bottomSpacing: VDSLayout.Spacing.space6X.value),
TextStyle.DeviceSpacingConfig([.boldTitle2XLarge, .title2XLarge, .boldFeatureXSmall, .featureXSmall], .init(otherStandardStyles: [.bodyLarge],
neighboring: [.bodyLarge], topSpacing: VDSLayout.Spacing.space3X.value,
spacing: 24.0, bottomSpacing: VDSLayout.Spacing.space6X.value)
deviceType: .iPad), ]),
])
TextStyle.DeviceSpacingConfig([.boldFeatureSmall, .featureSmall, .boldFeatureMedium, .featureMedium],
neighboring: [.titleMedium, .titleLarge],
spacing: 24.0,
deviceType: .iPad),
TextStyle.DeviceSpacingConfig([.boldFeatureSmall, .featureSmall, .boldFeatureMedium, .featureMedium],
neighboring: [.bodyLarge],
spacing: 24.0,
deviceType: .iPad),
TextStyle.DeviceSpacingConfig([.boldTitleXLarge, .titleXLarge],
neighboring: [.bodyLarge, .bodyMedium, .bodySmall, .titleMedium],
spacing: 12.0,
deviceType: .iPhone),
TextStyle.DeviceSpacingConfig([.boldTitle2XLarge, .title2XLarge, .boldFeatureXSmall, .featureXSmall],
neighboring: [.bodyLarge, .bodyMedium, .titleMedium],
spacing: 16,
deviceType: .iPhone),
TextStyle.DeviceSpacingConfig([.boldFeatureSmall, .featureSmall],
neighboring: [.titleLarge, .bodyLarge],
spacing: 16.0,
deviceType: .iPhone),
TextStyle.DeviceSpacingConfig([.boldFeatureMedium, .featureMedium],
neighboring: [.titleLarge, .titleXLarge],
spacing: 24.0,
deviceType: .iPhone),
TextStyle.DeviceSpacingConfig([.boldFeatureMedium, .featureMedium],
neighboring: [.bodyLarge],
spacing: 24.0,
deviceType: .iPhone)
]
return TextStyle.SpacingConfig(configs: configs)
}()
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Public Properties // MARK: - Public Properties
//-------------------------------------------------- //--------------------------------------------------
open var textPosition: TextPosition = .left { didSet { setNeedsUpdate() }} open var textPosition: TextPosition = .left { didSet { setNeedsUpdate() }}
//style
open var otherTextStyle: OtherTextStyle = UIDevice.isIPad ? .bodyLarge : .bodyMedium {
didSet {
setNeedsUpdate()
}
}
//first row //first row
open var eyebrowLabel = Label().with { open var eyebrowLabel = Label().with {
$0.setContentCompressionResistancePriority(.required, for: .vertical) $0.setContentCompressionResistancePriority(.required, for: .vertical)
@ -227,11 +203,20 @@ open class TitleLockup: View {
eyebrowModel = nil eyebrowModel = nil
titleModel = nil titleModel = nil
subTitleModel = nil subTitleModel = nil
otherTextStyle = UIDevice.isIPad ? .bodyLarge : .bodyMedium
shouldUpdateView = true shouldUpdateView = true
setNeedsUpdate() setNeedsUpdate()
} }
private var otherStandardStyle: OtherStandardStyle {
if let subTitleModel, !subTitleModel.text.isEmpty {
return subTitleModel.standardStyle
} else if let eyebrowModel, !eyebrowModel.text.isEmpty {
return eyebrowModel.standardStyle
} else {
return .bodyLarge
}
}
//-------------------------------------------------- //--------------------------------------------------
// MARK: - State // MARK: - State
//-------------------------------------------------- //--------------------------------------------------
@ -243,10 +228,20 @@ open class TitleLockup: View {
var titleTextIsEmpty = true var titleTextIsEmpty = true
var subTitleTextIsEmpty = true var subTitleTextIsEmpty = true
var topSpacing: CGFloat = 0.0
var bottomSpacing: CGFloat = 0.0
//get the spacing based on the title style and other style used for eyebrow and subtitle
if let titleModel,
let config = standardStyleConfiguration.spacing(for: titleModel.standardStyle, otherStandardStyle: otherStandardStyle) {
topSpacing = config.topSpacing
bottomSpacing = config.bottomSpacing
}
if let eyebrowModel, !eyebrowModel.text.isEmpty { if let eyebrowModel, !eyebrowModel.text.isEmpty {
eyebrowTextIsEmpty = false eyebrowTextIsEmpty = false
eyebrowLabel.textPosition = allLabelsTextPosition eyebrowLabel.textPosition = allLabelsTextPosition
eyebrowLabel.textStyle = otherTextStyle.value eyebrowLabel.textStyle = eyebrowModel.isBold ? otherStandardStyle.value.bold : otherStandardStyle.value.regular
eyebrowLabel.text = eyebrowModel.text eyebrowLabel.text = eyebrowModel.text
eyebrowLabel.attributes = eyebrowModel.textAttributes eyebrowLabel.attributes = eyebrowModel.textAttributes
eyebrowLabel.numberOfLines = eyebrowModel.numberOfLines eyebrowLabel.numberOfLines = eyebrowModel.numberOfLines
@ -258,7 +253,7 @@ open class TitleLockup: View {
if let titleModel, !titleModel.text.isEmpty { if let titleModel, !titleModel.text.isEmpty {
titleTextIsEmpty = false titleTextIsEmpty = false
titleLabel.textPosition = allLabelsTextPosition titleLabel.textPosition = allLabelsTextPosition
titleLabel.textStyle = titleModel.textStyle.value titleLabel.textStyle = titleModel.textStyle
titleLabel.text = titleModel.text titleLabel.text = titleModel.text
titleLabel.attributes = titleModel.textAttributes titleLabel.attributes = titleModel.textAttributes
titleLabel.numberOfLines = titleModel.numberOfLines titleLabel.numberOfLines = titleModel.numberOfLines
@ -270,7 +265,7 @@ open class TitleLockup: View {
if let subTitleModel, !subTitleModel.text.isEmpty { if let subTitleModel, !subTitleModel.text.isEmpty {
subTitleTextIsEmpty = false subTitleTextIsEmpty = false
subTitleLabel.textPosition = allLabelsTextPosition subTitleLabel.textPosition = allLabelsTextPosition
subTitleLabel.textStyle = otherTextStyle.value subTitleLabel.textStyle = otherStandardStyle.value.regular
subTitleLabel.text = subTitleModel.text subTitleLabel.text = subTitleModel.text
subTitleLabel.attributes = subTitleModel.textAttributes subTitleLabel.attributes = subTitleModel.textAttributes
subTitleLabel.numberOfLines = subTitleModel.numberOfLines subTitleLabel.numberOfLines = subTitleModel.numberOfLines
@ -281,16 +276,15 @@ open class TitleLockup: View {
} }
//if both first 2 rows not empty set spacing //if both first 2 rows not empty set spacing
if let eyebrowModel, let titleModel, !eyebrowModel.text.isEmpty, !titleModel.text.isEmpty { if !eyebrowTextIsEmpty && !titleTextIsEmpty {
stackView.spacing = topTextStyleSpacingConfig.spacing(for: titleModel.textStyle.value, neighboring: otherTextStyle.value) stackView.spacing = topSpacing
} else { } else {
stackView.spacing = 0.0 stackView.spacing = 0.0
} }
//if either first 2 rows not empty and subtile not empty, create space else collapse //if either first 2 rows not empty and subtile not empty, create space else collapse
if let titleModel, (!eyebrowTextIsEmpty || !titleTextIsEmpty) && !subTitleTextIsEmpty { if (!eyebrowTextIsEmpty || !titleTextIsEmpty) && !subTitleTextIsEmpty {
let bottomSpace = bottomTextStyleSpacingConfig.spacing(for: titleModel.textStyle.value, neighboring: otherTextStyle.value) stackView.setCustomSpacing(bottomSpacing, after: titleLabel)
stackView.setCustomSpacing(bottomSpace, after: titleLabel)
} else if (!eyebrowTextIsEmpty || !titleTextIsEmpty) && subTitleTextIsEmpty { } else if (!eyebrowTextIsEmpty || !titleTextIsEmpty) && subTitleTextIsEmpty {
stackView.setCustomSpacing(0.0, after: titleLabel) stackView.setCustomSpacing(0.0, after: titleLabel)
} }
@ -302,3 +296,78 @@ open class TitleLockup: View {
} }
} }
extension TitleLockup {
public struct StandardStyleConfigurationProvider {
public var styleConfigurations: [StandardStyleConfiguration]
public init(styleConfigurations: [StandardStyleConfiguration]) {
self.styleConfigurations = styleConfigurations
}
public func configuration(for titleStandardStyle: TitleStandardStyle) -> StandardStyleConfiguration? {
let deviceType: StandardStyleConfiguration.DeviceType = UIDevice.isIPad ? .iPad : .iPhone
guard let config: StandardStyleConfiguration = styleConfigurations.first(where: { return titleStandardStyle.isWithin($0.titleStandardStyles) && ($0.deviceType == deviceType || $0.deviceType == .all )}) else { return nil }
return config
}
public func isValid(otherStandardStyle: OtherStandardStyle, for titleStandardStyle: TitleStandardStyle) -> Bool {
guard let config = configuration(for: titleStandardStyle) else { return false }
return otherStandardStyle.isWithin(config.spacingConfigurations.flatMap {$0.otherStandardStyles})
}
public func spacing(for titleStandardStyle: TitleStandardStyle, otherStandardStyle: OtherStandardStyle) -> (otherStandardStyle: OtherStandardStyle, topSpacing: CGFloat, bottomSpacing: CGFloat)? {
guard let config = configuration(for: titleStandardStyle) else { return nil }
return config.styleSpacing(for: otherStandardStyle)
}
}
public struct StandardStyleConfiguration {
public enum DeviceType {
case iPhone, iPad, all
}
public var deviceType: DeviceType
public var titleStandardStyles:[TitleStandardStyle]
public var spacingConfigurations: [SpacingConfiguration]
public init(deviceType: DeviceType, titleStandardStyles: [TitleStandardStyle], spacingConfigurations: [SpacingConfiguration]) {
self.deviceType = deviceType
self.titleStandardStyles = titleStandardStyles
self.spacingConfigurations = spacingConfigurations
}
public var allOtherStandardStyles: [OtherStandardStyle] {
spacingConfigurations.flatMap {$0.otherStandardStyles}
}
public func styleSpacing(for otherStandardStyle: OtherStandardStyle) -> (otherStandardStyle: OtherStandardStyle, topSpacing: CGFloat, bottomSpacing: CGFloat) {
//set default return other style what you pass in
var realOtherStyle = otherStandardStyle
//flatten all of the other styles registered for the title styles
let allOtherStyles = spacingConfigurations.flatMap {$0.otherStandardStyles}
//get the default other style incase what is passed isn't within the registered collection
if let first = allOtherStyles.first, !realOtherStyle.isWithin(allOtherStyles) {
realOtherStyle = first
}
//get the config against the other style or return defaults
guard let styleSpacing = spacingConfigurations.first(where: {realOtherStyle.isWithin($0.otherStandardStyles)}) else {
return (realOtherStyle, VDSLayout.Spacing.space2X.value, VDSLayout.Spacing.space2X.value)
}
return (realOtherStyle, styleSpacing.topSpacing, styleSpacing.bottomSpacing)
}
}
public struct SpacingConfiguration {
public var otherStandardStyles: [OtherStandardStyle]
public var topSpacing: CGFloat
public var bottomSpacing: CGFloat
public init(otherStandardStyles: [OtherStandardStyle], topSpacing: CGFloat, bottomSpacing: CGFloat) {
self.otherStandardStyles = otherStandardStyles
self.topSpacing = topSpacing
self.bottomSpacing = bottomSpacing
}
}
}

View File

@ -10,15 +10,23 @@ import Foundation
extension TitleLockup { extension TitleLockup {
public struct EyebrowModel { public struct EyebrowModel {
public var text: String public var text: String
public var isBold: Bool
public var textAttributes: [any LabelAttributeModel]? public var textAttributes: [any LabelAttributeModel]?
public var standardStyle: OtherStandardStyle
public var numberOfLines: Int public var numberOfLines: Int
public init(text: String, public init(text: String,
isBold: Bool = false,
standardStyle: OtherStandardStyle = .bodyLarge,
textAttributes: [any LabelAttributeModel]? = nil, textAttributes: [any LabelAttributeModel]? = nil,
numberOfLines: Int = 0) { numberOfLines: Int = 0) {
self.text = text self.text = text
self.isBold = isBold
self.standardStyle = standardStyle
self.textAttributes = textAttributes self.textAttributes = textAttributes
self.numberOfLines = numberOfLines self.numberOfLines = numberOfLines
} }
public var textStyle: TextStyle { isBold ? standardStyle.value.bold : standardStyle.value.regular }
} }
} }

View File

@ -10,18 +10,25 @@ import Foundation
extension TitleLockup { extension TitleLockup {
public struct SubTitleModel { public struct SubTitleModel {
public var text: String public var text: String
public var standardStyle: OtherStandardStyle
public var textColor: Use public var textColor: Use
public var textAttributes: [any LabelAttributeModel]? public var textAttributes: [any LabelAttributeModel]?
public var numberOfLines: Int public var numberOfLines: Int
public init(text: String, public init(text: String,
standardStyle: OtherStandardStyle = .bodyLarge,
textColor: Use = .primary, textColor: Use = .primary,
textAttributes: [any LabelAttributeModel]? = nil, textAttributes: [any LabelAttributeModel]? = nil,
numberOfLines: Int = 0) { numberOfLines: Int = 0) {
self.text = text self.text = text
self.standardStyle = standardStyle
self.textColor = textColor self.textColor = textColor
self.textAttributes = textAttributes self.textAttributes = textAttributes
self.numberOfLines = numberOfLines self.numberOfLines = numberOfLines
} }
public var textStyle: TextStyle { standardStyle.value.regular }
} }
} }

View File

@ -11,46 +11,39 @@ extension TitleLockup {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Enums // MARK: - Enums
//-------------------------------------------------- //--------------------------------------------------
public enum TitleTextStyle: String, CaseIterable { public enum TitleStandardStyle: String, CaseIterable {
case featureMedium case featureMedium
case boldFeatureMedium
case featureSmall case featureSmall
case boldFeatureSmall
case featureXSmall case featureXSmall
case boldFeatureXSmall
case title2XLarge case title2XLarge
case boldTitle2XLarge
case titleXLarge case titleXLarge
case boldTitleXLarge
case titleLarge case titleLarge
case boldTitleLarge
case titleMedium case titleMedium
case boldTitleMedium
case titleSmall case titleSmall
case boldTitleSmall
public var defaultValue: TextStyle {.boldFeatureXSmall } public var defaultValue: TextStyle.StandardStyle {.featureXSmall }
public var value: TextStyle { public var value: TextStyle.StandardStyle {
TextStyle.textStyle(for: self.rawValue) ?? defaultValue TextStyle.StandardStyle(rawValue: self.rawValue) ?? defaultValue
} }
} }
public enum OtherTextStyle: String, CaseIterable { public enum OtherStandardStyle: String, CaseIterable {
case bodyLarge
case boldBodyLarge
case bodyMedium
case boldBodyMedium
case bodySmall case bodySmall
case boldBodySmall case bodyMedium
case bodyLarge
case titleSmall
case titleMedium
case titleLarge
case titleXLarge
public var defaultValue: TextStyle {.bodyLarge } public var defaultValue: TextStyle.StandardStyle { .bodyLarge }
public var value: TextStyle { public var value: TextStyle.StandardStyle {
TextStyle.textStyle(for: self.rawValue) ?? defaultValue TextStyle.StandardStyle(rawValue: self.rawValue) ?? defaultValue
} }
} }
} }

View File

@ -11,17 +11,23 @@ extension TitleLockup {
public struct TitleModel { public struct TitleModel {
public var text: String public var text: String
public var textAttributes: [any LabelAttributeModel]? public var textAttributes: [any LabelAttributeModel]?
public var textStyle: TitleTextStyle public var isBold: Bool
public var standardStyle: TitleStandardStyle
public var numberOfLines: Int public var numberOfLines: Int
public init(text: String, public init(text: String,
textAttributes: [any LabelAttributeModel]? = nil, textAttributes: [any LabelAttributeModel]? = nil,
textStyle: TitleTextStyle = .boldFeatureXSmall, isBold: Bool = true,
standardStyle: TitleStandardStyle = .featureXSmall,
numberOfLines: Int = 0) { numberOfLines: Int = 0) {
self.text = text self.text = text
self.isBold = isBold
self.textAttributes = textAttributes self.textAttributes = textAttributes
self.textStyle = textStyle self.standardStyle = standardStyle
self.numberOfLines = numberOfLines self.numberOfLines = numberOfLines
} }
public var textStyle: TextStyle { isBold ? standardStyle.value.bold : standardStyle.value.regular }
} }
} }