Merge branch 'release/7_6_0' into 'develop'

Release/7 6 0

See merge request BPHV_MIPS/mvm_core_ui!404
This commit is contained in:
Pfeil, Scott Robert 2020-04-23 10:46:01 -04:00
commit 697d27ddeb
32 changed files with 420 additions and 178 deletions

View File

@ -94,6 +94,7 @@
0A7BAFA1232BE61800FB8E22 /* Checkbox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */; };
0A7ECC5D243CE85300C828E8 /* DoughnutChartItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7ECC5C243CE85300C828E8 /* DoughnutChartItemModel.swift */; };
0A7ECC5F243CEB1200C828E8 /* ColorViewWithLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7ECC5E243CEB1200C828E8 /* ColorViewWithLabel.swift */; };
0A7ECC702441001C00C828E8 /* UIToolbar+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7ECC6F2441001C00C828E8 /* UIToolbar+Extension.swift */; };
0A7EF85B23D8A52800B2AAD1 /* EntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7EF85A23D8A52800B2AAD1 /* EntryFieldModel.swift */; };
0A7EF85D23D8A95600B2AAD1 /* TextEntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7EF85C23D8A95600B2AAD1 /* TextEntryFieldModel.swift */; };
0A7EF85F23D8ABC500B2AAD1 /* MdnEntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7EF85E23D8ABC500B2AAD1 /* MdnEntryFieldModel.swift */; };
@ -102,6 +103,8 @@
0A7EF86523D8AFFF00B2AAD1 /* ItemDropdownEntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7EF86423D8AFFF00B2AAD1 /* ItemDropdownEntryFieldModel.swift */; };
0A7EF86723D8B0AE00B2AAD1 /* DateDropdownEntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7EF86623D8B0AE00B2AAD1 /* DateDropdownEntryFieldModel.swift */; };
0AA33B3A2398524F0067DD0F /* Toggle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AA33B392398524F0067DD0F /* Toggle.swift */; };
0AB764D124460F6300E7FE72 /* UIDatePicker+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AB764D024460F6300E7FE72 /* UIDatePicker+Extension.swift */; };
0AB764D324460FA400E7FE72 /* UIPickerView+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AB764D224460FA400E7FE72 /* UIPickerView+Extension.swift */; };
0ABD136D237CAD1E0081388D /* DateDropdownEntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ABD136C237CAD1E0081388D /* DateDropdownEntryField.swift */; };
0ABD1371237DB0450081388D /* ItemDropdownEntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ABD1370237DB0450081388D /* ItemDropdownEntryField.swift */; };
0AE14F64238315D2005417F8 /* TextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE14F63238315D2005417F8 /* TextField.swift */; };
@ -531,6 +534,7 @@
0A7BAFA2232BE63400FB8E22 /* CheckboxLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckboxLabel.swift; sourceTree = "<group>"; };
0A7ECC5C243CE85300C828E8 /* DoughnutChartItemModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DoughnutChartItemModel.swift; sourceTree = "<group>"; };
0A7ECC5E243CEB1200C828E8 /* ColorViewWithLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorViewWithLabel.swift; sourceTree = "<group>"; };
0A7ECC6F2441001C00C828E8 /* UIToolbar+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIToolbar+Extension.swift"; sourceTree = "<group>"; };
0A7EF85A23D8A52800B2AAD1 /* EntryFieldModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EntryFieldModel.swift; sourceTree = "<group>"; };
0A7EF85C23D8A95600B2AAD1 /* TextEntryFieldModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextEntryFieldModel.swift; sourceTree = "<group>"; };
0A7EF85E23D8ABC500B2AAD1 /* MdnEntryFieldModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MdnEntryFieldModel.swift; sourceTree = "<group>"; };
@ -541,6 +545,8 @@
0A8321AE2355FE9500CB7F00 /* DigitBox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DigitBox.swift; sourceTree = "<group>"; };
0AA33B33239813C50067DD0F /* UIColor+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIColor+Extension.swift"; sourceTree = "<group>"; };
0AA33B392398524F0067DD0F /* Toggle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Toggle.swift; sourceTree = "<group>"; };
0AB764D024460F6300E7FE72 /* UIDatePicker+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIDatePicker+Extension.swift"; sourceTree = "<group>"; };
0AB764D224460FA400E7FE72 /* UIPickerView+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIPickerView+Extension.swift"; sourceTree = "<group>"; };
0ABD136C237CAD1E0081388D /* DateDropdownEntryField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateDropdownEntryField.swift; sourceTree = "<group>"; };
0ABD1370237DB0450081388D /* ItemDropdownEntryField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemDropdownEntryField.swift; sourceTree = "<group>"; };
0AE14F63238315D2005417F8 /* TextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextField.swift; sourceTree = "<group>"; };
@ -1146,6 +1152,9 @@
D21EE53B23AD3AD4003D1A30 /* NSLayoutConstraintAxis+Extension.swift */,
D202AFE5242A6A9C00E5BEDF /* UICollectionViewScrollPosition+Extension.swift */,
013F801823FB4A8E00AD8013 /* UIContentMode+Extension.swift */,
0A7ECC6F2441001C00C828E8 /* UIToolbar+Extension.swift */,
0AB764D024460F6300E7FE72 /* UIDatePicker+Extension.swift */,
0AB764D224460FA400E7FE72 /* UIPickerView+Extension.swift */,
);
path = Extensions;
sourceTree = "<group>";
@ -2231,6 +2240,7 @@
AA69AAF82445BF6800AF3D3B /* ListLeftVariableCheckboxBodyTextModel.swift in Sources */,
D2B18B812360945C00A9AEDC /* View.swift in Sources */,
C6FA7D5423C77A4A00A3614A /* NumberedList.swift in Sources */,
0A7ECC702441001C00C828E8 /* UIToolbar+Extension.swift in Sources */,
D29DF26D21E6AA0B003B2FB9 /* FLAnimatedImageView.m in Sources */,
525019E52406852100EED91C /* ListFourColumnDataUsageDividerModel.swift in Sources */,
0A7EF86723D8B0AE00B2AAD1 /* DateDropdownEntryFieldModel.swift in Sources */,
@ -2335,6 +2345,7 @@
012A88DB238ED45900FE3DA1 /* CarouselModel.swift in Sources */,
D29DF28C21E7AC2B003B2FB9 /* ViewConstrainingView.m in Sources */,
0AE14F64238315D2005417F8 /* TextField.swift in Sources */,
0AB764D124460F6300E7FE72 /* UIDatePicker+Extension.swift in Sources */,
D29DF17B21E69E1F003B2FB9 /* PrimaryButton.m in Sources */,
D2C78CD224228BBD00B69FDE /* ActionOpenPanelModel.swift in Sources */,
C695A68123C9830D00BFB94E /* NumberedListModel.swift in Sources */,
@ -2416,6 +2427,7 @@
8D4687E2242E2DE400802879 /* ListFourColumnDataUsageListItemModel.swift in Sources */,
D29E28DD23D7404C00ACEA85 /* ContainerHelper.swift in Sources */,
012A88C2238D7BCA00FE3DA1 /* CarouselItemModel.swift in Sources */,
0AB764D324460FA400E7FE72 /* UIPickerView+Extension.swift in Sources */,
D29DF29E21E7AE3B003B2FB9 /* MFStyler.m in Sources */,
94C661D923CCF4B400D9FE5B /* LeftRightLabelModel.swift in Sources */,
011D95AB2405C553000E3791 /* FormItemProtocol.swift in Sources */,

