Merge branch 'feature/code_condensing' into 'develop'

Feature/code condensing

See merge request BPHV_MIPS/mvm_core_ui!274
This commit is contained in:
Pfeil, Scott Robert 2020-02-24 14:35:14 -05:00
commit a132a51903
23 changed files with 251 additions and 170 deletions

View File

@ -24,7 +24,7 @@ public class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol {
public var title: String public var title: String
public var action: ActionModelProtocol public var action: ActionModelProtocol
public var enabled: Bool = true public var enabled: Bool = true
public var style: ButtonStyle? public var style: ButtonStyle? = .primary
public var size: ButtonSize? = .standard public var size: ButtonSize? = .standard
public var fillColor: Color? public var fillColor: Color?
public var textColor: Color? public var textColor: Color?

View File

@ -15,7 +15,7 @@ public class CaretLinkModel: ButtonModelProtocol, MoleculeModelProtocol {
public var title: String public var title: String
public var action: ActionModelProtocol public var action: ActionModelProtocol
public var enabledColor: Color = Color(uiColor: .black) public var enabledColor: Color = Color(uiColor: .black)
public var disabledColor: Color? = Color(uiColor: .mfSilver()) public var disabledColor: Color? = Color(uiColor: .mvmCoolGray6)
public var enabled = true public var enabled = true
public init(title: String, action: ActionModelProtocol) { public init(title: String, action: ActionModelProtocol) {

View File

@ -58,6 +58,8 @@ import Foundation
case isEnabled case isEnabled
case action case action
} }
init(isChecked: Bool = false) {}
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Codec // MARK: - Codec

View File

@ -37,7 +37,10 @@ public class CircleProgressModel: MoleculeModelProtocol {
public var colors = [Color]() public var colors = [Color]()
public var backgroundColor: Color? public var backgroundColor: Color?
public init() {} public init() {
updateStyle()
updateSize()
}
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case style case style

View File

@ -231,6 +231,7 @@ public typealias ActionBlock = () -> ()
attributedText = nil attributedText = nil
originalAttributedString = nil originalAttributedString = nil
text = labelModel.text text = labelModel.text
hero = labelModel.hero
Label.setLabel(self, withHTML: labelModel.html) Label.setLabel(self, withHTML: labelModel.html)
let alignment = LabelAlignment(rawValue: labelModel.textAlignment ?? "") let alignment = LabelAlignment(rawValue: labelModel.textAlignment ?? "")
@ -344,7 +345,6 @@ public typealias ActionBlock = () -> ()
} }
attributedText = attributedString attributedText = attributedString
originalAttributedString = attributedText originalAttributedString = attributedText
hero = labelModel.hero
} }
} }
@ -716,6 +716,7 @@ extension Label {
public func reset() { public func reset() {
text = nil text = nil
attributedText = nil attributedText = nil
hero = nil
textAlignment = .left textAlignment = .left
originalAttributedString = nil originalAttributedString = nil
styleB2(true) styleB2(true)
@ -807,9 +808,6 @@ extension Label {
- Attention: This method expects text to be set first. Otherwise, it will do nothing. - Attention: This method expects text to be set first. Otherwise, it will do nothing.
- parameter range: The range of text to be tapped. - parameter range: The range of text to be tapped.
- parameter actionMap:
- parameter delegate:
- parameter additionalData:
*/ */
@objc public func addTappableLinkAttribute(range: NSRange, actionMap: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?, delegateObject: DelegateObject?) { @objc public func addTappableLinkAttribute(range: NSRange, actionMap: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?, delegateObject: DelegateObject?) {

View File

@ -10,6 +10,10 @@
import Foundation import Foundation
@objcMembers public class LabelModel: MoleculeModelProtocol { @objcMembers public class LabelModel: MoleculeModelProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public static var identifier: String = "label" public static var identifier: String = "label"
public var backgroundColor: Color? public var backgroundColor: Color?
public var text: String public var text: String
@ -24,6 +28,10 @@ import Foundation
public var hero: Int? public var hero: Int?
public var makeWholeViewClickable: Bool? public var makeWholeViewClickable: Bool?
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case moleculeName case moleculeName
case text case text
@ -43,11 +51,19 @@ import Foundation
enum AttributeTypeKey: String, CodingKey { enum AttributeTypeKey: String, CodingKey {
case type case type
} }
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(text: String) { public init(text: String) {
self.text = text self.text = text
} }
//--------------------------------------------------
// MARK: - Codec
//--------------------------------------------------
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)
text = try typeContainer.decode(String.self, forKey: .text) text = try typeContainer.decode(String.self, forKey: .text)

View File

@ -139,7 +139,6 @@ import UIKit
topSeparatorView?.updateView(size) topSeparatorView?.updateView(size)
bottomSeparatorView?.updateView(size) bottomSeparatorView?.updateView(size)
molecule?.updateView(size) molecule?.updateView(size)
} }
@ -153,9 +152,7 @@ import UIKit
//TODO: Model, Change to model //TODO: Model, Change to model
public func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { public func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
guard let model = model as? ListItemModelProtocol else { guard let model = model as? ListItemModelProtocol else { return }
return
}
self.listItemModel = model self.listItemModel = model
style(with: model.style) style(with: model.style)
@ -194,20 +191,21 @@ import UIKit
return nil return nil
} }
// MARK: - Arrow // MARK: - Caret View
/// Adds the standard mvm style caret to the accessory view /// Adds the standard mvm style caret to the accessory view
@objc public func addCaretViewAccessory() { @objc public func addCaretViewAccessory() {
guard accessoryView == nil else { return } guard accessoryView == nil else { return }
caretView = CaretView(lineWidth: 1)
caretView?.translatesAutoresizingMaskIntoConstraints = true
caretView?.size = .small(.vertical)
caretView?.setConstraints()
if let size = caretView?.size?.dimensions() { let caret = CaretView(lineWidth: 1)
caret.translatesAutoresizingMaskIntoConstraints = true
caret.size = .small(.vertical)
if let size = caret.size?.dimensions() {
caret.frame = CGRect(origin: CGPoint.zero, size: size)
caretViewWidthSizeObject = MFSizeObject(standardSize: size.width, standardiPadPortraitSize: 9) caretViewWidthSizeObject = MFSizeObject(standardSize: size.width, standardiPadPortraitSize: 9)
caretViewHeightSizeObject = MFSizeObject(standardSize: size.height, standardiPadPortraitSize: 16) caretViewHeightSizeObject = MFSizeObject(standardSize: size.height, standardiPadPortraitSize: 16)
} }
accessoryView = caretView caretView = caret
accessoryView = caret
} }
/// NOTE: Should only be called when displayed or about to be displayed. /// NOTE: Should only be called when displayed or about to be displayed.
@ -217,11 +215,11 @@ import UIKit
layoutIfNeeded() layoutIfNeeded()
guard let heroLabel = findHeroLabel(views: contentView.subviews), let hero = heroLabel.hero else { return } guard let heroLabel = findHeroLabel(views: contentView.subviews), let hero = heroLabel.hero else { return }
let rect = Label.boundingRect(forCharacterRange: NSRange(location: hero, length: 1), in: heroLabel) let rect = Label.boundingRect(forCharacterRange: NSRange(location: hero, length: 1), in: heroLabel)
accessoryView?.center.y = contentView.convert(UIView(frame: rect).center, from: heroLabel).y accessoryView?.center.y = convert(UIView(frame: rect).center, from: heroLabel).y
heroAccessoryCenter = accessoryView?.center heroAccessoryCenter = accessoryView?.center
} }
/// Traverses the view hierarchy for a 🦸heroic Label. /// Traverses the view hierarchy for a 🦸 heroic Label.
private func findHeroLabel(views: [UIView]) -> Label? { private func findHeroLabel(views: [UIView]) -> Label? {
if views.isEmpty { if views.isEmpty {

View File

@ -27,6 +27,12 @@ public class ContainerModel: ContainerModelProtocol, Codable {
} }
public init() {} public init() {}
public convenience init(horizontalAlignment: UIStackView.Alignment? = nil, verticalAlignment: UIStackView.Alignment? = nil) {
self.init()
self.horizontalAlignment = horizontalAlignment
self.verticalAlignment = verticalAlignment
}
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)

View File

@ -8,49 +8,33 @@
import Foundation import Foundation
@objcMembers public class ListLeftVariableCheckboxAllTextAndLinks: TableViewCell { @objcMembers open class ListLeftVariableCheckboxAllTextAndLinks: TableViewCell {
public let checkbox = Checkbox(frame: .zero) public let checkbox = Checkbox(frame: .zero)
public let eyebrowHeadlineBodyLink = EyebrowHeadlineBodyLink(frame: .zero) public let eyebrowHeadlineBodyLink = EyebrowHeadlineBodyLink(frame: .zero)
public let stack = Stack<StackModel>(frame: .zero) public let stack = Stack<StackModel>(frame: .zero)
// MARK: - View Lifecycle // MARK: - View Lifecycle
open override func updateView(_ size: CGFloat) {
super.updateView(size)
stack.updateView(size)
}
override open func setupView() { override open func setupView() {
super.setupView() super.setupView()
stack.stackItems = [StackItem(andContain: checkbox),StackItem(andContain: eyebrowHeadlineBodyLink)] stack.stackItems = [StackItem(andContain: checkbox),StackItem(andContain: eyebrowHeadlineBodyLink)]
contentView.addSubview(stack) addMolecule(stack)
containerHelper.constrainView(stack)
}
// MARK:- ModelMoleculeViewProtocol
override open func reset() {
super.reset()
stack.reset()
} }
// MARK:- MVMCoreUIMoleculeViewProtocol // MARK:- MVMCoreUIMoleculeViewProtocol
public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
super.setWithModel(model, delegateObject, additionalData) super.setWithModel(model, delegateObject, additionalData)
guard let model = model as? ListLeftVariableCheckboxAllTextAndLinksModel else { return} guard let model = model as? ListLeftVariableCheckboxAllTextAndLinksModel else { return}
checkbox.setWithModel(model.checkbox, delegateObject, additionalData) checkbox.setWithModel(model.checkbox, delegateObject, additionalData)
eyebrowHeadlineBodyLink.setWithModel(model.eyebrowHeadlineBodyLink, delegateObject, additionalData) eyebrowHeadlineBodyLink.setWithModel(model.eyebrowHeadlineBodyLink, delegateObject, additionalData)
// Create a stack model to use for the internal stack and set the alignment of labels let stackModel = StackModel(molecules: [StackItemModel(horizontalAlignment: .fill),
let checkbox = StackItemModel() StackItemModel(horizontalAlignment: .leading)],
checkbox.horizontalAlignment = .fill axis: .horizontal)
let eyebrowHeadlineBodyLink = StackItemModel()
eyebrowHeadlineBodyLink.horizontalAlignment = .leading
let stackModel = StackModel(molecules: [checkbox,eyebrowHeadlineBodyLink])
stackModel.axis = .horizontal
stack.model = stackModel stack.model = stackModel
stack.restack() stack.restack()
} }
public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { open override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return 140 return 140
} }
} }

