Merge branch 'refactor/titleLockup' into 'develop'

refactor TextStyles to use StandardStyle for models and rules

See merge request BPHV_MIPS/vds_ios!85
This commit is contained in:
Bruce, Matt R 2023-06-29 20:33:07 +00:00
commit 7464814735
21 changed files with 441 additions and 280 deletions

View File

@ -44,6 +44,7 @@
EA4DB18528CA967F00103EE3 /* SelectorGroupHandlerBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA4DB18428CA967F00103EE3 /* SelectorGroupHandlerBase.swift */; }; EA4DB18528CA967F00103EE3 /* SelectorGroupHandlerBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA4DB18428CA967F00103EE3 /* SelectorGroupHandlerBase.swift */; };
EA4DB2FD28D3D0CA00103EE3 /* AnyEquatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA4DB2FC28D3D0CA00103EE3 /* AnyEquatable.swift */; }; EA4DB2FD28D3D0CA00103EE3 /* AnyEquatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA4DB2FC28D3D0CA00103EE3 /* AnyEquatable.swift */; };
EA4DB30228DCBCA500103EE3 /* Badge.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA4DB30128DCBCA500103EE3 /* Badge.swift */; }; EA4DB30228DCBCA500103EE3 /* Badge.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA4DB30128DCBCA500103EE3 /* Badge.swift */; };
EA513A952A4E1F82002A4DFF /* TitleLockupStyleConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA513A942A4E1F82002A4DFF /* TitleLockupStyleConfiguration.swift */; };
EA596ABD2A16B4EC00300C4B /* Tab.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA596ABC2A16B4EC00300C4B /* Tab.swift */; }; EA596ABD2A16B4EC00300C4B /* Tab.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA596ABC2A16B4EC00300C4B /* Tab.swift */; };
EA596ABF2A16B4F500300C4B /* Tabs.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA596ABE2A16B4F500300C4B /* Tabs.swift */; }; EA596ABF2A16B4F500300C4B /* Tabs.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA596ABE2A16B4F500300C4B /* Tabs.swift */; };
EA5E304C294CBDD00082B959 /* TileContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA5E304B294CBDD00082B959 /* TileContainer.swift */; }; EA5E304C294CBDD00082B959 /* TileContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA5E304B294CBDD00082B959 /* TileContainer.swift */; };
@ -177,6 +178,7 @@
EA4DB18428CA967F00103EE3 /* SelectorGroupHandlerBase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectorGroupHandlerBase.swift; sourceTree = "<group>"; }; EA4DB18428CA967F00103EE3 /* SelectorGroupHandlerBase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectorGroupHandlerBase.swift; sourceTree = "<group>"; };
EA4DB2FC28D3D0CA00103EE3 /* AnyEquatable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnyEquatable.swift; sourceTree = "<group>"; }; EA4DB2FC28D3D0CA00103EE3 /* AnyEquatable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnyEquatable.swift; sourceTree = "<group>"; };
EA4DB30128DCBCA500103EE3 /* Badge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Badge.swift; sourceTree = "<group>"; }; EA4DB30128DCBCA500103EE3 /* Badge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Badge.swift; sourceTree = "<group>"; };
EA513A942A4E1F82002A4DFF /* TitleLockupStyleConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TitleLockupStyleConfiguration.swift; sourceTree = "<group>"; };
EA596ABC2A16B4EC00300C4B /* Tab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tab.swift; sourceTree = "<group>"; }; EA596ABC2A16B4EC00300C4B /* Tab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tab.swift; sourceTree = "<group>"; };
EA596ABE2A16B4F500300C4B /* Tabs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tabs.swift; sourceTree = "<group>"; }; EA596ABE2A16B4F500300C4B /* Tabs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tabs.swift; sourceTree = "<group>"; };
EA5E304B294CBDD00082B959 /* TileContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TileContainer.swift; sourceTree = "<group>"; }; EA5E304B294CBDD00082B959 /* TileContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TileContainer.swift; sourceTree = "<group>"; };
@ -569,6 +571,7 @@
EA985BED2968A92400F2FF2E /* TitleLockupSubTitleModel.swift */, EA985BED2968A92400F2FF2E /* TitleLockupSubTitleModel.swift */,
EA985BEB2968A91200F2FF2E /* TitleLockupTitleModel.swift */, EA985BEB2968A91200F2FF2E /* TitleLockupTitleModel.swift */,
EA985BF12968B5BB00F2FF2E /* TitleLockupTextStyle.swift */, EA985BF12968B5BB00F2FF2E /* TitleLockupTextStyle.swift */,
EA513A942A4E1F82002A4DFF /* TitleLockupStyleConfiguration.swift */,
); );
path = TitleLockup; path = TitleLockup;
sourceTree = "<group>"; sourceTree = "<group>";
@ -795,7 +798,7 @@
attributes = { attributes = {
BuildIndependentTargetsInParallel = 1; BuildIndependentTargetsInParallel = 1;
LastSwiftUpdateCheck = 1340; LastSwiftUpdateCheck = 1340;
LastUpgradeCheck = 1340; LastUpgradeCheck = 1430;
TargetAttributes = { TargetAttributes = {
EA33616B288B19200071C351 = { EA33616B288B19200071C351 = {
CreatedOnToolsVersion = 13.4.1; CreatedOnToolsVersion = 13.4.1;
@ -917,6 +920,7 @@
EAF1FE9929D4850E00101452 /* Clickable.swift in Sources */, EAF1FE9929D4850E00101452 /* Clickable.swift in Sources */,
EAB5FEF829393A7200998C17 /* ButtonGroupConstants.swift in Sources */, EAB5FEF829393A7200998C17 /* ButtonGroupConstants.swift in Sources */,
EA3361AF288B26310071C351 /* FormFieldable.swift in Sources */, EA3361AF288B26310071C351 /* FormFieldable.swift in Sources */,
EA513A952A4E1F82002A4DFF /* TitleLockupStyleConfiguration.swift in Sources */,
44604AD729CE196600E62B51 /* Line.swift in Sources */, 44604AD729CE196600E62B51 /* Line.swift in Sources */,
EA5E3058295105A40082B959 /* Tilelet.swift in Sources */, EA5E3058295105A40082B959 /* Tilelet.swift in Sources */,
EA89201528B56CF4006B9984 /* RadioBoxGroup.swift in Sources */, EA89201528B56CF4006B9984 /* RadioBoxGroup.swift in Sources */,
@ -1105,13 +1109,15 @@
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
BUILD_LIBRARY_FOR_DISTRIBUTION = YES; BUILD_LIBRARY_FOR_DISTRIBUTION = YES;
CODE_SIGN_IDENTITY = "";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 24; CURRENT_PROJECT_VERSION = 25;
DEFINES_MODULE = YES; DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = ""; DEVELOPMENT_TEAM = "";
DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1; DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath"; DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_MODULE_VERIFIER = YES;
FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/../SharedFrameworks"; FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/../SharedFrameworks";
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_NSHumanReadableCopyright = ""; INFOPLIST_KEY_NSHumanReadableCopyright = "";
@ -1123,6 +1129,8 @@
"@loader_path/Frameworks", "@loader_path/Frameworks",
); );
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++";
MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu11 gnu++17";
PRODUCT_BUNDLE_IDENTIFIER = com.vzw.vds; PRODUCT_BUNDLE_IDENTIFIER = com.vzw.vds;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SKIP_INSTALL = YES; SKIP_INSTALL = YES;
@ -1138,13 +1146,15 @@
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
BUILD_LIBRARY_FOR_DISTRIBUTION = YES; BUILD_LIBRARY_FOR_DISTRIBUTION = YES;
CODE_SIGN_IDENTITY = "";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 24; CURRENT_PROJECT_VERSION = 25;
DEFINES_MODULE = YES; DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = ""; DEVELOPMENT_TEAM = "";
DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1; DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath"; DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_MODULE_VERIFIER = YES;
FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/../SharedFrameworks"; FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/../SharedFrameworks";
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_NSHumanReadableCopyright = ""; INFOPLIST_KEY_NSHumanReadableCopyright = "";
@ -1156,6 +1166,8 @@
"@loader_path/Frameworks", "@loader_path/Frameworks",
); );
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++";
MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu11 gnu++17";
PRODUCT_BUNDLE_IDENTIFIER = com.vzw.vds; PRODUCT_BUNDLE_IDENTIFIER = com.vzw.vds;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SKIP_INSTALL = YES; SKIP_INSTALL = YES;

View File

@ -368,7 +368,7 @@ open class BadgeIndicator: View {
let frame = badgeView.frame let frame = badgeView.frame
//default calculation if a dotSize isn't given //default calculation if a dotSize isn't given
var dot: CGFloat = frame.width * 0.1875 var dot: CGFloat = frame.height * 0.1875
if let dotSize, dotSize < frame.width, dotSize < frame.height { if let dotSize, dotSize < frame.width, dotSize < frame.height {
dot = dotSize dot = dotSize
} }

View File

@ -89,14 +89,7 @@ open class TextLinkCaret: ButtonBase {
//-------------------------------------------------- //--------------------------------------------------
override open var intrinsicContentSize: CGSize { override open var intrinsicContentSize: CGSize {
//get the labels size, if not the button //get the labels size, if not the button
let size = titleLabel?.intrinsicContentSize ?? super.intrinsicContentSize return titleLabel?.intrinsicContentSize ?? super.intrinsicContentSize
var itemWidth = size.width
if let caretWidth = imageAttribute?.width {
itemWidth += caretWidth
}
return CGSize(width: itemWidth, height: size.height)
} }
open override func updateView() { open override func updateView() {

View File

@ -21,30 +21,30 @@ extension Icon {
public init(name: String){ public init(name: String){
self.rawValue = name self.rawValue = name
} }
public static let checkmark = Name(name: "checkmark")
internal static let checkmarkBold = Name(name: "checkmark-bold")
public static let checkmarkAlt = Name(name: "checkmark-alt")
internal static let checkmarkAltBold = Name(name: "checkmark-alt-bold") internal static let checkmarkAltBold = Name(name: "checkmark-alt-bold")
public static let close = Name(name: "close") internal static let checkmarkBold = Name(name: "checkmark-bold")
internal static let closeBold = Name(name: "close-bold") internal static let closeBold = Name(name: "close-bold")
public static let error = Name(name: "error")
internal static let errorBold = Name(name: "error-bold") internal static let errorBold = Name(name: "error-bold")
public static let info = Name(name: "info")
internal static let infoBold = Name(name: "info-bold") internal static let infoBold = Name(name: "info-bold")
public static let multipleDocuments = Name(name: "multiple-documents")
public static let leftArrow = Name(name: "left-arrow")
public static let leftCaret = Name(name: "left-caret")
internal static let leftCaretBold = Name(name: "left-caret-bold") internal static let leftCaretBold = Name(name: "left-caret-bold")
internal static let paginationLeftArrow = Name(name: "pagination-left-arrow") internal static let paginationLeftArrow = Name(name: "pagination-left-arrow")
internal static let paginationLeftCaret = Name(name: "pagination-left-caret")
public static let rightArrow = Name(name: "right-arrow")
public static let rightCaret = Name(name: "right-caret")
internal static let rightCaretBold = Name(name: "right-caret-bold") internal static let rightCaretBold = Name(name: "right-caret-bold")
internal static let paginationRightArrow = Name(name: "pagination-right-arrow") internal static let paginationRightArrow = Name(name: "pagination-right-arrow")
internal static let paginationRightCaret = Name(name: "pagination-right-caret")
public static let warning = Name(name: "warning") internal static let verizonUp = Name(name: "verizon-up")
internal static let warningBold = Name(name: "warning-bold") internal static let warningBold = Name(name: "warning-bold")
public static let checkmark = Name(name: "checkmark")
public static let checkmarkAlt = Name(name: "checkmark-alt")
public static let close = Name(name: "close")
public static let error = Name(name: "error")
public static let info = Name(name: "info")
public static let multipleDocuments = Name(name: "multiple-documents")
public static let leftArrow = Name(name: "left-arrow")
public static let leftCaret = Name(name: "left-caret")
public static let rightArrow = Name(name: "right-arrow")
public static let rightCaret = Name(name: "right-caret")
public static let warning = Name(name: "warning")
} }
} }

View File

@ -73,7 +73,7 @@ extension Tabs {
private var leadingSpace: CGFloat { private var leadingSpace: CGFloat {
guard orientation == .vertical else { return 0 } guard orientation == .vertical else { return 0 }
return size == .medium ? VDSLayout.Spacing.space4X.value : VDSLayout.Spacing.space6X.value return VDSLayout.Spacing.space4X.value
} }
private var otherSpace: CGFloat { private var otherSpace: CGFloat {

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], .init(deviceType: .iPad,
neighboring: [.bodySmall, .bodyMedium, .bodyLarge], titleStandardStyles: [.titleSmall, .titleMedium],
spacing: 12.0, spacingConfigurations: [
deviceType: .iPad), .init(otherStandardStyles: [.bodySmall, .bodyMedium, .bodyLarge],
topSpacing: VDSLayout.Spacing.space2X.value,
TextStyle.DeviceSpacingConfig([.boldTitleXLarge, .titleXLarge], bottomSpacing: VDSLayout.Spacing.space2X.value)
neighboring: [.titleMedium, .bodyLarge], ]),
spacing: 12.0,
deviceType: .iPad), .init(deviceType: .iPad,
titleStandardStyles: [.titleLarge],
TextStyle.DeviceSpacingConfig([.boldTitle2XLarge, .title2XLarge, .boldFeatureXSmall, .featureXSmall], spacingConfigurations: [
neighboring: [.titleMedium, .titleLarge], .init(otherStandardStyles: [.bodyLarge, .bodySmall, .bodyMedium, .titleSmall],
spacing: 16.0, topSpacing: VDSLayout.Spacing.space3X.value,
deviceType: .iPad), bottomSpacing: VDSLayout.Spacing.space3X.value)
]),
TextStyle.DeviceSpacingConfig([.boldTitle2XLarge, .title2XLarge, .boldFeatureXSmall, .featureXSmall],
neighboring: [.bodyLarge], .init(deviceType: .iPad,
spacing: 12.0, titleStandardStyles: [.titleXLarge],
deviceType: .iPad), spacingConfigurations: [
.init(otherStandardStyles: [.titleMedium, .bodyLarge],
TextStyle.DeviceSpacingConfig([.boldFeatureSmall, .featureSmall, .boldFeatureMedium, .featureMedium], topSpacing: VDSLayout.Spacing.space3X.value,
neighboring: [.titleMedium, .titleLarge], bottomSpacing: VDSLayout.Spacing.space4X.value)
spacing: 16.0, ]),
deviceType: .iPad),
.init(deviceType: .iPad,
TextStyle.DeviceSpacingConfig([.boldFeatureSmall, .featureSmall, .boldFeatureMedium, .featureMedium], titleStandardStyles: [.title2XLarge, .featureXSmall],
neighboring: [.bodyLarge], spacingConfigurations: [
spacing: 12.0, .init(otherStandardStyles: [.bodyLarge],
deviceType: .iPad), topSpacing: VDSLayout.Spacing.space3X.value,
bottomSpacing: VDSLayout.Spacing.space6X.value),
TextStyle.DeviceSpacingConfig([.boldTitleXLarge, .titleXLarge],
neighboring: [.bodyLarge, .bodyMedium, .bodySmall, .titleMedium], .init(otherStandardStyles: [.titleMedium, .titleLarge],
spacing: 12.0, topSpacing: VDSLayout.Spacing.space4X.value,
deviceType: .iPhone), bottomSpacing: VDSLayout.Spacing.space6X.value),
]),
TextStyle.DeviceSpacingConfig([.boldTitle2XLarge, .title2XLarge, .boldFeatureXSmall, .featureXSmall],
neighboring: [.bodyLarge, .bodyMedium, .titleMedium], .init(deviceType: .iPad,
spacing: 12.0, titleStandardStyles: [.featureSmall, .featureMedium],
deviceType: .iPhone), spacingConfigurations: [
.init(otherStandardStyles: [.titleLarge, .titleMedium],
TextStyle.DeviceSpacingConfig([.boldFeatureSmall, .featureSmall], topSpacing: VDSLayout.Spacing.space4X.value,
neighboring: [.titleLarge, .bodyLarge], bottomSpacing: VDSLayout.Spacing.space6X.value),
spacing: 12.0,
deviceType: .iPhone), .init(otherStandardStyles: [.bodyLarge],
topSpacing: VDSLayout.Spacing.space3X.value,
TextStyle.DeviceSpacingConfig([.boldFeatureMedium, .featureMedium], bottomSpacing: VDSLayout.Spacing.space6X.value),
neighboring: [.titleLarge, .titleXLarge], ]),
spacing: 16.0,
deviceType: .iPhone), .init(deviceType: .iPhone,
titleStandardStyles: [.titleSmall],
TextStyle.DeviceSpacingConfig([.boldFeatureMedium, .featureMedium], spacingConfigurations: [
neighboring: [.bodyLarge], .init(otherStandardStyles: [.bodySmall, .bodyMedium],
spacing: 12.0, topSpacing: VDSLayout.Spacing.space2X.value,
deviceType: .iPhone) bottomSpacing: VDSLayout.Spacing.space2X.value)
] ]),
return TextStyle.SpacingConfig(configs: configs)
}() .init(deviceType: .iPhone,
titleStandardStyles: [.titleMedium, .titleLarge],
open var bottomTextStyleSpacingConfig: TextStyle.SpacingConfig = { spacingConfigurations: [
let configs = [ .init(otherStandardStyles: [.bodySmall, .bodyMedium, .bodyLarge],
TextStyle.DeviceSpacingConfig([.boldTitleLarge, .titleLarge], topSpacing: VDSLayout.Spacing.space2X.value,
neighboring: [.bodySmall, .bodyMedium, .bodyLarge], bottomSpacing: VDSLayout.Spacing.space2X.value)
spacing: 12.0, ]),
deviceType: .iPad),
.init(deviceType: .iPhone,
TextStyle.DeviceSpacingConfig([.boldTitleXLarge, .titleXLarge], titleStandardStyles: [.titleXLarge],
neighboring: [.titleMedium, .bodyLarge], spacingConfigurations: [
spacing: 16.0, .init(otherStandardStyles: [.bodyLarge, .bodySmall, .bodyMedium, .titleMedium],
deviceType: .iPad), topSpacing: VDSLayout.Spacing.space3X.value,
bottomSpacing: VDSLayout.Spacing.space3X.value)
TextStyle.DeviceSpacingConfig([.boldTitle2XLarge, .title2XLarge, .boldFeatureXSmall, .featureXSmall], ]),
neighboring: [.titleMedium, .titleLarge],
spacing: 24.0, .init(deviceType: .iPhone,
deviceType: .iPad), titleStandardStyles: [.title2XLarge, .featureXSmall],
spacingConfigurations: [
TextStyle.DeviceSpacingConfig([.boldTitle2XLarge, .title2XLarge, .boldFeatureXSmall, .featureXSmall], .init(otherStandardStyles: [.bodyLarge, .bodyMedium, .titleMedium],
neighboring: [.bodyLarge], topSpacing: VDSLayout.Spacing.space3X.value,
spacing: 24.0, bottomSpacing: VDSLayout.Spacing.space4X.value)
deviceType: .iPad), ]),
TextStyle.DeviceSpacingConfig([.boldFeatureSmall, .featureSmall, .boldFeatureMedium, .featureMedium], .init(deviceType: .iPhone,
neighboring: [.titleMedium, .titleLarge], titleStandardStyles: [.featureSmall],
spacing: 24.0, spacingConfigurations: [
deviceType: .iPad), .init(otherStandardStyles: [.titleLarge, .bodyLarge],
topSpacing: VDSLayout.Spacing.space3X.value,
TextStyle.DeviceSpacingConfig([.boldFeatureSmall, .featureSmall, .boldFeatureMedium, .featureMedium], bottomSpacing: VDSLayout.Spacing.space4X.value)
neighboring: [.bodyLarge], ]),
spacing: 24.0,
deviceType: .iPad), .init(deviceType: .iPhone,
titleStandardStyles: [.featureMedium],
TextStyle.DeviceSpacingConfig([.boldTitleXLarge, .titleXLarge], spacingConfigurations: [
neighboring: [.bodyLarge, .bodyMedium, .bodySmall, .titleMedium], .init(otherStandardStyles: [.titleLarge, .titleXLarge],
spacing: 12.0, topSpacing: VDSLayout.Spacing.space4X.value,
deviceType: .iPhone), bottomSpacing: VDSLayout.Spacing.space6X.value),
TextStyle.DeviceSpacingConfig([.boldTitle2XLarge, .title2XLarge, .boldFeatureXSmall, .featureXSmall], .init(otherStandardStyles: [.bodyLarge],
neighboring: [.bodyLarge, .bodyMedium, .titleMedium], topSpacing: VDSLayout.Spacing.space3X.value,
spacing: 16, bottomSpacing: VDSLayout.Spacing.space6X.value)
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
//-------------------------------------------------- //--------------------------------------------------
@ -242,11 +227,21 @@ open class TitleLockup: View {
var eyebrowTextIsEmpty = true var eyebrowTextIsEmpty = true
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)
} }
@ -300,5 +294,4 @@ open class TitleLockup: View {
titleLabel.isHidden = titleTextIsEmpty titleLabel.isHidden = titleTextIsEmpty
subTitleLabel.isHidden = subTitleTextIsEmpty subTitleLabel.isHidden = subTitleTextIsEmpty
} }
} }

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

@ -0,0 +1,85 @@
//
// TitleLockupStandardStyleConfiguration.swift
// VDS
//
// Created by Matt Bruce on 6/29/23.
//
import Foundation
import UIKit
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,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 }
} }
} }