View File

@ -9,6 +9,7 @@
import UIKit
@objcMembers public class ActionCollapseNotificationModel: ActionModelProtocol {
public static var identifier: String = "collapseNotification"
public var actionType: String
public var extraParameters: JSONValueDictionary?

View File

@ -9,7 +9,7 @@
import Foundation
public class ActionOpenPanelModel: ActionModelProtocol {
public enum Panel: String, Codable {
case left
case right

View File

@ -9,6 +9,7 @@
import Foundation
@objcMembers public class ActionTopAlertModel: ActionModelProtocol {
public static var identifier: String = "topAlert"
public var actionType: String = ActionTopAlertModel.identifier
public var pageType: String

View File

@ -69,7 +69,7 @@ import UIKit
textFieldTrailingConstraint = dropDownCaretView.leadingAnchor.constraint(equalTo: textField.trailingAnchor, constant: 6)
textFieldTrailingConstraint?.isActive = true
container.trailingAnchor.constraint(equalTo: dropDownCaretView.trailingAnchor, constant: 16).isActive = true
container.trailingAnchor.constraint(equalTo: dropDownCaretView.trailingAnchor, constant: Padding.Four).isActive = true
dropDownCaretView.centerYAnchor.constraint(equalTo: container.centerYAnchor).isActive = true
}

View File

@ -31,10 +31,9 @@ import UIKit
return formatter
}()
/// Update the property value to alter the format of how the date is presented.
public var dateFormat: String = "MMM d, y" {
didSet {
dateFormatter.dateFormat = dateFormat
}
didSet { dateFormatter.dateFormat = dateFormat }
}
//--------------------------------------------------
@ -69,10 +68,10 @@ import UIKit
public override func setupFieldContainerContent(_ container: UIView) {
super.setupFieldContainerContent(container)
datePicker = MVMCoreUICommonViewsUtility.addDatePicker(to: textField)
datePicker = UIDatePicker.addDatePicker(to: textField)
datePicker?.addTarget(self, action: #selector(pickerValueChanged), for: .valueChanged)
datePicker?.timeZone = NSTimeZone.system
MVMCoreUICommonViewsUtility.addDismissToolbar(textField, delegate: self)
UIToolbar.addDismissToolbar(to: textField, delegate: self, action: #selector(dismissFieldInput))
}
@objc public func setDatePickerDuration(from startDate: Date?, to endDate: Date?, showStartDate: Bool = true) {
@ -104,7 +103,7 @@ import UIKit
}
}
@objc override func dismissFieldInput(_ sender: Any?) {
@objc public override func dismissFieldInput(_ sender: Any?) {
setTextWith(date: datePicker?.date)
super.dismissFieldInput(sender)

View File

@ -22,24 +22,25 @@
//--------------------------------------------------
private enum CodingKeys: String, CodingKey {
case moleculeName
case dateFormat
}
//--------------------------------------------------
// MARK: - Initializers
// MARK: - Codec
//--------------------------------------------------
required public init(from decoder: Decoder) throws {
try super.init(from: decoder)
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
dateFormat = try typeContainer.decodeIfPresent(String.self, forKey: .dateFormat) ?? "MMM d, y"
if let dateFormat = try typeContainer.decodeIfPresent(String.self, forKey: .dateFormat) {
self.dateFormat = dateFormat
}
}
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(dateFormat, forKey: .dateFormat)
}
}

View File

@ -211,7 +211,9 @@ import UIKit
let digitBox = DigitBox()
digitBox.isAccessibilityElement = true
digitBox.digitField.inputAccessoryView = MVMCoreUICommonViewsUtility.getToolbarWithDoneButton(delegate: self)
let observingDelegate = delegateObject?.observingTextFieldDelegate ?? self
digitBox.digitField.inputAccessoryView = UIToolbar.getToolbarWithDoneButton(delegate: observingDelegate,
action: #selector(observingDelegate.dismissFieldInput))
digitBox.digitField.delegate = self
digitBox.digitBoxDelegate = self
return digitBox
@ -246,15 +248,6 @@ import UIKit
}
}
@objc public override func defaultValidationBlock() {
validationBlock = { enteredValue in
guard let enteredValue = enteredValue else { return false }
return enteredValue.count > 0 && enteredValue.count == self.digitBoxes.count
}
}
@objc public func selectPreviousDigitField(_ currentTextField: UITextField?, clear: Bool) {
var selectPreviousField = false
@ -322,7 +315,7 @@ import UIKit
return true
}
@objc override func dismissFieldInput(_ sender: Any?) {
@objc public override func dismissFieldInput(_ sender: Any?) {
digitBoxes.forEach {
if $0.isSelected {
@ -337,12 +330,18 @@ import UIKit
guard let model = model as? DigitEntryFieldModel else { return }
numberOfDigits = model.digits
setAsSecureTextEntry(model.secureEntry)
for digitBox in digitBoxes {
digitBox.digitField.inputAccessoryView = MVMCoreUICommonViewsUtility.getToolbarWithDoneButton(delegate: delegateObject?.observingTextFieldDelegate ?? self)
if let entryType = model.type {
setAsSecureTextEntry(entryType == .secure || entryType == .password)
}
let observingDelegate = delegateObject?.observingTextFieldDelegate ?? self
digitBoxes.forEach {
$0.digitField.inputAccessoryView = UIToolbar.getToolbarWithDoneButton(delegate: observingDelegate,
action: #selector(observingDelegate.dismissFieldInput))
}
super.set(with: model, delegateObject, additionalData)
}

View File

@ -17,34 +17,31 @@
}
public var digits: Int = 4
public var secureEntry: Bool = false
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------
private enum CodingKeys: String, CodingKey {
case moleculeName
case digits
case secureEntry
}
//--------------------------------------------------
// MARK: - Initializers
// MARK: - Codec
//--------------------------------------------------
required public init(from decoder: Decoder) throws {
try super.init(from: decoder)
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
digits = try typeContainer.decodeIfPresent(Int.self, forKey: .digits) ?? 4
secureEntry = try typeContainer.decodeIfPresent(Bool.self, forKey: .secureEntry) ?? false
if let digits = try typeContainer.decodeIfPresent(Int.self, forKey: .digits) {
self.digits = digits
}
}
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(digits, forKey: .digits)
try container.encode(secureEntry, forKey: .secureEntry)
}
}

View File

@ -20,7 +20,7 @@ import UIKit
public private(set) var titleLabel: Label = {
let label = Label()
label.font = MFStyler.fontRegularMicro()
label.font = Styler.Font.RegularMicro.getFont()
label.textColor = .mvmBlack
label.setContentCompressionResistancePriority(.required, for: .vertical)
return label
@ -31,12 +31,12 @@ import UIKit
/// Provides contextual information on the TextField.
public private(set) var feedbackLabel: Label = {
let label = Label()
label.font = MFStyler.fontRegularMicro()
label.font = Styler.Font.RegularMicro.getFont()
label.textColor = .mvmBlack
label.setContentCompressionResistancePriority(.required, for: .vertical)
return label
}()
//--------------------------------------------------
// MARK: - Delegate
//--------------------------------------------------
@ -48,14 +48,6 @@ import UIKit
//--------------------------------------------------
public var isValid: Bool = false
public var errorMessage: String?
public var standardMessage: String? {
didSet {
if !showError {
feedback = standardMessage
}
}
}
//--------------------------------------------------
// MARK: - Computed Properties
@ -75,7 +67,7 @@ import UIKit
public var showError: Bool {
get { return entryFieldContainer.showError }
set (error) {
self.feedback = error ? self.errorMessage : self.standardMessage
self.feedback = error ? entryFieldModel?.errorMessage : entryFieldModel?.feedback
self.entryFieldContainer.showError = error
}
}
@ -121,6 +113,10 @@ import UIKit
}
}
public var entryFieldModel: EntryFieldModel? {
return model as? EntryFieldModel
}
//--------------------------------------------------
// MARK: - Constraints
//--------------------------------------------------
@ -174,8 +170,6 @@ import UIKit
@objc final public override func setupView() {
super.setupView()
guard subviews.isEmpty else { return }
isAccessibilityElement = false
setContentCompressionResistancePriority(.required, for: .vertical)
accessibilityElements = [titleLabel, feedbackLabel]
@ -193,7 +187,7 @@ import UIKit
entryFieldContainer.setContentCompressionResistancePriority(.required, for: .vertical)
setupFieldContainerContent(entryFieldContainer)
titleContainerDistance = entryFieldContainer.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 4)
titleContainerDistance = entryFieldContainer.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: Padding.One)
titleContainerDistance?.isActive = true
entryFieldContainerLeading = entryFieldContainer.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor)
entryFieldContainerLeading?.isActive = true
@ -202,7 +196,7 @@ import UIKit
addSubview(feedbackLabel)
feedbackContainerDistance = feedbackLabel.topAnchor.constraint(equalTo: entryFieldContainer.bottomAnchor, constant: PaddingOne)
feedbackContainerDistance = feedbackLabel.topAnchor.constraint(equalTo: entryFieldContainer.bottomAnchor, constant: Padding.Two)
feedbackContainerDistance?.isActive = true
feedbackLabelLeading = feedbackLabel.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor)
feedbackLabelLeading?.isActive = true
@ -217,11 +211,11 @@ import UIKit
entryFieldContainer.refreshUI()
}
/// Method to override.
/// Intended to add the interactive content (i.e. textField) to the entryFieldContainer.
@objc open func setupFieldContainerContent(_ container: UIView) {
// To be overridden by subclass.
}
/**
Method to override.
Intended to add the interactive content (i.e. textField) to the entryFieldContainer.
*/
@objc open func setupFieldContainerContent(_ container: UIView) { }
@objc open override func updateView(_ size: CGFloat) {
super.updateView(size)
@ -240,10 +234,11 @@ import UIKit
backgroundColor = .clear
isAccessibilityElement = false
titleLabel.font = MFStyler.fontRegularMicro()
titleLabel.font = Styler.Font.RegularMicro.getFont()
titleLabel.textColor = .mvmBlack
feedbackLabel.font = MFStyler.fontRegularMicro()
feedbackLabel.font = Styler.Font.RegularMicro.getFont()
feedbackLabel.textColor = .mvmBlack
feedbackLabel.text = nil
entryFieldContainer.reset()
}
@ -257,7 +252,6 @@ import UIKit
title = model.title
feedback = model.feedback
errorMessage = model.errorMessage
isEnabled = model.enabled
if let isLocked = model.locked {

View File

@ -22,29 +22,22 @@ import Foundation
public var backgroundColor: Color?
public var title: String?
public var feedback: String?
public var errorMessage: String = ""
public var errorMessage: String?
public var enabled: Bool = true
public var locked: Bool?
public var selected: Bool?
public var text: String?
public var fieldKey: String?
public var groupName: String = FormValidator.defaultGroupName
public var baseValue: AnyHashable?
public var isValid: Bool? {
didSet {
updateUI?()
}
didSet { updateUI?() }
}
/// Temporary binding mechanism for the view to update on enable changes.
public var updateUI: (() -> Void)?
public var updateUI: (() -> ())?
public func setValidity(_ valid: Bool, rule: RulesProtocol) {
self.isValid = valid
}
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------
@ -62,11 +55,19 @@ import Foundation
case fieldKey
case groupName
}
//--------------------------------------------------
// MARK: - Validation Methods
//--------------------------------------------------
public func formFieldValue() -> AnyHashable? {
return text
}
public func setValidity(_ valid: Bool, rule: RulesProtocol) {
self.isValid = valid
}
//--------------------------------------------------
// MARK: - Initializers
//--------------------------------------------------
@ -76,17 +77,20 @@ import Foundation
baseValue = text
}
//--------------------------------------------------
// 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)
title = try typeContainer.decodeIfPresent(String.self, forKey: .title)
feedback = try typeContainer.decodeIfPresent(String.self, forKey: .feedback)
errorMessage = try typeContainer.decodeIfPresent(String.self, forKey: .errorMessage) ?? ""
errorMessage = try typeContainer.decodeIfPresent(String.self, forKey: .errorMessage)
enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) ?? true
locked = try typeContainer.decodeIfPresent(Bool.self, forKey: .locked)
selected = try typeContainer.decodeIfPresent(Bool.self, forKey: .selected)
text = try typeContainer.decodeIfPresent(String.self, forKey: .text)
baseValue = text
fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey)
if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) {
@ -100,11 +104,11 @@ import Foundation
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encodeIfPresent(title, forKey: .title)
try container.encodeIfPresent(feedback, forKey: .feedback)
try container.encode(errorMessage, forKey: .errorMessage)
try container.encode(enabled, forKey: .enabled)
try container.encode(locked, forKey: .locked)
try container.encode(selected, forKey: .selected)
try container.encodeIfPresent(text, forKey: .text)
try container.encodeIfPresent(locked, forKey: .locked)
try container.encodeIfPresent(selected, forKey: .selected)
try container.encodeIfPresent(errorMessage, forKey: .errorMessage)
try container.encode(enabled, forKey: .enabled)
try container.encodeIfPresent(fieldKey, forKey: .fieldKey)
try container.encodeIfPresent(groupName, forKey: .groupName)
}