View File

@ -28,7 +28,7 @@ public class ListLeftVariableCheckboxAllTextAndLinksModel: ListItemModel, Molecu
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)
eyebrowHeadlineBodyLink = try typeContainer.decode(EyebrowHeadlineBodyLinkModel.self, forKey: .eyebrowHeadlineBodyLink) eyebrowHeadlineBodyLink = try typeContainer.decode(EyebrowHeadlineBodyLinkModel.self, forKey: .eyebrowHeadlineBodyLink)
checkbox = try typeContainer.decode(CheckboxModel.self, forKey: .checkbox) checkbox = try typeContainer.decodeIfPresent(CheckboxModel.self, forKey: .checkbox) ?? CheckboxModel()
try super.init(from: decoder) try super.init(from: decoder)
} }

View File

@ -9,7 +9,7 @@
import Foundation import Foundation
import UIKit import UIKit
@objcMembers public class ListLeftVariableIconWithRightCaret: TableViewCell { @objcMembers open class ListLeftVariableIconWithRightCaret: TableViewCell {
//----------------------------------------------------- //-----------------------------------------------------
// MARK: - Outlets // MARK: - Outlets
@ -22,17 +22,11 @@ import UIKit
//----------------------------------------------------- //-----------------------------------------------------
// MARK: - View Lifecycle // MARK: - View Lifecycle
//------------------------------------------------------- //-------------------------------------------------------
open override func updateView(_ size: CGFloat) {
super.updateView(size)
stack.updateView(size)
}
override open func setupView() { override open func setupView() {
super.setupView() super.setupView()
stack.translatesAutoresizingMaskIntoConstraints = false
stack.stackItems = [StackItem(andContain: leftImage),StackItem(andContain: leftLabel),StackItem(andContain: rightLabel)] stack.stackItems = [StackItem(andContain: leftImage),StackItem(andContain: leftLabel),StackItem(andContain: rightLabel)]
contentView.addSubview(stack) addMolecule(stack)
containerHelper.constrainView(stack)
leftLabel.setContentHuggingPriority(UILayoutPriority(rawValue: 901), for: .horizontal) leftLabel.setContentHuggingPriority(UILayoutPriority(rawValue: 901), for: .horizontal)
rightLabel.setContentHuggingPriority(UILayoutPriority(rawValue: 902), for: .horizontal) rightLabel.setContentHuggingPriority(UILayoutPriority(rawValue: 902), for: .horizontal)
} }
@ -40,32 +34,28 @@ import UIKit
//---------------------------------------------------- //----------------------------------------------------
// MARK: - Molecule // MARK: - Molecule
//------------------------------------------------------ //------------------------------------------------------
override open func reset() { open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
super.reset()
stack.reset()
}
public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
super.setWithModel(model, delegateObject, additionalData) super.setWithModel(model, delegateObject, additionalData)
guard let model = model as? ListLeftVariableIconWithRightCaretModel else { return} guard let model = model as? ListLeftVariableIconWithRightCaretModel else { return}
leftImage.setWithModel(model.image, delegateObject, additionalData) leftImage.setWithModel(model.image, delegateObject, additionalData)
leftLabel.setWithModel(model.leftLabel, delegateObject, additionalData) leftLabel.setWithModel(model.leftLabel, delegateObject, additionalData)
rightLabel.setWithModel(model.rightLabel, delegateObject, additionalData) rightLabel.setWithModel(model.rightLabel, delegateObject, additionalData)
// Create a stack model to use for the internal stack and set the alignment of labels let stackModel = StackModel(molecules: [StackItemModel(horizontalAlignment: .fill),
let leftImage = StackItemModel() StackItemModel(horizontalAlignment: .fill),
leftImage.horizontalAlignment = .fill StackItemModel(horizontalAlignment: .trailing)],
let leftLabel = StackItemModel() axis: .horizontal)
leftLabel.horizontalAlignment = .fill
let rightLabel = StackItemModel()
rightLabel.horizontalAlignment = .trailing
let stackModel = StackModel(molecules: [leftImage,leftLabel,rightLabel])
stackModel.axis = .horizontal
stack.model = stackModel stack.model = stackModel
stack.restack() stack.restack()
} }
public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { open override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return 90 return 90
} }
open override func reset() {
super.reset()
leftLabel.styleB2(true)
rightLabel.styleB2(true)
}
} }

