Merge branch 'develop' into bugfix/PRODDEF-24073

This commit is contained in:
Keerthy 2024-03-15 22:43:39 +05:30
commit 6ab685d906
29 changed files with 321 additions and 253 deletions

View File

@ -9,17 +9,23 @@
import Foundation import Foundation
import UIKit import UIKit
import VDS import VDS
import Combine
@objcMembers open class ButtonGroup: VDS.ButtonGroup, VDSMoleculeViewProtocol { open class ButtonGroup: VDS.ButtonGroup, VDSMoleculeViewProtocol {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Properties // MARK: - Properties
//-------------------------------------------------- //--------------------------------------------------
public var model: MoleculeModelProtocol?
open var viewModel: ButtonGroupModel! open var viewModel: ButtonGroupModel!
open var delegateObject: MVMCoreUIDelegateObject? open var delegateObject: MVMCoreUIDelegateObject?
open var additionalData: [AnyHashable : Any]? open var additionalData: [AnyHashable : Any]?
open var previousModel: ButtonGroupModel? open var previousModel: ButtonGroupModel?
/// For notifying the delegate of layout updates.
private var contentSizeObservation: Cancellable?
private var previousSize: CGSize?
//-------------------------------------------------- //--------------------------------------------------
// MARK: - MoleculeViewProtocol // MARK: - MoleculeViewProtocol
//-------------------------------------------------- //--------------------------------------------------
@ -74,6 +80,15 @@ import VDS
// force redraw // force redraw
setNeedsUpdate() setNeedsUpdate()
} }
// Notify the delegate of a size change.
previousSize = bounds.size
contentSizeObservation = contentSizePublisher.sink { [weak self] size in
guard let self = self,
!MVMCoreGetterUtility.fequal(a: Float(size.height), b: Float(self.previousSize?.height ?? Self.estimatedHeight(with: self.viewModel, self.delegateObject) ?? VDS.Button.Size.large.height)) else { return }
self.previousSize = size
self.delegateObject?.moleculeDelegate?.moleculeLayoutUpdated(self)
}
} }
//-------------------------------------------------- //--------------------------------------------------

View File

@ -182,29 +182,7 @@ public typealias ActionBlock = () -> ()
} }
@objc public func resetAttributeStyle() { @objc public func resetAttributeStyle() {
/* setNeedsUpdate()
* This is to address a reuse issue with iOS 13 and up.
* Even if you set text & attributedText to nil, the moment you set text with a value,
* attributedText will hold a dirty value from a previously reused cell even if reset() is
* appropriately called.
* Only other reference found of issue: https://www.thetopsites.net/article/58142205.shtml
*/
if let text = text, !text.isEmpty {
//create the primary string
let mutableText = NSMutableAttributedString.mutableText(for: text,
textStyle: textStyle,
useScaledFont: useScaledFont,
textColor: textColorConfiguration.getColor(self),
alignment: textAlignment,
lineBreakMode: lineBreakMode)
if let attributes = attributes {
mutableText.apply(attributes: attributes)
}
self.attributedText = mutableText
}
} }
public func viewModelDidUpdate() { public func viewModelDidUpdate() {
@ -221,7 +199,6 @@ public typealias ActionBlock = () -> ()
} }
if let style = viewModel.fontStyle?.vdsTextStyle() { if let style = viewModel.fontStyle?.vdsTextStyle() {
font = style.font
textStyle = style textStyle = style
} else if let fontName = viewModel.fontName { } else if let fontName = viewModel.fontName {
// there is a TextStyle.defaultStyle // there is a TextStyle.defaultStyle
@ -229,10 +206,12 @@ public typealias ActionBlock = () -> ()
if let fontSize { if let fontSize {
standardFontSize = fontSize standardFontSize = fontSize
} }
if let customStyle = style(for: fontName, pointSize: fontSize ?? standardFontSize), customStyle != textStyle { if let newFont = UIFont(name: fontName, size: fontSize ?? standardFontSize) {
font = customStyle.font font = newFont
textStyle = customStyle
} }
} else if let fontSize = viewModel.fontSize {
standardFontSize = fontSize
font = textStyle.font.withSize(fontSize)
} }
if let color = viewModel.textColor { if let color = viewModel.textColor {
@ -248,26 +227,6 @@ public typealias ActionBlock = () -> ()
} }
} }
/// See if the font that is currently set matches a VDS Font and if so grab the matching TextStyle or create custom TextStyle that
/// that the Label will use moving forward.
private func checkforFontChange() {
guard let customStyle = style(for: font.fontName, pointSize: font.pointSize), customStyle != textStyle
else { return }
textStyle = customStyle
}
private func style(for fontName: String, pointSize: CGFloat) -> TextStyle? {
guard let vdsFont = Font.from(fontName: fontName),
let customStyle = TextStyle.style(from: vdsFont, pointSize: pointSize)
else { return nil }
return customStyle
}
open override func updateView() {
checkforFontChange()
super.updateView()
}
open override func updateAccessibility() { open override func updateAccessibility() {
super.updateAccessibility() super.updateAccessibility()

View File

@ -21,10 +21,10 @@ extension Styler.Font {
case .TitleXLarge: actualFont = .RegularTitleXLarge case .TitleXLarge: actualFont = .RegularTitleXLarge
case .H1: actualFont = .RegularTitle2XLarge case .H1: actualFont = .RegularTitle2XLarge
case .H32: actualFont = .RegularTitleXLarge case .H32: actualFont = .RegularTitleXLarge
case .H2: actualFont = .RegularTitleLarge case .H2: actualFont = .RegularTitleXLarge
case .B20: actualFont = .RegularBodyLarge case .B20: actualFont = .RegularBodyLarge
case .H3: actualFont = .BoldTitleMedium case .H3: actualFont = .BoldTitleMedium
case .B1: actualFont = .BoldBodySmall case .B1: actualFont = .RegularTitleSmall
case .B2: actualFont = .RegularBodySmall case .B2: actualFont = .RegularBodySmall
case .B3: actualFont = .RegularMicro case .B3: actualFont = .RegularMicro
default: break default: break
@ -54,12 +54,3 @@ extension VDS.Font {
Self.allCases.filter({$0.fontName == fontName }).first Self.allCases.filter({$0.fontName == fontName }).first
} }
} }
extension VDS.TextStyle {
internal static func style(from font: VDS.Font, pointSize: CGFloat) -> TextStyle? {
guard let first = allCases.filter({$0.fontFace == font && $0.pointSize == pointSize}).first else {
return TextStyle(rawValue: "Custom-TextStyle", fontFace: font, pointSize: pointSize)
}
return first
}
}

View File

@ -8,14 +8,14 @@
import Foundation import Foundation
@objcMembers open class HeadersH1Button: HeaderView { open class HeadersH1Button: HeaderView {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Outlets // MARK: - Outlets
//-------------------------------------------------- //--------------------------------------------------
public let headlineBody = HeadlineBody() public let titleLockup = TitleLockup()
public let buttons = TwoButtonView() public let buttons = TwoButtonView()
public lazy var stack: Stack<StackModel> = { public lazy var stack: Stack<StackModel> = {
Stack<StackModel>.createStack(with: [headlineBody, buttons], spacing: Padding.Eighteen) Stack<StackModel>.createStack(with: [titleLockup, buttons], spacing: Padding.Eighteen)
}() }()
//------------------------------------------------------- //-------------------------------------------------------
@ -23,7 +23,6 @@ import Foundation
//------------------------------------------------------- //-------------------------------------------------------
open override func setupView() { open override func setupView() {
super.setupView() super.setupView()
headlineBody.styleLandingPageHeader()
addMolecule(stack) addMolecule(stack)
stack.restack() stack.restack()
} }
@ -35,14 +34,9 @@ import Foundation
super.set(with: model, delegateObject, additionalData) super.set(with: model, delegateObject, additionalData)
guard let model = model as? HeadersH1ButtonModel else { return } guard let model = model as? HeadersH1ButtonModel else { return }
headlineBody.set(with: model.headlineBody, delegateObject, additionalData) titleLockup.set(with: model.titleLockup, delegateObject, additionalData)
buttons.set(with: model.buttons, delegateObject, additionalData) buttons.set(with: model.buttons, delegateObject, additionalData)
} }
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { 121 } open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { 121 }
open override func reset() {
super.reset()
headlineBody.styleLandingPageHeader()
}
} }