View File

@ -8,6 +8,8 @@
import UIKit
public typealias TextFieldAndPickerDelegate = (UITextFieldDelegate & UIPickerViewDelegate & UIPickerViewDataSource)
open class ItemDropdownEntryField: BaseDropdownEntryField {
//--------------------------------------------------
@ -62,7 +64,7 @@ open class ItemDropdownEntryField: BaseDropdownEntryField {
@objc open override func setupFieldContainerContent(_ container: UIView) {
super.setupFieldContainerContent(container)
pickerView = MVMCoreUICommonViewsUtility.addPicker(to: textField, delegate: self)
pickerView = UIPickerView.addPicker(to: textField, delegate: self, dismissAction: #selector(dismissFieldInput))
textField.hideBlinkingCaret = true
textField.autocorrectionType = .no
uiTextFieldDelegate = self

View File

@ -17,17 +17,21 @@
public var options: [String] = []
public var selectedIndex: Int = 0
public override func formFieldValue() -> AnyHashable? {
guard !options.isEmpty else { return nil }
return options[selectedIndex]
}
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------
private enum CodingKeys: String, CodingKey {
case moleculeName
case options
case selectedIndex
}
//--------------------------------------------------
// MARK: - Initializers
//--------------------------------------------------
@ -35,14 +39,17 @@
required public init(from decoder: Decoder) throws {
try super.init(from: decoder)
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
options = try typeContainer.decode([String].self, forKey: .options)
selectedIndex = try typeContainer.decodeIfPresent(Int.self, forKey: .selectedIndex) ?? 0
if let selectedIndex = try typeContainer.decodeIfPresent(Int.self, forKey: .selectedIndex) {
self.selectedIndex = selectedIndex
}
}
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(options, forKey: .options)
try container.encode(options, forKey: .selectedIndex)
}

View File

@ -48,6 +48,18 @@ import MVMCore
set { text = MVMCoreUIUtility.formatMdn(newValue) }
}
/// Toggles selected or original (unselected) UI.
public override var isSelected: Bool {
get { return entryFieldContainer.isSelected }
set (selected) {
if selected && showError {
showError = false
}
super.isSelected = selected
}
}
//--------------------------------------------------
// MARK: - Initializers
//--------------------------------------------------
@ -77,11 +89,14 @@ import MVMCore
super.setupFieldContainerContent(container)
textField.keyboardType = .numberPad
}
open override func setupTextFieldToolbar() {
let toolbar = MVMCoreUICommonViewsUtility.makeEmptyToolbar()
let toolbar = UIToolbar.createEmptyToolbar()
let space = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let contacts = UIBarButtonItem(title: MVMCoreUIUtility.hardcodedString(withKey: "textfield_contacts_barbutton"), style: .plain, target: self, action: #selector(getContacts(_:)))
let dismissButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(dismissFieldInput(_:)))
let contacts = UIBarButtonItem(title: MVMCoreUIUtility.hardcodedString(withKey: "textfield_contacts_barbutton"), style: .plain, target: self, action: #selector(getContacts))
let dismissButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(dismissFieldInput))
toolbar.items = [contacts, space, dismissButton]
textField.inputAccessoryView = toolbar
}
@ -107,18 +122,18 @@ import MVMCore
isValid = true
return true
}
let isValid = hasValidMDN()
if isValid {
isValid = hasValidMDN()
if self.isValid {
showError = false
} else {
errorMessage = errorMessage ?? MVMCoreUIUtility.hardcodedString(withKey: "textfield_phone_format_error_message")
entryFieldModel?.errorMessage = entryFieldModel?.errorMessage ?? MVMCoreUIUtility.hardcodedString(withKey: "textfield_phone_format_error_message")
showError = true
UIAccessibility.post(notification: .layoutChanged, argument: textField)
}
return isValid
}
@ -196,7 +211,7 @@ import MVMCore
}
@objc public func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
return proprietorTextDelegate?.textFieldShouldBeginEditing?(textField) ?? true
}