View File

@ -19,6 +19,7 @@ public class ListLeftVariableIconWithRightCaretModel: ListItemModel, MoleculeMod
if image.height == nil { if image.height == nil {
image.height = 30.0 image.height = 30.0
} }
rightLabel.hero = 0
} }
public init(image: ImageViewModel, leftLabel: LabelModel, rightLabel: LabelModel) { public init(image: ImageViewModel, leftLabel: LabelModel, rightLabel: LabelModel) {
@ -43,7 +44,7 @@ public class ListLeftVariableIconWithRightCaretModel: ListItemModel, MoleculeMod
try super.init(from: decoder) try super.init(from: decoder)
} }
public override func encode(to encoder: Encoder) throws { public 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(moleculeName, forKey: .moleculeName) try container.encode(moleculeName, forKey: .moleculeName)

View File

@ -13,46 +13,30 @@ import Foundation
let rightLabel = Label.commonLabelB2(true) let rightLabel = Label.commonLabelB2(true)
let stack = Stack<StackModel>(frame: .zero) let stack = Stack<StackModel>(frame: .zero)
//-------------------------------------------------
// MARK: - View Cycle
//-------------------------------------------------
open override func updateView(_ size: CGFloat) {
super.updateView(size)
stack.updateView(size)
}
//------------------------------------------------- //-------------------------------------------------
// MARK: - Setup // MARK: - Setup
//------------------------------------------------- //-------------------------------------------------
open override func setupView() { open override func setupView() {
super.setupView() super.setupView()
rightLabel.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 900), for: .horizontal) rightLabel.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 900), for: .horizontal)
stack.translatesAutoresizingMaskIntoConstraints = false
stack.stackItems = [StackItem(andContain: leftLabel),StackItem(andContain: wheel),StackItem(andContain: rightLabel)] stack.stackItems = [StackItem(andContain: leftLabel),StackItem(andContain: wheel),StackItem(andContain: rightLabel)]
contentView.addSubview(stack) addMolecule(stack)
containerHelper.constrainView(stack)
} }
//------------------------------------------------- //-------------------------------------------------
// MARK: - ModelMoleculeViewProtocol // MARK: - ModelMoleculeViewProtocol
//------------------------------------------------- //-------------------------------------------------
public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
super.setWithModel(model, delegateObject, additionalData) super.setWithModel(model, delegateObject, additionalData)
guard let model = model as? ListRVWheelModel else { return } guard let model = model as? ListRVWheelModel else { return }
leftLabel.setWithModel(model.leftLabel, delegateObject, additionalData) leftLabel.setWithModel(model.leftLabel, delegateObject, additionalData)
rightLabel.setWithModel(model.rightLabel, delegateObject, additionalData) rightLabel.setWithModel(model.rightLabel, delegateObject, additionalData)
wheel.setWithModel(model.wheel, delegateObject, additionalData) wheel.setWithModel(model.wheel, delegateObject, additionalData)
// Create a stack model to use for the internal stack and set the alignment of models let stackModel = StackModel(molecules: [StackItemModel(horizontalAlignment: .leading),
let leftLabelStackItem = StackItemModel() StackItemModel(horizontalAlignment: .fill),
leftLabelStackItem.horizontalAlignment = .leading StackItemModel(spacing: 4, horizontalAlignment: .fill)],
let wheelStackItem = StackItemModel() axis: .horizontal)
wheelStackItem.horizontalAlignment = .fill
let rightLabelStackItem = StackItemModel()
rightLabelStackItem.horizontalAlignment = .fill
rightLabelStackItem.spacing = 4
let stackModel = StackModel(molecules: [leftLabelStackItem,wheelStackItem,rightLabelStackItem])
stackModel.axis = .horizontal
stack.model = stackModel stack.model = stackModel
stack.restack() stack.restack()
} }
@ -62,7 +46,6 @@ import Foundation
//------------------------------------------------- //-------------------------------------------------
open override func reset() { open override func reset() {
super.reset() super.reset()
stack.reset()
leftLabel.styleB1(true) leftLabel.styleB1(true)
rightLabel.styleB2(true) rightLabel.styleB2(true)
} }