View File

@ -79,12 +79,14 @@ open class Toggle: Control, Changeable {
private var toggleColorConfiguration = ControlColorConfiguration().with { private var toggleColorConfiguration = ControlColorConfiguration().with {
$0.setSurfaceColors(VDSColor.elementsSecondaryOnlight, VDSColor.paletteGray44, forState: .normal) $0.setSurfaceColors(VDSColor.elementsSecondaryOnlight, VDSColor.paletteGray44, forState: .normal)
$0.setSurfaceColors(VDSColor.interactiveDisabledOnlight, VDSColor.interactiveDisabledOndark, forState: .disabled) $0.setSurfaceColors(VDSColor.interactiveDisabledOnlight, VDSColor.interactiveDisabledOndark, forState: .disabled)
$0.setSurfaceColors(VDSColor.interactiveDisabledOnlight, VDSColor.interactiveDisabledOndark, forState: [.selected, .disabled])
$0.setSurfaceColors(VDSColor.paletteGreen26, VDSColor.paletteGreen36, forState: .selected) $0.setSurfaceColors(VDSColor.paletteGreen26, VDSColor.paletteGreen36, forState: .selected)
} }
private var knobColorConfiguration = ControlColorConfiguration().with { private var knobColorConfiguration = ControlColorConfiguration().with {
$0.setSurfaceColors(VDSColor.elementsPrimaryOndark, VDSColor.elementsPrimaryOndark, forState: .normal) $0.setSurfaceColors(VDSColor.elementsPrimaryOndark, VDSColor.elementsPrimaryOndark, forState: .normal)
$0.setSurfaceColors(VDSColor.paletteGray95, VDSColor.paletteGray44, forState: .disabled) $0.setSurfaceColors(VDSColor.paletteGray95, VDSColor.paletteGray44, forState: .disabled)
$0.setSurfaceColors(VDSColor.paletteGray95, VDSColor.paletteGray44, forState: [.selected, .disabled])
$0.setSurfaceColors(VDSColor.elementsPrimaryOndark, VDSColor.elementsPrimaryOndark, forState: .selected) $0.setSurfaceColors(VDSColor.elementsPrimaryOndark, VDSColor.elementsPrimaryOndark, forState: .selected)
} }

View File

@ -20,7 +20,8 @@ extension NSAttributedString {
extension NSMutableAttributedString { extension NSMutableAttributedString {
public static func mutableText(for text: String, textStyle: TextStyle, textColor: UIColor, alignment: NSTextAlignment = .left, lineBreakMode: NSLineBreakMode) -> NSMutableAttributedString { public static func mutableText(for text: String, textStyle: TextStyle, textColor: UIColor, alignment: NSTextAlignment = .left, lineBreakMode: NSLineBreakMode) -> NSMutableAttributedString {
let startingAttributes = [NSAttributedString.Key.font: textStyle.font, NSAttributedString.Key.foregroundColor: textColor] let font = textStyle.font
let startingAttributes = [NSAttributedString.Key.font: font, NSAttributedString.Key.foregroundColor: textColor]
let attributedString = NSMutableAttributedString(string: text, attributes: startingAttributes) let attributedString = NSMutableAttributedString(string: text, attributes: startingAttributes)
//get the range //get the range
@ -35,13 +36,22 @@ extension NSMutableAttributedString {
paragraph.alignment = alignment paragraph.alignment = alignment
paragraph.lineBreakMode = lineBreakMode paragraph.lineBreakMode = lineBreakMode
if textStyle.lineSpacing > 0 {
paragraph.lineSpacing = textStyle.lineSpacing
}
//set lineHeight //set lineHeight
if textStyle.lineHeight > 0.0 { if textStyle.lineHeight > 0.0 {
let lineHeight = textStyle.lineHeight let lineHeight = textStyle.lineHeight
paragraph.maximumLineHeight = lineHeight // if textStyle.lineHeight > textStyle.pointSize {
paragraph.minimumLineHeight = lineHeight paragraph.maximumLineHeight = lineHeight
paragraph.minimumLineHeight = lineHeight
// paragraph.lineHeightMultiple = lineHeight / textStyle.pointSize
// } else {
// paragraph.lineHeightMultiple = lineHeight / font.pointSize
// }
} }
attributedString.addAttribute( .baselineOffset, value: textStyle.baselineOffset, range: entireRange)
attributedString.addAttribute( .paragraphStyle, value: paragraph, range: entireRange) attributedString.addAttribute( .paragraphStyle, value: paragraph, range: entireRange)
return attributedString return attributedString

View File

@ -7,6 +7,7 @@
import Foundation import Foundation
import VDSColorTokens import VDSColorTokens
import UIKit
extension VDSColor { extension VDSColor {
public static let paletteYellow62 = UIColor(hexString: "#FED60E") public static let paletteYellow62 = UIColor(hexString: "#FED60E")

View File

@ -0,0 +1,15 @@
{
"images" : [
{
"filename" : "verizon-up.svg",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true
}
}

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 26.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 21.6 21.6" style="enable-background:new 0 0 21.6 21.6;" xml:space="preserve">
<path d="M19.8,19.8h-18v-18h18V19.8z M2.9,18.7h15.7V2.9H2.9V18.7z M12.4,8.1h-1.6v7.2h1.7v-2.6c0.4,0.5,0.9,0.7,1.5,0.7
c1.3-0.1,2.4-1.2,2.3-2.5c0-0.1,0-0.1,0-0.2C16.3,9.2,15.4,8,14,8c-0.6,0-1.2,0.3-1.6,0.8L12.4,8.1z M14.4,11.7
c-0.1,0.3-0.5,0.5-0.8,0.5c-0.8,0-1.2-0.6-1.2-1.4c0-0.8,0.4-1.5,1.1-1.5s1.1,0.6,1.1,1.5C14.6,11.1,14.6,11.4,14.4,11.7 M5.3,11.5
V8.1H7v3c0,0.6,0.3,0.9,0.8,0.9c0.5,0,0.9-0.4,0.9-0.9c0,0,0-0.1,0-0.1V8.1h1.7v5.1H8.8v-0.6l0,0c-0.4,0.5-1,0.8-1.6,0.8
c-1,0.1-1.8-0.6-1.9-1.6C5.3,11.7,5.3,11.6,5.3,11.5L5.3,11.5z"/>
</svg>

After

Width:  |  Height:  |  Size: 898 B

View File

@ -1,6 +1,14 @@
1.0.26
=======
- CXTDT-426626 - Toggle - Disabled "on" state
- CXTDT-427165 - Text Link Caret - Container should not have left/right padding
1.0.25 1.0.25
======= =======
- TEMPORARY: Added BaselineOffset, LineSpacing to TextStyle
- Added Size, Width, Height, Horizontal/Vertical Padding + more to Badge Indicator - Added Size, Width, Height, Horizontal/Vertical Padding + more to Badge Indicator
- CXTDT-424370 - Icons are fuzzy when resized
- CXTDT-426521 - Tabs - Vertical Tablet spacing
1.0.24 1.0.24
======= =======

View File

@ -29,6 +29,8 @@ public struct TextStyle: Equatable, RawRepresentable {
public let lineHeight: CGFloat public let lineHeight: CGFloat
public let letterSpacing: CGFloat public let letterSpacing: CGFloat
public let fontFace: Font public let fontFace: Font
public let lineSpacing: CGFloat
public let baselineOffset: CGFloat
public init?(rawValue: String) { public init?(rawValue: String) {
guard let style = TextStyle.textStyle(for: rawValue) else { return nil } guard let style = TextStyle.textStyle(for: rawValue) else { return nil }
@ -37,14 +39,22 @@ public struct TextStyle: Equatable, RawRepresentable {
self.lineHeight = style.lineHeight self.lineHeight = style.lineHeight
self.letterSpacing = style.letterSpacing self.letterSpacing = style.letterSpacing
self.fontFace = style.fontFace self.fontFace = style.fontFace
self.lineSpacing = style.lineSpacing
self.baselineOffset = style.baselineOffset
} }
public init(rawValue: String, fontFace: Font, pointSize: CGFloat = 0.0, lineHeight: CGFloat = 0.0, letterSpacing: CGFloat = 0.0) { public init(rawValue: String, fontFace: Font, pointSize: CGFloat = 0.0, lineHeight: CGFloat = 0.0, letterSpacing: CGFloat = 0.0, lineSpacing: CGFloat = 0.0, baselineOffset: CGFloat = 0.0) {
self.rawValue = rawValue self.rawValue = rawValue
self.fontFace = fontFace self.fontFace = fontFace
self.pointSize = pointSize self.pointSize = pointSize
self.lineHeight = lineHeight self.lineHeight = lineHeight
self.letterSpacing = letterSpacing self.letterSpacing = letterSpacing
self.lineSpacing = lineSpacing
self.baselineOffset = baselineOffset
}
public var isBold: Bool {
rawValue.hasPrefix("bold")
} }
} }
@ -255,9 +265,43 @@ extension TextStyle {
boldMicro boldMicro
] ]
} }
} }
extension TextStyle {
public enum StandardStyle: String, CaseIterable {
case featureXLarge,
featureLarge,
featureMedium,
featureSmall,
featureXSmall,
title2XLarge,
titleXLarge,
titleLarge,
titleMedium,
titleSmall,
bodyLarge,
bodyMedium,
bodySmall,
micro
public var bold: TextStyle {
return TextStyle(rawValue: "bold\(rawValue.prefix(1).uppercased())\(rawValue.dropFirst())")!
}
public var regular: TextStyle {
TextStyle(rawValue: rawValue)!
}
}
public func toStandardStyle() -> StandardStyle {
var rawName = rawValue
if rawName.hasPrefix("bold") {
let updatedRaw = rawName.replacingOccurrences(of: "bold", with: "")
rawName = updatedRaw.prefix(1).lowercased() + updatedRaw.dropFirst()
}
return StandardStyle(rawValue: rawName)!
}
}
//MARK: FontCategory //MARK: FontCategory
extension TextStyle { extension TextStyle {
@ -344,8 +388,8 @@ extension TextStyle {
} }
} }
extension TextStyle { extension RawRepresentable where Self.RawValue: Equatable {
public func isWithin(_ collection: [TextStyle]) -> Bool { public func isWithin(_ collection: [Self]) -> Bool {
(collection.first(where: {$0 == self}) != nil) (collection.first(where: {$0 == self}) != nil)
} }
} }