View File

@ -15,7 +15,7 @@ import UIKit
/// Called when the entered text becomes invalid based on the validation block
@objc optional func isInvalid(textfield: TextEntryField?)
/// Dismisses the keyboard.
@objc optional func dismissFieldInput(sender: Any?)
@objc optional func dismissFieldInput(_ sender: Any?)
}
@ -28,7 +28,7 @@ import UIKit
let textField = TextField()
textField.isAccessibilityElement = true
textField.setContentCompressionResistancePriority(.required, for: .vertical)
textField.font = MFStyler.fontRegularBodyLarge()
textField.font = Styler.Font.RegularBodyLarge.getFont()
textField.textColor = .mvmBlack
textField.smartQuotesType = .no
textField.smartDashesType = .no
@ -36,13 +36,19 @@ import UIKit
return textField
}()
public lazy var errorImage: UIImageView = {
let image = MVMCoreUIUtility.imageNamed("alert_standard")
let imageView = UIImageView(image: image)
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.heightAnchor.constraint(equalToConstant: 20).isActive = true
imageView.widthAnchor.constraint(equalToConstant: 20).isActive = true
return imageView
}()
//--------------------------------------------------
// MARK: - Stored Properties
//--------------------------------------------------
/// Set enabled and disabled colors to be utilized when setting this texfield's isEnabled property.
public var textColor: (enabled: UIColor?, disabled: UIColor?) = (.mvmBlack, .mvmCoolGray3)
private var observingForChange: Bool = false
/// Validate on each entry in the textField. Default: true
@ -54,7 +60,7 @@ import UIKit
public var textEntryFieldModel: TextEntryFieldModel? {
return model as? TextEntryFieldModel
}
//--------------------------------------------------
// MARK: - Computed Properties
//--------------------------------------------------
@ -68,7 +74,7 @@ import UIKit
guard let self = self else { return }
self.textField.isEnabled = enabled
self.textField.textColor = enabled ? self.textColor.enabled : self.textColor.disabled
self.textField.textColor = enabled ? self.textEntryFieldModel?.enabledTextColor.uiColor : self.textEntryFieldModel?.disabledTextColor.uiColor
}
}
}
@ -78,11 +84,15 @@ import UIKit
set (error) {
if error {
textField.accessibilityValue = String(format: MVMCoreUIUtility.hardcodedString(withKey: "textfield_error_message") ?? "", textField.text ?? "", errorMessage ?? "")
textField.accessibilityValue = String(format: MVMCoreUIUtility.hardcodedString(withKey: "textfield_error_message") ?? "", textField.text ?? "", entryFieldModel?.errorMessage ?? "")
} else {
textField.accessibilityValue = nil
}
if textField.isSecureTextEntry {
showErrorView(error)
}
super.showError = error
}
}
@ -102,12 +112,6 @@ import UIKit
set { textField.placeholder = newValue }
}
//--------------------------------------------------
// MARK: - Property Observers
//--------------------------------------------------
public var validationBlock: ((_ value: String?) -> Bool)?
//--------------------------------------------------
// MARK: - Delegate Properties
//--------------------------------------------------
@ -169,21 +173,21 @@ import UIKit
@objc open override func setupFieldContainerContent(_ container: UIView) {
textField.font = MFStyler.fontRegularBodyLarge()
textField.font = Styler.Font.RegularBodyLarge.getFont()
container.addSubview(textField)
NSLayoutConstraint.activate([
textField.heightAnchor.constraint(equalToConstant: 24),
textField.topAnchor.constraint(equalTo: container.topAnchor, constant: 12),
textField.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: 16),
container.bottomAnchor.constraint(equalTo: textField.bottomAnchor, constant: 12)
textField.heightAnchor.constraint(equalToConstant: Padding.Five),
textField.topAnchor.constraint(equalTo: container.topAnchor, constant: Padding.Three),
textField.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: Padding.Three),
container.bottomAnchor.constraint(equalTo: textField.bottomAnchor, constant: Padding.Three)
])
textFieldTrailingConstraint = container.trailingAnchor.constraint(equalTo: textField.trailingAnchor, constant: 16)
textFieldTrailingConstraint = container.trailingAnchor.constraint(equalTo: textField.trailingAnchor, constant: Padding.Three)
textFieldTrailingConstraint?.isActive = true
textField.addTarget(self, action: #selector(startEditing), for: .editingDidBegin)
textField.addTarget(self, action: #selector(dismissFieldInput(_:)), for: .editingDidEnd)
textField.addTarget(self, action: #selector(dismissFieldInput), for: .editingDidEnd)
let tap = UITapGestureRecognizer(target: self, action: #selector(startEditing))
entryFieldContainer.addGestureRecognizer(tap)
@ -194,37 +198,31 @@ import UIKit
@objc open override func updateView(_ size: CGFloat) {
super.updateView(size)
textField.font = MFStyler.fontRegularBodyLarge()
textField.font = Styler.Font.RegularBodyLarge.getFont()
layoutIfNeeded()
}
open override func reset() {
super.reset()
textField.font = MFStyler.fontRegularBodyLarge()
textField.font = Styler.Font.RegularBodyLarge.getFont()
}
@objc deinit {
setBothTextDelegates(to: nil)
}
@objc public func setBothTextDelegates(to delegate: (UITextFieldDelegate & ObservingTextFieldDelegate)?) {
observingTextFieldDelegate = delegate
uiTextFieldDelegate = delegate
}
open func setupTextFieldToolbar() {
let observingDelegate = observingTextFieldDelegate ?? self
textField.inputAccessoryView = UIToolbar.getToolbarWithDoneButton(delegate: observingDelegate,
action: #selector(observingDelegate.dismissFieldInput))
}
//--------------------------------------------------
// MARK: - Observing for Change (TextFieldDelegate)
//--------------------------------------------------
public func defaultValidationBlock() {
validationBlock = { enteredValue in
guard let enteredValue = enteredValue else { return false }
return enteredValue.count > 0
}
}
@discardableResult
@objc override open func resignFirstResponder() -> Bool {
if validateWhenDoneEditing {
@ -240,11 +238,11 @@ import UIKit
text = textField.text
_ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate)
}
@objc public func updateValidation(_ isValid: Bool) {
let previousValidity = self.isValid
self.isValid = isValid
if previousValidity && !isValid {
showError = true
observingTextFieldDelegate?.isInvalid?(textfield: self)
@ -276,10 +274,30 @@ import UIKit
}
}
@objc func dismissFieldInput(_ sender: Any?) {
@objc public func dismissFieldInput(_ sender: Any?) {
resignFirstResponder()
}
private func showErrorView(_ show: Bool) {
if show {
entryFieldContainer.addSubview(errorImage)
textFieldTrailingConstraint?.isActive = false
textFieldTrailingConstraint = errorImage.leadingAnchor.constraint(equalTo: textField.trailingAnchor, constant: Padding.Two)
textFieldTrailingConstraint?.isActive = true
entryFieldContainer.trailingAnchor.constraint(equalTo: errorImage.trailingAnchor, constant: Padding.Three).isActive = true
errorImage.centerYAnchor.constraint(equalTo: entryFieldContainer.centerYAnchor).isActive = true
} else {
errorImage.removeFromSuperview()
textFieldTrailingConstraint?.isActive = false
textFieldTrailingConstraint = entryFieldContainer.trailingAnchor.constraint(equalTo: textField.trailingAnchor, constant: Padding.Two)
textFieldTrailingConstraint?.isActive = true
}
}
//--------------------------------------------------
// MARK: - MoleculeViewProtocol
//--------------------------------------------------
@ -288,37 +306,39 @@ import UIKit
super.set(with: model, delegateObject, additionalData)
guard let model = model as? TextEntryFieldModel else { return }
model.updateUI = { [weak self] in
MVMCoreDispatchUtility.performBlock(onMainThread: {
if self?.isSelected ?? false {
self?.updateValidation(model.isValid ?? true)
guard let self = self else { return }
if self.isSelected {
self.updateValidation(model.isValid ?? true)
}
})
}
self.delegateObject = delegateObject
FormValidator.setupValidation(for: model, delegate: delegateObject?.formHolderDelegate)
textColor.enabled = model.enabledTextColor?.uiColor
textColor.disabled = model.disabledTextColor?.uiColor
FormValidator.setupValidation(for: model, delegate: delegateObject?.formHolderDelegate)
text = model.text
placeholder = model.placeholder
switch model.type {
case .password:
case .password, .secure:
textField.isSecureTextEntry = true
case .number:
textField.keyboardType = .numberPad
case .email:
textField.keyboardType = .emailAddress
default:
break
}
defaultValidationBlock()
uiTextFieldDelegate = delegateObject?.uiTextFieldDelegate
observingTextFieldDelegate = delegateObject?.observingTextFieldDelegate
textField.inputAccessoryView = MVMCoreUICommonViewsUtility.getToolbarWithDoneButton(delegate: observingTextFieldDelegate ?? self)
setupTextFieldToolbar()
}
}

View File

@ -8,9 +8,13 @@
@objcMembers public class TextEntryFieldModel: EntryFieldModel {
//--------------------------------------------------
// MARK: - Types
//--------------------------------------------------
public enum EntryType: String, Codable {
case password
case secure
case number
case email
}
@ -24,8 +28,8 @@
}
public var placeholder: String?
public var enabledTextColor: Color?
public var disabledTextColor: Color?
public var enabledTextColor: Color = Color(uiColor: .mvmBlack)
public var disabledTextColor: Color = Color(uiColor: .mvmCoolGray3)
public var type: EntryType?
//--------------------------------------------------
@ -34,7 +38,6 @@
private enum CodingKeys: String, CodingKey {
case moleculeName
case text
case placeholder
case enabledTextColor
case disabledTextColor
@ -42,27 +45,31 @@
}
//--------------------------------------------------
// MARK: - Initializers
// MARK: - Codec
//--------------------------------------------------
required public init(from decoder: Decoder) throws {
try super.init(from: decoder)
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
text = try typeContainer.decodeIfPresent(String.self, forKey: .text)
placeholder = try typeContainer.decodeIfPresent(String.self, forKey: .placeholder)
enabledTextColor = try typeContainer.decodeIfPresent(Color.self, forKey: .enabledTextColor)
disabledTextColor = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledTextColor)
type = try typeContainer.decodeIfPresent(EntryType.self, forKey: .type)
if let enabledTextColor = try typeContainer.decodeIfPresent(Color.self, forKey: .enabledTextColor) {
self.enabledTextColor = enabledTextColor
}
if let disabledTextColor = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledTextColor) {
self.disabledTextColor = disabledTextColor
}
}
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.encodeIfPresent(text, forKey: .text)
try container.encodeIfPresent(placeholder, forKey: .placeholder)
try container.encodeIfPresent(enabledTextColor, forKey: .enabledTextColor)
try container.encodeIfPresent(disabledTextColor, forKey: .disabledTextColor)
try container.encode(enabledTextColor, forKey: .enabledTextColor)
try container.encode(disabledTextColor, forKey: .disabledTextColor)
try container.encodeIfPresent(type, forKey: .type)
}
}

View File

@ -131,8 +131,26 @@ public typealias ActionBlockConfirmation = () -> (Bool)
private var widthConstraint: NSLayoutConstraint?
private func constrainKnob() {
knobLeadingConstraint?.isActive = !isOn
knobTrailingConstraint?.isActive = isOn
knobLeadingConstraint?.isActive = false
knobTrailingConstraint?.isActive = false
_ = isOn ? constrainKnobOn() : constrainKnobOff()
knobTrailingConstraint?.isActive = true
knobLeadingConstraint?.isActive = true
}
private func constrainKnobOn() {
knobTrailingConstraint = trailingAnchor.constraint(equalTo: knobView.trailingAnchor, constant: 1)
knobLeadingConstraint = knobView.leadingAnchor.constraint(greaterThanOrEqualTo: leadingAnchor)
}
private func constrainKnobOff() {
knobTrailingConstraint = trailingAnchor.constraint(greaterThanOrEqualTo: knobView.trailingAnchor)
knobLeadingConstraint = knobView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 1)
}
//--------------------------------------------------
@ -189,6 +207,8 @@ public typealias ActionBlockConfirmation = () -> (Bool)
layer.cornerRadius = Self.getContainerHeight() / 2.0
knobView.layer.cornerRadius = Self.getKnobHeight() / 2.0
changeStateNoAnimation(isOn)
}
public override func setupView() {
@ -218,9 +238,7 @@ public typealias ActionBlockConfirmation = () -> (Bool)
knobView.topAnchor.constraint(greaterThanOrEqualTo: topAnchor).isActive = true
bottomAnchor.constraint(greaterThanOrEqualTo: knobView.bottomAnchor).isActive = true
knobTrailingConstraint = trailingAnchor.constraint(equalTo: knobView.trailingAnchor, constant: 1)
knobLeadingConstraint = knobView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 1)
knobLeadingConstraint?.isActive = true
constrainKnobOff()
}
public override func reset() {
@ -228,9 +246,8 @@ public typealias ActionBlockConfirmation = () -> (Bool)
backgroundColor = containerTintColor.off
knobView.backgroundColor = knobTintColor.off
accessibilityLabel = MVMCoreUIUtility.hardcodedString(withKey: "Toggle_buttonlabel")
isAnimated = true
isOn = false
constrainKnob()
didToggleAction = nil
shouldToggleAction = { return true }
}
@ -352,10 +369,15 @@ public typealias ActionBlockConfirmation = () -> (Bool)
containerTintColor.off = model.offTintColor.uiColor
knobTintColor.on = model.onKnobTintColor.uiColor
knobTintColor.off = model.offKnobTintColor.uiColor
changeStateNoAnimation(model.state)
isOn = model.state
changeStateNoAnimation(isOn)
isAnimated = model.animated
isEnabled = model.enabled
if let accessibileString = model.accessibilityText {
accessibilityLabel = accessibileString
}
if let actionMap = model.action?.toJSON() {
didToggleAction = { MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: additionalData, delegateObject: delegateObject) }
}