View File

@ -20,6 +20,12 @@ public class ListRVWheelModel: ListItemModel, MoleculeModelProtocol {
super.init() super.init()
} }
/// Defaults to set
override public func setDefaults() {
super.setDefaults()
rightLabel.hero = 0
}
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case moleculeName case moleculeName
case leftLabel case leftLabel
@ -31,7 +37,7 @@ public class ListRVWheelModel: ListItemModel, MoleculeModelProtocol {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self) let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
leftLabel = try typeContainer.decode(LabelModel.self, forKey: .leftLabel) leftLabel = try typeContainer.decode(LabelModel.self, forKey: .leftLabel)
rightLabel = try typeContainer.decode(LabelModel.self, forKey: .rightLabel) rightLabel = try typeContainer.decode(LabelModel.self, forKey: .rightLabel)
wheel = try typeContainer.decode(CircleProgressModel.self, forKey: .wheel) wheel = try typeContainer.decodeIfPresent(CircleProgressModel.self, forKey: .wheel) ?? CircleProgressModel()
try super.init(from: decoder) try super.init(from: decoder)
} }

View File

@ -8,12 +8,11 @@
import Foundation import Foundation
@objcMembers public class ListRightVariablePayments: TableViewCell { @objcMembers open class ListRightVariablePayments: TableViewCell {
//----------------------------------------------------- //-----------------------------------------------------
// MARK: - Outlets // MARK: - Outlets
//------------------------------------------------------- //-------------------------------------------------------
let leftLabel = Label.commonLabelB1(true) let leftLabel = Label.commonLabelB1(true)
let rightImage = MFLoadImageView(pinnedEdges: .all) let rightImage = MFLoadImageView(pinnedEdges: .all)
let stack = Stack<StackModel>(frame: .zero) let stack = Stack<StackModel>(frame: .zero)
@ -21,49 +20,34 @@ import Foundation
//----------------------------------------------------- //-----------------------------------------------------
// MARK: - View Lifecycle // MARK: - View Lifecycle
//------------------------------------------------------- //-------------------------------------------------------
open override func updateView(_ size: CGFloat) {
super.updateView(size)
stack.updateView(size)
}
override open func setupView() { override open func setupView() {
super.setupView() super.setupView()
guard leftLabel.superview == nil else {
return
}
stack.translatesAutoresizingMaskIntoConstraints = false
stack.stackItems = [StackItem(andContain: leftLabel),StackItem(andContain: rightImage)] stack.stackItems = [StackItem(andContain: leftLabel),StackItem(andContain: rightImage)]
contentView.addSubview(stack) addMolecule(stack)
containerHelper.constrainView(stack)
} }
//---------------------------------------------------- //----------------------------------------------------
// MARK: - Molecule // MARK: - Molecule
//------------------------------------------------------ //------------------------------------------------------
override open func reset() { open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
super.reset()
stack.reset()
}
public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
super.setWithModel(model, delegateObject, additionalData) super.setWithModel(model, delegateObject, additionalData)
guard let model = model as? ListRightVariablePaymentsModel else { return } guard let model = model as? ListRightVariablePaymentsModel else { return }
leftLabel.setWithModel(model.leftLabel, delegateObject, additionalData) leftLabel.setWithModel(model.leftLabel, delegateObject, additionalData)
rightImage.setWithModel(model.image, delegateObject, additionalData) rightImage.setWithModel(model.image, delegateObject, additionalData)
// Create a stack model to use for the internal stack and set the alignment of label and image let stackModel = StackModel(molecules: [StackItemModel(horizontalAlignment: .leading),
let leftLabel = StackItemModel() StackItemModel(horizontalAlignment: .fill)],
leftLabel.horizontalAlignment = .leading axis: .horizontal)
let rightImage = StackItemModel()
rightImage.horizontalAlignment = .fill
let stackModel = StackModel(molecules: [leftLabel,rightImage])
stackModel.axis = .horizontal
stack.model = stackModel stack.model = stackModel
stack.restack() stack.restack()
} }
public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { open override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return 65 return 65
} }
open override func reset() {
super.reset()
leftLabel.styleB1(true)
}
} }

