This commit is contained in:
Pfeil, Scott Robert 2020-04-01 16:10:28 -04:00
commit 7f25dd7356
42 changed files with 472 additions and 198 deletions

View File

@ -128,6 +128,8 @@
8D24041123E7FB9E009E23BE /* ListLeftVariableIconWithRightCaret.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D24041023E7FB9E009E23BE /* ListLeftVariableIconWithRightCaret.swift */; }; 8D24041123E7FB9E009E23BE /* ListLeftVariableIconWithRightCaret.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D24041023E7FB9E009E23BE /* ListLeftVariableIconWithRightCaret.swift */; };
8D24041523E7FC0B009E23BE /* ListLeftVariableIconWithRightCaretModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D24041423E7FC0B009E23BE /* ListLeftVariableIconWithRightCaretModel.swift */; }; 8D24041523E7FC0B009E23BE /* ListLeftVariableIconWithRightCaretModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D24041423E7FC0B009E23BE /* ListLeftVariableIconWithRightCaretModel.swift */; };
8D448E5524050A46006211BB /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D448E5424050A46006211BB /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift */; }; 8D448E5524050A46006211BB /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D448E5424050A46006211BB /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift */; };
8D4687E2242E2DE400802879 /* ListFourColumnDataUsageListItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D4687E1242E2DE400802879 /* ListFourColumnDataUsageListItemModel.swift */; };
8D4687E4242E2DF300802879 /* ListFourColumnDataUsageListItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D4687E3242E2DF300802879 /* ListFourColumnDataUsageListItem.swift */; };
942C372E241149170066E45E /* NHaasGroteskDSStd-75Bd.otf in Resources */ = {isa = PBXBuildFile; fileRef = 942C372C241149170066E45E /* NHaasGroteskDSStd-75Bd.otf */; }; 942C372E241149170066E45E /* NHaasGroteskDSStd-75Bd.otf in Resources */ = {isa = PBXBuildFile; fileRef = 942C372C241149170066E45E /* NHaasGroteskDSStd-75Bd.otf */; };
942C372F241149170066E45E /* NHaasGroteskDSStd-55Rg.otf in Resources */ = {isa = PBXBuildFile; fileRef = 942C372D241149170066E45E /* NHaasGroteskDSStd-55Rg.otf */; }; 942C372F241149170066E45E /* NHaasGroteskDSStd-55Rg.otf in Resources */ = {isa = PBXBuildFile; fileRef = 942C372D241149170066E45E /* NHaasGroteskDSStd-55Rg.otf */; };
942C378C2412F4FA0066E45E /* ModalMoleculeListTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 942C378B2412F4FA0066E45E /* ModalMoleculeListTemplate.swift */; }; 942C378C2412F4FA0066E45E /* ModalMoleculeListTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 942C378B2412F4FA0066E45E /* ModalMoleculeListTemplate.swift */; };
@ -510,6 +512,8 @@
8D24041023E7FB9E009E23BE /* ListLeftVariableIconWithRightCaret.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableIconWithRightCaret.swift; sourceTree = "<group>"; }; 8D24041023E7FB9E009E23BE /* ListLeftVariableIconWithRightCaret.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableIconWithRightCaret.swift; sourceTree = "<group>"; };
8D24041423E7FC0B009E23BE /* ListLeftVariableIconWithRightCaretModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableIconWithRightCaretModel.swift; sourceTree = "<group>"; }; 8D24041423E7FC0B009E23BE /* ListLeftVariableIconWithRightCaretModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableIconWithRightCaretModel.swift; sourceTree = "<group>"; };
8D448E5424050A46006211BB /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListOneColumnFullWidthTextAllTextAndLinksModel.swift; sourceTree = "<group>"; }; 8D448E5424050A46006211BB /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListOneColumnFullWidthTextAllTextAndLinksModel.swift; sourceTree = "<group>"; };
8D4687E1242E2DE400802879 /* ListFourColumnDataUsageListItemModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListFourColumnDataUsageListItemModel.swift; sourceTree = "<group>"; };
8D4687E3242E2DF300802879 /* ListFourColumnDataUsageListItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListFourColumnDataUsageListItem.swift; sourceTree = "<group>"; };
9402C34F23A2CEA3004B974C /* LeftRightLabelModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LeftRightLabelModel.swift; sourceTree = "<group>"; }; 9402C34F23A2CEA3004B974C /* LeftRightLabelModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LeftRightLabelModel.swift; sourceTree = "<group>"; };
942C372C241149170066E45E /* NHaasGroteskDSStd-75Bd.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "NHaasGroteskDSStd-75Bd.otf"; sourceTree = "<group>"; }; 942C372C241149170066E45E /* NHaasGroteskDSStd-75Bd.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "NHaasGroteskDSStd-75Bd.otf"; sourceTree = "<group>"; };
942C372D241149170066E45E /* NHaasGroteskDSStd-55Rg.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "NHaasGroteskDSStd-55Rg.otf"; sourceTree = "<group>"; }; 942C372D241149170066E45E /* NHaasGroteskDSStd-55Rg.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "NHaasGroteskDSStd-55Rg.otf"; sourceTree = "<group>"; };
@ -1006,6 +1010,15 @@
path = Extensions; path = Extensions;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
D20492F12434CB5F00A5EED6 /* FourColumn */ = {
isa = PBXGroup;
children = (
8D4687E1242E2DE400802879 /* ListFourColumnDataUsageListItemModel.swift */,
8D4687E3242E2DF300802879 /* ListFourColumnDataUsageListItem.swift */,
);
path = FourColumn;
sourceTree = "<group>";
};
D213347423842FE3008E41B3 /* Controllers */ = { D213347423842FE3008E41B3 /* Controllers */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@ -1201,6 +1214,7 @@
D22B38EA23F4E08B00490EF6 /* List */ = { D22B38EA23F4E08B00490EF6 /* List */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
D20492F12434CB5F00A5EED6 /* FourColumn */,
D22D8396241FDE4700D3DF69 /* TwoColumn */, D22D8396241FDE4700D3DF69 /* TwoColumn */,
52267A0523FFE0A900906CBA /* OneColumn */, 52267A0523FFE0A900906CBA /* OneColumn */,
AA4FC2A323F4F69600E251DB /* RightVariable */, AA4FC2A323F4F69600E251DB /* RightVariable */,
@ -2022,6 +2036,7 @@
D2D6CD4222E78FAB00D701B8 /* ThreeLayerTemplate.swift in Sources */, D2D6CD4222E78FAB00D701B8 /* ThreeLayerTemplate.swift in Sources */,
01EB368F23609801006832FA /* LabelModel.swift in Sources */, 01EB368F23609801006832FA /* LabelModel.swift in Sources */,
942C378E2412F5B60066E45E /* ModalMoleculeStackTemplate.swift in Sources */, 942C378E2412F5B60066E45E /* ModalMoleculeStackTemplate.swift in Sources */,
8D4687E4242E2DF300802879 /* ListFourColumnDataUsageListItem.swift in Sources */,
01F2A03223A4498200D954D8 /* CaretLinkModel.swift in Sources */, 01F2A03223A4498200D954D8 /* CaretLinkModel.swift in Sources */,
0A7BAFA1232BE61800FB8E22 /* Checkbox.swift in Sources */, 0A7BAFA1232BE61800FB8E22 /* Checkbox.swift in Sources */,
011B58F023A2AA980085F53C /* ListItemModelProtocol.swift in Sources */, 011B58F023A2AA980085F53C /* ListItemModelProtocol.swift in Sources */,
@ -2160,6 +2175,7 @@
BB6C6AC924225290005F7224 /* ListOneColumnTextWithWhitespaceDividerShortModel.swift in Sources */, BB6C6AC924225290005F7224 /* ListOneColumnTextWithWhitespaceDividerShortModel.swift in Sources */,
C695A69423C9909000BFB94E /* DoughnutChartModel.swift in Sources */, C695A69423C9909000BFB94E /* DoughnutChartModel.swift in Sources */,
D29DF32421ED0DA2003B2FB9 /* TextButtonView.m in Sources */, D29DF32421ED0DA2003B2FB9 /* TextButtonView.m in Sources */,
8D4687E2242E2DE400802879 /* ListFourColumnDataUsageListItemModel.swift in Sources */,
D29E28DD23D7404C00ACEA85 /* ContainerHelper.swift in Sources */, D29E28DD23D7404C00ACEA85 /* ContainerHelper.swift in Sources */,
012A88C2238D7BCA00FE3DA1 /* CarouselItemModel.swift in Sources */, 012A88C2238D7BCA00FE3DA1 /* CarouselItemModel.swift in Sources */,
D29DF29E21E7AE3B003B2FB9 /* MFStyler.m in Sources */, D29DF29E21E7AE3B003B2FB9 /* MFStyler.m in Sources */,

View File

@ -128,9 +128,7 @@ import UIKit
self.delegateObject = delegateObject self.delegateObject = delegateObject
isSelected = model.state isSelected = model.state
let radioButtonModel = RadioButtonSelectionHelper.setupForRadioButtonGroup(model, RadioButtonSelectionHelper.setupForRadioButtonGroup(model, self, delegateObject: delegateObject)
formValidator: delegateObject?.formHolderDelegate?.formValidator)
FormValidator.setupValidation(for: radioButtonModel, delegate: delegateObject?.formHolderDelegate)
} }
public override func reset() { public override func reset() {

View File

@ -20,16 +20,20 @@ import UIKit
self.fieldKey = fieldKey self.fieldKey = fieldKey
} }
public static func setupForRadioButtonGroup(_ radioButtonModel: RadioButtonModel, formValidator: FormValidator?) -> RadioButtonSelectionHelper { public static func setupForRadioButtonGroup(_ radioButtonModel: RadioButtonModel, _ radioButton: RadioButton, delegateObject: MVMCoreUIDelegateObject?) {
guard let groupName = radioButtonModel.fieldKey, guard let groupName = radioButtonModel.fieldKey,
let formValidator = formValidator else { let formValidator = delegateObject?.formHolderDelegate?.formValidator else {
return RadioButtonSelectionHelper(radioButtonModel.fieldKey) return
} }
let radioButtonSelectionHelper = formValidator.radioButtonsModelByGroup[groupName] ?? RadioButtonSelectionHelper(radioButtonModel.fieldKey) let radioButtonSelectionHelper = formValidator.radioButtonsModelByGroup[groupName] ?? RadioButtonSelectionHelper(radioButtonModel.fieldKey)
radioButtonSelectionHelper.fieldGroupName = radioButtonModel.fieldKey radioButtonSelectionHelper.fieldGroupName = radioButtonModel.fieldKey
formValidator.radioButtonsModelByGroup[groupName] = radioButtonSelectionHelper formValidator.radioButtonsModelByGroup[groupName] = radioButtonSelectionHelper
return radioButtonSelectionHelper
if radioButtonModel.state {
radioButtonSelectionHelper.selectedRadioButton = radioButton
}
FormValidator.setupValidation(molecule: radioButtonSelectionHelper, delegate: delegateObject?.formHolderDelegate)
} }
public func selected(_ radioButton: RadioButton) { public func selected(_ radioButton: RadioButton) {

View File

@ -211,7 +211,7 @@ import UIKit
let digitBox = DigitBox() let digitBox = DigitBox()
digitBox.isAccessibilityElement = true digitBox.isAccessibilityElement = true
MVMCoreUICommonViewsUtility.addDismissToolbar(digitBox.digitField, delegate: self) digitBox.digitField.inputAccessoryView = MVMCoreUICommonViewsUtility.getToolbarWithDoneButton(delegate: self)
digitBox.digitField.delegate = self digitBox.digitField.delegate = self
digitBox.digitBoxDelegate = self digitBox.digitBoxDelegate = self
return digitBox return digitBox
@ -333,12 +333,10 @@ import UIKit
} }
public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
guard let model = model as? DigitEntryFieldModel else { return } guard let model = model as? DigitEntryFieldModel else { return }
numberOfDigits = model.digits numberOfDigits = model.digits
setAsSecureTextEntry(model.secureEntry) setAsSecureTextEntry(model.secureEntry)
for digitBox in digitBoxes { for digitBox in digitBoxes {

View File

@ -116,8 +116,7 @@ import UIKit
set (newFeedback) { set (newFeedback) {
feedbackLabel.text = newFeedback feedbackLabel.text = newFeedback
feedbackLabel.accessibilityElementsHidden = feedbackLabel.text?.isEmpty ?? true feedbackLabel.accessibilityElementsHidden = feedbackLabel.text?.isEmpty ?? true
entryFieldContainer.refreshUI() entryFieldContainer.refreshUI(updateMoleculeLayout: true)
delegateObject?.moleculeDelegate?.moleculeLayoutUpdated(self)
} }
} }