View File

@ -0,0 +1,37 @@
//
// UIDatePicker+Extension.swift
// MVMCoreUI
//
// Created by Kevin Christiano on 4/14/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
public extension UIDatePicker {
class func addDatePicker(to textField: UITextField) -> UIDatePicker {
let datePicker = UIDatePicker()
datePicker.backgroundColor = .mvmWhite
datePicker.datePickerMode = .date
let locale = NSLocale.current as NSLocale
datePicker.locale = locale as Locale
datePicker.calendar = locale.object(forKey: .calendar) as? Calendar
textField.inputView = datePicker
return datePicker
}
class func addTimeAndDatePicker(to textField: UITextField) -> UIDatePicker {
let datePicker = UIDatePicker()
datePicker.backgroundColor = .mvmWhite
datePicker.datePickerMode = .time
textField.inputView = datePicker
return datePicker
}
}

View File

@ -0,0 +1,38 @@
//
// UIPickerView.swift
// MVMCoreUI
//
// Created by Kevin Christiano on 4/14/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
public extension UIPickerView {
class func createPickerView() -> UIPickerView {
let picker = UIPickerView(frame: .zero)
picker.backgroundColor = .mvmWhite
picker.showsSelectionIndicator = true
return picker
}
class func addPicker(to textField: UITextField, delegate: TextFieldAndPickerDelegate?, dismissAction: Selector?) -> UIPickerView {
// Sets up the picker (same tag as the textfield)
let picker = createPickerView()
picker.delegate = delegate
picker.dataSource = delegate
picker.tag = textField.tag
textField.inputView = picker
// Adds a dismiss toolbar, since all fields with pickers should have one.
if let dismissAction = dismissAction {
UIToolbar.addDismissToolbar(to: textField, delegate: delegate, action: dismissAction)
}
return picker
}
}