View File

@ -13,15 +13,16 @@ public class HeadersH1ButtonModel: HeaderModel, MoleculeModelProtocol, ParentMol
// MARK: - Properties // MARK: - Properties
//-------------------------------------------------- //--------------------------------------------------
public static var identifier: String = "headerH1Btn" public static var identifier: String = "headerH1Btn"
public var headlineBody: HeadlineBodyModel public var titleLockup: TitleLockupModel
public var buttons: TwoButtonViewModel public var buttons: TwoButtonViewModel
private var helper = DeprecatedHeadlineBodyHelper()
public var children: [MoleculeModelProtocol] { public var children: [MoleculeModelProtocol] {
[headlineBody, buttons] [titleLockup, buttons]
} }
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool { public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool {
return try replaceChildMolecule(at: &headlineBody, with: molecule) return try replaceChildMolecule(at: &titleLockup, with: molecule)
|| replaceChildMolecule(at: &buttons, with: molecule) || replaceChildMolecule(at: &buttons, with: molecule)
} }
@ -29,8 +30,8 @@ public class HeadersH1ButtonModel: HeaderModel, MoleculeModelProtocol, ParentMol
// MARK: - Initializer // MARK: - Initializer
//-------------------------------------------------- //--------------------------------------------------
public init(headlineBody: HeadlineBodyModel, buttons: TwoButtonViewModel) { public init(titleLockup: TitleLockupModel, buttons: TwoButtonViewModel) {
self.headlineBody = headlineBody self.titleLockup = titleLockup
self.buttons = buttons self.buttons = buttons
super.init() super.init()
} }
@ -40,10 +41,13 @@ public class HeadersH1ButtonModel: HeaderModel, MoleculeModelProtocol, ParentMol
//-------------------------------------------------- //--------------------------------------------------
public override func setDefaults() { public override func setDefaults() {
if headlineBody.headline?.accessibilityTraits == nil {
headlineBody.headline?.accessibilityTraits = .header
}
super.setDefaults() super.setDefaults()
if titleLockup.title.fontStyle == nil {
titleLockup.title.fontStyle = Styler.Font.RegularTitle2XLarge
}
if titleLockup.subTitle?.fontStyle == nil {
titleLockup.subTitle?.fontStyle = Styler.Font.RegularTitleMedium
}
} }
//-------------------------------------------------- //--------------------------------------------------
@ -52,7 +56,7 @@ public class HeadersH1ButtonModel: HeaderModel, MoleculeModelProtocol, ParentMol
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case moleculeName case moleculeName
case headlineBody case titleLockup
case buttons case buttons
} }
@ -61,7 +65,7 @@ public class HeadersH1ButtonModel: HeaderModel, MoleculeModelProtocol, ParentMol
//-------------------------------------------------- //--------------------------------------------------
required public init(from decoder: Decoder) throws { required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self) let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
headlineBody = try typeContainer.decode(HeadlineBodyModel.self, forKey: .headlineBody) titleLockup = try helper.deprecatedCreate(from: decoder) ?? typeContainer.decodeMolecule(codingKey: .titleLockup)
buttons = try typeContainer.decode(TwoButtonViewModel.self, forKey: .buttons) buttons = try typeContainer.decode(TwoButtonViewModel.self, forKey: .buttons)
try super.init(from: decoder) try super.init(from: decoder)
} }
@ -70,7 +74,8 @@ public class HeadersH1ButtonModel: HeaderModel, MoleculeModelProtocol, ParentMol
try super.encode(to: encoder) try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self) var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName) try container.encode(moleculeName, forKey: .moleculeName)
try container.encode(headlineBody, forKey: .headlineBody)
try container.encode(buttons, forKey: .buttons) try container.encode(buttons, forKey: .buttons)
guard try !helper.deprecatedEncode(to: encoder) else { return }
try container.encode(titleLockup, forKey: .titleLockup)
} }
} }

View File

@ -8,20 +8,19 @@
import Foundation import Foundation
@objcMembers open class HeadersH1NoButtonsBodyText: HeaderView { open class HeadersH1NoButtonsBodyText: HeaderView {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Outlets // MARK: - Outlets
//-------------------------------------------------- //--------------------------------------------------
public let headlineBody = HeadlineBody() public let titleLockup = TitleLockup()
//------------------------------------------------------- //-------------------------------------------------------
// MARK: - View Lifecycle // MARK: - View Lifecycle
//------------------------------------------------------- //-------------------------------------------------------
open override func setupView() { open override func setupView() {
super.setupView() super.setupView()
headlineBody.styleLandingPageHeader() addMolecule(titleLockup)
addMolecule(headlineBody)
} }
//---------------------------------------------------- //----------------------------------------------------
@ -31,13 +30,8 @@ import Foundation
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
super.set(with: model, delegateObject, additionalData) super.set(with: model, delegateObject, additionalData)
guard let model = model as? HeadersH1NoButtonsBodyTextModel else { return } guard let model = model as? HeadersH1NoButtonsBodyTextModel else { return }
headlineBody.set(with: model.headlineBody, delegateObject, additionalData) titleLockup.set(with: model.titleLockup, delegateObject, additionalData)
} }
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { 121 } open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { 121 }
open override func reset() {
super.reset()
headlineBody.styleLandingPageHeader()
}
} }

View File