View File

@ -49,6 +49,10 @@ import UIKit
/// Validate when user resigns editing. Default: true /// Validate when user resigns editing. Default: true
public var validateWhenDoneEditing: Bool = true public var validateWhenDoneEditing: Bool = true
public var textEntryFieldModel: TextEntryFieldModel? {
return model as? TextEntryFieldModel
}
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Computed Properties // MARK: - Computed Properties
@ -87,7 +91,7 @@ import UIKit
get { return textField.text } get { return textField.text }
set { set {
textField.text = newValue textField.text = newValue
(model as? TextEntryFieldModel)?.text = newValue textEntryFieldModel?.text = newValue
} }
} }
@ -171,7 +175,8 @@ import UIKit
textField.heightAnchor.constraint(equalToConstant: 24), textField.heightAnchor.constraint(equalToConstant: 24),
textField.topAnchor.constraint(equalTo: container.topAnchor, constant: 12), textField.topAnchor.constraint(equalTo: container.topAnchor, constant: 12),
textField.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: 16), textField.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: 16),
container.bottomAnchor.constraint(equalTo: textField.bottomAnchor, constant: 12)]) container.bottomAnchor.constraint(equalTo: textField.bottomAnchor, constant: 12)
])
textFieldTrailingConstraint = container.trailingAnchor.constraint(equalTo: textField.trailingAnchor, constant: 16) textFieldTrailingConstraint = container.trailingAnchor.constraint(equalTo: textField.trailingAnchor, constant: 16)
textFieldTrailingConstraint?.isActive = true textFieldTrailingConstraint?.isActive = true

View File

@ -158,6 +158,7 @@ import MVMCore
super.init(frame: frame) super.init(frame: frame)
accessibilityTraits = .button accessibilityTraits = .button
isAccessibilityElement = true
accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: "checkbox_action_hint") accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: "checkbox_action_hint")
updateAccessibilityLabel() updateAccessibilityLabel()
} }
@ -198,8 +199,6 @@ import MVMCore
open override func setupView() { open override func setupView() {
super.setupView() super.setupView()
guard constraints.isEmpty else { return }
isUserInteractionEnabled = true isUserInteractionEnabled = true
translatesAutoresizingMaskIntoConstraints = false translatesAutoresizingMaskIntoConstraints = false
backgroundColor = .clear backgroundColor = .clear
@ -390,8 +389,6 @@ import MVMCore
widthConstraint?.constant = dimension widthConstraint?.constant = dimension
heightConstraint?.constant = dimension heightConstraint?.constant = dimension
} }
//layoutIfNeeded()
} }
public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {

View File

@ -130,6 +130,7 @@ public typealias ActionBlock = () -> ()
required public init(model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { required public init(model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
super.init(frame: .zero) super.init(frame: .zero)
setupView()
styleB2(true) styleB2(true)
set(with: model, delegateObject, additionalData) set(with: model, delegateObject, additionalData)
} }
@ -322,6 +323,7 @@ public typealias ActionBlock = () -> ()
text = labelModel.text text = labelModel.text
hero = labelModel.hero hero = labelModel.hero
Label.setLabel(self, withHTML: labelModel.html) Label.setLabel(self, withHTML: labelModel.html)
isAccessibilityElement = hasText
switch labelModel.textAlignment { switch labelModel.textAlignment {
case .center: case .center:
@ -428,6 +430,7 @@ public typealias ActionBlock = () -> ()
continue continue
} }
} }
attributedText = attributedString attributedText = attributedString
originalAttributedString = attributedText originalAttributedString = attributedText
} }

View File