View File

@ -0,0 +1,56 @@
//
// UIToolbar+Extension.swift
// MVMCoreUI
//
// Created by Kevin Christiano on 4/10/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
public protocol TextFieldOrView { }
extension UITextView: TextFieldOrView { }
extension UITextField: TextFieldOrView { }
public extension UIToolbar {
class func createEmptyToolbar() -> UIToolbar {
let toolbar = UIToolbar(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 44))
toolbar.autoresizingMask = [.flexibleLeftMargin, .flexibleRightMargin, .flexibleWidth]
toolbar.barStyle = .default
toolbar.barTintColor = .mvmCoolGray3
toolbar.tintColor = .mvmBlack
toolbar.isTranslucent = true
return toolbar
}
class func getToolbarWithDoneButton(delegate: Any?, action: Selector) -> UIToolbar {
let toolbar = createEmptyToolbar()
let space = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let button = UIBarButtonItem(barButtonSystemItem: .done, target: delegate, action: action)
toolbar.setItems([space, button], animated: false)
return toolbar
}
class func addDismissToolbar(to object: TextFieldOrView, delegate: Any?, action: Selector) {
let toolbar = Self.getToolbarWithDoneButton(delegate: delegate, action: action)
switch object {
case is UITextField:
(object as? UITextField)?.inputAccessoryView = toolbar
case is UITextView:
(object as? UITextView)?.inputAccessoryView = toolbar
default:
return
}
}
}