View File

@ -20,6 +20,12 @@ public class ListRightVariablePaymentsModel: ListItemModel, MoleculeModelProtoco
super.init() super.init()
} }
/// Defaults to set
override public func setDefaults() {
super.setDefaults()
leftLabel.hero = 0
}
static func createPayPalImage() -> ImageViewModel { static func createPayPalImage() -> ImageViewModel {
let image = ImageViewModel(image: "imageName_PayPal_logo") let image = ImageViewModel(image: "imageName_PayPal_logo")
image.localBundle = MVMCoreUIUtility.bundleForMVMCoreUI() image.localBundle = MVMCoreUIUtility.bundleForMVMCoreUI()

View File

@ -16,23 +16,16 @@ import Foundation
let stack = Stack<StackModel>(frame: .zero) let stack = Stack<StackModel>(frame: .zero)
// MARK: - MFViewProtocol // MARK: - MFViewProtocol
open override func updateView(_ size: CGFloat) {
super.updateView(size)
stack.updateView(size)
}
open override func setupView() { open override func setupView() {
super.setupView() super.setupView()
//using stackItems to align the three headlineBody //using stackItems to align the three headlineBody
stack.translatesAutoresizingMaskIntoConstraints = false
stack.stackItems = [StackItem(andContain: leftHeadlineBody),StackItem(andContain: centerHeadLineBody),StackItem(andContain: rightHeadLineBody)] stack.stackItems = [StackItem(andContain: leftHeadlineBody),StackItem(andContain: centerHeadLineBody),StackItem(andContain: rightHeadLineBody)]
contentView.addSubview(stack) addMolecule(stack)
containerHelper.constrainView(stack)
} }
// MARK: - MVMCoreUIMoleculeViewProtocol // MARK: - MVMCoreUIMoleculeViewProtocol
public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
super.setWithModel(model, delegateObject, additionalData) super.setWithModel(model, delegateObject, additionalData)
guard let model = model as? ListThreeColumnPlanDataDividerModel else { return } guard let model = model as? ListThreeColumnPlanDataDividerModel else { return }
leftHeadlineBody.setWithModel(model.leftHeadlineBody, delegateObject, additionalData) leftHeadlineBody.setWithModel(model.leftHeadlineBody, delegateObject, additionalData)
@ -40,24 +33,15 @@ import Foundation
rightHeadLineBody.setWithModel(model.rightHeadlineBody, delegateObject, additionalData) rightHeadLineBody.setWithModel(model.rightHeadlineBody, delegateObject, additionalData)
// Create a stack model to use for the internal stack and set the alignment of models // Create a stack model to use for the internal stack and set the alignment of models
let leftHeadlineBodyAlignment = StackItemModel(percent: 33) let stackModel = StackModel(molecules: [StackItemModel(percent: 33, horizontalAlignment: .leading),
leftHeadlineBodyAlignment.horizontalAlignment = .leading StackItemModel(percent: 34, horizontalAlignment: .center),
let centerHeadLineBodyAlignment = StackItemModel(percent: 34) StackItemModel(percent: 33, horizontalAlignment: .trailing)],
centerHeadLineBodyAlignment.horizontalAlignment = .center axis: .horizontal)
let rightHeadLineBodyAlignment = StackItemModel(percent: 33)
rightHeadLineBodyAlignment.horizontalAlignment = .trailing
let stackModel = StackModel(molecules: [leftHeadlineBodyAlignment,centerHeadLineBodyAlignment,rightHeadLineBodyAlignment])
stackModel.axis = .horizontal
stack.model = stackModel stack.model = stackModel
stack.restack() stack.restack()
} }
open override func reset() { open override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
super.reset()
stack.reset()
}
public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
return 121 return 121
} }
} }