@ -12,6 +12,19 @@ import Foundation
@objcMembers public class LabelModel: MoleculeModelProtocol { @objcMembers public class LabelModel: MoleculeModelProtocol {
public enum FontStyle: String, Codable { public enum FontStyle: String, Codable {
case Title2XLarge
case TitleXLarge
case BoldTitleLarge
case RegularTitleLarge
case BoldTitleMedium
case RegularTitleMedium
case BoldBodyLarge
case RegularBodyLarge
case BoldBodySmall
case RegularBodySmall
case BoldMicro
case RegularMicro
// Legacy
case H1 case H1
case H2 case H2
case H3 case H3

View File

@ -189,8 +189,11 @@ public typealias ActionBlockConfirmation = () -> (Bool)
public override func setupView() { public override func setupView() {
super.setupView() super.setupView()
guard subviews.isEmpty else { return } guard subviews.isEmpty else { return }
isAccessibilityElement = true
accessibilityTraits = .button
accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: "AccToggleHint")
accessibilityLabel = MVMCoreUIUtility.hardcodedString(withKey: "Toggle_buttonlabel")
heightConstraint = heightAnchor.constraint(equalToConstant: Self.containerSize.height) heightConstraint = heightAnchor.constraint(equalToConstant: Self.containerSize.height)
heightConstraint?.isActive = true heightConstraint?.isActive = true
@ -214,8 +217,6 @@ public typealias ActionBlockConfirmation = () -> (Bool)
knobTrailingConstraint = trailingAnchor.constraint(equalTo: knobView.trailingAnchor, constant: 1) knobTrailingConstraint = trailingAnchor.constraint(equalTo: knobView.trailingAnchor, constant: 1)
knobLeadingConstraint = knobView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 1) knobLeadingConstraint = knobView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 1)
knobLeadingConstraint?.isActive = true knobLeadingConstraint?.isActive = true
accessibilityLabel = MVMCoreUIUtility.hardcodedString(withKey: "Toggle_buttonlabel")
} }
public override func reset() { public override func reset() {
@ -336,15 +337,13 @@ public typealias ActionBlockConfirmation = () -> (Bool)
// MARK:- MoleculeViewProtocol // MARK:- MoleculeViewProtocol
public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
guard let toggleModel = model as? ToggleModel else { super.set(with: model, delegateObject, additionalData)
return
}
self.model = model
self.delegateObject = delegateObject self.delegateObject = delegateObject
FormValidator.setupValidation(for: toggleModel, delegate: delegateObject?.formHolderDelegate)
guard let model = model as? ToggleModel else { return } guard let model = model as? ToggleModel else { return }
FormValidator.setupValidation(molecule: model, delegate: delegateObject?.formHolderDelegate)
if let color = model.onTintColor?.uiColor { if let color = model.onTintColor?.uiColor {
containerTintColor?.on = color containerTintColor?.on = color
} }

View File

@ -12,11 +12,12 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableMo
public static var identifier: String = "toggle" public static var identifier: String = "toggle"
public var backgroundColor: Color? public var backgroundColor: Color?
public var state: Bool = true public var state: Bool = false
public var animated: Bool = true public var animated: Bool = true
public var enabled: Bool = true public var enabled: Bool = true
public var action: ActionModelProtocol? public var action: ActionModelProtocol?
public var alternateAction: ActionModelProtocol? public var alternateAction: ActionModelProtocol?
public var accessibilityText: String?
public var onTintColor: Color? public var onTintColor: Color?
public var offTintColor: Color? public var offTintColor: Color?
public var onKnobTintColor: Color? public var onKnobTintColor: Color?
@ -25,7 +26,11 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableMo
public var fieldKey: String? public var fieldKey: String?
public var groupName: String = FormValidator.defaultGroupName public var groupName: String = FormValidator.defaultGroupName
public var baseValue: AnyHashable? public var baseValue: AnyHashable?
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case moleculeName case moleculeName
case state case state
@ -34,6 +39,7 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableMo
case action case action
case backgroundColor case backgroundColor
case alternateAction case alternateAction
case accessibilityText
case onTintColor case onTintColor
case offTintColor case offTintColor
case onKnobTintColor case onKnobTintColor
@ -42,17 +48,30 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableMo
case groupName case groupName
} }
//--------------------------------------------------
// MARK: - Methods
//--------------------------------------------------
public func formFieldValue() -> AnyHashable? { public func formFieldValue() -> AnyHashable? {
return state return state
} }
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(_ state: Bool) { public init(_ state: Bool) {
self.state = state self.state = state
baseValue = state baseValue = state
} }
//--------------------------------------------------
// 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)
if let state = try typeContainer.decodeIfPresent(Bool.self, forKey: .state) { if let state = try typeContainer.decodeIfPresent(Bool.self, forKey: .state) {
self.state = state self.state = state
} }
@ -69,7 +88,8 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableMo
offTintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .offTintColor) offTintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .offTintColor)
onKnobTintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .onKnobTintColor) onKnobTintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .onKnobTintColor)
offKnobTintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .offKnobTintColor) offKnobTintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .offKnobTintColor)
accessibilityText = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityText)
baseValue = state baseValue = state
fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey) fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey)
if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) { if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) {
@ -84,10 +104,13 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableMo
try container.encodeModelIfPresent(alternateAction, forKey: .alternateAction) try container.encodeModelIfPresent(alternateAction, forKey: .alternateAction)
try container.encode(moleculeName, forKey: .moleculeName) try container.encode(moleculeName, forKey: .moleculeName)
try container.encode(state, forKey: .state) try container.encode(state, forKey: .state)
try container.encode(animated, forKey: .animated)
try container.encode(enabled, forKey: .enabled)
try container.encodeIfPresent(onTintColor, forKey: .onTintColor) try container.encodeIfPresent(onTintColor, forKey: .onTintColor)
try container.encodeIfPresent(onKnobTintColor, forKey: .onKnobTintColor) try container.encodeIfPresent(onKnobTintColor, forKey: .onKnobTintColor)
try container.encodeIfPresent(onKnobTintColor, forKey: .onKnobTintColor) try container.encodeIfPresent(onKnobTintColor, forKey: .onKnobTintColor)
try container.encodeIfPresent(offKnobTintColor, forKey: .offKnobTintColor) try container.encodeIfPresent(offKnobTintColor, forKey: .offKnobTintColor)
try container.encodeIfPresent(accessibilityText, forKey: .accessibilityText)
try container.encodeIfPresent(fieldKey, forKey: .fieldKey) try container.encodeIfPresent(fieldKey, forKey: .fieldKey)
try container.encodeIfPresent(groupName, forKey: .groupName) try container.encodeIfPresent(groupName, forKey: .groupName)
} }

View File

@ -18,18 +18,18 @@ import Foundation
} }
/// Registers the model with the model registry and the view with the mapper. /// Registers the model with the model registry and the view with the mapper.
func register<M: ModelProtocol, V: MoleculeViewProtocol>(viewClass: V.Type, viewModelClass: M.Type) { public func register<M: ModelProtocol, V: MoleculeViewProtocol>(viewClass: V.Type, viewModelClass: M.Type) {
try? ModelRegistry.register(viewModelClass) try? ModelRegistry.register(viewModelClass)
moleculeMapping.updateValue(viewClass, forKey: viewModelClass.identifier) moleculeMapping.updateValue(viewClass, forKey: viewModelClass.identifier)
} }
/// Returns the type of molecule view for the given model /// Returns the type of molecule view for the given model
func getMoleculeClass(_ model: MoleculeModelProtocol) -> MoleculeViewProtocol.Type? { public func getMoleculeClass(_ model: MoleculeModelProtocol) -> MoleculeViewProtocol.Type? {
return moleculeMapping[model.moleculeName] return moleculeMapping[model.moleculeName]
} }
/// Creates a molecule with the given model. /// Creates a molecule with the given model.
func createMolecule(_ model: MoleculeModelProtocol, delegateObject: MVMCoreUIDelegateObject? = nil, additionalData: [AnyHashable: Any]? = nil) -> MoleculeViewProtocol? { public func createMolecule(_ model: MoleculeModelProtocol, delegateObject: MVMCoreUIDelegateObject? = nil, additionalData: [AnyHashable: Any]? = nil) -> MoleculeViewProtocol? {
guard let type = moleculeMapping[model.moleculeName] else { return nil } guard let type = moleculeMapping[model.moleculeName] else { return nil }
return type.init(model: model, delegateObject, additionalData) return type.init(model: model, delegateObject, additionalData)
} }
@ -136,6 +136,7 @@ import Foundation
MoleculeObjectMapping.shared()?.register(viewClass: ListTwoColumnCompareChanges.self, viewModelClass: ListTwoColumnCompareChangesModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListTwoColumnCompareChanges.self, viewModelClass: ListTwoColumnCompareChangesModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: ListTwoColumnPriceDetails.self, viewModelClass: ListTwoColumnPriceDetailsModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListTwoColumnPriceDetails.self, viewModelClass: ListTwoColumnPriceDetailsModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: ListTwoColumnPriceDescription.self, viewModelClass: ListTwoColumnPriceDescriptionModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListTwoColumnPriceDescription.self, viewModelClass: ListTwoColumnPriceDescriptionModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: ListFourColumnDataUsageListItem.self, viewModelClass: ListFourColumnDataUsageListItemModel.self)
// Designed Section Dividers // Designed Section Dividers
MoleculeObjectMapping.shared()?.register(viewClass: ListFourColumnDataUsageDivider.self, viewModelClass: ListFourColumnDataUsageDividerModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListFourColumnDataUsageDivider.self, viewModelClass: ListFourColumnDataUsageDividerModel.self)

View File