View File

@ -17,6 +17,7 @@ import Foundation
private enum CodingKeys: String, CodingKey {
case moleculeName
case backgroundColor
case spacing
case percent
case gone
@ -33,6 +34,7 @@ import Foundation
if let gone = try typeContainer.decodeIfPresent(Bool.self, forKey: .gone) {
self.gone = gone
}
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
try super.init(from: decoder)
}
@ -43,5 +45,6 @@ import Foundation
try container.encodeIfPresent(spacing, forKey: .spacing)
try container.encodeIfPresent(percent, forKey: .percent)
try container.encode(gone, forKey: .gone)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
}
}

View File

@ -8,11 +8,19 @@
import UIKit
@objcMembers open class LabelToggle: View {
public let label = Label.commonLabelB1(true)
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public let label = Label.createLabelBoldBodySmall(true)
public let toggle = Toggle()
//--------------------------------------------------
// MARK: - MVMCoreViewProtocol
//--------------------------------------------------
open override func updateView(_ size: CGFloat) {
super.updateView(size)
label.updateView(size)
@ -21,28 +29,26 @@ import UIKit
open override func setupView() {
super.setupView()
guard toggle.superview == nil else {
return
}
addSubview(label)
addSubview(toggle)
label.setContentHuggingPriority(UILayoutPriority.required, for: NSLayoutConstraint.Axis.vertical)
label.setContentHuggingPriority(.required, for: .vertical)
NSLayoutConstraint.pinViews(leftView: label, rightView: toggle, alignTop: false)
}
// MARK:- MoleculeViewProtocol
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
guard let model = model as? LabelToggleModel,
let toggleHeight = Toggle.estimatedHeight(with: model.toggle, delegateObject),
let labelHeight = Label.estimatedHeight(with: model.label, delegateObject) else { return nil }
let labelHeight = Label.estimatedHeight(with: model.label, delegateObject)
else { return nil }
return max(toggleHeight, labelHeight)
}
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
guard let labelToggleModel = model as? LabelToggleModel else {
return
}
guard let labelToggleModel = model as? LabelToggleModel else { return }
label.set(with: labelToggleModel.label, delegateObject, additionalData)
toggle.set(with: labelToggleModel.toggle, delegateObject, additionalData)
}
@ -52,6 +58,6 @@ import UIKit
super.reset()
label.reset()
toggle.reset()
label.styleB1(true)
label.styleBoldBodySmall(true)
}
}