View File

@ -26,6 +26,9 @@ public class ListThreeColumnPlanDataDividerModel: ListItemModel, MoleculeModelPr
override public func setDefaults() { override public func setDefaults() {
super.setDefaults() super.setDefaults()
style = "tallDivider" style = "tallDivider"
leftHeadlineBody.style = "itemHeader"
centerHeadlineBody.style = "itemHeader"
rightHeadlineBody.style = "itemHeader"
} }
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {

View File

@ -16,13 +16,14 @@ import Foundation
public var percent: Int? public var percent: Int?
public var gone: Bool = false public var gone: Bool = false
public convenience init(gone: Bool) { public convenience init(spacing: CGFloat? = nil, percent: Int? = nil, horizontalAlignment: UIStackView.Alignment? = nil, verticalAlignment: UIStackView.Alignment? = nil, gone: Bool? = nil) {
self.init()
self.gone = gone
}
public convenience init(percent: Int) {
self.init() self.init()
self.horizontalAlignment = horizontalAlignment
self.verticalAlignment = verticalAlignment
self.spacing = spacing
self.percent = percent self.percent = percent
if let gone = gone {
self.gone = gone
}
} }
} }

View File

@ -9,19 +9,30 @@
import UIKit import UIKit
@objcMembers open class EyebrowHeadlineBodyLink: Container { @objcMembers open class EyebrowHeadlineBodyLink: Container {
//--------------------------------------------------
// MARK: - Outlets
//--------------------------------------------------
let stack = Stack<StackModel>(frame: .zero) let stack = Stack<StackModel>(frame: .zero)
let eyebrow = Label.commonLabelB3(true) let eyebrow = Label.commonLabelB3(true)
let headline = Label.commonLabelB1(true) let headline = Label.commonLabelB1(true)
let body = Label.commonLabelB2(true) let body = Label.commonLabelB2(true)
let link = Link() let link = Link()
var casteModel: EyebrowHeadlineBodyLinkModel? { var casteModel: EyebrowHeadlineBodyLinkModel? {
get { return model as? EyebrowHeadlineBodyLinkModel } get { return model as? EyebrowHeadlineBodyLinkModel }
} }
//--------------------------------------------------
// MARK: - MFViewProtocol // MARK: - MFViewProtocol
//--------------------------------------------------
open override func setupView() { open override func setupView() {
super.setupView() super.setupView()
stack.stackItems = [StackItem(andContain: eyebrow),StackItem(andContain: headline),StackItem(andContain: body),StackItem(andContain: link)] stack.stackItems = [StackItem(andContain: eyebrow),
StackItem(andContain: headline),
StackItem(andContain: body),
StackItem(andContain: link)]
addSubview(stack) addSubview(stack)
NSLayoutConstraint.constraintPinSubview(toSuperview: stack) NSLayoutConstraint.constraintPinSubview(toSuperview: stack)
} }
@ -31,7 +42,10 @@ import UIKit
stack.updateView(size) stack.updateView(size)
} }
//--------------------------------------------------
// MARK: - MVMCoreUIMoleculeViewProtocol // MARK: - MVMCoreUIMoleculeViewProtocol
//--------------------------------------------------
open override func reset() { open override func reset() {
super.reset() super.reset()
stack.reset() stack.reset()
@ -41,16 +55,23 @@ import UIKit
body.styleB2(true) body.styleB2(true)
} }
// MARK:- ModelMoleculeViewProtocol //--------------------------------------------------
open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { // MARK: - ModelMoleculeViewProtocol
//--------------------------------------------------
open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
super.setWithModel(model, delegateObject, additionalData) super.setWithModel(model, delegateObject, additionalData)
eyebrow.setWithModel(casteModel?.eyebrow, delegateObject, additionalData) eyebrow.setWithModel(casteModel?.eyebrow, delegateObject, additionalData)
headline.setWithModel(casteModel?.headline, delegateObject, additionalData) headline.setWithModel(casteModel?.headline, delegateObject, additionalData)
body.setWithModel(casteModel?.body, delegateObject, additionalData) body.setWithModel(casteModel?.body, delegateObject, additionalData)
link.setWithModel(casteModel?.link, delegateObject, additionalData) link.setWithModel(casteModel?.link, delegateObject, additionalData)
// Create a stack model to use for the internal stack. // Create a stack model to use for the internal stack.
let stackModel = StackModel(molecules: [StackItemModel(gone: !eyebrow.hasText),StackItemModel(gone: !headline.hasText),StackItemModel(gone: !body.hasText),StackItemModel(gone: (link.titleLabel?.text?.count ?? 0) == 0)]) let stackModel = StackModel(molecules: [StackItemModel(gone: !eyebrow.hasText),
StackItemModel(gone: !headline.hasText),
StackItemModel(gone: !body.hasText),
StackItemModel(gone: (link.titleLabel?.text?.count ?? 0) == 0)])
stackModel.spacing = 0 stackModel.spacing = 0
stack.model = stackModel stack.model = stackModel
stack.restack() stack.restack()

View File

@ -8,7 +8,11 @@
import Foundation import Foundation
public struct EyebrowHeadlineBodyLinkModel: MoleculeModelProtocol { public class EyebrowHeadlineBodyLinkModel: MoleculeModelProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public static var identifier: String = "eyebrowHeadlineBodyLink" public static var identifier: String = "eyebrowHeadlineBodyLink"
public var moleculeName: String? = EyebrowHeadlineBodyLinkModel.identifier public var moleculeName: String? = EyebrowHeadlineBodyLinkModel.identifier
public var backgroundColor: Color? public var backgroundColor: Color?
@ -16,4 +20,72 @@ public struct EyebrowHeadlineBodyLinkModel: MoleculeModelProtocol {
public var headline: LabelModel? public var headline: LabelModel?
public var body: LabelModel? public var body: LabelModel?
public var link: LinkModel? public var link: LinkModel?
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(eyebrow: LabelModel? = nil, headline: LabelModel? = nil, body: LabelModel? = nil, link: LinkModel? = nil) throws {
// TODO: This class initializers should ensure that atleast one item is set.
/*guard eyebrow != nil || headline != nil || body != nil || link != nil else {
throw
}*/
self.eyebrow = eyebrow
self.headline = headline
self.body = body
self.link = link
setDefaults()
}
//--------------------------------------------------
// MARK: - Method
//--------------------------------------------------
/// Defaults to set
public func setDefaults() {
if let headline = headline {
headline.hero = 0
}
}
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------
private enum CodingKeys: String, CodingKey {
case moleculeName
case backgroundColor
case eyebrow
case headline
case body
case link
}
//--------------------------------------------------
// MARK: - Codec
//--------------------------------------------------
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
eyebrow = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .eyebrow)
headline = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .headline)
body = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .body)
link = try typeContainer.decodeIfPresent(LinkModel.self, forKey: .link)
setDefaults()
// TODO: This class initializers should ensure that atleast one item is set.
/*guard eyebrow != nil || headline != nil || body != nil || link != nil else {
throw
}*/
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encodeIfPresent(eyebrow, forKey: .eyebrow)
try container.encodeIfPresent(headline, forKey: .headline)
try container.encodeIfPresent(body, forKey: .body)
try container.encodeIfPresent(link, forKey: .link)
}
} }