@ -0,0 +1,77 @@
//
// ListFourColumnDataUsageListItem.swift
// MVMCoreUI
//
// Created by Kruthika KP on 27/03/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
@objcMembers public class ListFourColumnDataUsageListItem: TableViewCell {
//-----------------------------------------------------
// MARK: - Outlets
//-----------------------------------------------------
var stack: Stack<StackModel>
let label1 = Label.commonLabelB2(true)
let label2 = Label.commonLabelB2(true)
let label3 = Label.commonLabelB2(true)
let label4 = Label.commonLabelB2(true)
let arrow = Arrow(frame: .zero)
let arrowAndLabel2Stack: Stack<StackModel>
//-----------------------------------------------------
// MARK: - Initializers
//-----------------------------------------------------
public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
arrowAndLabel2Stack = Stack<StackModel>.createStack(with: [(view: arrow, model: StackItemModel(horizontalAlignment: .fill)),
(view: label2, model: StackItemModel(horizontalAlignment: .leading))],
axis: .horizontal, spacing: 4)
label2.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 900), for: .horizontal)
label2.setContentHuggingPriority(UILayoutPriority(rawValue: 900), for: .horizontal)
stack = Stack<StackModel>.createStack(with: [(view: label1, model: StackItemModel(percent: 19, horizontalAlignment: .leading)),
(view: arrowAndLabel2Stack, model: StackItemModel(percent: 44, horizontalAlignment: .fill)),
(view: label3, model: StackItemModel(percent:17,horizontalAlignment: .leading)),
(view: label4, model: StackItemModel(percent:20,horizontalAlignment: .leading))],
axis: .horizontal,spacing: 8)
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
public required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
//-----------------------------------------------------
// MARK: - View Lifecycle
//-----------------------------------------------------
override open func setupView() {
super.setupView()
addMolecule(stack)
arrow.pinHeightAndWidth()
arrowAndLabel2Stack.restack()
stack.restack()
}
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
super.set(with: model, delegateObject, additionalData)
guard let model = model as? ListFourColumnDataUsageListItemModel else { return }
label1.set(with: model.label1, delegateObject, additionalData)
label2.set(with: model.label2, delegateObject, additionalData)
label3.set(with: model.label3, delegateObject, additionalData)
label4.set(with: model.label4, delegateObject, additionalData)
arrow.set(with: model.arrow, delegateObject, additionalData)
}
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return 121
}
open override func reset() {
super.reset()
label1.styleB2(true)
label2.styleB2(true)
label3.styleB2(true)
label4.styleB2(true)
}
}

View File

@ -0,0 +1,57 @@
//
// ListFourColumnDataUsageListItemModel.swift
// MVMCoreUI
//
// Created by Kruthika KP on 27/03/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
public class ListFourColumnDataUsageListItemModel: ListItemModel, MoleculeModelProtocol {
public static var identifier: String = "list4C"
public var label1: LabelModel
public var arrow: ArrowModel
public var label2: LabelModel
public var label3: LabelModel
public var label4: LabelModel
public init(label1:LabelModel, label2:LabelModel, label3:LabelModel,label4:LabelModel, arrow:ArrowModel) {
self.label1 = label1
self.label2 = label2
self.label3 = label3
self.label4 = label4
self.arrow = arrow
super.init()
}
private enum CodingKeys: String, CodingKey {
case moleculeName
case label1
case label2
case label3
case label4
case arrow
}
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
label1 = try typeContainer.decode(LabelModel.self, forKey: .label1)
label2 = try typeContainer.decode(LabelModel.self, forKey: .label2)
label3 = try typeContainer.decode(LabelModel.self, forKey: .label3)
label4 = try typeContainer.decode(LabelModel.self, forKey: .label4)
arrow = try typeContainer.decode(ArrowModel.self, forKey: .arrow)
try super.init(from: decoder)
}
public override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encode(label1, forKey: .label1)
try container.encode(label2, forKey: .label2)
try container.encode(label3, forKey: .label3)
try container.encode(label4, forKey: .label4)
try container.encode(arrow, forKey: .arrow)
}
}

View File