@ -6,50 +6,48 @@
// Copyright © 2020 Verizon Wireless. All rights reserved. // Copyright © 2020 Verizon Wireless. All rights reserved.
// //
public class HeadersH1NoButtonsBodyTextModel: HeaderModel, MoleculeModelProtocol, ParentMoleculeModelProtocol { public class HeadersH1NoButtonsBodyTextModel: HeaderModel, MoleculeModelProtocol, ParentMoleculeModelProtocol {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Properties // MARK: - Properties
//-------------------------------------------------- //--------------------------------------------------
public static var identifier: String = "headerH1" public static var identifier: String = "headerH1"
public var headlineBody: HeadlineBodyModel public var titleLockup: TitleLockupModel
private var helper = DeprecatedHeadlineBodyHelper()
public var children: [MoleculeModelProtocol] { public var children: [MoleculeModelProtocol] {
[headlineBody] [titleLockup]
} }
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool { public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool {
return try replaceChildMolecule(at: &headlineBody, with: molecule) return try replaceChildMolecule(at: &titleLockup, with: molecule)
}
public override func setDefaults() {
super.setDefaults()
if titleLockup.title.fontStyle == nil {
titleLockup.title.fontStyle = Styler.Font.RegularTitle2XLarge
}
if titleLockup.subTitle?.fontStyle == nil {
titleLockup.subTitle?.fontStyle = Styler.Font.RegularTitleMedium
}
} }
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Initializer // MARK: - Initializer
//-------------------------------------------------- //--------------------------------------------------
public init(headlineBody: HeadlineBodyModel) { public init(titleLockup: TitleLockupModel) {
self.headlineBody = headlineBody self.titleLockup = titleLockup
super.init() super.init()
} }
//--------------------------------------------------
// MARK: - Subclass
//--------------------------------------------------
public override func setDefaults() {
if headlineBody.headline?.accessibilityTraits == nil {
headlineBody.headline?.accessibilityTraits = .header
}
super.setDefaults()
}
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Keys // MARK: - Keys
//-------------------------------------------------- //--------------------------------------------------
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case moleculeName case moleculeName
case headlineBody case titleLockup
} }
//-------------------------------------------------- //--------------------------------------------------
@ -57,7 +55,7 @@ public class HeadersH1NoButtonsBodyTextModel: HeaderModel, MoleculeModelProtocol
//-------------------------------------------------- //--------------------------------------------------
required public init(from decoder: Decoder) throws { required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self) let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
headlineBody = try typeContainer.decode(HeadlineBodyModel.self, forKey: .headlineBody) titleLockup = try helper.deprecatedCreate(from: decoder) ?? typeContainer.decodeMolecule(codingKey: .titleLockup)
try super.init(from: decoder) try super.init(from: decoder)
} }
@ -65,6 +63,55 @@ public class HeadersH1NoButtonsBodyTextModel: HeaderModel, MoleculeModelProtocol
try super.encode(to: encoder) try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self) var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName) try container.encode(moleculeName, forKey: .moleculeName)
try container.encode(headlineBody, forKey: .headlineBody) guard try !helper.deprecatedEncode(to: encoder) else { return }
try container.encode(titleLockup, forKey: .titleLockup)
}
}
public struct DeprecatedHeadlineBodyHelper {
var headlineBody: HeadlineBodyModel?
private enum DeprecatedCodingKeys: String, CodingKey {
case headlineBody
}
public mutating func deprecatedCreate(from decoder: Decoder) throws -> TitleLockupModel? {
let typeContainer = try decoder.container(keyedBy: DeprecatedCodingKeys.self)
headlineBody = try typeContainer.decodeIfPresent(HeadlineBodyModel.self, forKey: .headlineBody)
guard let headlineBody = headlineBody else { return nil }
return try createTitleLockupModel(headlineBody: headlineBody)
}
public func deprecatedEncode(to encoder: Encoder) throws -> Bool {
guard let headlineBody = headlineBody else { return false }
var container = encoder.container(keyedBy: DeprecatedCodingKeys.self)
try container.encode(headlineBody, forKey: DeprecatedCodingKeys.headlineBody)
return true
}
public func createTitleLockupModel(defaultStyle: HeadlineBodyModel.Style = .header, headlineBody: HeadlineBodyModel) throws -> TitleLockupModel {
guard let headline = headlineBody.headline else { throw ModelRegistry.Error.decoderOther(message: "headline is required for this use case.") }
var body = headlineBody.body
switch headlineBody.style ?? defaultStyle {
case .landingHeader:
headline.fontStyle = Styler.Font.RegularTitle2XLarge
body?.fontStyle = Styler.Font.RegularTitleMedium
case .itemHeader:
headline.fontStyle = Styler.Font.BoldTitleLarge
body?.fontStyle = Styler.Font.RegularBodyLarge
default:
headline.fontStyle = Styler.Font.RegularTitleXLarge
body?.fontStyle = Styler.Font.RegularTitleMedium
}
let model = try TitleLockupModel(title: headline, subTitle: body)
model.id = headlineBody.id
return model
}
public func createHeadlineBodyModel(titleLockup: TitleLockupModel) -> HeadlineBodyModel {
var headlineBody = HeadlineBodyModel(headline: titleLockup.title)
headlineBody.body = titleLockup.subTitle
headlineBody.id = titleLockup.id
return headlineBody
} }
} }

View File

@ -9,15 +9,15 @@
import Foundation import Foundation
@objcMembers open class HeadersH2Buttons: HeaderView { open class HeadersH2Buttons: HeaderView {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Outlets // MARK: - Outlets
//-------------------------------------------------- //--------------------------------------------------
public let headlineBody = HeadlineBody() public let titleLockup = TitleLockup()
public let buttons = TwoButtonView() public let buttons = TwoButtonView()
public lazy var stack: Stack<StackModel> = { public lazy var stack: Stack<StackModel> = {
return Stack<StackModel>.createStack(with: [headlineBody, buttons], spacing: PaddingDefaultVerticalSpacing3) return Stack<StackModel>.createStack(with: [titleLockup, buttons], spacing: PaddingDefaultVerticalSpacing3)
}() }()
//------------------------------------------------------- //-------------------------------------------------------
@ -26,7 +26,6 @@ import Foundation
open override func setupView() { open override func setupView() {
super.setupView() super.setupView()
headlineBody.stylePageHeader()
addMolecule(stack) addMolecule(stack)
stack.restack() stack.restack()
} }
@ -40,16 +39,11 @@ import Foundation
guard let model = model as? HeadersH2ButtonsModel else { return } guard let model = model as? HeadersH2ButtonsModel else { return }
headlineBody.set(with: model.headlineBody, delegateObject, additionalData) titleLockup.set(with: model.titleLockup, delegateObject, additionalData)
buttons.set(with: model.buttons, delegateObject, additionalData) buttons.set(with: model.buttons, delegateObject, additionalData)
} }
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return 121 return 121
} }
open override func reset() {
super.reset()
headlineBody.stylePageHeader()
}
} }

View File

@ -15,15 +15,16 @@ public class HeadersH2ButtonsModel: HeaderModel, MoleculeModelProtocol, ParentMo
//-------------------------------------------------- //--------------------------------------------------
public static var identifier: String = "headerH2Btns" public static var identifier: String = "headerH2Btns"
public var headlineBody: HeadlineBodyModel public var titleLockup: TitleLockupModel
public var buttons: TwoButtonViewModel public var buttons: TwoButtonViewModel
private var helper = DeprecatedHeadlineBodyHelper()
public var children: [MoleculeModelProtocol] { public var children: [MoleculeModelProtocol] {
[headlineBody, buttons] [titleLockup, buttons]
} }
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool { public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool {
return try replaceChildMolecule(at: &headlineBody, with: molecule) return try replaceChildMolecule(at: &titleLockup, with: molecule)
|| replaceChildMolecule(at: &buttons, with: molecule) || replaceChildMolecule(at: &buttons, with: molecule)
} }
@ -31,8 +32,8 @@ public class HeadersH2ButtonsModel: HeaderModel, MoleculeModelProtocol, ParentMo
// MARK: - Initializer // MARK: - Initializer
//-------------------------------------------------- //--------------------------------------------------
public init(headlineBody: HeadlineBodyModel, buttons: TwoButtonViewModel) { public init(titleLockup: TitleLockupModel, buttons: TwoButtonViewModel) {
self.headlineBody = headlineBody self.titleLockup = titleLockup
self.buttons = buttons self.buttons = buttons
super.init() super.init()
} }
@ -48,8 +49,11 @@ public class HeadersH2ButtonsModel: HeaderModel, MoleculeModelProtocol, ParentMo
if bottomPadding == nil { if bottomPadding == nil {
bottomPadding = Padding.Component.VerticalMarginSpacing bottomPadding = Padding.Component.VerticalMarginSpacing
} }
if headlineBody.headline?.accessibilityTraits == nil { if titleLockup.title.fontStyle == nil {
headlineBody.headline?.accessibilityTraits = .header titleLockup.title.fontStyle = Styler.Font.RegularTitleXLarge
}
if titleLockup.subTitle?.fontStyle == nil {
titleLockup.subTitle?.fontStyle = Styler.Font.RegularTitleMedium
} }
super.setDefaults() super.setDefaults()
} }
@ -60,7 +64,7 @@ public class HeadersH2ButtonsModel: HeaderModel, MoleculeModelProtocol, ParentMo
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case moleculeName case moleculeName
case headlineBody case titleLockup
case buttons case buttons
} }
@ -70,7 +74,7 @@ public class HeadersH2ButtonsModel: HeaderModel, MoleculeModelProtocol, ParentMo
required public init(from decoder: Decoder) throws { required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self) let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
headlineBody = try typeContainer.decode(HeadlineBodyModel.self, forKey: .headlineBody) titleLockup = try typeContainer.decodeMolecule(codingKey: .titleLockup)
buttons = try typeContainer.decode(TwoButtonViewModel.self, forKey: .buttons) buttons = try typeContainer.decode(TwoButtonViewModel.self, forKey: .buttons)
try super.init(from: decoder) try super.init(from: decoder)
} }
@ -79,7 +83,8 @@ public class HeadersH2ButtonsModel: HeaderModel, MoleculeModelProtocol, ParentMo
try super.encode(to: encoder) try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self) var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName) try container.encode(moleculeName, forKey: .moleculeName)
try container.encode(headlineBody, forKey: .headlineBody)
try container.encode(buttons, forKey: .buttons) try container.encode(buttons, forKey: .buttons)
guard try !helper.deprecatedEncode(to: encoder) else { return }
try container.encode(titleLockup, forKey: .titleLockup)
} }
} }