View File

@ -48,6 +48,7 @@ import Foundation
if let spacing = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .spacing) {
self.spacing = spacing
}
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
try super.init(from: decoder)
}
@ -58,5 +59,6 @@ import Foundation
try container.encodeIfPresent(axis.rawValueString, forKey: .axis)
try container.encodeIfPresent(spacing, forKey: .spacing)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
}
}

View File

@ -36,7 +36,7 @@ open class ScrollingViewController: ViewController {
super.viewDidLoad()
// Adds the tap gesture to dismiss the keyboard.
dismissKeyboardTapGesture = UITapGestureRecognizer(target: self, action: #selector(dismissFieldInput(sender:)))
dismissKeyboardTapGesture = UITapGestureRecognizer(target: self, action: #selector(dismissFieldInput))
view.addGestureRecognizer(dismissKeyboardTapGesture!)
dismissKeyboardTapGesture?.isEnabled = false
scrollView.alwaysBounceVertical = false

View File

@ -405,7 +405,7 @@ import UIKit
}
}
@objc open func dismissFieldInput(sender: Any?) {
@objc open func dismissFieldInput(_ sender: Any?) {
selectedField?.resignFirstResponder()
}

View File

@ -25,9 +25,7 @@ import UIKit
/// Total control over the drawn top, bottom, left and right borders.
public var disableAllBorders = false {
didSet {
bottomBar?.isHidden = disableAllBorders
}
didSet { bottomBar?.isHidden = disableAllBorders }
}
private(set) var fieldState: FieldState = .original {

View File

@ -10,10 +10,8 @@ import Foundation
open class Styler {
//--------------------------------------------------
// MARK: - Enums
//--------------------------------------------------
// MARK:- Font Enum
public enum Font: String, Codable {
case Title2XLarge
case TitleXLarge

View File

@ -0,0 +1,23 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "alert_standard @1x.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "alert_standard @2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "alert_standard @3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 525 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 771 B

View File

@ -14,7 +14,7 @@ public extension MVMCoreUICommonViewsUtility {
let toolbar = self.makeEmptyToolbar()
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))
button.tintColor = .black
toolbar.setItems([space, button], animated: false)