Merge branch 'feature/vds-form-controls' into feature/vds-radiobox
This commit is contained in:
commit
73893d36d7
@ -7,6 +7,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
import VDS
|
||||||
|
|
||||||
@objcMembers open class FormFieldModel: MoleculeModelProtocol, FormFieldProtocol, FormRuleWatcherFieldProtocol, UIUpdatableModelProtocol {
|
@objcMembers open class FormFieldModel: MoleculeModelProtocol, FormFieldProtocol, FormRuleWatcherFieldProtocol, UIUpdatableModelProtocol {
|
||||||
|
|
||||||
@ -28,6 +29,16 @@ import Foundation
|
|||||||
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?
|
||||||
|
|
||||||
|
public var inverted: Bool = false
|
||||||
|
public var surface: Surface { inverted ? .dark : .light }
|
||||||
|
|
||||||
|
public var dynamicErrorMessage: String? {
|
||||||
|
didSet {
|
||||||
|
isValid = dynamicErrorMessage?.isEmpty ?? true
|
||||||
|
updateUIDynamicError?()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public var isValid: Bool? = true {
|
public var isValid: Bool? = true {
|
||||||
didSet { updateUI?() }
|
didSet { updateUI?() }
|
||||||
@ -36,6 +47,9 @@ import Foundation
|
|||||||
/// Temporary binding mechanism for the view to update on enable changes.
|
/// Temporary binding mechanism for the view to update on enable changes.
|
||||||
public var updateUI: ActionBlock?
|
public var updateUI: ActionBlock?
|
||||||
|
|
||||||
|
// TODO: Remove once updateUI is fixed with isSelected
|
||||||
|
public var updateUIDynamicError: ActionBlock?
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Initializer
|
// MARK: - Initializer
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
@ -56,6 +70,7 @@ import Foundation
|
|||||||
case required
|
case required
|
||||||
case fieldKey
|
case fieldKey
|
||||||
case groupName
|
case groupName
|
||||||
|
case inverted
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
@ -63,7 +78,7 @@ import Foundation
|
|||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|
||||||
open func formFieldValue() -> AnyHashable? {
|
open func formFieldValue() -> AnyHashable? {
|
||||||
fatalError("developer must implement")
|
fatalError("developer must implement")
|
||||||
}
|
}
|
||||||
|
|
||||||
open func formFieldServerValue() -> AnyHashable? {
|
open func formFieldServerValue() -> AnyHashable? {
|
||||||
@ -93,9 +108,13 @@ import Foundation
|
|||||||
readOnly = try typeContainer.decodeIfPresent(Bool.self, forKey: .readOnly) ?? false
|
readOnly = try typeContainer.decodeIfPresent(Bool.self, forKey: .readOnly) ?? false
|
||||||
fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey)
|
fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey)
|
||||||
groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) ?? FormValidator.defaultGroupName
|
groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) ?? FormValidator.defaultGroupName
|
||||||
|
|
||||||
|
if let inverted = try typeContainer.decodeIfPresent(Bool.self, forKey: .inverted) {
|
||||||
|
self.inverted = inverted
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func encode(to encoder: Encoder) throws {
|
open func encode(to encoder: Encoder) throws {
|
||||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||||
try container.encode(id, forKey: .id)
|
try container.encode(id, forKey: .id)
|
||||||
try container.encodeIfPresent(moleculeName, forKey: .moleculeName)
|
try container.encodeIfPresent(moleculeName, forKey: .moleculeName)
|
||||||
@ -106,5 +125,6 @@ import Foundation
|
|||||||
try container.encode(readOnly, forKey: .readOnly)
|
try container.encode(readOnly, forKey: .readOnly)
|
||||||
try container.encode(enabled, forKey: .enabled)
|
try container.encode(enabled, forKey: .enabled)
|
||||||
try container.encode(required, forKey: .required)
|
try container.encode(required, forKey: .required)
|
||||||
|
try container.encode(inverted, forKey: .inverted)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,79 +9,39 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
|
|
||||||
@objcMembers open class EntryFieldModel: MoleculeModelProtocol, FormFieldProtocol, FormRuleWatcherFieldProtocol, UIUpdatableModelProtocol, ClearableModelProtocol {
|
@objcMembers open class EntryFieldModel: FormFieldModel, ClearableModelProtocol {
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Properties
|
// MARK: - Properties
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|
||||||
public class var identifier: String { "" }
|
|
||||||
public var id: String = UUID().uuidString
|
|
||||||
|
|
||||||
public var backgroundColor: Color?
|
|
||||||
public var accessibilityIdentifier: String?
|
|
||||||
public var shouldClearText: Bool = false
|
public var shouldClearText: Bool = false
|
||||||
public var dynamicErrorMessage: String? {
|
|
||||||
didSet {
|
|
||||||
isValid = dynamicErrorMessage?.isEmpty ?? true
|
|
||||||
updateUIDynamicError?()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public var errorMessage: String?
|
|
||||||
public var errorTextColor: Color?
|
public var errorTextColor: Color?
|
||||||
public var enabled: Bool = true
|
|
||||||
public var required: Bool = true
|
|
||||||
public var readOnly: Bool = false
|
|
||||||
public var showError: Bool?
|
|
||||||
public var hideBorders = false
|
public var hideBorders = false
|
||||||
public var locked: Bool?
|
public var locked: Bool?
|
||||||
public var selected: 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 wasInitiallySelected: Bool = false
|
public var wasInitiallySelected: Bool = false
|
||||||
|
public var text: String?
|
||||||
public var title: String?
|
public var title: String?
|
||||||
public var feedback: String?
|
public var feedback: String?
|
||||||
public var shouldMaskRecordedView: Bool? = true
|
public var shouldMaskRecordedView: Bool? = true
|
||||||
|
|
||||||
//used to drive the EntryFieldView UI
|
//used to drive the EntryFieldView UI
|
||||||
public var titleStateLabel: FormLabelModel
|
public var titleStateLabel = FormLabelModel(text: "")
|
||||||
public var feedbackStateLabel: FormLabelModel
|
public var feedbackStateLabel = FormLabelModel(text: "")
|
||||||
|
|
||||||
public var isValid: Bool? = true {
|
|
||||||
didSet { updateUI?() }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Temporary binding mechanism for the view to update on enable changes.
|
|
||||||
public var updateUI: ActionBlock?
|
|
||||||
|
|
||||||
// TODO: Remove once updateUI is fixed with isSelected
|
|
||||||
public var updateUIDynamicError: ActionBlock?
|
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Keys
|
// MARK: - Keys
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|
||||||
private enum CodingKeys: String, CodingKey {
|
private enum CodingKeys: String, CodingKey {
|
||||||
case id
|
|
||||||
case moleculeName
|
|
||||||
case backgroundColor
|
case backgroundColor
|
||||||
case accessibilityIdentifier
|
|
||||||
case title
|
case title
|
||||||
case enabled
|
|
||||||
case readOnly
|
|
||||||
case feedback
|
case feedback
|
||||||
case errorMessage
|
|
||||||
case errorTextColor
|
case errorTextColor
|
||||||
case locked
|
case locked
|
||||||
case selected
|
case selected
|
||||||
case showError
|
|
||||||
case hideBorders
|
case hideBorders
|
||||||
case text
|
case text
|
||||||
case fieldKey
|
|
||||||
case groupName
|
|
||||||
case required
|
|
||||||
case shouldMaskRecordedView
|
case shouldMaskRecordedView
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,7 +52,7 @@ import Foundation
|
|||||||
// MARK: - Validation Methods
|
// MARK: - Validation Methods
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|
||||||
public func formFieldValue() -> AnyHashable? {
|
open override func formFieldValue() -> AnyHashable? {
|
||||||
guard enabled else { return nil }
|
guard enabled else { return nil }
|
||||||
|
|
||||||
if dynamicErrorMessage != nil {
|
if dynamicErrorMessage != nil {
|
||||||
@ -100,30 +60,15 @@ import Foundation
|
|||||||
}
|
}
|
||||||
return text
|
return text
|
||||||
}
|
}
|
||||||
|
|
||||||
open func formFieldServerValue() -> AnyHashable? {
|
|
||||||
return formFieldValue()
|
|
||||||
}
|
|
||||||
|
|
||||||
public func setValidity(_ valid: Bool, errorMessage: String?) {
|
|
||||||
|
|
||||||
if let ruleErrorMessage = errorMessage, fieldKey != nil {
|
|
||||||
self.errorMessage = ruleErrorMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
self.isValid = valid
|
|
||||||
updateUI?()
|
|
||||||
}
|
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Initializers
|
// MARK: - Initializers
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|
||||||
public init(with text: String) {
|
public init(with text: String) {
|
||||||
|
super.init()
|
||||||
self.text = text
|
self.text = text
|
||||||
baseValue = text
|
baseValue = text
|
||||||
self.titleStateLabel = FormLabelModel(text: "")
|
|
||||||
self.feedbackStateLabel = FormLabelModel(text: "")
|
|
||||||
setDefaults()
|
setDefaults()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,7 +76,7 @@ import Foundation
|
|||||||
// MARK: - Initializers
|
// MARK: - Initializers
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
public func clear() {
|
public func clear() {
|
||||||
self.text = ""
|
text = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
@ -139,54 +84,35 @@ import Foundation
|
|||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|
||||||
required public init(from decoder: Decoder) throws {
|
required public init(from decoder: Decoder) throws {
|
||||||
|
try super.init(from: decoder)
|
||||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString
|
|
||||||
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||||
accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier)
|
|
||||||
title = try typeContainer.decodeIfPresent(String.self, forKey: .title)
|
title = try typeContainer.decodeIfPresent(String.self, forKey: .title)
|
||||||
feedback = try typeContainer.decodeIfPresent(String.self, forKey: .feedback)
|
feedback = try typeContainer.decodeIfPresent(String.self, forKey: .feedback)
|
||||||
errorMessage = try typeContainer.decodeIfPresent(String.self, forKey: .errorMessage)
|
|
||||||
errorTextColor = try typeContainer.decodeIfPresent(Color.self, forKey: .errorTextColor)
|
errorTextColor = try typeContainer.decodeIfPresent(Color.self, forKey: .errorTextColor)
|
||||||
enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) ?? true
|
|
||||||
required = try typeContainer.decodeIfPresent(Bool.self, forKey: .required) ?? true
|
|
||||||
readOnly = try typeContainer.decodeIfPresent(Bool.self, forKey: .readOnly) ?? false
|
|
||||||
locked = try typeContainer.decodeIfPresent(Bool.self, forKey: .locked)
|
locked = try typeContainer.decodeIfPresent(Bool.self, forKey: .locked)
|
||||||
selected = try typeContainer.decodeIfPresent(Bool.self, forKey: .selected)
|
selected = try typeContainer.decodeIfPresent(Bool.self, forKey: .selected)
|
||||||
text = try typeContainer.decodeIfPresent(String.self, forKey: .text)
|
text = try typeContainer.decodeIfPresent(String.self, forKey: .text)
|
||||||
hideBorders = try typeContainer.decodeIfPresent(Bool.self, forKey: .hideBorders) ?? false
|
hideBorders = try typeContainer.decodeIfPresent(Bool.self, forKey: .hideBorders) ?? false
|
||||||
baseValue = text
|
baseValue = text
|
||||||
fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey)
|
|
||||||
shouldMaskRecordedView = try typeContainer.decodeIfPresent(Bool.self, forKey: .shouldMaskRecordedView) ?? shouldMaskRecordedView
|
shouldMaskRecordedView = try typeContainer.decodeIfPresent(Bool.self, forKey: .shouldMaskRecordedView) ?? shouldMaskRecordedView
|
||||||
if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) {
|
titleStateLabel = FormLabelModel(text: title ?? "")
|
||||||
self.groupName = groupName
|
feedbackStateLabel = FormLabelModel(model: LabelModel(text: feedback ?? "",
|
||||||
}
|
|
||||||
self.titleStateLabel = FormLabelModel(text: title ?? "")
|
|
||||||
self.feedbackStateLabel = FormLabelModel(model: LabelModel(text: feedback ?? "",
|
|
||||||
fontStyle: FormLabelModel.defaultFontStyle,
|
fontStyle: FormLabelModel.defaultFontStyle,
|
||||||
textColor: Color(uiColor: .mvmCoolGray6)))
|
textColor: Color(uiColor: .mvmCoolGray6)))
|
||||||
setDefaults()
|
setDefaults()
|
||||||
}
|
}
|
||||||
|
|
||||||
public func encode(to encoder: Encoder) throws {
|
open override func encode(to encoder: Encoder) throws {
|
||||||
|
try super.encode(to: encoder)
|
||||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||||
try container.encode(id, forKey: .id)
|
|
||||||
try container.encodeIfPresent(moleculeName, forKey: .moleculeName)
|
|
||||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||||
try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier)
|
|
||||||
try container.encodeIfPresent(title, forKey: .title)
|
try container.encodeIfPresent(title, forKey: .title)
|
||||||
try container.encodeIfPresent(feedback, forKey: .feedback)
|
try container.encodeIfPresent(feedback, forKey: .feedback)
|
||||||
try container.encodeIfPresent(text, forKey: .text)
|
try container.encodeIfPresent(text, forKey: .text)
|
||||||
try container.encodeIfPresent(locked, forKey: .locked)
|
try container.encodeIfPresent(locked, forKey: .locked)
|
||||||
try container.encodeIfPresent(showError, forKey: .showError)
|
|
||||||
try container.encodeIfPresent(selected, forKey: .selected)
|
try container.encodeIfPresent(selected, forKey: .selected)
|
||||||
try container.encodeIfPresent(errorTextColor, forKey: .errorTextColor)
|
try container.encodeIfPresent(errorTextColor, forKey: .errorTextColor)
|
||||||
try container.encodeIfPresent(errorMessage, forKey: .errorMessage)
|
|
||||||
try container.encodeIfPresent(fieldKey, forKey: .fieldKey)
|
|
||||||
try container.encodeIfPresent(groupName, forKey: .groupName)
|
|
||||||
|
|
||||||
try container.encode(readOnly, forKey: .readOnly)
|
|
||||||
try container.encode(enabled, forKey: .enabled)
|
|
||||||
try container.encode(required, forKey: .required)
|
|
||||||
try container.encode(hideBorders, forKey: .hideBorders)
|
try container.encode(hideBorders, forKey: .hideBorders)
|
||||||
try container.encode(shouldMaskRecordedView, forKey: .shouldMaskRecordedView)
|
try container.encode(shouldMaskRecordedView, forKey: .shouldMaskRecordedView)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -96,3 +96,17 @@ open class TooltipModel: MoleculeModelProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension TooltipModel {
|
||||||
|
public func toVDSTooltipModel() -> Tooltip.TooltipModel {
|
||||||
|
var moleculeView: MoleculeViewProtocol?
|
||||||
|
if let molecule, let view = ModelRegistry.createMolecule(molecule) {
|
||||||
|
moleculeView = view
|
||||||
|
}
|
||||||
|
return .init(closeButtonText: closeButtonText,
|
||||||
|
title: title,
|
||||||
|
content: content,
|
||||||
|
contentView: moleculeView
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -25,21 +25,31 @@ extension VDS.ButtonIcon.Size: Codable {}
|
|||||||
extension VDS.ButtonIcon.BadgeIndicatorModel.ExpandDirection: Codable {}
|
extension VDS.ButtonIcon.BadgeIndicatorModel.ExpandDirection: Codable {}
|
||||||
extension VDS.ButtonIcon.SurfaceType: Codable {}
|
extension VDS.ButtonIcon.SurfaceType: Codable {}
|
||||||
extension VDS.ButtonGroup.Alignment: Codable {}
|
extension VDS.ButtonGroup.Alignment: Codable {}
|
||||||
|
extension VDS.CarouselScrollbar.Layout: Codable {}
|
||||||
|
extension VDS.DatePicker.DateFormat: Codable {}
|
||||||
|
extension VDS.EntryFieldBase.HelperTextPlacement: Codable {}
|
||||||
extension VDS.Icon.Name: Codable {}
|
extension VDS.Icon.Name: Codable {}
|
||||||
extension VDS.Icon.Size: Codable {}
|
extension VDS.Icon.Size: Codable {}
|
||||||
|
extension VDS.InputField.CreditCardType: Codable {}
|
||||||
|
extension VDS.InputField.DateFormat: Codable {}
|
||||||
|
extension VDS.InputField.FieldType: Codable {}
|
||||||
|
extension VDS.Line.Style: Codable {}
|
||||||
|
extension VDS.Line.Orientation: Codable {}
|
||||||
extension VDS.Tabs.Orientation: Codable {}
|
extension VDS.Tabs.Orientation: Codable {}
|
||||||
extension VDS.Tabs.IndicatorPosition: Codable {}
|
extension VDS.Tabs.IndicatorPosition: Codable {}
|
||||||
extension VDS.Tabs.Overflow: Codable {}
|
extension VDS.Tabs.Overflow: Codable {}
|
||||||
extension VDS.Tabs.Size: Codable {}
|
extension VDS.Tabs.Size: Codable {}
|
||||||
|
extension VDS.TextArea.Height: Codable {}
|
||||||
extension VDS.TextLink.Size: Codable {}
|
extension VDS.TextLink.Size: Codable {}
|
||||||
extension VDS.TextLinkCaret.IconPosition: Codable {}
|
extension VDS.TextLinkCaret.IconPosition: Codable {}
|
||||||
extension VDS.TileContainerBase.AspectRatio: Codable {}
|
extension VDS.TileContainerBase.AspectRatio: Codable {}
|
||||||
extension VDS.Tilelet.Padding: Codable {}
|
extension VDS.Tilelet.Padding: Codable {}
|
||||||
extension VDS.TitleLockup.TextAlignment: Codable {}
|
extension VDS.TitleLockup.TextAlignment: Codable {}
|
||||||
|
extension VDS.Toggle.TextSize: Codable {}
|
||||||
|
extension VDS.Toggle.TextPosition: Codable {}
|
||||||
|
extension VDS.Toggle.TextWeight: Codable {}
|
||||||
extension VDS.Tooltip.FillColor: Codable {}
|
extension VDS.Tooltip.FillColor: Codable {}
|
||||||
extension VDS.Tooltip.Size: Codable {}
|
extension VDS.Tooltip.Size: Codable {}
|
||||||
extension VDS.Line.Style: Codable {}
|
|
||||||
extension VDS.Line.Orientation: Codable {}
|
|
||||||
extension VDS.Use: Codable {}
|
extension VDS.Use: Codable {}
|
||||||
|
|
||||||
extension VDS.Button.Size: RawRepresentableCodable {
|
extension VDS.Button.Size: RawRepresentableCodable {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user