View File

@ -7,14 +7,14 @@
// //
import Foundation import Foundation
@objcMembers open class HeadersH2CaretLink: HeaderView { open class HeadersH2CaretLink: HeaderView {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Outlets // MARK: - Outlets
//-------------------------------------------------- //--------------------------------------------------
public let headlineBody = HeadlineBody() public let titleLockup = TitleLockup()
public let caretLink = CaretLink() public let caretLink = CaretLink()
public lazy var stack: Stack<StackModel> = { public lazy var stack: Stack<StackModel> = {
return Stack<StackModel>.createStack(with: [headlineBody, caretLink]) return Stack<StackModel>.createStack(with: [titleLockup, caretLink])
}() }()
//------------------------------------------------------- //-------------------------------------------------------
@ -22,7 +22,6 @@ import Foundation
//------------------------------------------------------- //-------------------------------------------------------
open override func setupView() { open override func setupView() {
super.setupView() super.setupView()
headlineBody.stylePageHeader()
addMolecule(stack) addMolecule(stack)
stack.restack() stack.restack()
} }
@ -33,16 +32,11 @@ import Foundation
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
super.set(with: model, delegateObject, additionalData) super.set(with: model, delegateObject, additionalData)
guard let model = model as? HeadersH2CaretLinkModel else { return } guard let model = model as? HeadersH2CaretLinkModel else { return }
headlineBody.set(with: model.headlineBody, delegateObject, additionalData) titleLockup.set(with: model.titleLockup, delegateObject, additionalData)
caretLink.set(with: model.caretLink, delegateObject, additionalData) caretLink.set(with: model.caretLink, delegateObject, additionalData)
} }
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return 121 return 121
} }
open override func reset() {
super.reset()
headlineBody.stylePageHeader()
}
} }

View File

@ -12,23 +12,24 @@ public class HeadersH2CaretLinkModel: HeaderModel, MoleculeModelProtocol, Parent
// MARK: - Properties // MARK: - Properties
//-------------------------------------------------- //--------------------------------------------------
public static var identifier: String = "headerH2CrtBtn" public static var identifier: String = "headerH2CrtBtn"
public var headlineBody: HeadlineBodyModel public var titleLockup: TitleLockupModel
public var caretLink: CaretLinkModel public var caretLink: CaretLinkModel
private var helper = DeprecatedHeadlineBodyHelper()
public var children: [MoleculeModelProtocol] { public var children: [MoleculeModelProtocol] {
[headlineBody, caretLink] [titleLockup, caretLink]
} }
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool { public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool {
return try replaceChildMolecule(at: &headlineBody, with: molecule) return try replaceChildMolecule(at: &titleLockup, with: molecule)
|| replaceChildMolecule(at: &caretLink, with: molecule) || replaceChildMolecule(at: &caretLink, with: molecule)
} }
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Initializer // MARK: - Initializer
//-------------------------------------------------- //--------------------------------------------------
public init(headlineBody: HeadlineBodyModel, caretLink: CaretLinkModel) { public init(titleLockup: TitleLockupModel, caretLink: CaretLinkModel) {
self.headlineBody = headlineBody self.titleLockup = titleLockup
self.caretLink = caretLink self.caretLink = caretLink
super.init() super.init()
} }
@ -43,8 +44,11 @@ public class HeadersH2CaretLinkModel: HeaderModel, MoleculeModelProtocol, Parent
if bottomPadding == nil { if bottomPadding == nil {
bottomPadding = Padding.Component.VerticalMarginSpacing bottomPadding = Padding.Component.VerticalMarginSpacing
} }
if headlineBody.headline?.accessibilityTraits == nil { if titleLockup.title.fontStyle == nil {
headlineBody.headline?.accessibilityTraits = .header titleLockup.title.fontStyle = Styler.Font.RegularTitleXLarge
}
if titleLockup.subTitle?.fontStyle == nil {
titleLockup.subTitle?.fontStyle = Styler.Font.RegularTitleMedium
} }
super.setDefaults() super.setDefaults()
} }
@ -54,7 +58,7 @@ public class HeadersH2CaretLinkModel: HeaderModel, MoleculeModelProtocol, Parent
//-------------------------------------------------- //--------------------------------------------------
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case moleculeName case moleculeName
case headlineBody case titleLockup
case caretLink case caretLink
} }
@ -63,7 +67,7 @@ public class HeadersH2CaretLinkModel: HeaderModel, MoleculeModelProtocol, Parent
//-------------------------------------------------- //--------------------------------------------------
required public init(from decoder: Decoder) throws { required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self) let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
headlineBody = try typeContainer.decode(HeadlineBodyModel.self, forKey: .headlineBody) titleLockup = try typeContainer.decodeMolecule(codingKey: .titleLockup)
caretLink = try typeContainer.decode(CaretLinkModel.self, forKey: .caretLink) caretLink = try typeContainer.decode(CaretLinkModel.self, forKey: .caretLink)
try super.init(from: decoder) try super.init(from: decoder)
} }
@ -72,7 +76,8 @@ public class HeadersH2CaretLinkModel: HeaderModel, MoleculeModelProtocol, Parent
try super.encode(to: encoder) try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self) var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName) try container.encode(moleculeName, forKey: .moleculeName)
try container.encode(headlineBody, forKey: .headlineBody)
try container.encode(caretLink, forKey: .caretLink) try container.encode(caretLink, forKey: .caretLink)
guard try !helper.deprecatedEncode(to: encoder) else { return }
try container.encode(titleLockup, forKey: .titleLockup)
} }
} }

View File

@ -8,14 +8,14 @@
import Foundation import Foundation
@objcMembers open class HeadersH2Link: HeaderView { open class HeadersH2Link: HeaderView {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Outlets // MARK: - Outlets
//-------------------------------------------------- //--------------------------------------------------
public let headlineBody = HeadlineBody() public let titleLockup = TitleLockup()
public let link = Link() public let link = Link()
public lazy var stack: Stack<StackModel> = { public lazy var stack: Stack<StackModel> = {
return Stack<StackModel>.createStack(with: [headlineBody, link]) return Stack<StackModel>.createStack(with: [titleLockup, link])
}() }()
//------------------------------------------------------- //-------------------------------------------------------
@ -23,7 +23,6 @@ import Foundation
//------------------------------------------------------- //-------------------------------------------------------
open override func setupView() { open override func setupView() {
super.setupView() super.setupView()
headlineBody.stylePageHeader()
addMolecule(stack) addMolecule(stack)
stack.restack() stack.restack()
} }
@ -34,16 +33,11 @@ import Foundation
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
super.set(with: model, delegateObject, additionalData) super.set(with: model, delegateObject, additionalData)
guard let model = model as? HeadersH2LinkModel else { return } guard let model = model as? HeadersH2LinkModel else { return }
headlineBody.set(with: model.headlineBody, delegateObject, additionalData) titleLockup.set(with: model.titleLockup, delegateObject, additionalData)
link.set(with: model.link, delegateObject, additionalData) link.set(with: model.link, delegateObject, additionalData)
} }
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return 121 return 121
} }
open override func reset() {
super.reset()
headlineBody.stylePageHeader()
}
} }