View File

@ -8,15 +8,24 @@
import Foundation import Foundation
open class Stack<T>: Container where T: StackModelProtocol { open class Stack<T>: Container where T: StackModelProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
var contentView: UIView = MVMCoreUICommonViewsUtility.commonView() var contentView: UIView = MVMCoreUICommonViewsUtility.commonView()
var stackModel: T? { var stackModel: T? {
get { return model as? T } get { return model as? T }
} }
var stackItems: [UIView] = [] var stackItems: [UIView] = []
//--------------------------------------------------
// MARK: - Helpers // MARK: - Helpers
//--------------------------------------------------
public func pinView(_ view: UIView, toView: UIView, attribute: NSLayoutConstraint.Attribute, relation: NSLayoutConstraint.Relation, priority: UILayoutPriority, constant: CGFloat) { public func pinView(_ view: UIView, toView: UIView, attribute: NSLayoutConstraint.Attribute, relation: NSLayoutConstraint.Relation, priority: UILayoutPriority, constant: CGFloat) {
let constraint = NSLayoutConstraint(item: view, attribute: attribute, relatedBy: relation, toItem: toView, attribute: attribute, multiplier: 1.0, constant: constant) let constraint = NSLayoutConstraint(item: view, attribute: attribute, relatedBy: relation, toItem: toView, attribute: attribute, multiplier: 1.0, constant: constant)
constraint.priority = priority constraint.priority = priority
constraint.isActive = true constraint.isActive = true
@ -45,13 +54,16 @@ open class Stack<T>: Container where T: StackModelProtocol {
item.removeFromSuperview() item.removeFromSuperview()
} }
} }
//--------------------------------------------------
// MARK: - Initializers
//--------------------------------------------------
// MARK: - Inits
public override init(frame: CGRect) { public override init(frame: CGRect) {
super.init(frame: frame) super.init(frame: frame)
} }
public init(withJSON json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) { public init(withJSON json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
super.init(frame: CGRect.zero) super.init(frame: CGRect.zero)
setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
} }
@ -60,12 +72,13 @@ open class Stack<T>: Container where T: StackModelProtocol {
fatalError("init(coder:) has not been implemented") fatalError("init(coder:) has not been implemented")
} }
//--------------------------------------------------
// MARK: - MFViewProtocol // MARK: - MFViewProtocol
//--------------------------------------------------
public override func setupView() { public override func setupView() {
super.setupView() super.setupView()
guard contentView.superview == nil else { guard contentView.superview == nil else { return }
return
}
MVMCoreUIUtility.setMarginsFor(contentView, leading: 0, top: 0, trailing: 0, bottom: 0) MVMCoreUIUtility.setMarginsFor(contentView, leading: 0, top: 0, trailing: 0, bottom: 0)
translatesAutoresizingMaskIntoConstraints = false translatesAutoresizingMaskIntoConstraints = false
backgroundColor = .clear backgroundColor = .clear
@ -82,7 +95,10 @@ open class Stack<T>: Container where T: StackModelProtocol {
} }
} }
//--------------------------------------------------
// MARK: - MVMCoreUIMoleculeViewProtocol // MARK: - MVMCoreUIMoleculeViewProtocol
//--------------------------------------------------
public override func reset() { public override func reset() {
super.reset() super.reset()
backgroundColor = .clear backgroundColor = .clear
@ -91,7 +107,7 @@ open class Stack<T>: Container where T: StackModelProtocol {
} }
} }
public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
let previousModel = self.model let previousModel = self.model
super.setWithModel(model, delegateObject, additionalData) super.setWithModel(model, delegateObject, additionalData)
removeAllItemViews() removeAllItemViews()
@ -132,6 +148,7 @@ open class Stack<T>: Container where T: StackModelProtocol {
guard let model = molecule as? T else { return 0 } guard let model = molecule as? T else { return 0 }
let horizontal = model.axis == .horizontal let horizontal = model.axis == .horizontal
var estimatedHeight: CGFloat = 0 var estimatedHeight: CGFloat = 0
for case let item in model.molecules { for case let item in model.molecules {
if item.gone { continue } if item.gone { continue }
let height = (MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(item) as? ModelMoleculeViewProtocol.Type)?.estimatedHeight(forRow: item, delegateObject: delegateObject) ?? 0 let height = (MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(item) as? ModelMoleculeViewProtocol.Type)?.estimatedHeight(forRow: item, delegateObject: delegateObject) ?? 0
@ -158,26 +175,31 @@ open class Stack<T>: Container where T: StackModelProtocol {
return modules.count > 0 ? modules : nil return modules.count > 0 ? modules : nil
} }
//--------------------------------------------------
// MARK: - Subclassables // MARK: - Subclassables
//--------------------------------------------------
/// Can be subclassed to create views when we get stack item models and have no views yet /// Can be subclassed to create views when we get stack item models and have no views yet
func createStackItemsFromModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { func createStackItemsFromModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { }
}
/// Can be subclassed to set stack items with model when we already have views /// Can be subclassed to set stack items with model when we already have views
func setStackItemsFromModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { func setStackItemsFromModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
guard let models = stackModel?.molecules else { return } guard let models = stackModel?.molecules else { return }
for (index, element) in models.enumerated() { for (index, element) in models.enumerated() {
(stackItems[index] as? ModelMoleculeViewProtocol)?.setWithModel(element, delegateObject, additionalData) (stackItems[index] as? ModelMoleculeViewProtocol)?.setWithModel(element, delegateObject, additionalData)
} }
} }
//--------------------------------------------------
// MARK: - Adding to stack // MARK: - Adding to stack
//--------------------------------------------------
/// Gets the percent modifier. This value is used to help properly calculate percent for stack items when spacing is involved. /// Gets the percent modifier. This value is used to help properly calculate percent for stack items when spacing is involved.
private func getTotalSpace() -> CGFloat { private func getTotalSpace() -> CGFloat {
guard let stackModel = stackModel else { return 0.0 } guard let stackModel = stackModel else { return 0.0 }
var totalSpace: CGFloat = 0.0 var totalSpace: CGFloat = 0.0
var firstMoleculeFound = false var firstMoleculeFound = false
for stackItemModel in stackModel.molecules { for stackItemModel in stackModel.molecules {
guard !stackItemModel.gone else { continue } guard !stackItemModel.gone else { continue }
let spacing = stackItemModel.spacing ?? stackModel.spacing let spacing = stackItemModel.spacing ?? stackModel.spacing
@ -222,7 +244,7 @@ open class Stack<T>: Container where T: StackModelProtocol {
pinView(view, toView: contentView, attribute: .leading, relation: .equal, priority: .required, constant: 0) pinView(view, toView: contentView, attribute: .leading, relation: .equal, priority: .required, constant: 0)
pinView(contentView, toView: view, attribute: .trailing, relation: .equal, priority: .required, constant: 0) pinView(contentView, toView: view, attribute: .trailing, relation: .equal, priority: .required, constant: 0)
if let percent = model.percent { if let percent = model.percent {
let multiplier = CGFloat(percent)/100.0 let multiplier = CGFloat(percent) / 100.0
let constant = multiplier * totalSpacing let constant = multiplier * totalSpacing
view.heightAnchor.constraint(equalTo: contentView.heightAnchor, multiplier: multiplier, constant: -constant).isActive = true view.heightAnchor.constraint(equalTo: contentView.heightAnchor, multiplier: multiplier, constant: -constant).isActive = true
} }
@ -241,7 +263,7 @@ open class Stack<T>: Container where T: StackModelProtocol {
pinView(view, toView: contentView, attribute: .top, relation: .equal, priority: .required, constant: 0) pinView(view, toView: contentView, attribute: .top, relation: .equal, priority: .required, constant: 0)
pinView(contentView, toView: view, attribute: .bottom, relation: .equal, priority: .required, constant: 0) pinView(contentView, toView: view, attribute: .bottom, relation: .equal, priority: .required, constant: 0)
if let percent = model.percent { if let percent = model.percent {
let multiplier = CGFloat(percent)/100.0 let multiplier = CGFloat(percent) / 100.0
let constant = multiplier * totalSpacing let constant = multiplier * totalSpacing
view.widthAnchor.constraint(equalTo: contentView.widthAnchor, multiplier: multiplier, constant: -constant).isActive = true view.widthAnchor.constraint(equalTo: contentView.widthAnchor, multiplier: multiplier, constant: -constant).isActive = true
} }

View File

@ -16,8 +16,9 @@ import Foundation
public var spacing: CGFloat = 16.0 public var spacing: CGFloat = 16.0
public var useStackSpacingBeforeFirstItem = false public var useStackSpacingBeforeFirstItem = false
public init(molecules: [StackItemModel]) { public init(molecules: [StackItemModel], axis: NSLayoutConstraint.Axis = .vertical) {
self.molecules = molecules self.molecules = molecules
self.axis = axis
} }
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {