From def2e8ae7c2d3c822cfa9eab1440bacae4eff941 Mon Sep 17 00:00:00 2001 From: Sumanth Nadigadda Date: Sat, 9 Apr 2022 02:37:31 +0530 Subject: [PATCH 1/4] Adding new component - title lockup --- MVMCoreUI.xcodeproj/project.pbxproj | 8 + .../EyebrowHeadlineBody.swift | 159 +++++++++++++++++ .../EyebrowHeadlineBodyModel.swift | 167 ++++++++++++++++++ .../OtherHandlers/CoreUIModelMapping.swift | 1 + 4 files changed, 335 insertions(+) create mode 100644 MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBody.swift create mode 100644 MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyModel.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 1c042443..407051bd 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -146,6 +146,8 @@ 32F8804624765C6E00C2ACB3 /* ListLeftVariableNumberedListAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32F8804524765C6E00C2ACB3 /* ListLeftVariableNumberedListAllTextAndLinksModel.swift */; }; 32F8804824765C8400C2ACB3 /* ListLeftVariableNumberedListAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32F8804724765C8400C2ACB3 /* ListLeftVariableNumberedListAllTextAndLinks.swift */; }; 4457904E27ECE989002B1E1E /* UIImageRenderingMode+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4457904D27ECE989002B1E1E /* UIImageRenderingMode+Extension.swift */; }; + 4461F77A2800AB2D00BA0222 /* EyebrowHeadlineBodyModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4461F7792800AB2D00BA0222 /* EyebrowHeadlineBodyModel.swift */; }; + 4461F77C2800AB6C00BA0222 /* EyebrowHeadlineBody.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4461F77B2800AB6C00BA0222 /* EyebrowHeadlineBody.swift */; }; 522679C123FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 522679BF23FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinks.swift */; }; 522679C223FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 522679C023FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinksModel.swift */; }; 52267A0723FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52267A0623FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift */; }; @@ -734,6 +736,8 @@ 32F8804524765C6E00C2ACB3 /* ListLeftVariableNumberedListAllTextAndLinksModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableNumberedListAllTextAndLinksModel.swift; sourceTree = ""; }; 32F8804724765C8400C2ACB3 /* ListLeftVariableNumberedListAllTextAndLinks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableNumberedListAllTextAndLinks.swift; sourceTree = ""; }; 4457904D27ECE989002B1E1E /* UIImageRenderingMode+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImageRenderingMode+Extension.swift"; sourceTree = ""; }; + 4461F7792800AB2D00BA0222 /* EyebrowHeadlineBodyModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EyebrowHeadlineBodyModel.swift; sourceTree = ""; }; + 4461F77B2800AB6C00BA0222 /* EyebrowHeadlineBody.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EyebrowHeadlineBody.swift; sourceTree = ""; }; 522679BF23FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinks.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListLeftVariableCheckboxAllTextAndLinks.swift; sourceTree = ""; }; 522679C023FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinksModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListLeftVariableCheckboxAllTextAndLinksModel.swift; sourceTree = ""; }; 52267A0623FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListOneColumnFullWidthTextAllTextAndLinks.swift; sourceTree = ""; }; @@ -1637,6 +1641,8 @@ EA5124FC243601600051A3A4 /* BGImageHeadlineBodyButton.swift */, 0A775F2524893916009EFB58 /* ThreeHeadlineBodyLink.swift */, 0A775F2724893937009EFB58 /* ThreeHeadlineBodyLinkModel.swift */, + 4461F7792800AB2D00BA0222 /* EyebrowHeadlineBodyModel.swift */, + 4461F77B2800AB6C00BA0222 /* EyebrowHeadlineBody.swift */, ); path = VerticalCombinationViews; sourceTree = ""; @@ -2731,6 +2737,7 @@ D260106323D0C05000764D80 /* StackItemModel.swift in Sources */, D2E2A99823D8D63C000B42E6 /* ActionDetailWithImageModel.swift in Sources */, D28764AC245898A400CB882D /* ThreeLayerFillMiddleTemplateModel.swift in Sources */, + 4461F77A2800AB2D00BA0222 /* EyebrowHeadlineBodyModel.swift in Sources */, BBBBC87D24374A4900B0F079 /* ListThreeColumnBillChangesDividerModel.swift in Sources */, D2ED2800254B0E0300A1C293 /* MVMCoreAlertHandler+Extension.swift in Sources */, D2ED27EE254B0CE700A1C293 /* ActionAlertModel.swift in Sources */, @@ -2923,6 +2930,7 @@ 32F8804624765C6E00C2ACB3 /* ListLeftVariableNumberedListAllTextAndLinksModel.swift in Sources */, 011D958524042432000E3791 /* RulesProtocol.swift in Sources */, 4457904E27ECE989002B1E1E /* UIImageRenderingMode+Extension.swift in Sources */, + 4461F77C2800AB6C00BA0222 /* EyebrowHeadlineBody.swift in Sources */, D23118B325124E18001C8440 /* Notification.swift in Sources */, AA9972502475309F00FC7472 /* ListLeftVariableIconAllTextLinksModel.swift in Sources */, AA69AAF62445BF5700AF3D3B /* ListLeftVariableCheckboxBodyText.swift in Sources */, diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBody.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBody.swift new file mode 100644 index 00000000..7e9c5dc0 --- /dev/null +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBody.swift @@ -0,0 +1,159 @@ +// +// EyebrowHeadlineBody.swift +// MVMCoreUI +// +// Created by Nadigadda, Sumanth on 08/04/22. +// Copyright © 2022 Verizon Wireless. All rights reserved. +// + +@objcMembers open class EyebrowHeadlineBody: View { + //-------------------------------------------------- + // MARK: - Outlets + //-------------------------------------------------- + + public let stack = Stack(frame: .zero) + public let eyebrow = Label(fontStyle: .RegularBodySmall) + public let headline = Label(fontStyle: .RegularBodySmall) + public let body = Label(fontStyle: .RegularBodySmall) + + var castModel: EyebrowHeadlineBodyModel? { + get { return model as? EyebrowHeadlineBodyModel } + } + + //-------------------------------------------------- + // MARK: - Initialization + //-------------------------------------------------- + + public convenience init(spacing: CGFloat) { + self.init(frame: .zero) + stack.stackModel?.spacing = spacing + stack.restack() + } + + //-------------------------------------------------- + // MARK: - MFViewProtocol + //-------------------------------------------------- + + open override func setupView() { + super.setupView() + stack.setAndCreateModel(with: [eyebrow, headline, body]) + stack.stackModel?.spacing = 0 + addSubview(stack) + NSLayoutConstraint.constraintPinSubview(toSuperview: stack) + stack.restack() + } + + open override func updateView(_ size: CGFloat) { + super.updateView(size) + stack.stackModel?.spacing = castModel?.style.defaultSpacing() ?? EyebrowHeadlineBodyModel.Style.large.defaultSpacing() + stack.updateView(size) + } + + //-------------------------------------------------- + // MARK: - MoleculeViewProtocol + //-------------------------------------------------- + + open override func reset() { + super.reset() + stack.reset() + eyebrow.setFontStyle(.RegularBodySmall) + headline.setFontStyle(.RegularBodySmall) + body.setFontStyle(.RegularBodySmall) + } + + //-------------------------------------------------- + // MARK: - MoleculeViewProtocol + //-------------------------------------------------- + + open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + super.set(with: model, delegateObject, additionalData) + setStyle(style: castModel?.style) + + ///Updating the text color + castModel?.eyebrow?.textColor = castModel?.headlineColor + castModel?.headline.textColor = castModel?.headlineColor + castModel?.body?.textColor = castModel?.bodyColor + + if let alignment = castModel?.alignment, let textAlignment = NSTextAlignment(rawValue: alignment.rawValue) { + castModel?.eyebrow?.textAlignment = textAlignment + castModel?.headline.textAlignment = textAlignment + castModel?.body?.textAlignment = textAlignment + } + + stack.updateContainedMolecules(with: [castModel?.eyebrow, + castModel?.headline, + castModel?.body], + delegateObject, additionalData) + } + + open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + return 65 + } + + //-------------------------------------------------- + // MARK: - Methods + //-------------------------------------------------- + + public func setStyle(style: EyebrowHeadlineBodyModel.Style? = .large) { + + ///If eyebrow style is not available, will set font style based on the component + ///Eyebrow and body share the same font size + if castModel?.eyebrow?.fontStyle == nil { + castModel?.eyebrow?.fontStyle = style?.defaultBodyFontStyle() + } + + ///If headline style is not available, will set font style based on the component + if castModel?.headline.fontStyle == nil { + castModel?.headline.fontStyle = style?.defaultHeadlineFontStyle() + } + + ///If body style is not available, will set font style based on the component + if castModel?.body?.fontStyle == nil { + castModel?.body?.fontStyle = style?.defaultBodyFontStyle() + } + } + + //-------------------------------------------------- + // MARK: - Accessibility Helpers + //-------------------------------------------------- + + /// Returns the labels text in one message. + func getAccessibilityMessage() -> String? { + + var message = "" + + if let eyebrowLabel = eyebrow.text { + message += eyebrowLabel + ", " + } + + if let headlineLabel = headline.text { + message += headlineLabel + ", " + } + + if let bodyLabel = body.text { + message += bodyLabel + } + + return message.count > 0 ? message : nil + } + + /// Returns an array of the appropriate accessibility elements. + func getAccessibilityElements() -> [Any]? { + + var elements: [UIView] = [] + + if eyebrow.hasText { + elements.append(eyebrow) + } + + if headline.hasText { + elements.append(headline) + } + + if body.hasText { + elements.append(body) + } + + return elements.count > 0 ? elements : nil + } +} diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyModel.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyModel.swift new file mode 100644 index 00000000..97b37637 --- /dev/null +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyModel.swift @@ -0,0 +1,167 @@ +// +// EyebrowHeadlineBodyModel.swift +// MVMCoreUI +// +// Created by Nadigadda, Sumanth on 08/04/22. +// Copyright © 2022 Verizon Wireless. All rights reserved. +// + +import VDSColorTokens + +public class EyebrowHeadlineBodyModel: MoleculeModelProtocol, ParentMoleculeModelProtocol { + + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + + public static var identifier: String = "eyebrowHeadlineBody" + public var moleculeName: String = EyebrowHeadlineBodyModel.identifier + + public var eyebrow: LabelModel? + public var headline: LabelModel + public var body: LabelModel? + + public var style: Style = .large + public var alignment: Alignment = .left + public var inverted: Bool = false + + private var _backgroundColor: Color? + public var backgroundColor: Color? { + get { + return inverted ? Color(uiColor: VDSColor.backgroundPrimaryDark) : Color(uiColor: VDSColor.backgroundPrimaryLight) + } + set { + _backgroundColor = newValue + } + } + + public var headlineColor: Color? { + return inverted ? Color(uiColor: VDSColor.elementsPrimaryOndark) : Color(uiColor: VDSColor.elementsPrimaryOnlight) + } + + public var bodyColor: Color? { + return inverted ? Color(uiColor: VDSColor.elementsSecondaryOndark) : Color(uiColor: VDSColor.elementsSecondaryOnlight) + } + + public var children: [MoleculeModelProtocol] { + [eyebrow, headline, body].compactMap { (molecule: MoleculeModelProtocol?) in molecule } + } + + //-------------------------------------------------- + // MARK: - Initializer + //-------------------------------------------------- + + public init(eyebrow: LabelModel? = nil, headline: LabelModel, body: LabelModel? = nil) throws { + + self.eyebrow = eyebrow + self.headline = headline + self.body = body + } + + //-------------------------------------------------- + // MARK: - Enum + //-------------------------------------------------- + + /// Convenience styles for common situations. + public enum Style: String, Codable { + case small + case medium + case large + case xlarge + case xxlarge + + func defaultHeadlineFontStyle() -> Styler.Font { + + switch self { + case .small: + return .BoldBodyLarge + case .medium: + return .BoldTitleMedium + case .large: + return .BoldTitleLarge + case .xlarge: + return .TitleXLarge + case .xxlarge: + return .Title2XLarge + } + } + + func defaultBodyFontStyle() -> Styler.Font { + + switch self { + case .small,.medium,.large: + return .RegularBodySmall + case .xlarge,.xxlarge: + return .RegularBodyLarge + } + } + + func defaultSpacing() -> CGFloat { + + switch self { + case .small,.medium,.large: + return Padding.One + case .xlarge: + return Padding.Three + case .xxlarge: + return Padding.Four + } + } + } + + public enum Alignment: String, Codable { + case left + case center + } + + //-------------------------------------------------- + // MARK: - Keys + //-------------------------------------------------- + + private enum CodingKeys: String, CodingKey { + case moleculeName + case backgroundColor + case eyebrow + case headline + case body + case inverted + case alignment + case style + } + + //-------------------------------------------------- + // MARK: - Codec + //-------------------------------------------------- + + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + eyebrow = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .eyebrow) + headline = try typeContainer.decodeMolecule(codingKey: .headline) + body = try typeContainer.decodeMoleculeIfPresent(codingKey: .body) + + if let style = try typeContainer.decodeIfPresent(Style.self, forKey: .style) { + self.style = style + } + + if let alignment = try typeContainer.decodeIfPresent(Alignment.self, forKey: .alignment) { + self.alignment = alignment + } + + if let inverted = try typeContainer.decodeIfPresent(Bool.self, forKey: .inverted) { + self.inverted = inverted + } + backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(moleculeName, forKey: .moleculeName) + try container.encodeIfPresent(eyebrow, forKey: .eyebrow) + try container.encodeModelIfPresent(headline, forKey: .headline) + try container.encodeIfPresent(body, forKey: .body) + try container.encodeIfPresent(style, forKey: .style) + try container.encode(alignment, forKey: .alignment) + try container.encode(inverted, forKey: .inverted) + try container.encodeIfPresent(_backgroundColor, forKey: .backgroundColor) + } +} diff --git a/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift b/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift index 2a7c9d90..5527813b 100644 --- a/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift +++ b/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift @@ -87,6 +87,7 @@ open class CoreUIModelMapping: ModelMapping { ModelRegistry.register(handler: BGImageHeadlineBodyButton.self, for: BGImageHeadlineBodyButtonModel.self) ModelRegistry.register(handler: ThreeHeadlineBodyLink.self, for: ThreeHeadlineBodyLinkModel.self) ModelRegistry.register(handler: ImageButton.self, for: ImageButtonModel.self) + ModelRegistry.register(handler: EyebrowHeadlineBody.self, for: EyebrowHeadlineBodyModel.self) // MARK:- Left Right Molecules ModelRegistry.register(handler: CornerLabels.self, for: CornerLabelsModel.self) From 8ca99f5802327f607baa28be6afe8aa2eda3070e Mon Sep 17 00:00:00 2001 From: Sumanth Nadigadda Date: Tue, 26 Apr 2022 02:24:41 +0530 Subject: [PATCH 2/4] Setting label alignment changes per title lock up alignment --- .../EyebrowHeadlineBody.swift | 39 ++++++++++--------- .../EyebrowHeadlineBodyModel.swift | 2 +- 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBody.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBody.swift index 7e9c5dc0..cf58a95f 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBody.swift +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBody.swift @@ -11,10 +11,15 @@ // MARK: - Outlets //-------------------------------------------------- - public let stack = Stack(frame: .zero) public let eyebrow = Label(fontStyle: .RegularBodySmall) public let headline = Label(fontStyle: .RegularBodySmall) public let body = Label(fontStyle: .RegularBodySmall) + public lazy var stack: Stack = { + return Stack.createStack(with: [(view: eyebrow, model: StackItemModel(horizontalAlignment: .fill)), + (view: headline, model: StackItemModel(horizontalAlignment: .fill)), + (view: body, model: StackItemModel(horizontalAlignment: .fill))], + axis: .vertical) + }() var castModel: EyebrowHeadlineBodyModel? { get { return model as? EyebrowHeadlineBodyModel } @@ -24,9 +29,8 @@ // MARK: - Initialization //-------------------------------------------------- - public convenience init(spacing: CGFloat) { + public convenience init() { self.init(frame: .zero) - stack.stackModel?.spacing = spacing stack.restack() } @@ -36,8 +40,6 @@ open override func setupView() { super.setupView() - stack.setAndCreateModel(with: [eyebrow, headline, body]) - stack.stackModel?.spacing = 0 addSubview(stack) NSLayoutConstraint.constraintPinSubview(toSuperview: stack) stack.restack() @@ -56,9 +58,6 @@ open override func reset() { super.reset() stack.reset() - eyebrow.setFontStyle(.RegularBodySmall) - headline.setFontStyle(.RegularBodySmall) - body.setFontStyle(.RegularBodySmall) } //-------------------------------------------------- @@ -67,22 +66,24 @@ open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { super.set(with: model, delegateObject, additionalData) - setStyle(style: castModel?.style) + guard let model = model as? EyebrowHeadlineBodyModel else { return } + + setStyle(style: model.style) ///Updating the text color - castModel?.eyebrow?.textColor = castModel?.headlineColor - castModel?.headline.textColor = castModel?.headlineColor - castModel?.body?.textColor = castModel?.bodyColor + model.eyebrow?.textColor = model.headlineColor + model.headline.textColor = model.headlineColor + model.body?.textColor = model.bodyColor - if let alignment = castModel?.alignment, let textAlignment = NSTextAlignment(rawValue: alignment.rawValue) { - castModel?.eyebrow?.textAlignment = textAlignment - castModel?.headline.textAlignment = textAlignment - castModel?.body?.textAlignment = textAlignment + if let textAlignment = NSTextAlignment(rawValue: model.alignment.rawValue) { + model.eyebrow?.textAlignment = textAlignment + model.headline.textAlignment = textAlignment + model.body?.textAlignment = textAlignment } - stack.updateContainedMolecules(with: [castModel?.eyebrow, - castModel?.headline, - castModel?.body], + stack.updateContainedMolecules(with: [model.eyebrow, + model.headline, + model.body], delegateObject, additionalData) } diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyModel.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyModel.swift index 97b37637..dbf8377c 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyModel.swift +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyModel.swift @@ -100,7 +100,7 @@ public class EyebrowHeadlineBodyModel: MoleculeModelProtocol, ParentMoleculeMode switch self { case .small,.medium,.large: - return Padding.One + return Padding.Two case .xlarge: return Padding.Three case .xxlarge: From 083e52bc1919320b69b3a2f6e4a8356965cc1ee2 Mon Sep 17 00:00:00 2001 From: Sumanth Nadigadda Date: Wed, 4 May 2022 01:35:21 +0530 Subject: [PATCH 3/4] TitleLockup model changes --- MVMCoreUI.xcodeproj/project.pbxproj | 16 ++-- .../LockUps/TitleLockup.swift} | 78 +++++----------- .../LockUps/TitleLockupModel.swift} | 91 +++++++++++++------ .../OtherHandlers/CoreUIModelMapping.swift | 2 +- 4 files changed, 95 insertions(+), 92 deletions(-) rename MVMCoreUI/Atomic/Molecules/{VerticalCombinationViews/EyebrowHeadlineBody.swift => DesignedComponents/LockUps/TitleLockup.swift} (54%) rename MVMCoreUI/Atomic/Molecules/{VerticalCombinationViews/EyebrowHeadlineBodyModel.swift => DesignedComponents/LockUps/TitleLockupModel.swift} (59%) diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 407051bd..730d98aa 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -145,9 +145,9 @@ 32D2609724C19E2100B56344 /* LockupsPlanSMLXLModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32D2609524C19E2100B56344 /* LockupsPlanSMLXLModel.swift */; }; 32F8804624765C6E00C2ACB3 /* ListLeftVariableNumberedListAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32F8804524765C6E00C2ACB3 /* ListLeftVariableNumberedListAllTextAndLinksModel.swift */; }; 32F8804824765C8400C2ACB3 /* ListLeftVariableNumberedListAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32F8804724765C8400C2ACB3 /* ListLeftVariableNumberedListAllTextAndLinks.swift */; }; + 444FB7C12821B73200DFE692 /* TitleLockup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 444FB7C02821B73200DFE692 /* TitleLockup.swift */; }; + 444FB7C32821B76B00DFE692 /* TitleLockupModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 444FB7C22821B76B00DFE692 /* TitleLockupModel.swift */; }; 4457904E27ECE989002B1E1E /* UIImageRenderingMode+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4457904D27ECE989002B1E1E /* UIImageRenderingMode+Extension.swift */; }; - 4461F77A2800AB2D00BA0222 /* EyebrowHeadlineBodyModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4461F7792800AB2D00BA0222 /* EyebrowHeadlineBodyModel.swift */; }; - 4461F77C2800AB6C00BA0222 /* EyebrowHeadlineBody.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4461F77B2800AB6C00BA0222 /* EyebrowHeadlineBody.swift */; }; 522679C123FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 522679BF23FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinks.swift */; }; 522679C223FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 522679C023FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinksModel.swift */; }; 52267A0723FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52267A0623FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift */; }; @@ -735,9 +735,9 @@ 32D2609524C19E2100B56344 /* LockupsPlanSMLXLModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LockupsPlanSMLXLModel.swift; sourceTree = ""; }; 32F8804524765C6E00C2ACB3 /* ListLeftVariableNumberedListAllTextAndLinksModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableNumberedListAllTextAndLinksModel.swift; sourceTree = ""; }; 32F8804724765C8400C2ACB3 /* ListLeftVariableNumberedListAllTextAndLinks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableNumberedListAllTextAndLinks.swift; sourceTree = ""; }; + 444FB7C02821B73200DFE692 /* TitleLockup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TitleLockup.swift; sourceTree = ""; }; + 444FB7C22821B76B00DFE692 /* TitleLockupModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TitleLockupModel.swift; sourceTree = ""; }; 4457904D27ECE989002B1E1E /* UIImageRenderingMode+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImageRenderingMode+Extension.swift"; sourceTree = ""; }; - 4461F7792800AB2D00BA0222 /* EyebrowHeadlineBodyModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EyebrowHeadlineBodyModel.swift; sourceTree = ""; }; - 4461F77B2800AB6C00BA0222 /* EyebrowHeadlineBody.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EyebrowHeadlineBody.swift; sourceTree = ""; }; 522679BF23FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinks.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListLeftVariableCheckboxAllTextAndLinks.swift; sourceTree = ""; }; 522679C023FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinksModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListLeftVariableCheckboxAllTextAndLinksModel.swift; sourceTree = ""; }; 52267A0623FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListOneColumnFullWidthTextAllTextAndLinks.swift; sourceTree = ""; }; @@ -1435,6 +1435,8 @@ 525019DC2406430800EED91C /* ListProgressBarData.swift */, AA45AA0A24BF0263007A6EA7 /* LockUpsPlanNamesModel.swift */, AA45AA0C24BF0276007A6EA7 /* LockUpsPlanNames.swift */, + 444FB7C22821B76B00DFE692 /* TitleLockupModel.swift */, + 444FB7C02821B73200DFE692 /* TitleLockup.swift */, ); path = LockUps; sourceTree = ""; @@ -1641,8 +1643,6 @@ EA5124FC243601600051A3A4 /* BGImageHeadlineBodyButton.swift */, 0A775F2524893916009EFB58 /* ThreeHeadlineBodyLink.swift */, 0A775F2724893937009EFB58 /* ThreeHeadlineBodyLinkModel.swift */, - 4461F7792800AB2D00BA0222 /* EyebrowHeadlineBodyModel.swift */, - 4461F77B2800AB6C00BA0222 /* EyebrowHeadlineBody.swift */, ); path = VerticalCombinationViews; sourceTree = ""; @@ -2669,6 +2669,7 @@ 0A7BAD74232A8DC700FB8E22 /* HeadlineBodyButton.swift in Sources */, 3265B30424BCA749000D154B /* HeadersH1NoButtonsBodyText.swift in Sources */, AAA7CD69250641F90045B959 /* HeartModel.swift in Sources */, + 444FB7C12821B73200DFE692 /* TitleLockup.swift in Sources */, D2FB151D23A40F1500C20E10 /* MoleculeStackItem.swift in Sources */, D28BA7452481652D00B75CB8 /* TabBarProtocol.swift in Sources */, AA11A41F23F15D3100D7962F /* ListRightVariablePayments.swift in Sources */, @@ -2737,7 +2738,6 @@ D260106323D0C05000764D80 /* StackItemModel.swift in Sources */, D2E2A99823D8D63C000B42E6 /* ActionDetailWithImageModel.swift in Sources */, D28764AC245898A400CB882D /* ThreeLayerFillMiddleTemplateModel.swift in Sources */, - 4461F77A2800AB2D00BA0222 /* EyebrowHeadlineBodyModel.swift in Sources */, BBBBC87D24374A4900B0F079 /* ListThreeColumnBillChangesDividerModel.swift in Sources */, D2ED2800254B0E0300A1C293 /* MVMCoreAlertHandler+Extension.swift in Sources */, D2ED27EE254B0CE700A1C293 /* ActionAlertModel.swift in Sources */, @@ -2863,6 +2863,7 @@ 525019E52406852100EED91C /* ListFourColumnDataUsageDividerModel.swift in Sources */, 32D2609624C19E2100B56344 /* LockupsPlanSMLXL.swift in Sources */, 0A7EF86723D8B0AE00B2AAD1 /* DateDropdownEntryFieldModel.swift in Sources */, + 444FB7C32821B76B00DFE692 /* TitleLockupModel.swift in Sources */, D29C94D5242901C9003813BA /* MVMCoreUICommonViewsUtility+Extension.swift in Sources */, D260105323CEA61600764D80 /* ToggleModel.swift in Sources */, 014AA72523C501E2006F3E93 /* ContainerModel.swift in Sources */, @@ -2930,7 +2931,6 @@ 32F8804624765C6E00C2ACB3 /* ListLeftVariableNumberedListAllTextAndLinksModel.swift in Sources */, 011D958524042432000E3791 /* RulesProtocol.swift in Sources */, 4457904E27ECE989002B1E1E /* UIImageRenderingMode+Extension.swift in Sources */, - 4461F77C2800AB6C00BA0222 /* EyebrowHeadlineBody.swift in Sources */, D23118B325124E18001C8440 /* Notification.swift in Sources */, AA9972502475309F00FC7472 /* ListLeftVariableIconAllTextLinksModel.swift in Sources */, AA69AAF62445BF5700AF3D3B /* ListLeftVariableCheckboxBodyText.swift in Sources */, diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBody.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/LockUps/TitleLockup.swift similarity index 54% rename from MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBody.swift rename to MVMCoreUI/Atomic/Molecules/DesignedComponents/LockUps/TitleLockup.swift index cf58a95f..bc069b27 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBody.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/LockUps/TitleLockup.swift @@ -1,28 +1,28 @@ // -// EyebrowHeadlineBody.swift +// TitleLockup.swift // MVMCoreUI // -// Created by Nadigadda, Sumanth on 08/04/22. +// Created by Nadigadda, Sumanth on 04/05/22. // Copyright © 2022 Verizon Wireless. All rights reserved. // -@objcMembers open class EyebrowHeadlineBody: View { +@objcMembers open class TitleLockup: View { //-------------------------------------------------- // MARK: - Outlets //-------------------------------------------------- public let eyebrow = Label(fontStyle: .RegularBodySmall) - public let headline = Label(fontStyle: .RegularBodySmall) - public let body = Label(fontStyle: .RegularBodySmall) + public let title = Label(fontStyle: .RegularBodySmall) + public let subTitle = Label(fontStyle: .RegularBodySmall) public lazy var stack: Stack = { return Stack.createStack(with: [(view: eyebrow, model: StackItemModel(horizontalAlignment: .fill)), - (view: headline, model: StackItemModel(horizontalAlignment: .fill)), - (view: body, model: StackItemModel(horizontalAlignment: .fill))], + (view: title, model: StackItemModel(horizontalAlignment: .fill)), + (view: subTitle, model: StackItemModel(horizontalAlignment: .fill))], axis: .vertical) }() - var castModel: EyebrowHeadlineBodyModel? { - get { return model as? EyebrowHeadlineBodyModel } + var castModel: TitleLockupModel? { + get { return model as? TitleLockupModel } } //-------------------------------------------------- @@ -31,7 +31,6 @@ public convenience init() { self.init(frame: .zero) - stack.restack() } //-------------------------------------------------- @@ -47,7 +46,7 @@ open override func updateView(_ size: CGFloat) { super.updateView(size) - stack.stackModel?.spacing = castModel?.style.defaultSpacing() ?? EyebrowHeadlineBodyModel.Style.large.defaultSpacing() + stack.stackModel?.spacing = castModel?.style.defaultSpacing() ?? TitleLockupModel.Style.large.defaultSpacing() stack.updateView(size) } @@ -66,24 +65,11 @@ open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { super.set(with: model, delegateObject, additionalData) - guard let model = model as? EyebrowHeadlineBodyModel else { return } - - setStyle(style: model.style) - - ///Updating the text color - model.eyebrow?.textColor = model.headlineColor - model.headline.textColor = model.headlineColor - model.body?.textColor = model.bodyColor - - if let textAlignment = NSTextAlignment(rawValue: model.alignment.rawValue) { - model.eyebrow?.textAlignment = textAlignment - model.headline.textAlignment = textAlignment - model.body?.textAlignment = textAlignment - } - + guard let model = model as? TitleLockupModel else { return } + stack.updateContainedMolecules(with: [model.eyebrow, - model.headline, - model.body], + model.title, + model.subTitle], delegateObject, additionalData) } @@ -91,29 +77,6 @@ return 65 } - //-------------------------------------------------- - // MARK: - Methods - //-------------------------------------------------- - - public func setStyle(style: EyebrowHeadlineBodyModel.Style? = .large) { - - ///If eyebrow style is not available, will set font style based on the component - ///Eyebrow and body share the same font size - if castModel?.eyebrow?.fontStyle == nil { - castModel?.eyebrow?.fontStyle = style?.defaultBodyFontStyle() - } - - ///If headline style is not available, will set font style based on the component - if castModel?.headline.fontStyle == nil { - castModel?.headline.fontStyle = style?.defaultHeadlineFontStyle() - } - - ///If body style is not available, will set font style based on the component - if castModel?.body?.fontStyle == nil { - castModel?.body?.fontStyle = style?.defaultBodyFontStyle() - } - } - //-------------------------------------------------- // MARK: - Accessibility Helpers //-------------------------------------------------- @@ -127,11 +90,11 @@ message += eyebrowLabel + ", " } - if let headlineLabel = headline.text { + if let headlineLabel = title.text { message += headlineLabel + ", " } - if let bodyLabel = body.text { + if let bodyLabel = subTitle.text { message += bodyLabel } @@ -147,14 +110,15 @@ elements.append(eyebrow) } - if headline.hasText { - elements.append(headline) + if title.hasText { + elements.append(title) } - if body.hasText { - elements.append(body) + if subTitle.hasText { + elements.append(subTitle) } return elements.count > 0 ? elements : nil } } + diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/LockUps/TitleLockupModel.swift similarity index 59% rename from MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyModel.swift rename to MVMCoreUI/Atomic/Molecules/DesignedComponents/LockUps/TitleLockupModel.swift index dbf8377c..a4351cf4 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/LockUps/TitleLockupModel.swift @@ -1,25 +1,25 @@ // -// EyebrowHeadlineBodyModel.swift +// TitleLockupModel.swift // MVMCoreUI // -// Created by Nadigadda, Sumanth on 08/04/22. +// Created by Nadigadda, Sumanth on 04/05/22. // Copyright © 2022 Verizon Wireless. All rights reserved. // import VDSColorTokens -public class EyebrowHeadlineBodyModel: MoleculeModelProtocol, ParentMoleculeModelProtocol { +public class TitleLockupModel: MoleculeModelProtocol, ParentMoleculeModelProtocol { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- - public static var identifier: String = "eyebrowHeadlineBody" - public var moleculeName: String = EyebrowHeadlineBodyModel.identifier + public static var identifier: String = "titleLockup" + public var moleculeName: String = TitleLockupModel.identifier public var eyebrow: LabelModel? - public var headline: LabelModel - public var body: LabelModel? + public var title: LabelModel + public var subTitle: LabelModel? public var style: Style = .large public var alignment: Alignment = .left @@ -35,27 +35,27 @@ public class EyebrowHeadlineBodyModel: MoleculeModelProtocol, ParentMoleculeMode } } - public var headlineColor: Color? { + public var titleColor: Color? { return inverted ? Color(uiColor: VDSColor.elementsPrimaryOndark) : Color(uiColor: VDSColor.elementsPrimaryOnlight) } - public var bodyColor: Color? { + public var subTitleColor: Color? { return inverted ? Color(uiColor: VDSColor.elementsSecondaryOndark) : Color(uiColor: VDSColor.elementsSecondaryOnlight) } public var children: [MoleculeModelProtocol] { - [eyebrow, headline, body].compactMap { (molecule: MoleculeModelProtocol?) in molecule } + [eyebrow, title, subTitle].compactMap { (molecule: MoleculeModelProtocol?) in molecule } } //-------------------------------------------------- // MARK: - Initializer //-------------------------------------------------- - public init(eyebrow: LabelModel? = nil, headline: LabelModel, body: LabelModel? = nil) throws { + public init(eyebrow: LabelModel? = nil, title: LabelModel, subTitle: LabelModel? = nil) throws { self.eyebrow = eyebrow - self.headline = headline - self.body = body + self.title = title + self.subTitle = subTitle } //-------------------------------------------------- @@ -122,8 +122,8 @@ public class EyebrowHeadlineBodyModel: MoleculeModelProtocol, ParentMoleculeMode case moleculeName case backgroundColor case eyebrow - case headline - case body + case title + case subTitle case inverted case alignment case style @@ -136,32 +136,71 @@ public class EyebrowHeadlineBodyModel: MoleculeModelProtocol, ParentMoleculeMode required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) eyebrow = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .eyebrow) - headline = try typeContainer.decodeMolecule(codingKey: .headline) - body = try typeContainer.decodeMoleculeIfPresent(codingKey: .body) - - if let style = try typeContainer.decodeIfPresent(Style.self, forKey: .style) { - self.style = style + title = try typeContainer.decodeMolecule(codingKey: .title) + subTitle = try typeContainer.decodeMoleculeIfPresent(codingKey: .subTitle) + + if let newStyle = try typeContainer.decodeIfPresent(Style.self, forKey: .style) { + style = newStyle + setStyle(style: newStyle) } - if let alignment = try typeContainer.decodeIfPresent(Alignment.self, forKey: .alignment) { - self.alignment = alignment + if let newAlignment = try typeContainer.decodeIfPresent(Alignment.self, forKey: .alignment) { + alignment = newAlignment } - if let inverted = try typeContainer.decodeIfPresent(Bool.self, forKey: .inverted) { - self.inverted = inverted + if let invertedStatus = try typeContainer.decodeIfPresent(Bool.self, forKey: .inverted) { + inverted = invertedStatus } backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) + updateLabelAttributes() } public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(moleculeName, forKey: .moleculeName) try container.encodeIfPresent(eyebrow, forKey: .eyebrow) - try container.encodeModelIfPresent(headline, forKey: .headline) - try container.encodeIfPresent(body, forKey: .body) + try container.encodeModel(title, forKey: .title) + try container.encodeIfPresent(subTitle, forKey: .subTitle) try container.encodeIfPresent(style, forKey: .style) try container.encode(alignment, forKey: .alignment) try container.encode(inverted, forKey: .inverted) try container.encodeIfPresent(_backgroundColor, forKey: .backgroundColor) } + + //-------------------------------------------------- + // MARK: - Model updates + //-------------------------------------------------- + + private func setStyle(style: Style) { + + ///If eyebrow style is not available, will set font style based on the component + ///Eyebrow and body share the same font size + if eyebrow?.fontStyle == nil { + eyebrow?.fontStyle = style.defaultBodyFontStyle() + } + + ///If title style is not available, will set font style based on the component + if title.fontStyle == nil { + title.fontStyle = style.defaultHeadlineFontStyle() + } + + ///If subtitle style is not available, will set font style based on the component + if subTitle?.fontStyle == nil { + subTitle?.fontStyle = style.defaultBodyFontStyle() + } + } + + private func updateLabelAttributes() { + ///Updating the text color + eyebrow?.textColor = titleColor + title.textColor = titleColor + subTitle?.textColor = subTitleColor + + ///Updating the text alignment for all labels + if let textAlignment = NSTextAlignment(rawValue: alignment.rawValue) { + eyebrow?.textAlignment = textAlignment + title.textAlignment = textAlignment + subTitle?.textAlignment = textAlignment + } + } } diff --git a/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift b/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift index 5527813b..ef051b88 100644 --- a/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift +++ b/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift @@ -87,7 +87,6 @@ open class CoreUIModelMapping: ModelMapping { ModelRegistry.register(handler: BGImageHeadlineBodyButton.self, for: BGImageHeadlineBodyButtonModel.self) ModelRegistry.register(handler: ThreeHeadlineBodyLink.self, for: ThreeHeadlineBodyLinkModel.self) ModelRegistry.register(handler: ImageButton.self, for: ImageButtonModel.self) - ModelRegistry.register(handler: EyebrowHeadlineBody.self, for: EyebrowHeadlineBodyModel.self) // MARK:- Left Right Molecules ModelRegistry.register(handler: CornerLabels.self, for: CornerLabelsModel.self) @@ -205,6 +204,7 @@ open class CoreUIModelMapping: ModelMapping { // MARK:- LockUps ModelRegistry.register(handler: LockUpsPlanNames.self, for: LockUpsPlanNamesModel.self) ModelRegistry.register(handler: LockupsPlanSMLXL.self, for: LockupsPlanSMLXLModel.self) + ModelRegistry.register(handler: TitleLockup.self, for: TitleLockupModel.self) // MARK: - Top Notifications ModelRegistry.register(handler: NotificationView.self, for: NotificationModel.self) From 0a5c9b78eda7633298b255e9cbf02394edd60503 Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Tue, 21 Jun 2022 16:26:57 -0400 Subject: [PATCH 4/4] Switch to UIStackView for simplicity. update inits. update didSets Removed style, allow dependency on title style like in the figma. --- .../LockUps/TitleLockup.swift | 15 +- .../LockUps/TitleLockupModel.swift | 183 +++++++++--------- 2 files changed, 103 insertions(+), 95 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/LockUps/TitleLockup.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/LockUps/TitleLockup.swift index bc069b27..b48e4ddb 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/LockUps/TitleLockup.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/LockUps/TitleLockup.swift @@ -14,11 +14,11 @@ public let eyebrow = Label(fontStyle: .RegularBodySmall) public let title = Label(fontStyle: .RegularBodySmall) public let subTitle = Label(fontStyle: .RegularBodySmall) - public lazy var stack: Stack = { - return Stack.createStack(with: [(view: eyebrow, model: StackItemModel(horizontalAlignment: .fill)), - (view: title, model: StackItemModel(horizontalAlignment: .fill)), - (view: subTitle, model: StackItemModel(horizontalAlignment: .fill))], - axis: .vertical) + public lazy var stack: UIStackView = { + let stack = UIStackView(arrangedSubviews: [eyebrow, title, subTitle]) + stack.translatesAutoresizingMaskIntoConstraints = false + stack.axis = .vertical + return stack }() var castModel: TitleLockupModel? { @@ -41,12 +41,10 @@ super.setupView() addSubview(stack) NSLayoutConstraint.constraintPinSubview(toSuperview: stack) - stack.restack() } open override func updateView(_ size: CGFloat) { super.updateView(size) - stack.stackModel?.spacing = castModel?.style.defaultSpacing() ?? TitleLockupModel.Style.large.defaultSpacing() stack.updateView(size) } @@ -66,7 +64,8 @@ open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { super.set(with: model, delegateObject, additionalData) guard let model = model as? TitleLockupModel else { return } - + stack.setCustomSpacing(model.defaultEyebrowTitleSpacing(), after: eyebrow) + stack.setCustomSpacing(model.defaultTitleSubTitleSpacing(), after: title) stack.updateContainedMolecules(with: [model.eyebrow, model.title, model.subTitle], diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/LockUps/TitleLockupModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/LockUps/TitleLockupModel.swift index a4351cf4..4548207d 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/LockUps/TitleLockupModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/LockUps/TitleLockupModel.swift @@ -21,9 +21,25 @@ public class TitleLockupModel: MoleculeModelProtocol, ParentMoleculeModelProtoco public var title: LabelModel public var subTitle: LabelModel? - public var style: Style = .large - public var alignment: Alignment = .left - public var inverted: Bool = false + public var alignment: Alignment = .left { + didSet { + ///Updating the text alignment for all labels + if let textAlignment = NSTextAlignment(rawValue: alignment.rawValue) { + eyebrow?.textAlignment = textAlignment + title.textAlignment = textAlignment + subTitle?.textAlignment = textAlignment + } + } + } + + public var inverted: Bool = false { + didSet { + ///Updating the text color + eyebrow?.textColor = titleColor + title.textColor = titleColor + subTitle?.textColor = subTitleColor + } + } private var _backgroundColor: Color? public var backgroundColor: Color? { @@ -52,68 +68,63 @@ public class TitleLockupModel: MoleculeModelProtocol, ParentMoleculeModelProtoco //-------------------------------------------------- public init(eyebrow: LabelModel? = nil, title: LabelModel, subTitle: LabelModel? = nil) throws { - self.eyebrow = eyebrow self.title = title self.subTitle = subTitle + updateLabelAttributes() } //-------------------------------------------------- // MARK: - Enum //-------------------------------------------------- - /// Convenience styles for common situations. - public enum Style: String, Codable { - case small - case medium - case large - case xlarge - case xxlarge - - func defaultHeadlineFontStyle() -> Styler.Font { - - switch self { - case .small: - return .BoldBodyLarge - case .medium: - return .BoldTitleMedium - case .large: - return .BoldTitleLarge - case .xlarge: - return .TitleXLarge - case .xxlarge: - return .Title2XLarge - } - } - - func defaultBodyFontStyle() -> Styler.Font { - - switch self { - case .small,.medium,.large: - return .RegularBodySmall - case .xlarge,.xxlarge: - return .RegularBodyLarge - } - } - - func defaultSpacing() -> CGFloat { - - switch self { - case .small,.medium,.large: - return Padding.Two - case .xlarge: - return Padding.Three - case .xxlarge: - return Padding.Four - } - } - } - public enum Alignment: String, Codable { case left case center } + //-------------------------------------------------- + // MARK: - Styling + //-------------------------------------------------- + + /// Returns the default fontStyle for the subtitle, based on the title fontStyle. + func defaultSubtitleFontStyle() -> Styler.Font { + switch title.fontStyle { + case .RegularTitleXLarge, .RegularTitle2XLarge, .RegularFeatureXSmall: + return .RegularBodyLarge + case .RegularFeatureSmall, .RegularFeatureMedium: + return .RegularTitleLarge + default: + return .RegularBodySmall + } + } + + /// Returns the default spacing between the eyebrow and title, based on the title fontStyle. + func defaultEyebrowTitleSpacing() -> CGFloat { + switch title.fontStyle { + case .RegularTitleXLarge, .RegularTitle2XLarge, .RegularFeatureXSmall, .RegularFeatureSmall: + return Padding.Three + case .RegularFeatureMedium: + return subTitle?.fontStyle == .RegularBodyLarge ? Padding.Three : Padding.Four + default: + return Padding.Two + } + } + + /// Returns the default spacing between the title and subTitle, based on the title fontStyle. + func defaultTitleSubTitleSpacing() -> CGFloat { + switch title.fontStyle { + case .RegularTitleXLarge: + return Padding.Three + case .RegularTitle2XLarge, .RegularFeatureXSmall, .RegularFeatureSmall: + return Padding.Four + case .RegularFeatureMedium: + return Padding.Five + default: + return Padding.Two + } + } + //-------------------------------------------------- // MARK: - Keys //-------------------------------------------------- @@ -126,7 +137,6 @@ public class TitleLockupModel: MoleculeModelProtocol, ParentMoleculeModelProtoco case subTitle case inverted case alignment - case style } //-------------------------------------------------- @@ -135,14 +145,9 @@ public class TitleLockupModel: MoleculeModelProtocol, ParentMoleculeModelProtoco required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - eyebrow = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .eyebrow) title = try typeContainer.decodeMolecule(codingKey: .title) + eyebrow = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .eyebrow) subTitle = try typeContainer.decodeMoleculeIfPresent(codingKey: .subTitle) - - if let newStyle = try typeContainer.decodeIfPresent(Style.self, forKey: .style) { - style = newStyle - setStyle(style: newStyle) - } if let newAlignment = try typeContainer.decodeIfPresent(Alignment.self, forKey: .alignment) { alignment = newAlignment @@ -151,7 +156,9 @@ public class TitleLockupModel: MoleculeModelProtocol, ParentMoleculeModelProtoco if let invertedStatus = try typeContainer.decodeIfPresent(Bool.self, forKey: .inverted) { inverted = invertedStatus } + backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) + updateLabelAttributes() } @@ -161,7 +168,6 @@ public class TitleLockupModel: MoleculeModelProtocol, ParentMoleculeModelProtoco try container.encodeIfPresent(eyebrow, forKey: .eyebrow) try container.encodeModel(title, forKey: .title) try container.encodeIfPresent(subTitle, forKey: .subTitle) - try container.encodeIfPresent(style, forKey: .style) try container.encode(alignment, forKey: .alignment) try container.encode(inverted, forKey: .inverted) try container.encodeIfPresent(_backgroundColor, forKey: .backgroundColor) @@ -170,37 +176,40 @@ public class TitleLockupModel: MoleculeModelProtocol, ParentMoleculeModelProtoco //-------------------------------------------------- // MARK: - Model updates //-------------------------------------------------- - - private func setStyle(style: Style) { - - ///If eyebrow style is not available, will set font style based on the component - ///Eyebrow and body share the same font size - if eyebrow?.fontStyle == nil { - eyebrow?.fontStyle = style.defaultBodyFontStyle() - } - - ///If title style is not available, will set font style based on the component - if title.fontStyle == nil { - title.fontStyle = style.defaultHeadlineFontStyle() - } - - ///If subtitle style is not available, will set font style based on the component - if subTitle?.fontStyle == nil { - subTitle?.fontStyle = style.defaultBodyFontStyle() - } - } - + private func updateLabelAttributes() { - ///Updating the text color - eyebrow?.textColor = titleColor - title.textColor = titleColor - subTitle?.textColor = subTitleColor + // If subtitle style is not available, will set font style based on the component + if subTitle?.fontStyle == nil { + subTitle?.fontStyle = defaultSubtitleFontStyle() + } - ///Updating the text alignment for all labels + // If eyebrow style is not available, will set font style based on the component. Eyebrow and subtitle share the same font size + if eyebrow?.fontStyle == nil { + eyebrow?.fontStyle = subTitle?.fontStyle + } + + // Updating the text color + if eyebrow?.textColor == nil { + eyebrow?.textColor = subTitleColor + } + if title.textColor == nil { + title.textColor = titleColor + } + if subTitle?.textColor == nil { + subTitle?.textColor = subTitleColor + } + + // Updating the text alignment for all labels if let textAlignment = NSTextAlignment(rawValue: alignment.rawValue) { - eyebrow?.textAlignment = textAlignment - title.textAlignment = textAlignment - subTitle?.textAlignment = textAlignment + if eyebrow?.textAlignment == nil { + eyebrow?.textAlignment = textAlignment + } + if title.textAlignment == nil { + title.textAlignment = textAlignment + } + if subTitle?.textAlignment == nil { + subTitle?.textAlignment = textAlignment + } } } }