View File

@ -14,15 +14,16 @@ public class HeadersH2LinkModel: HeaderModel, MoleculeModelProtocol, ParentMolec
//-------------------------------------------------- //--------------------------------------------------
public static var identifier: String = "headerH2Link" public static var identifier: String = "headerH2Link"
public var headlineBody: HeadlineBodyModel public var titleLockup: TitleLockupModel
public var link: LinkModel public var link: LinkModel
private var helper = DeprecatedHeadlineBodyHelper()
public var children: [MoleculeModelProtocol] { public var children: [MoleculeModelProtocol] {
[headlineBody, link] [titleLockup, link]
} }
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool { public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool {
return try replaceChildMolecule(at: &headlineBody, with: molecule) return try replaceChildMolecule(at: &titleLockup, with: molecule)
|| replaceChildMolecule(at: &link, with: molecule) || replaceChildMolecule(at: &link, with: molecule)
} }
@ -30,8 +31,8 @@ public class HeadersH2LinkModel: HeaderModel, MoleculeModelProtocol, ParentMolec
// MARK: - Initializer // MARK: - Initializer
//-------------------------------------------------- //--------------------------------------------------
public init(headlineBody: HeadlineBodyModel, link: LinkModel) { public init(titleLockup: TitleLockupModel, link: LinkModel) {
self.headlineBody = headlineBody self.titleLockup = titleLockup
self.link = link self.link = link
super.init() super.init()
} }
@ -47,8 +48,11 @@ public class HeadersH2LinkModel: HeaderModel, MoleculeModelProtocol, ParentMolec
if bottomPadding == nil { if bottomPadding == nil {
bottomPadding = Padding.Component.VerticalMarginSpacing bottomPadding = Padding.Component.VerticalMarginSpacing
} }
if headlineBody.headline?.accessibilityTraits == nil { if titleLockup.title.fontStyle == nil {
headlineBody.headline?.accessibilityTraits = .header titleLockup.title.fontStyle = Styler.Font.RegularTitleXLarge
}
if titleLockup.subTitle?.fontStyle == nil {
titleLockup.subTitle?.fontStyle = Styler.Font.RegularTitleMedium
} }
super.setDefaults() super.setDefaults()
} }
@ -59,7 +63,7 @@ public class HeadersH2LinkModel: HeaderModel, MoleculeModelProtocol, ParentMolec
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case moleculeName case moleculeName
case headlineBody case titleLockup
case link case link
} }
@ -69,7 +73,7 @@ public class HeadersH2LinkModel: HeaderModel, MoleculeModelProtocol, ParentMolec
required public init(from decoder: Decoder) throws { required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self) let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
headlineBody = try typeContainer.decode(HeadlineBodyModel.self, forKey: .headlineBody) titleLockup = try typeContainer.decodeMolecule(codingKey: .titleLockup)
link = try typeContainer.decode(LinkModel.self, forKey: .link) link = try typeContainer.decode(LinkModel.self, forKey: .link)
try super.init(from: decoder) try super.init(from: decoder)
} }
@ -78,7 +82,8 @@ public class HeadersH2LinkModel: HeaderModel, MoleculeModelProtocol, ParentMolec
try super.encode(to: encoder) try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self) var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName) try container.encode(moleculeName, forKey: .moleculeName)
try container.encode(headlineBody, forKey: .headlineBody)
try container.encode(link, forKey: .link) try container.encode(link, forKey: .link)
guard try !helper.deprecatedEncode(to: encoder) else { return }
try container.encode(titleLockup, forKey: .titleLockup)
} }
} }

View File

@ -9,12 +9,12 @@
import Foundation import Foundation
@objcMembers open class HeadersH2NoButtonsBodyText: HeaderView { open class HeadersH2NoButtonsBodyText: HeaderView {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Outlets // MARK: - Outlets
//-------------------------------------------------- //--------------------------------------------------
public let headlineBody = HeadlineBody() public let titleLockup = TitleLockup()
//------------------------------------------------------- //-------------------------------------------------------
// MARK: - View Lifecycle // MARK: - View Lifecycle
@ -22,8 +22,7 @@ import Foundation
open override func setupView() { open override func setupView() {
super.setupView() super.setupView()
headlineBody.stylePageHeader() addMolecule(titleLockup)
addMolecule(headlineBody)
} }
//---------------------------------------------------- //----------------------------------------------------
@ -34,15 +33,10 @@ import Foundation
guard let model = model as? HeadersH2NoButtonsBodyTextModel else { return } guard let model = model as? HeadersH2NoButtonsBodyTextModel else { return }
headlineBody.set(with: model.headlineBody, delegateObject, additionalData) titleLockup.set(with: model.titleLockup, delegateObject, additionalData)
} }
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return 121 return 121
} }
open override func reset() {
super.reset()
headlineBody.stylePageHeader()
}
} }

View File

@ -15,22 +15,23 @@ public class HeadersH2NoButtonsBodyTextModel: HeaderModel, MoleculeModelProtocol
//-------------------------------------------------- //--------------------------------------------------
public static var identifier: String = "headerH2" public static var identifier: String = "headerH2"
public var headlineBody: HeadlineBodyModel public var titleLockup: TitleLockupModel
private var helper = DeprecatedHeadlineBodyHelper()
public var children: [MoleculeModelProtocol] { public var children: [MoleculeModelProtocol] {
[headlineBody] [titleLockup]
} }
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool { public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool {
return try replaceChildMolecule(at: &headlineBody, with: molecule) return try replaceChildMolecule(at: &titleLockup, with: molecule)
} }
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Initializer // MARK: - Initializer
//-------------------------------------------------- //--------------------------------------------------
public init(headlineBody: HeadlineBodyModel) { public init(titleLockup: TitleLockupModel) {
self.headlineBody = headlineBody self.titleLockup = titleLockup
super.init() super.init()
} }
@ -41,8 +42,11 @@ public class HeadersH2NoButtonsBodyTextModel: HeaderModel, MoleculeModelProtocol
if bottomPadding == nil { if bottomPadding == nil {
bottomPadding = Padding.Component.VerticalMarginSpacing bottomPadding = Padding.Component.VerticalMarginSpacing
} }
if headlineBody.headline?.accessibilityTraits == nil { if titleLockup.title.fontStyle == nil {
headlineBody.headline?.accessibilityTraits = .header titleLockup.title.fontStyle = Styler.Font.RegularTitleXLarge
}
if titleLockup.subTitle?.fontStyle == nil {
titleLockup.subTitle?.fontStyle = Styler.Font.RegularTitleMedium
} }
super.setDefaults() super.setDefaults()
} }
@ -53,7 +57,7 @@ public class HeadersH2NoButtonsBodyTextModel: HeaderModel, MoleculeModelProtocol
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case moleculeName case moleculeName
case headlineBody case titleLockup
} }
//-------------------------------------------------- //--------------------------------------------------
@ -62,7 +66,7 @@ public class HeadersH2NoButtonsBodyTextModel: HeaderModel, MoleculeModelProtocol
required public init(from decoder: Decoder) throws { required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self) let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
headlineBody = try typeContainer.decode(HeadlineBodyModel.self, forKey: .headlineBody) titleLockup = try helper.deprecatedCreate(from: decoder) ?? typeContainer.decodeMolecule(codingKey: .titleLockup)
try super.init(from: decoder) try super.init(from: decoder)
} }
@ -70,6 +74,7 @@ public class HeadersH2NoButtonsBodyTextModel: HeaderModel, MoleculeModelProtocol
try super.encode(to: encoder) try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self) var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName) try container.encode(moleculeName, forKey: .moleculeName)
try container.encode(headlineBody, forKey: .headlineBody) guard try !helper.deprecatedEncode(to: encoder) else { return }
try container.encode(titleLockup, forKey: .titleLockup)
} }
} }