@ -9,11 +9,18 @@
import Foundation import Foundation
@objcMembers open class ListLeftVariableCheckboxAllTextAndLinks: TableViewCell { @objcMembers open class ListLeftVariableCheckboxAllTextAndLinks: TableViewCell {
public let checkbox = Checkbox(frame: .zero) //--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public let checkbox = Checkbox()
public let eyebrowHeadlineBodyLink = EyebrowHeadlineBodyLink(frame: .zero) public let eyebrowHeadlineBodyLink = EyebrowHeadlineBodyLink(frame: .zero)
public var stack: Stack<StackModel> public var stack: Stack<StackModel>
//--------------------------------------------------
// MARK: - Initializers // MARK: - Initializers
//--------------------------------------------------
public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
stack = Stack<StackModel>.createStack(with: [(view: checkbox, model: StackItemModel(horizontalAlignment: .fill)), stack = Stack<StackModel>.createStack(with: [(view: checkbox, model: StackItemModel(horizontalAlignment: .fill)),
(view: eyebrowHeadlineBodyLink, model: StackItemModel(horizontalAlignment: .leading))], (view: eyebrowHeadlineBodyLink, model: StackItemModel(horizontalAlignment: .leading))],
@ -25,17 +32,25 @@ import Foundation
fatalError("init(coder:) has not been implemented") fatalError("init(coder:) has not been implemented")
} }
// MARK: - View Lifecycle //--------------------------------------------------
// MARK: - Life Cycle
//--------------------------------------------------
override open func setupView() { override open func setupView() {
super.setupView() super.setupView()
addMolecule(stack) addMolecule(stack)
stack.restack() stack.restack()
} }
// MARK:- MoleculeViewProtocol //--------------------------------------------------
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { // MARK: - MVMCoreUIMoleculeViewProtocol
//--------------------------------------------------
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? ListLeftVariableCheckboxAllTextAndLinksModel else { return}
guard let model = model as? ListLeftVariableCheckboxAllTextAndLinksModel else { return }
checkbox.set(with: model.checkbox, delegateObject, additionalData) checkbox.set(with: model.checkbox, delegateObject, additionalData)
eyebrowHeadlineBodyLink.set(with: model.eyebrowHeadlineBodyLink, delegateObject, additionalData) eyebrowHeadlineBodyLink.set(with: model.eyebrowHeadlineBodyLink, delegateObject, additionalData)
} }

View File

@ -9,10 +9,10 @@
import UIKit import UIKit
@objcMembers open class ListLeftVariableRadioButtonAndPaymentMethod: TableViewCell { @objcMembers open class ListLeftVariableRadioButtonAndPaymentMethod: TableViewCell {
//----------------------------------------------------- //-----------------------------------------------------
// MARK: - Outlets // MARK: - Outlets
//----------------------------------------------------- //-----------------------------------------------------
let radioButton = RadioButton(frame: .zero) let radioButton = RadioButton(frame: .zero)
let leftImage = MFLoadImageView(pinnedEdges: .all) let leftImage = MFLoadImageView(pinnedEdges: .all)
let eyebrowHeadlineBodyLink = EyebrowHeadlineBodyLink() let eyebrowHeadlineBodyLink = EyebrowHeadlineBodyLink()
@ -21,6 +21,7 @@ import UIKit
//----------------------------------------------------- //-----------------------------------------------------
// MARK: - Initializers // MARK: - Initializers
//----------------------------------------------------- //-----------------------------------------------------
public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
stack = Stack<StackModel>.createStack(with: [(view: radioButton, model: StackItemModel(horizontalAlignment: .fill)), stack = Stack<StackModel>.createStack(with: [(view: radioButton, model: StackItemModel(horizontalAlignment: .fill)),
(view: leftImage, model: StackItemModel(horizontalAlignment: .fill)), (view: leftImage, model: StackItemModel(horizontalAlignment: .fill)),
@ -36,6 +37,7 @@ import UIKit
//----------------------------------------------------- //-----------------------------------------------------
// MARK: - View Lifecycle // MARK: - View Lifecycle
//----------------------------------------------------- //-----------------------------------------------------
override open func setupView() { override open func setupView() {
super.setupView() super.setupView()
leftImage.addSizeConstraintsForAspectRatio = true leftImage.addSizeConstraintsForAspectRatio = true
@ -54,6 +56,7 @@ import UIKit
//---------------------------------------------------- //----------------------------------------------------
// MARK: - Molecule // MARK: - Molecule
//---------------------------------------------------- //----------------------------------------------------
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? ListLeftVariableRadioButtonAndPaymentMethodModel else { return} guard let model = model as? ListLeftVariableRadioButtonAndPaymentMethodModel else { return}

View File

@ -8,6 +8,7 @@
import Foundation import Foundation
@objcMembers public class DropDownListItemModel: ListItemModel, MoleculeModelProtocol { @objcMembers public class DropDownListItemModel: ListItemModel, MoleculeModelProtocol {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Properties // MARK: - Properties
@ -17,6 +18,10 @@ import Foundation
public var molecules: [[ListItemModelProtocol & MoleculeModelProtocol]] public var molecules: [[ListItemModelProtocol & MoleculeModelProtocol]]
public var dropDown: ItemDropdownEntryFieldModel public var dropDown: ItemDropdownEntryFieldModel
//--------------------------------------------------
// MARK: - Methods
//--------------------------------------------------
/// Defaults to set /// Defaults to set
public override func setDefaults() { public override func setDefaults() {
super.setDefaults() super.setDefaults()
@ -24,14 +29,25 @@ import Foundation
line = LineModel(type: .none) line = LineModel(type: .none)
style = "sectionFooter" style = "sectionFooter"
} }
//--------------------------------------------------
// MARK: - Functions
//--------------------------------------------------
public class func verify(dropdown: ItemDropdownEntryFieldModel, molecules: [[ListItemModelProtocol & MoleculeModelProtocol]]) throws {
guard dropdown.options.count == molecules.count else {
throw MolecularError.countImbalance("dropdown.options.count is not equal to molecules.count")
}
}
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Initializer // MARK: - Initializer
//-------------------------------------------------- //--------------------------------------------------
public init(molecules: [[ListItemModelProtocol & MoleculeModelProtocol]], dropDown: ItemDropdownEntryFieldModel) { public init(molecules: [[ListItemModelProtocol & MoleculeModelProtocol]], dropDown: ItemDropdownEntryFieldModel) throws {
self.molecules = molecules self.molecules = molecules
self.dropDown = dropDown self.dropDown = dropDown
try Self.verify(dropdown: dropDown, molecules: molecules)
super.init() super.init()
} }
@ -53,6 +69,7 @@ import Foundation
let typeContainer = try decoder.container(keyedBy: CodingKeys.self) let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
molecules = try typeContainer.decodeModels2DIfPresent(codingKey: .molecules) ?? [[]] molecules = try typeContainer.decodeModels2DIfPresent(codingKey: .molecules) ?? [[]]
dropDown = try typeContainer.decode(ItemDropdownEntryFieldModel.self, forKey: .dropDown) dropDown = try typeContainer.decode(ItemDropdownEntryFieldModel.self, forKey: .dropDown)
try Self.verify(dropdown: dropDown, molecules: molecules)
try super.init(from: decoder) try super.init(from: decoder)
} }

View File

@ -46,7 +46,7 @@ import UIKit
} }
public override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { public override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
guard let moleculeModel = (model as? MoleculeContainerModel)?.molecule, guard let moleculeModel = (model as? MoleculeListItemModel)?.molecule,
let classType = MoleculeObjectMapping.shared()?.getMoleculeClass(moleculeModel), let classType = MoleculeObjectMapping.shared()?.getMoleculeClass(moleculeModel),
let height = classType.estimatedHeight(with: moleculeModel, delegateObject) let height = classType.estimatedHeight(with: moleculeModel, delegateObject)
else { return 80 } else { return 80 }

View File

@ -9,6 +9,10 @@
import Foundation import Foundation
@objcMembers public class StackItemModel: ContainerModel, StackItemModelProtocol, MoleculeModelProtocol { @objcMembers public class StackItemModel: ContainerModel, StackItemModelProtocol, MoleculeModelProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public static var identifier: String = "simpleStackItem" public static var identifier: String = "simpleStackItem"
public var moleculeName: String = StackItemModel.identifier public var moleculeName: String = StackItemModel.identifier
public var backgroundColor: Color? public var backgroundColor: Color?
@ -16,12 +20,18 @@ import Foundation
public var percent: Int? public var percent: Int?
public var gone: Bool = false public var gone: Bool = false
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public convenience init(spacing: CGFloat? = nil, percent: Int? = nil, horizontalAlignment: UIStackView.Alignment? = nil, verticalAlignment: UIStackView.Alignment? = nil, gone: Bool? = nil) { public convenience init(spacing: CGFloat? = nil, percent: Int? = nil, horizontalAlignment: UIStackView.Alignment? = nil, verticalAlignment: UIStackView.Alignment? = nil, gone: Bool? = nil) {
self.init() self.init()
self.horizontalAlignment = horizontalAlignment self.horizontalAlignment = horizontalAlignment
self.verticalAlignment = verticalAlignment self.verticalAlignment = verticalAlignment
self.spacing = spacing self.spacing = spacing
self.percent = percent self.percent = percent
if let gone = gone { if let gone = gone {
self.gone = gone self.gone = gone
} }

View File

@ -19,4 +19,26 @@ public class LabelToggleModel: MoleculeModelProtocol {
self.label = label self.label = label
self.toggle = toggle self.toggle = toggle
} }
private enum CodingKeys: String, CodingKey {
case moleculeName
case backgroundColor
case label
case toggle
}
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey:.backgroundColor)
label = try typeContainer.decode(LabelModel.self, forKey:.label)
toggle = try typeContainer.decode(ToggleModel.self, forKey:.toggle)
}
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.encode(label, forKey: .label)
try container.encode(toggle, forKey: .toggle)
}
} }

View File

@ -19,7 +19,7 @@ import UIKit
public let body = Label.commonLabelB2(true) public let body = Label.commonLabelB2(true)
public let link = Link() public let link = Link()
var casteModel: EyebrowHeadlineBodyLinkModel? { var castModel: EyebrowHeadlineBodyLinkModel? {
get { return model as? EyebrowHeadlineBodyLinkModel } get { return model as? EyebrowHeadlineBodyLinkModel }
} }
@ -59,10 +59,10 @@ import UIKit
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)
eyebrow.setOptional(with: casteModel?.eyebrow, delegateObject, additionalData) eyebrow.setOptional(with: castModel?.eyebrow, delegateObject, additionalData)
headline.setOptional(with: casteModel?.headline, delegateObject, additionalData) headline.setOptional(with: castModel?.headline, delegateObject, additionalData)
body.setOptional(with: casteModel?.body, delegateObject, additionalData) body.setOptional(with: castModel?.body, delegateObject, additionalData)
link.setOptional(with: casteModel?.link, delegateObject, additionalData) link.setOptional(with: castModel?.link, delegateObject, additionalData)
// Hide labels if neeeded. // Hide labels if neeeded.
stack.stackModel?.molecules[0].gone = !eyebrow.hasText stack.stackModel?.molecules[0].gone = !eyebrow.hasText

View File

@ -9,9 +9,10 @@
import UIKit import UIKit
open class HeadlineBody: View { open class HeadlineBody: View {
let headlineLabel = Label.commonLabelH2(true) let headlineLabel = Label.commonLabelH2(true)
let messageLabel = Label.commonLabelB2(true) let messageLabel = Label.commonLabelB2(true)
var spaceBetweenLabelsConstant = PaddingTwo var spaceBetweenLabelsConstant = PaddingOne
var spaceBetweenLabels: NSLayoutConstraint? var spaceBetweenLabels: NSLayoutConstraint?
var leftConstraintTitle: NSLayoutConstraint? var leftConstraintTitle: NSLayoutConstraint?
var rightConstraintTitle: NSLayoutConstraint? var rightConstraintTitle: NSLayoutConstraint?
@ -71,8 +72,6 @@ open class HeadlineBody: View {
open override func setupView() { open override func setupView() {
super.setupView() super.setupView()
guard subviews.isEmpty else { return }
backgroundColor = .clear backgroundColor = .clear
clipsToBounds = true clipsToBounds = true
@ -81,6 +80,10 @@ open class HeadlineBody: View {
addSubview(view) addSubview(view)
NSLayoutConstraint.constraintPinSubview(toSuperview: view) NSLayoutConstraint.constraintPinSubview(toSuperview: view)
view.isAccessibilityElement = false
view.shouldGroupAccessibilityChildren = true
view.accessibilityElements = [headlineLabel, messageLabel]
view.addSubview(headlineLabel) view.addSubview(headlineLabel)
view.addSubview(messageLabel) view.addSubview(messageLabel)

View File

@ -28,11 +28,11 @@ open class Carousel: View {
/// The number of pages that there are. Used for the page control and for calculations. Should not include the looping dummy cells. Be sure to set this if subclassing and not using the molecules. /// The number of pages that there are. Used for the page control and for calculations. Should not include the looping dummy cells. Be sure to set this if subclassing and not using the molecules.
open var numberOfPages = 0 open var numberOfPages = 0
/// The json for the molecules. /// The models for the molecules.
var molecules: [MoleculeModelProtocol]? var molecules: [MoleculeModelProtocol]?
/// The horizontal alignment of the cell in the collection view. Only noticeable if the itemWidthPercent is less than 100%. /// The horizontal alignment of the cell in the collection view. Only noticeable if the itemWidthPercent is less than 100%.
var itemAlignment = UICollectionView.ScrollPosition.left public var itemAlignment = UICollectionView.ScrollPosition.left
/// From 0-1. The item width as a percent of the carousel width. /// From 0-1. The item width as a percent of the carousel width.
public var itemWidthPercent: Float = 1 public var itemWidthPercent: Float = 1

View File

@ -15,10 +15,11 @@ open class Stack<T>: Container where T: (StackModelProtocol & MoleculeModelProto
//-------------------------------------------------- //--------------------------------------------------
open var contentView: UIView = MVMCoreUICommonViewsUtility.commonView() open var contentView: UIView = MVMCoreUICommonViewsUtility.commonView()
open var stackItems: [UIView] = []
open var stackModel: T? { open var stackModel: T? {
get { return model as? T } get { return model as? T }
} }
open var stackItems: [UIView] = []
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Helpers // MARK: - Helpers
@ -37,15 +38,21 @@ open class Stack<T>: Container where T: (StackModelProtocol & MoleculeModelProto
guard let stackModel = stackModel else { return } guard let stackModel = stackModel else { return }
let stackItems = self.stackItems let stackItems = self.stackItems
self.stackItems = [] self.stackItems = []
let lastItemIndex = stackModel.molecules.lastIndex(where: { (item) -> Bool in let lastItemIndex = stackModel.molecules.lastIndex { !$0.gone }
return !item.gone
})
// Adds the views // Adds the views
let totalSpace = getTotalSpace() let totalSpace = getTotalSpace()
for (index, view) in stackItems.enumerated() { for (index, view) in stackItems.enumerated() {
addView(view, stackModel.molecules[index], totalSpacing: totalSpace, lastItem: lastItemIndex == index) addView(view, stackModel.molecules[index], totalSpacing: totalSpace, lastItem: lastItemIndex == index)
} }
isAccessibilityElement = false
var accessibleViews: [Any] = []
for (index, view) in stackItems.enumerated() where !stackModel.molecules[index].gone {
accessibleViews.append(view)
}
accessibilityElements = accessibleViews
} }
/// Removes all stack items views from the view. /// Removes all stack items views from the view.

View File

@ -1,6 +1,12 @@
import Foundation import Foundation
public enum MolecularError: Swift.Error {
case error(String)
case countImbalance(String)
}
public protocol MoleculeModelProtocol: ModelProtocol { public protocol MoleculeModelProtocol: ModelProtocol {
var moleculeName: String { get } var moleculeName: String { get }
var backgroundColor: Color? { get set } var backgroundColor: Color? { get set }

View File

@ -1,20 +0,0 @@
//
// PageModelProtocol.swift
// MVMCoreUI
//
// Created by Scott Pfeil on 1/9/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
public protocol PageModelProtocol {
var pageType: String { get set }
var screenHeading: String? { get set }
<<<<<<< HEAD
var navigationItem: NavigationItemModelProtocol? { get set }
=======
var isAtomicTabs: Bool? { get set }
var navigationItem: (NavigationItemModelProtocol & MoleculeModelProtocol)? { get set }
>>>>>>> 18f86575e604bb7b53b6bdac4fc677951979031f
}

View File

@ -20,7 +20,6 @@ public extension TemplateProtocol where Self: ViewController {
let data = try JSONSerialization.data(withJSONObject: pageJSON) let data = try JSONSerialization.data(withJSONObject: pageJSON)
let decoder = JSONDecoder() let decoder = JSONDecoder()
let templateModel = try decoder.decode(TemplateModel.self, from: data) let templateModel = try decoder.decode(TemplateModel.self, from: data)
print(templateModel.toJSONString() ?? "")
self.templateModel = templateModel self.templateModel = templateModel
self.pageModel = templateModel as? MVMControllerModelProtocol self.pageModel = templateModel as? MVMControllerModelProtocol
} }

View File

@ -1,30 +0,0 @@
//
// ModalMoleculeListTemplate.swift
// MVMCoreUI
//
// Created by Ryan on 3/6/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import UIKit
open class ModalMoleculeListTemplate: MoleculeListTemplate {
<<<<<<< HEAD
override open func handleNewData() {
MVMCoreUICommonViewsUtility.addCloseButton(to: view, action: {[weak self] _ in
if let _ = self {
MVMCoreNavigationHandler.shared()?.removeCurrentViewController()
}
=======
public var closeButton: MFCustomButton?
override open func newDataBuildScreen() {
super.newDataBuildScreen()
closeButton = MVMCoreUICommonViewsUtility.addCloseButton(to: view, action: { [weak self] _ in
self?.dismiss()
>>>>>>> develop
}, verticalCentered: false)
super.handleNewData()
}
}

View File

@ -1,58 +0,0 @@
//
// StackPageTemplate.swift
// MVMCoreUI
//
// Created by Suresh, Kamlesh on 11/22/19.
// Copyright © 2019 Verizon Wireless. All rights reserved.
//
import Foundation
@objcMembers public class StackPageTemplateModel: TemplateModel {
public override class var identifier: String {
return "stack"
}
public var header: MoleculeModelProtocol?
public var moleculeStack: MoleculeStackModel
public var footer: MoleculeModelProtocol?
public init(pageType: String, moleculeStack: MoleculeStackModel) {
self.moleculeStack = moleculeStack
super.init(pageType: pageType)
}
private enum CodingKeys: String, CodingKey {
<<<<<<< HEAD
=======
case pageType
case template
case screenHeading
>>>>>>> develop
case header
case footer
case stack
}
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
moleculeStack = try typeContainer.decode(MoleculeStackModel.self, forKey: .stack)
header = try typeContainer.decodeModelIfPresent(codingKey: .header)
footer = try typeContainer.decodeModelIfPresent(codingKey: .footer)
try super.init(from: decoder)
}
public override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self)
<<<<<<< HEAD
=======
try container.encode(pageType, forKey: .pageType)
try container.encode(template, forKey: .template)
>>>>>>> develop
try container.encode(moleculeStack, forKey: .stack)
try container.encodeModelIfPresent(header, forKey: .header)
try container.encodeModelIfPresent(footer, forKey: .footer)
}
}

View File

@ -12,6 +12,7 @@ import UIKit
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Properties // MARK: - Properties
//-------------------------------------------------- //--------------------------------------------------
open var model: MoleculeModelProtocol? open var model: MoleculeModelProtocol?
private var initialSetupPerformed = false private var initialSetupPerformed = false
@ -81,7 +82,7 @@ extension Control: AppleGuidelinesProtocol {
// MARK: - MVMCoreViewProtocol // MARK: - MVMCoreViewProtocol
extension Control: MVMCoreViewProtocol { extension Control: MVMCoreViewProtocol {
open func updateView(_ size: CGFloat) {} open func updateView(_ size: CGFloat) { }
/// Will be called only once. /// Will be called only once.
open func setupView() { open func setupView() {

View File

@ -8,7 +8,7 @@
import UIKit import UIKit
@objcMembers open class TableViewCell: UITableViewCell, MoleculeViewProtocol, MoleculeListCellProtocol { @objcMembers open class TableViewCell: UITableViewCell, MoleculeViewProtocol, MoleculeListCellProtocol, MVMCoreViewProtocol {
open var molecule: MoleculeViewProtocol? open var molecule: MoleculeViewProtocol?
open var listItemModel: ListItemModelProtocol? open var listItemModel: ListItemModelProtocol?
@ -197,10 +197,13 @@ import UIKit
// MARK: - Caret View // 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 }
let caret = CaretView(lineWidth: 1) let caret = CaretView(lineWidth: 1)
caret.translatesAutoresizingMaskIntoConstraints = true caret.translatesAutoresizingMaskIntoConstraints = true
caret.isAccessibilityElement = true
caret.accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: "AccTabHint")
caret.size = .small(.vertical) caret.size = .small(.vertical)
if let size = caret.size?.dimensions() { if let size = caret.size?.dimensions() {
caret.frame = CGRect(origin: CGPoint.zero, size: size) caret.frame = CGRect(origin: CGPoint.zero, size: size)
@ -246,7 +249,7 @@ import UIKit
// MARK: - MoleculeListCellProtocol // MARK: - MoleculeListCellProtocol
/// For when the separator between cells shows using json and frequency. Default is type: standard, frequency: allExceptTop. /// For when the separator between cells shows using json and frequency. Default is type: standard, frequency: allExceptTop.
public func setLines(with model: LineModel?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?, indexPath: IndexPath) { public func setLines(with model: LineModel?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?, indexPath: IndexPath) {
addSeparatorsIfNeeded() addSeparatorsIfNeeded()
if let model = model { if let model = model {
topSeparatorView?.set(with: model, delegateObject, additionalData) topSeparatorView?.set(with: model, delegateObject, additionalData)
@ -258,7 +261,7 @@ import UIKit
setSeparatorFrequency(model?.frequency ?? .allExceptTop, indexPath: indexPath) setSeparatorFrequency(model?.frequency ?? .allExceptTop, indexPath: indexPath)
} }
public func didSelectCell(at index: IndexPath, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) { public func didSelectCell(at index: IndexPath, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
//TODO: Use object when handleAction is rewrote to handle action model //TODO: Use object when handleAction is rewrote to handle action model
if let actionMap = self.listItemModel?.action?.toJSON() { if let actionMap = self.listItemModel?.action?.toJSON() {
MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: additionalData, delegateObject: delegateObject) MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: additionalData, delegateObject: delegateObject)

View File

@ -33,7 +33,7 @@ import UIKit
/// Checks if the screen width has changed /// Checks if the screen width has changed
open func screenSizeChanged() -> Bool { open func screenSizeChanged() -> Bool {
return MVMCoreGetterUtility.cgfequalwiththreshold(previousScreenSize.width, view.bounds.size.width, 0.1) return !MVMCoreGetterUtility.cgfequalwiththreshold(previousScreenSize.width, view.bounds.size.width, 0.1)
} }
// MARK: - Response handling // MARK: - Response handling
@ -276,17 +276,18 @@ import UIKit
open override func viewDidLayoutSubviews() { open override func viewDidLayoutSubviews() {
// Add to fix a constraint bug where the width is zero and things get messed up. // Add to fix a constraint bug where the width is zero and things get messed up.
guard isViewLoaded, guard isViewLoaded, view.bounds.width > 1 else {
view.bounds.width > 1 else { super.viewDidLayoutSubviews()
super.viewDidLayoutSubviews() return
return
} }
if needsUpdateUI || screenSizeChanged() { if needsUpdateUI || screenSizeChanged() {
updateViews() updateViews()
needsUpdateUI = false needsUpdateUI = false
} }
previousScreenSize = view.bounds.size; previousScreenSize = view.bounds.size;
super.viewDidLayoutSubviews() super.viewDidLayoutSubviews()
} }

View File

@ -8,13 +8,15 @@
import Foundation import Foundation
extension UIStackView: MoleculeViewProtocol { extension UIStackView: MVMCoreViewProtocol {
public func updateView(_ size: CGFloat) { public func updateView(_ size: CGFloat) {
for view in arrangedSubviews { for view in arrangedSubviews {
(view as? MVMCoreViewProtocol)?.updateView(size) (view as? MVMCoreViewProtocol)?.updateView(size)
} }
} }
}
extension UIStackView: MoleculeViewProtocol {
public func reset() { public func reset() {
for view in arrangedSubviews { for view in arrangedSubviews {
(view as? MoleculeViewProtocol)?.reset() (view as? MoleculeViewProtocol)?.reset()

View File

@ -9,6 +9,10 @@
import Foundation import Foundation
open class ContainerModel: ContainerModelProtocol, Codable { open class ContainerModel: ContainerModelProtocol, Codable {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public var horizontalAlignment: UIStackView.Alignment? public var horizontalAlignment: UIStackView.Alignment?
public var verticalAlignment: UIStackView.Alignment? public var verticalAlignment: UIStackView.Alignment?
public var useHorizontalMargins: Bool? public var useHorizontalMargins: Bool?
@ -17,6 +21,10 @@ open class ContainerModel: ContainerModelProtocol, Codable {
public var topMarginPadding: CGFloat? public var topMarginPadding: CGFloat?
public var bottomMarginPadding: CGFloat? public var bottomMarginPadding: CGFloat?
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case verticalAlignment case verticalAlignment
case horizontalAlignment case horizontalAlignment
@ -26,6 +34,10 @@ open class ContainerModel: ContainerModelProtocol, Codable {
case bottomMarginPadding case bottomMarginPadding
} }
//--------------------------------------------------
// MARK: - Initializers
//--------------------------------------------------
public init() {} public init() {}
public convenience init(horizontalAlignment: UIStackView.Alignment? = nil, verticalAlignment: UIStackView.Alignment? = nil) { public convenience init(horizontalAlignment: UIStackView.Alignment? = nil, verticalAlignment: UIStackView.Alignment? = nil) {
@ -33,6 +45,10 @@ open class ContainerModel: ContainerModelProtocol, Codable {
self.horizontalAlignment = horizontalAlignment self.horizontalAlignment = horizontalAlignment
self.verticalAlignment = verticalAlignment self.verticalAlignment = verticalAlignment
} }
//--------------------------------------------------
// 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)

View File

@ -260,13 +260,21 @@ import UIKit
refreshUI(bottomBarSize: 1) refreshUI(bottomBarSize: 1)
} }
open func refreshUI(bottomBarSize: CGFloat? = nil) { open func refreshUI(bottomBarSize: CGFloat? = nil, updateMoleculeLayout: Bool = false) {
if !disableAllBorders { if !disableAllBorders {
let size: CGFloat = bottomBarSize ?? (showError ? 4 : 1) let size: CGFloat = bottomBarSize ?? (showError ? 4 : 1)
var heightChanged = false
if let bottomHeight = bottomBar?.bounds.height {
heightChanged = size != bottomHeight
}
bottomBar?.frame = CGRect(x: 0, y: bounds.height - size, width: bounds.width, height: size) bottomBar?.frame = CGRect(x: 0, y: bounds.height - size, width: bounds.width, height: size)
delegateObject?.moleculeDelegate?.moleculeLayoutUpdated(self) if updateMoleculeLayout || heightChanged {
delegateObject?.moleculeDelegate?.moleculeLayoutUpdated(self)
}
setNeedsDisplay() setNeedsDisplay()
layoutIfNeeded() layoutIfNeeded()
} }

View File

@ -30,6 +30,11 @@ import UIKit
primaryButton?.isEnabled = enabled primaryButton?.isEnabled = enabled
} }
public init(withJSON json: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?) {
super.init(frame: .zero)
setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
}
// MARK: - MVMCoreViewProtocol // MARK: - MVMCoreViewProtocol
open override func updateView(_ size: CGFloat) { open override func updateView(_ size: CGFloat) {
super.updateView(size) super.updateView(size)
@ -44,6 +49,11 @@ import UIKit
alignCenterHorizontal() alignCenterHorizontal()
} }
// MARK: - MVMCoreUIMoleculeViewProtocol
open func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
primaryButton?.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
}
// MARK: - Constraining // MARK: - Constraining
open override func copyBackgroundColor() -> Bool { open override func copyBackgroundColor() -> Bool {
return true return true

View File

@ -10,6 +10,7 @@
#import <MVMCoreUI/MFCustomButton.h> #import <MVMCoreUI/MFCustomButton.h>
#import <MVMCoreUI/MFTextField.h> #import <MVMCoreUI/MFTextField.h>
#import <MVMCoreUI/MFView.h> #import <MVMCoreUI/MFView.h>
@class MVMCoreUIDelegateObject;
typedef enum : NSUInteger { typedef enum : NSUInteger {
PrimaryButtonTypeRed, PrimaryButtonTypeRed,
@ -117,6 +118,9 @@ static CGFloat const PrimaryButtonSmallHeight = 30.0;
- (void)resetButtonType:(PrimaryButtonType)type small:(BOOL)isSmall bordered:(BOOL)bordered; - (void)resetButtonType:(PrimaryButtonType)type small:(BOOL)isSmall bordered:(BOOL)bordered;
- (void)resetButtonType:(PrimaryButtonType)type tiny:(BOOL)isTiny bordered:(BOOL)bordered; - (void)resetButtonType:(PrimaryButtonType)type tiny:(BOOL)isTiny bordered:(BOOL)bordered;
// Convenience setter for common keys
- (void)setWithJSON:(nullable NSDictionary *)json delegateObject:(nullable MVMCoreUIDelegateObject *)delegateObject additionalData:(nullable NSDictionary *)additionalData;
#pragma mark - Handling Validations #pragma mark - Handling Validations
// Sets the enabled property depending on the validity checks // Sets the enabled property depending on the validity checks

View File

@ -655,6 +655,47 @@
return button; return button;
} }
- (void)setWithJSON:(NSDictionary *)json delegateObject:(MVMCoreUIDelegateObject *)delegateObject additionalData:(NSDictionary *)additionalData {
self.primaryButtonType = PrimaryButtonTypeCustom;
NSString *style = [json string:@"style"];
if ([style isEqualToString:@"primary"]) {
[self setAsStandardCustom];
} else if ([style isEqualToString:@"secondary"]) {
[self setAsSecondaryCustom];
}
NSString *color = [json string:@"fillColor"];
if (color) {
self.fillColor = [UIColor mfGetColorForHex:color];
}
if ((color = [json string:KeyTextColor])) {
self.textColor = [UIColor mfGetColorForHex:color];
}
if ((color = [json string:@"borderColor"])) {
self.borderColor = [UIColor mfGetColorForHex:color];
}
_bordered = self.borderColor != nil;
if ((color = [json string:@"disabledFillColor"])) {
self.disabledFillColor = [UIColor mfGetColorForHex:color];
}
if ((color = [json string:@"disabledTextColor"])) {
self.disabledTextColor = [UIColor mfGetColorForHex:color];
}
if ((color = [json string:@"disabledBorderColor"])) {
self.disabledBorderColor = [UIColor mfGetColorForHex:color];
}
NSString *size = [json string:@"size"];
if ([size isEqualToString:@"small"]) {
[self setAsSmallButton:YES];
} else if ([size isEqualToString:@"tiny"]) {
[self setAsTiny:YES];
} else {
[self setAsSmallButton:NO];
}
[self setWithActionMap:json delegateObject:delegateObject additionalData:additionalData];
}
#pragma mark - Constraining Protocol #pragma mark - Constraining Protocol
- (UIStackViewAlignment)horizontalAlignment { - (UIStackViewAlignment)horizontalAlignment {

View File

@ -6,52 +6,73 @@
Copyright © 2017 myverizon. All rights reserved. Copyright © 2017 myverizon. All rights reserved.
*/ */
//// Accessibility // MARK: Accessibility
"AccCloseButton" = "Close"; "AccCloseButton" = "Close";
"swipe_to_select_with_action_hint" = "swipe up or down to select action, then double tap to select."; "swipe_to_select_with_action_hint" = "swipe up or down to select action, then double tap to select.";
// Tab
// MARK: Tab
"AccTab" = ", tab"; "AccTab" = ", tab";
"AccTabHint" = "Double tap to select."; "AccTabHint" = "Double tap to select.";
"AccTabIndex" = ", %ld of %ld"; "AccTabIndex" = ", %ld of %ld";
// top alert
// MARK: Top alert
"toptabbar_tab_selected" = ", tab, Selected"; "toptabbar_tab_selected" = ", tab, Selected";
"AccTopAlertClosed" = "Top alert notification is closed."; "AccTopAlertClosed" = "Top alert notification is closed.";
"top_alert_notification" = "Top alert notification"; "top_alert_notification" = "Top alert notification";
// Textfield
// MARK: Textfield
"textfield_today_string" = "Today"; "textfield_today_string" = "Today";
"textfield_error_message" = "%@.\n The error message.\n %@"; "textfield_error_message" = "%@.\n The error message.\n %@";
"textfield_picker_item" = " picker item"; "textfield_picker_item" = " picker item";
"textfield_regular" = " regular"; "textfield_regular" = " regular";
"textfield_disabled_state" = "disabled"; "textfield_disabled_state" = "disabled";
// MDNTextfield
// MARK: MDNTextfield
"textfield_contacts_barbutton" = "My Contacts"; "textfield_contacts_barbutton" = "My Contacts";
"textfield_phone_format_error_message" = "Invalid phone number format."; "textfield_phone_format_error_message" = "Invalid phone number format.";
// DigitTextfield
// MARK: DigitTextfield
"mfdigittextfield_regular" = " regular"; "mfdigittextfield_regular" = " regular";
// Camera
// MARK: Camera
"AccCameraButton" = "Camera Button"; "AccCameraButton" = "Camera Button";
"AccCameraHint" = "Double tap to launch camera for scanning"; "AccCameraHint" = "Double tap to launch camera for scanning";
// Checkbox
// MARK: Checkbox
"checkbox_action_hint" = "Double tap to change state"; "checkbox_action_hint" = "Double tap to change state";
"checkbox_checked_state" = "Checked"; "checkbox_checked_state" = "Checked";
"checkbox_unchecked_state" = "Unchecked"; "checkbox_unchecked_state" = "Unchecked";
"checkbox_desc_state" = "%@ CheckBox %@"; "checkbox_desc_state" = "%@ CheckBox %@";
// Radio Button
// MARK: Radio Button
"radio_action_hint" = "Double tap to select"; "radio_action_hint" = "Double tap to select";
"radio_selected_state" = "Selected"; "radio_selected_state" = "Selected";
"radio_not_selected_state" = "Not Selected"; "radio_not_selected_state" = "Not Selected";
"radio_desc_state" = "Option"; "radio_desc_state" = "Option";
// Switch
// MARK: Switch / Toggle
"mfswitch_buttonlabel" = "Switch Button"; "mfswitch_buttonlabel" = "Switch Button";
"Toggle_buttonlabel" = "Toggle Button";
"AccOn" = "on"; "AccOn" = "on";
"AccOff" = "off"; "AccOff" = "off";
"AccToggleHint" = "double tap to toggle"; "AccToggleHint" = "double tap to toggle";
// Carousel
// MARK: Carousel
"MVMCoreUIPageControl_currentpage_index" = "page %ld of %ld"; "MVMCoreUIPageControl_currentpage_index" = "page %ld of %ld";
"MVMCoreUIPageControlslides_currentpage_index" = "slide %ld of %ld"; "MVMCoreUIPageControlslides_currentpage_index" = "slide %ld of %ld";
//Styler
// MARK: Styler
"CountDownDay" = " day"; "CountDownDay" = " day";
"CountDownHour" = " hour"; "CountDownHour" = " hour";
"CountDownMin" = " min"; "CountDownMin" = " min";

View File

@ -86,7 +86,7 @@ NSString * const MFAccTopAlertClosed = @"Top alert notification is closed.";
- (void)pinATopViewController:(UIViewController *)viewController { - (void)pinATopViewController:(UIViewController *)viewController {
self.statusBarHeightConstraint.active = NO; self.statusBarHeightConstraint.active = NO;
id topGuide = viewController.view.safeAreaLayoutGuide.topAnchor; id topGuide = viewController.topLayoutGuide;
self.statusBarBottomConstraint = [NSLayoutConstraint constraintWithItem:self.statusBarView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:topGuide attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0]; self.statusBarBottomConstraint = [NSLayoutConstraint constraintWithItem:self.statusBarView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:topGuide attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0];
self.statusBarBottomConstraint.active = YES; self.statusBarBottomConstraint.active = YES;
} }

View File

@ -9,12 +9,15 @@
import Foundation import Foundation
public extension MVMCoreUICommonViewsUtility { public extension MVMCoreUICommonViewsUtility {
static func getToolbarWithDoneButton(delegate: ObservingTextFieldDelegate) -> UIToolbar { static func getToolbarWithDoneButton(delegate: ObservingTextFieldDelegate) -> UIToolbar {
let toolbar = self.makeEmptyToolbar() let toolbar = self.makeEmptyToolbar()
let space = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) let space = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let button = UIBarButtonItem(barButtonSystemItem: .done, target: delegate, action: #selector(ObservingTextFieldDelegate.dismissFieldInput(sender:))) let button = UIBarButtonItem(barButtonSystemItem: .done, target: delegate, action: #selector(ObservingTextFieldDelegate.dismissFieldInput(sender:)))
button.tintColor = .black button.tintColor = .black
toolbar.setItems([space, button], animated: false) toolbar.setItems([space, button], animated: false)
return toolbar return toolbar
} }
} }

View File

@ -260,15 +260,15 @@ static const CGFloat VertialShadowOffset = 6;
UIBezierPath *shadowPath = [UIBezierPath bezierPath]; UIBezierPath *shadowPath = [UIBezierPath bezierPath];
//get the variables for frame //get the variables for frame
CGFloat x = 0; CGFloat x = rect.origin.x;
CGFloat y = 0; CGFloat y = rect.origin.y;
CGFloat width = CGRectGetWidth(rect); CGFloat width = CGRectGetWidth(rect);
CGFloat height = CGRectGetHeight(rect); CGFloat height = CGRectGetHeight(rect);
[shadowPath moveToPoint:CGPointMake(x + HorizontalShadowInset, y)]; [shadowPath moveToPoint:CGPointMake(x + HorizontalShadowInset, y)];
[shadowPath addLineToPoint:CGPointMake(width - HorizontalShadowInset, y)]; [shadowPath addLineToPoint:CGPointMake(x + width - HorizontalShadowInset, y)];
[shadowPath addLineToPoint:CGPointMake(width - HorizontalShadowInset, height-VertialShadowOffset/2)]; [shadowPath addLineToPoint:CGPointMake(x + width - HorizontalShadowInset, height-VertialShadowOffset/2)];
[shadowPath addQuadCurveToPoint:CGPointMake(x + HorizontalShadowInset, height - VertialShadowOffset/2) controlPoint:CGPointMake(width/2.f, height - VertialShadowOffset * 1.5)]; [shadowPath addQuadCurveToPoint:CGPointMake(x + HorizontalShadowInset, height - VertialShadowOffset/2) controlPoint:CGPointMake((x + width)/2.f, height - VertialShadowOffset * 1.5)];
[shadowPath addLineToPoint:CGPointMake(x + HorizontalShadowInset, y)]; [shadowPath addLineToPoint:CGPointMake(x + HorizontalShadowInset, y)];
[shadowPath closePath]; [shadowPath closePath];