View File

@ -9,15 +9,15 @@
import Foundation import Foundation
@objcMembers open class HeadersH2TinyButton: HeaderView { open class HeadersH2TinyButton: HeaderView {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Outlets // MARK: - Outlets
//-------------------------------------------------- //--------------------------------------------------
public let headlineBody = HeadlineBody() public let titleLockup = TitleLockup()
public let button = PillButton() public let button = PillButton()
public lazy var stack: Stack<StackModel> = { public lazy var stack: Stack<StackModel> = {
return Stack<StackModel>.createStack(with: [(view: headlineBody, model: StackItemModel(horizontalAlignment: .fill)), return Stack<StackModel>.createStack(with: [(view: titleLockup, model: StackItemModel(horizontalAlignment: .fill)),
(view: button, model: StackItemModel(spacing: spacingBetwenHeadlineBodyAndButton, horizontalAlignment: .leading))], (view: button, model: StackItemModel(spacing: spacingBetwenHeadlineBodyAndButton, horizontalAlignment: .leading))],
axis: .vertical) axis: .vertical)
}() }()
@ -34,7 +34,6 @@ import Foundation
open override func setupView() { open override func setupView() {
super.setupView() super.setupView()
headlineBody.stylePageHeader()
addMolecule(stack) addMolecule(stack)
stack.restack() stack.restack()
} }
@ -48,16 +47,11 @@ import Foundation
guard let model = model as? HeadersH2TinyButtonModel else { return } guard let model = model as? HeadersH2TinyButtonModel else { return }
headlineBody.set(with: model.headlineBody, delegateObject, additionalData) titleLockup.set(with: model.titleLockup, delegateObject, additionalData)
button.set(with: model.button, delegateObject, additionalData) button.set(with: model.button, delegateObject, additionalData)
} }
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return 121 return 121
} }
open override func reset() {
super.reset()
headlineBody.stylePageHeader()
}
} }

View File

@ -15,15 +15,16 @@ public class HeadersH2TinyButtonModel: HeaderModel, MoleculeModelProtocol, Paren
//-------------------------------------------------- //--------------------------------------------------
public static var identifier: String = "headerH2BtnTny" public static var identifier: String = "headerH2BtnTny"
public var headlineBody: HeadlineBodyModel public var titleLockup: TitleLockupModel
public var button: ButtonModel public var button: ButtonModel
private var helper = DeprecatedHeadlineBodyHelper()
public var children: [MoleculeModelProtocol] { public var children: [MoleculeModelProtocol] {
[headlineBody, button] [titleLockup, button]
} }
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool { public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool {
return try replaceChildMolecule(at: &headlineBody, with: molecule) return try replaceChildMolecule(at: &titleLockup, with: molecule)
|| replaceChildMolecule(at: &button, with: molecule) || replaceChildMolecule(at: &button, with: molecule)
} }
@ -31,8 +32,8 @@ public class HeadersH2TinyButtonModel: HeaderModel, MoleculeModelProtocol, Paren
// MARK: - Initializer // MARK: - Initializer
//-------------------------------------------------- //--------------------------------------------------
public init(headlineBody: HeadlineBodyModel, button: ButtonModel) { public init(titleLockup: TitleLockupModel, button: ButtonModel) {
self.headlineBody = headlineBody self.titleLockup = titleLockup
self.button = button self.button = button
super.init() super.init()
} }
@ -48,8 +49,11 @@ public class HeadersH2TinyButtonModel: HeaderModel, MoleculeModelProtocol, Paren
if bottomPadding == nil { if bottomPadding == nil {
bottomPadding = Padding.Component.VerticalMarginSpacing bottomPadding = Padding.Component.VerticalMarginSpacing
} }
if headlineBody.headline?.accessibilityTraits == nil { if titleLockup.title.fontStyle == nil {
headlineBody.headline?.accessibilityTraits = .header titleLockup.title.fontStyle = Styler.Font.RegularTitleXLarge
}
if titleLockup.subTitle?.fontStyle == nil {
titleLockup.subTitle?.fontStyle = Styler.Font.RegularTitleMedium
} }
super.setDefaults() super.setDefaults()
button.style = .secondary button.style = .secondary
@ -62,7 +66,7 @@ public class HeadersH2TinyButtonModel: HeaderModel, MoleculeModelProtocol, Paren
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case moleculeName case moleculeName
case headlineBody case titleLockup
case button case button
} }
@ -72,7 +76,7 @@ public class HeadersH2TinyButtonModel: HeaderModel, MoleculeModelProtocol, Paren
required public init(from decoder: Decoder) throws { required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self) let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
headlineBody = try typeContainer.decode(HeadlineBodyModel.self, forKey: .headlineBody) titleLockup = try typeContainer.decodeMolecule(codingKey: .titleLockup)
button = try typeContainer.decode(ButtonModel.self, forKey: .button) button = try typeContainer.decode(ButtonModel.self, forKey: .button)
try super.init(from: decoder) try super.init(from: decoder)
} }
@ -81,7 +85,8 @@ public class HeadersH2TinyButtonModel: HeaderModel, MoleculeModelProtocol, Paren
try super.encode(to: encoder) try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self) var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName) try container.encode(moleculeName, forKey: .moleculeName)
try container.encode(headlineBody, forKey: .headlineBody)
try container.encode(button, forKey: .button) try container.encode(button, forKey: .button)
guard try !helper.deprecatedEncode(to: encoder) else { return }
try container.encode(titleLockup, forKey: .titleLockup)
} }
} }

View File

@ -31,7 +31,7 @@ open class HeaderView: Container {
(molecule as? MVMCoreViewProtocol)?.updateView(size) (molecule as? MVMCoreViewProtocol)?.updateView(size)
} }
public override func setupView() { open override func setupView() {
super.setupView() super.setupView()
line.setStyle(.none) line.setStyle(.none)
addSubview(line) addSubview(line)

View File

@ -7,9 +7,9 @@
// //
@objcMembers public class HeaderModel: ContainerModel { open class HeaderModel: ContainerModel {
public var backgroundColor: Color? open var backgroundColor: Color?
public var line: LineModel? open var line: LineModel?
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case line case line
@ -17,7 +17,7 @@
} }
/// Defaults to set /// Defaults to set
public override func setDefaults() { open override func setDefaults() {
if useHorizontalMargins == nil { if useHorizontalMargins == nil {
useHorizontalMargins = true useHorizontalMargins = true
} }
@ -43,7 +43,7 @@
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
} }
public override func encode(to encoder: Encoder) throws { open override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder) try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self) var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(line, forKey: .line) try container.encode(line, forKey: .line)

View File

@ -41,16 +41,6 @@ import VDS
} }
} }
} }
//--------------------------------------------------
// MARK: - Public Properties Overrides
//--------------------------------------------------
open override var selectedIndex: Int {
didSet {
guard let viewModel else { return }
viewModel.selectedIndex = selectedIndex
}
}
//------------------------------------------------- //-------------------------------------------------
// MARK: - Layout Views // MARK: - Layout Views

View File

@ -17,11 +17,11 @@ import VDS
open var viewModel: TwoButtonViewModel! open var viewModel: TwoButtonViewModel!
open var delegateObject: MVMCoreUIDelegateObject? open var delegateObject: MVMCoreUIDelegateObject?
open var additionalData: [AnyHashable : Any]? open var additionalData: [AnyHashable : Any]?
open var primaryButton = PillButton() open var primaryButton = PillButton()
open var secondaryButton = PillButton() open var secondaryButton = PillButton()
private var buttonGroup = VDS.ButtonGroup() private var buttonGroup = VDS.ButtonGroup()
private var heightConstraint: NSLayoutConstraint?
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Lifecycle // MARK: - Lifecycle
//-------------------------------------------------- //--------------------------------------------------
@ -34,6 +34,7 @@ import VDS
buttonGroup.alignment = .center buttonGroup.alignment = .center
buttonGroup.rowQuantityPhone = 2 buttonGroup.rowQuantityPhone = 2
buttonGroup.rowQuantityTablet = 2 buttonGroup.rowQuantityTablet = 2
heightConstraint = height(constant: VDS.Button.Size.large.height, priority: .required)
} }
//-------------------------------------------------- //--------------------------------------------------
@ -70,6 +71,8 @@ import VDS
if buttons.count != buttonGroup.buttons.count { if buttons.count != buttonGroup.buttons.count {
buttonGroup.buttons = buttons buttonGroup.buttons = buttons
} }
heightConstraint?.constant = primaryButton.size == .small || secondaryButton.size == .small ? VDS.Button.Size.small.height : VDS.Button.Size.large.height
} }
//-------------------------------------------------- //--------------------------------------------------

View File

@ -38,6 +38,7 @@ public class TwoButtonViewModel: ParentMoleculeModelProtocol {
case backgroundColor case backgroundColor
case primaryButton case primaryButton
case secondaryButton case secondaryButton
case fillContainer
} }
//-------------------------------------------------- //--------------------------------------------------
@ -69,6 +70,7 @@ public class TwoButtonViewModel: ParentMoleculeModelProtocol {
try decoder.setContext(value: Use.secondary, for: "style") { try decoder.setContext(value: Use.secondary, for: "style") {
self.secondaryButton = try typeContainer.decodeMoleculeIfPresent(codingKey: .secondaryButton) self.secondaryButton = try typeContainer.decodeMoleculeIfPresent(codingKey: .secondaryButton)
} }
fillContainer = try typeContainer.decodeIfPresent(Bool.self, forKey: .fillContainer) ?? false
} }
public func encode(to encoder: Encoder) throws { public func encode(to encoder: Encoder) throws {
@ -78,5 +80,6 @@ public class TwoButtonViewModel: ParentMoleculeModelProtocol {
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encodeIfPresent(primaryButton, forKey: .primaryButton) try container.encodeIfPresent(primaryButton, forKey: .primaryButton)
try container.encodeIfPresent(secondaryButton, forKey: .secondaryButton) try container.encodeIfPresent(secondaryButton, forKey: .secondaryButton)
try container.encodeIfPresent(fillContainer, forKey: .fillContainer)
} }
} }

View File

@ -14,7 +14,7 @@
public let stack = Stack<StackModel>(frame: .zero) public let stack = Stack<StackModel>(frame: .zero)
public let eyebrow = Label(fontStyle: .RegularMicro) public let eyebrow = Label(fontStyle: .RegularMicro)
public let headline = Label(fontStyle: .BoldBodySmall) public let headline = Label(fontStyle: .RegularTitleSmall)
public let body = Label(fontStyle: .RegularBodySmall, true) public let body = Label(fontStyle: .RegularBodySmall, true)
public let link = Link() public let link = Link()
@ -58,7 +58,7 @@
super.reset() super.reset()
stack.reset() stack.reset()
eyebrow.setFontStyle(.RegularMicro) eyebrow.setFontStyle(.RegularMicro)
headline.setFontStyle(.BoldBodySmall) headline.setFontStyle(.RegularTitleSmall)
body.setFontStyle(.RegularBodySmall) body.setFontStyle(.RegularBodySmall)
} }

View File

@ -60,9 +60,9 @@ open class HeadlineBody: View {
} }
public func stylePageHeader() { public func stylePageHeader() {
headlineLabel.setFontStyle(.RegularTitleLarge) headlineLabel.setFontStyle(.RegularTitleXLarge)
messageLabel.setFontStyle(.RegularBodyLarge) messageLabel.setFontStyle(.RegularTitleMedium)
spaceBetweenLabelsConstant = Padding.Two spaceBetweenLabelsConstant = Padding.Four
} }
public func styleListItem() { public func styleListItem() {
@ -72,8 +72,8 @@ open class HeadlineBody: View {
} }
public func styleListItemDivider() { public func styleListItemDivider() {
headlineLabel.setFontStyle(.BoldTitleSmall) headlineLabel.setFontStyle(.BoldTitleLarge)
messageLabel.setFontStyle(.RegularBodySmall) messageLabel.setFontStyle(.RegularBodyLarge)
spaceBetweenLabelsConstant = Padding.Two spaceBetweenLabelsConstant = Padding.Two
} }

View File

@ -6,8 +6,8 @@
// Copyright © 2019 Suresh, Kamlesh. All rights reserved. // Copyright © 2019 Suresh, Kamlesh. All rights reserved.
// //
import MVMCore
@objcMembers open class HeadlineBodyModel: ParentMoleculeModelProtocol { open class HeadlineBodyModel: ParentMoleculeModelProtocol {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Properties // MARK: - Properties
//-------------------------------------------------- //--------------------------------------------------
@ -90,3 +90,24 @@
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
} }
} }
public extension HeadlineBodyModel {
func createHeaderTitleLockupModel(defaultStyle: Style = .header) throws -> TitleLockupModel {
guard let headline = headline else { throw ModelRegistry.Error.decoderOther(message: "headline is required for this use case.") }
var body = self.body
switch style ?? defaultStyle {
case .landingHeader:
headline.fontStyle = Styler.Font.RegularTitle2XLarge
body?.fontStyle = Styler.Font.RegularTitleMedium
case .itemHeader:
headline.fontStyle = Styler.Font.BoldTitleLarge
body?.fontStyle = Styler.Font.RegularBodyLarge
default:
headline.fontStyle = Styler.Font.RegularTitleXLarge
body?.fontStyle = Styler.Font.RegularTitleMedium
}
let model = try TitleLockupModel(title: headline, subTitle: body)
model.id = id
return model
}
}

View File

@ -55,6 +55,9 @@ open class Carousel: View {
/// The view that we use for paging /// The view that we use for paging
public var pagingView: (MoleculeViewProtocol & CarouselPageControlProtocol)? public var pagingView: (MoleculeViewProtocol & CarouselPageControlProtocol)?
/// The pagingView anchor to the bottom of the carousel. Disabled when the pagingView is hidden.
public var pagingBottomPin: NSLayoutConstraint?
/// If the carousel should loop after scrolling past the first and final cells. /// If the carousel should loop after scrolling past the first and final cells.
public var loop = false public var loop = false
@ -89,10 +92,10 @@ open class Carousel: View {
// Go to current cell. layoutIfNeeded is needed otherwise cellForItem returns nil for peaking logic. The dispatch is a sad way to ensure the collection view is ready to be scrolled. // Go to current cell. layoutIfNeeded is needed otherwise cellForItem returns nil for peaking logic. The dispatch is a sad way to ensure the collection view is ready to be scrolled.
guard let model = model as? CarouselModel, !model.molecules.isEmpty, guard let model = model as? CarouselModel, !model.molecules.isEmpty,
(model.paging == true || loop == true) else { return } (model.paging == true || loop == true) else { return }
DispatchQueue.main.async { DispatchQueue.main.async { [self] in
self.collectionView.scrollToItem(at: IndexPath(row: self.currentIndex, section: 0), at: self.itemAlignment, animated: false) collectionView.scrollToItem(at: IndexPath(row: currentIndex, section: 0), at: itemAlignment, animated: false)
self.collectionView.layoutIfNeeded() collectionView.layoutIfNeeded()
self.showPeaking(true) showPeaking(true)
} }
} }
@ -137,6 +140,16 @@ open class Carousel: View {
(cell as? MVMCoreViewProtocol)?.updateView(size) (cell as? MVMCoreViewProtocol)?.updateView(size)
} }
layoutCollection() layoutCollection()
// Check must be dispatched to main for the layout to complete in layoutCollection.
DispatchQueue.main.async { [self] in
let shouldHidePager = molecules?.count ?? 0 < 2 || collectionView.contentSize.width < bounds.width
if let pagingView = pagingView, shouldHidePager != pagingView.isHidden {
pagingView.isHidden = shouldHidePager
pagingBottomPin?.isActive = !shouldHidePager
delegateObject?.moleculeDelegate?.moleculeLayoutUpdated(self)
}
}
} }
//-------------------------------------------------- //--------------------------------------------------
@ -276,7 +289,8 @@ open class Carousel: View {
addSubview(pagingView) addSubview(pagingView)
pagingView.centerXAnchor.constraint(equalTo: collectionView.centerXAnchor).isActive = true pagingView.centerXAnchor.constraint(equalTo: collectionView.centerXAnchor).isActive = true
collectionView.bottomAnchor.constraint(equalTo: pagingView.centerYAnchor, constant: position).isActive = true collectionView.bottomAnchor.constraint(equalTo: pagingView.centerYAnchor, constant: position).isActive = true
bottomAnchor.constraint(greaterThanOrEqualTo: pagingView.bottomAnchor).isActive = true pagingBottomPin = bottomAnchor.constraint(greaterThanOrEqualTo: pagingView.bottomAnchor)
pagingBottomPin?.isActive = true
bottomPin = bottomAnchor.constraint(equalTo: collectionView.bottomAnchor) bottomPin = bottomAnchor.constraint(equalTo: collectionView.bottomAnchor)
bottomPin?.priority = .defaultLow bottomPin?.priority = .defaultLow
bottomPin?.isActive = true bottomPin?.isActive = true

View File

@ -21,7 +21,9 @@ public protocol VDSMoleculeViewProtocol: MoleculeViewProtocol, MVMCoreViewProtoc
} }
extension VDSMoleculeViewProtocol { extension VDSMoleculeViewProtocol {
public func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { public func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
self.model = model
guard let castedModel = model as? ViewModel else { return } guard let castedModel = model as? ViewModel else { return }
self.delegateObject = delegateObject self.delegateObject = delegateObject
self.additionalData = additionalData self.additionalData = additionalData

View File

@ -18,6 +18,8 @@
public var line: LineModel? public var line: LineModel?
public var scrollToRowIndex: Int? public var scrollToRowIndex: Int?
public var singleCellSelection: Bool = false public var singleCellSelection: Bool = false
public var footerlessSpacerHeight: CGFloat?
public var footerlessSpacerColor: Color?
public override var rootMolecules: [MoleculeModelProtocol] { public override var rootMolecules: [MoleculeModelProtocol] {
if let molecules = molecules { if let molecules = molecules {
@ -60,6 +62,8 @@
case line case line
case scrollToRowIndex case scrollToRowIndex
case singleCellSelection case singleCellSelection
case footerlessSpacerHeight
case footerlessSpacerColor
} }
//-------------------------------------------------- //--------------------------------------------------
@ -74,6 +78,8 @@
if let singleCellSelection = try typeContainer.decodeIfPresent(Bool.self, forKey: .singleCellSelection) { if let singleCellSelection = try typeContainer.decodeIfPresent(Bool.self, forKey: .singleCellSelection) {
self.singleCellSelection = singleCellSelection self.singleCellSelection = singleCellSelection
} }
footerlessSpacerColor = try typeContainer.decodeIfPresent(Color.self, forKey: .footerlessSpacerColor)
footerlessSpacerHeight = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .footerlessSpacerHeight)
try super.init(from: decoder) try super.init(from: decoder)
try validateModelHasContent() try validateModelHasContent()
} }
@ -85,5 +91,7 @@
try container.encode(line, forKey: .line) try container.encode(line, forKey: .line)
try container.encode(singleCellSelection, forKey: .singleCellSelection) try container.encode(singleCellSelection, forKey: .singleCellSelection)
try container.encodeIfPresent(scrollToRowIndex, forKey: .scrollToRowIndex) try container.encodeIfPresent(scrollToRowIndex, forKey: .scrollToRowIndex)
try container.encodeIfPresent(footerlessSpacerColor, forKey: .footerlessSpacerColor)
try container.encodeIfPresent(footerlessSpacerHeight, forKey: .footerlessSpacerHeight)
} }
} }

View File

@ -69,16 +69,21 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
return molecule return molecule
} }
override open func viewForBottom() -> UIView { open override func viewForBottom() -> UIView {
guard let footerModel = templateModel?.footer, // If there is a footer molecule return the molecule.
let molecule = generateMoleculeView(from: footerModel) if let footerModel = templateModel?.footer,
else { let molecule = generateMoleculeView(from: footerModel) {
let view = super.viewForBottom() return molecule
view.backgroundColor = templateModel?.backgroundColor?.uiColor ?? .clear
return view
} }
// Otherwise setup a bottom spacer view.
return molecule let view: UIView
if let footerlessSpacerHeight = templateModel?.footerlessSpacerHeight {
view = MVMCoreUICommonViewsUtility.getView(with: footerlessSpacerHeight <= 0.5 ? 0.5 : footerlessSpacerHeight)
} else {
view = super.viewForBottom()
}
view.backgroundColor = templateModel?.footerlessSpacerColor?.uiColor ?? templateModel?.backgroundColor?.uiColor ?? .clear
return view
} }
open override func handleNewData() { open override func handleNewData() {
@ -198,7 +203,29 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
open override func moleculeLayoutUpdated(_ molecule: MoleculeViewProtocol) { open override func moleculeLayoutUpdated(_ molecule: MoleculeViewProtocol) {
guard let tableView = tableView else { return } guard let tableView = tableView else { return }
let id = molecule.model?.id
// Check for header
var inHeaderOrFooter = false
if let _ = templateModel?.header?.findFirstMolecule(by: { compareModel in id == compareModel.id }) {
showHeader(nil)
inHeaderOrFooter = true
}
// Check for footer
if let _ = templateModel?.footer?.findFirstMolecule(by: { compareModel in id == compareModel.id }) {
showFooter(nil)
inHeaderOrFooter = true
}
// If the view is in a header or footer, need to update the constraints.
if inHeaderOrFooter {
view.setNeedsUpdateConstraints()
view.updateConstraintsIfNeeded()
return
}
// If the view is in a cell, refresh the table ui.
let point = molecule.convert(molecule.bounds.origin, to: tableView) let point = molecule.convert(molecule.bounds.origin, to: tableView)
if let indexPath = tableView.indexPathForRow(at: point), tableView.indexPathsForVisibleRows?.contains(indexPath) ?? false { if let indexPath = tableView.indexPathForRow(at: point), tableView.indexPathsForVisibleRows?.contains(indexPath) ?? false {
refreshTable() refreshTable()