Merge branch 'feature/atomic-vds-new-forms-atoms' into 'develop'
Last of the VDS FormFields ### Summary Added in 1. Checkboxes (VDS CheckboxGroup) 2. RadioButtons (VDS RadioButtonGroup) 3. CalendarView (VDS CalendarBase) 4. DatePickerEntryField (VDS DatePicker) ### JIRA Ticket https://onejira.verizon.com/browse/ONEAPP-7001 https://onejira.verizon.com/browse/ONEAPP-7004 https://onejira.verizon.com/browse/ONEAPP-7016 https://onejira.verizon.com/browse/ONEAPP-7958 Co-authored-by: Matt Bruce <matt.bruce@verizon.com> See merge request https://gitlab.verizon.com/BPHV_MIPS/mvm_core_ui/-/merge_requests/1176
This commit is contained in:
commit
c2e10582f8
@ -594,6 +594,14 @@
|
|||||||
EA6642932BCDA97D00D81DC4 /* TileContainerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA6642922BCDA97D00D81DC4 /* TileContainerModel.swift */; };
|
EA6642932BCDA97D00D81DC4 /* TileContainerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA6642922BCDA97D00D81DC4 /* TileContainerModel.swift */; };
|
||||||
EA6E8B952B504A43000139B4 /* ButtonGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA6E8B942B504A43000139B4 /* ButtonGroup.swift */; };
|
EA6E8B952B504A43000139B4 /* ButtonGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA6E8B942B504A43000139B4 /* ButtonGroup.swift */; };
|
||||||
EA6E8B972B504A4D000139B4 /* ButtonGroupModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA6E8B962B504A4D000139B4 /* ButtonGroupModel.swift */; };
|
EA6E8B972B504A4D000139B4 /* ButtonGroupModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA6E8B962B504A4D000139B4 /* ButtonGroupModel.swift */; };
|
||||||
|
EA7AE5472C73C01A00107C74 /* CheckboxesModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7AE5462C73C01A00107C74 /* CheckboxesModel.swift */; };
|
||||||
|
EA7AE5492C7403DC00107C74 /* Checkboxes.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7AE5482C7403DC00107C74 /* Checkboxes.swift */; };
|
||||||
|
EA7AE54B2C74CACA00107C74 /* RadioButtons.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7AE54A2C74CACA00107C74 /* RadioButtons.swift */; };
|
||||||
|
EA7AE54D2C74CAD700107C74 /* RadioButtonsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7AE54C2C74CAD700107C74 /* RadioButtonsModel.swift */; };
|
||||||
|
EA7AE54F2C74EB3700107C74 /* CalendarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7AE54E2C74EB3700107C74 /* CalendarView.swift */; };
|
||||||
|
EA7AE5512C74EB4500107C74 /* CalendarViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7AE5502C74EB4500107C74 /* CalendarViewModel.swift */; };
|
||||||
|
EA7AE5532C74F1F600107C74 /* DatePickerEntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7AE5522C74F1F600107C74 /* DatePickerEntryField.swift */; };
|
||||||
|
EA7AE5552C74F20600107C74 /* DatePickerEntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7AE5542C74F20600107C74 /* DatePickerEntryFieldModel.swift */; };
|
||||||
EA7D81602B2B6E6800D29F9E /* Icon.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7D815F2B2B6E6800D29F9E /* Icon.swift */; };
|
EA7D81602B2B6E6800D29F9E /* Icon.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7D815F2B2B6E6800D29F9E /* Icon.swift */; };
|
||||||
EA7D81622B2B6E7F00D29F9E /* IconModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7D81612B2B6E7F00D29F9E /* IconModel.swift */; };
|
EA7D81622B2B6E7F00D29F9E /* IconModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7D81612B2B6E7F00D29F9E /* IconModel.swift */; };
|
||||||
EA7D81642B2BABCB00D29F9E /* TooltipModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7D81632B2BABCB00D29F9E /* TooltipModel.swift */; };
|
EA7D81642B2BABCB00D29F9E /* TooltipModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7D81632B2BABCB00D29F9E /* TooltipModel.swift */; };
|
||||||
@ -1223,6 +1231,14 @@
|
|||||||
EA6642922BCDA97D00D81DC4 /* TileContainerModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TileContainerModel.swift; sourceTree = "<group>"; };
|
EA6642922BCDA97D00D81DC4 /* TileContainerModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TileContainerModel.swift; sourceTree = "<group>"; };
|
||||||
EA6E8B942B504A43000139B4 /* ButtonGroup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonGroup.swift; sourceTree = "<group>"; };
|
EA6E8B942B504A43000139B4 /* ButtonGroup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonGroup.swift; sourceTree = "<group>"; };
|
||||||
EA6E8B962B504A4D000139B4 /* ButtonGroupModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonGroupModel.swift; sourceTree = "<group>"; };
|
EA6E8B962B504A4D000139B4 /* ButtonGroupModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonGroupModel.swift; sourceTree = "<group>"; };
|
||||||
|
EA7AE5462C73C01A00107C74 /* CheckboxesModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckboxesModel.swift; sourceTree = "<group>"; };
|
||||||
|
EA7AE5482C7403DC00107C74 /* Checkboxes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Checkboxes.swift; sourceTree = "<group>"; };
|
||||||
|
EA7AE54A2C74CACA00107C74 /* RadioButtons.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioButtons.swift; sourceTree = "<group>"; };
|
||||||
|
EA7AE54C2C74CAD700107C74 /* RadioButtonsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioButtonsModel.swift; sourceTree = "<group>"; };
|
||||||
|
EA7AE54E2C74EB3700107C74 /* CalendarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CalendarView.swift; sourceTree = "<group>"; };
|
||||||
|
EA7AE5502C74EB4500107C74 /* CalendarViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CalendarViewModel.swift; sourceTree = "<group>"; };
|
||||||
|
EA7AE5522C74F1F600107C74 /* DatePickerEntryField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatePickerEntryField.swift; sourceTree = "<group>"; };
|
||||||
|
EA7AE5542C74F20600107C74 /* DatePickerEntryFieldModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatePickerEntryFieldModel.swift; sourceTree = "<group>"; };
|
||||||
EA7D815F2B2B6E6800D29F9E /* Icon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Icon.swift; sourceTree = "<group>"; };
|
EA7D815F2B2B6E6800D29F9E /* Icon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Icon.swift; sourceTree = "<group>"; };
|
||||||
EA7D81612B2B6E7F00D29F9E /* IconModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IconModel.swift; sourceTree = "<group>"; };
|
EA7D81612B2B6E7F00D29F9E /* IconModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IconModel.swift; sourceTree = "<group>"; };
|
||||||
EA7D81632B2BABCB00D29F9E /* TooltipModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TooltipModel.swift; sourceTree = "<group>"; };
|
EA7D81632B2BABCB00D29F9E /* TooltipModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TooltipModel.swift; sourceTree = "<group>"; };
|
||||||
@ -2031,8 +2047,12 @@
|
|||||||
BBAA4F00243D8E3B005AAD5F /* RadioBoxModel.swift */,
|
BBAA4F00243D8E3B005AAD5F /* RadioBoxModel.swift */,
|
||||||
D264FAA6243FE13B00D98315 /* RadioBox.swift */,
|
D264FAA6243FE13B00D98315 /* RadioBox.swift */,
|
||||||
0116A4E4228B19640094F3ED /* RadioButtonSelectionHelper.swift */,
|
0116A4E4228B19640094F3ED /* RadioButtonSelectionHelper.swift */,
|
||||||
|
EA7AE54C2C74CAD700107C74 /* RadioButtonsModel.swift */,
|
||||||
|
EA7AE54A2C74CACA00107C74 /* RadioButtons.swift */,
|
||||||
011D95AE2407266E000E3791 /* RadioButtonModel.swift */,
|
011D95AE2407266E000E3791 /* RadioButtonModel.swift */,
|
||||||
01004F2F22721C3800991ECC /* RadioButton.swift */,
|
01004F2F22721C3800991ECC /* RadioButton.swift */,
|
||||||
|
EA7AE5462C73C01A00107C74 /* CheckboxesModel.swift */,
|
||||||
|
EA7AE5482C7403DC00107C74 /* Checkboxes.swift */,
|
||||||
31BE15CA23D8924C00452370 /* CheckboxModel.swift */,
|
31BE15CA23D8924C00452370 /* CheckboxModel.swift */,
|
||||||
0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */,
|
0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */,
|
||||||
AAC6F166243332E400F295C1 /* RadioSwatchesModel.swift */,
|
AAC6F166243332E400F295C1 /* RadioSwatchesModel.swift */,
|
||||||
@ -2362,6 +2382,8 @@
|
|||||||
EA7D815F2B2B6E6800D29F9E /* Icon.swift */,
|
EA7D815F2B2B6E6800D29F9E /* Icon.swift */,
|
||||||
EA7D81632B2BABCB00D29F9E /* TooltipModel.swift */,
|
EA7D81632B2BABCB00D29F9E /* TooltipModel.swift */,
|
||||||
EA7D81652B2BABD200D29F9E /* Tooltip.swift */,
|
EA7D81652B2BABD200D29F9E /* Tooltip.swift */,
|
||||||
|
EA7AE5502C74EB4500107C74 /* CalendarViewModel.swift */,
|
||||||
|
EA7AE54E2C74EB3700107C74 /* CalendarView.swift */,
|
||||||
);
|
);
|
||||||
path = Views;
|
path = Views;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -2513,6 +2535,8 @@
|
|||||||
D2BEFEF5248A954C00FAB3A9 /* FormFields */ = {
|
D2BEFEF5248A954C00FAB3A9 /* FormFields */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
EA7AE5542C74F20600107C74 /* DatePickerEntryFieldModel.swift */,
|
||||||
|
EA7AE5522C74F1F600107C74 /* DatePickerEntryField.swift */,
|
||||||
EA5DBDAA2C35B6C500290DF8 /* FormFieldModel.swift */,
|
EA5DBDAA2C35B6C500290DF8 /* FormFieldModel.swift */,
|
||||||
D2BEFEF6248A957A00FAB3A9 /* Tags */,
|
D2BEFEF6248A957A00FAB3A9 /* Tags */,
|
||||||
D29DF22B21E6A0FA003B2FB9 /* TextFields */,
|
D29DF22B21E6A0FA003B2FB9 /* TextFields */,
|
||||||
@ -2848,6 +2872,7 @@
|
|||||||
AA7F32AD246C0F8C00C965BA /* ListLeftVariableRadioButtonAllTextAndLinks.swift in Sources */,
|
AA7F32AD246C0F8C00C965BA /* ListLeftVariableRadioButtonAllTextAndLinks.swift in Sources */,
|
||||||
EAA482CE2B45F2F300978105 /* MFLoadingSpinner+VDS.swift in Sources */,
|
EAA482CE2B45F2F300978105 /* MFLoadingSpinner+VDS.swift in Sources */,
|
||||||
D272F5F92473163100BD1A8F /* BarButtonItem.swift in Sources */,
|
D272F5F92473163100BD1A8F /* BarButtonItem.swift in Sources */,
|
||||||
|
EA7AE54D2C74CAD700107C74 /* RadioButtonsModel.swift in Sources */,
|
||||||
D2D2FCF3252B72CF0033EAAA /* MoleculeSectionFooter.swift in Sources */,
|
D2D2FCF3252B72CF0033EAAA /* MoleculeSectionFooter.swift in Sources */,
|
||||||
0A9D09202433796500D2E6C0 /* BarsIndicatorView.swift in Sources */,
|
0A9D09202433796500D2E6C0 /* BarsIndicatorView.swift in Sources */,
|
||||||
D2E2A99423D8CCBC000B42E6 /* HeadlineBodyLinkModel.swift in Sources */,
|
D2E2A99423D8CCBC000B42E6 /* HeadlineBodyLinkModel.swift in Sources */,
|
||||||
@ -2862,6 +2887,7 @@
|
|||||||
EAB14BC127D935F00012AB2C /* RuleCompareModelProtocol.swift in Sources */,
|
EAB14BC127D935F00012AB2C /* RuleCompareModelProtocol.swift in Sources */,
|
||||||
011D95A924057AC7000E3791 /* FormGroupWatcherFieldProtocol.swift in Sources */,
|
011D95A924057AC7000E3791 /* FormGroupWatcherFieldProtocol.swift in Sources */,
|
||||||
EA1B02DE2C41BFD200F0758B /* RuleVDSModel.swift in Sources */,
|
EA1B02DE2C41BFD200F0758B /* RuleVDSModel.swift in Sources */,
|
||||||
|
EA7AE5532C74F1F600107C74 /* DatePickerEntryField.swift in Sources */,
|
||||||
EA985C892981AB7100F2FF2E /* VDS-TextStyle.swift in Sources */,
|
EA985C892981AB7100F2FF2E /* VDS-TextStyle.swift in Sources */,
|
||||||
BB2BF0EA2452A9BB001D0FC2 /* ListDeviceComplexButtonSmall.swift in Sources */,
|
BB2BF0EA2452A9BB001D0FC2 /* ListDeviceComplexButtonSmall.swift in Sources */,
|
||||||
D20C700B250BFDE40095B21C /* NotificationContainerView.swift in Sources */,
|
D20C700B250BFDE40095B21C /* NotificationContainerView.swift in Sources */,
|
||||||
@ -3108,7 +3134,9 @@
|
|||||||
AA69AAF62445BF5700AF3D3B /* ListLeftVariableCheckboxBodyText.swift in Sources */,
|
AA69AAF62445BF5700AF3D3B /* ListLeftVariableCheckboxBodyText.swift in Sources */,
|
||||||
AFA4935729EE3DCC001A9663 /* AlertDelegateProtocol.swift in Sources */,
|
AFA4935729EE3DCC001A9663 /* AlertDelegateProtocol.swift in Sources */,
|
||||||
58A9DD7D2AC2103300F5E0B0 /* ReplaceableMoleculeBehaviorModel.swift in Sources */,
|
58A9DD7D2AC2103300F5E0B0 /* ReplaceableMoleculeBehaviorModel.swift in Sources */,
|
||||||
|
EA7AE54B2C74CACA00107C74 /* RadioButtons.swift in Sources */,
|
||||||
D264FAA3243E632F00D98315 /* ProgrammaticCollectionViewController.swift in Sources */,
|
D264FAA3243E632F00D98315 /* ProgrammaticCollectionViewController.swift in Sources */,
|
||||||
|
EA7AE5552C74F20600107C74 /* DatePickerEntryFieldModel.swift in Sources */,
|
||||||
D29DF27A21E7A533003B2FB9 /* MVMCoreUISession.m in Sources */,
|
D29DF27A21E7A533003B2FB9 /* MVMCoreUISession.m in Sources */,
|
||||||
27F9736A246750BE00CAB5C5 /* ScreenBrightnessModifierBehavior.swift in Sources */,
|
27F9736A246750BE00CAB5C5 /* ScreenBrightnessModifierBehavior.swift in Sources */,
|
||||||
EA6E8B972B504A4D000139B4 /* ButtonGroupModel.swift in Sources */,
|
EA6E8B972B504A4D000139B4 /* ButtonGroupModel.swift in Sources */,
|
||||||
@ -3265,6 +3293,7 @@
|
|||||||
01F2C20327C81F9700DC3D36 /* SubNavManagerNavigationController.swift in Sources */,
|
01F2C20327C81F9700DC3D36 /* SubNavManagerNavigationController.swift in Sources */,
|
||||||
EABFC1412763BB8D00E78B40 /* FormLabel.swift in Sources */,
|
EABFC1412763BB8D00E78B40 /* FormLabel.swift in Sources */,
|
||||||
AA997252247530B100FC7472 /* ListLeftVariableIconAllTextLinks.swift in Sources */,
|
AA997252247530B100FC7472 /* ListLeftVariableIconAllTextLinks.swift in Sources */,
|
||||||
|
EA7AE5492C7403DC00107C74 /* Checkboxes.swift in Sources */,
|
||||||
D2A5146122121FBF00345BFB /* MoleculeStackTemplate.swift in Sources */,
|
D2A5146122121FBF00345BFB /* MoleculeStackTemplate.swift in Sources */,
|
||||||
D23EA7FB2475F09800D60C34 /* CarouselItemProtocol.swift in Sources */,
|
D23EA7FB2475F09800D60C34 /* CarouselItemProtocol.swift in Sources */,
|
||||||
D2E2A9A323E096B1000B42E6 /* DisableableModelProtocol.swift in Sources */,
|
D2E2A9A323E096B1000B42E6 /* DisableableModelProtocol.swift in Sources */,
|
||||||
@ -3295,6 +3324,7 @@
|
|||||||
BB6C6AC824225290005F7224 /* ListOneColumnTextWithWhitespaceDividerShort.swift in Sources */,
|
BB6C6AC824225290005F7224 /* ListOneColumnTextWithWhitespaceDividerShort.swift in Sources */,
|
||||||
0A41BA6E2344FCD400D4C0BC /* CATransaction+Extension.swift in Sources */,
|
0A41BA6E2344FCD400D4C0BC /* CATransaction+Extension.swift in Sources */,
|
||||||
D21B7F73243BAC6800051ABF /* CollectionItemModelProtocol.swift in Sources */,
|
D21B7F73243BAC6800051ABF /* CollectionItemModelProtocol.swift in Sources */,
|
||||||
|
EA7AE5512C74EB4500107C74 /* CalendarViewModel.swift in Sources */,
|
||||||
AA104B1A24474A66004D2810 /* HeadersH2Buttons.swift in Sources */,
|
AA104B1A24474A66004D2810 /* HeadersH2Buttons.swift in Sources */,
|
||||||
C7192E7D23C301750050C2A0 /* HeadLineBodyCaretLinkImage.swift in Sources */,
|
C7192E7D23C301750050C2A0 /* HeadLineBodyCaretLinkImage.swift in Sources */,
|
||||||
D2D2FCF0252B72AF0033EAAA /* MoleculeSectionFooterModel.swift in Sources */,
|
D2D2FCF0252B72AF0033EAAA /* MoleculeSectionFooterModel.swift in Sources */,
|
||||||
@ -3315,6 +3345,7 @@
|
|||||||
D2D3957D252FDBCD00047B11 /* ModalSectionListTemplateModel.swift in Sources */,
|
D2D3957D252FDBCD00047B11 /* ModalSectionListTemplateModel.swift in Sources */,
|
||||||
D2B9D0E4265EEE9D0084735C /* MoleculeListProtocol.swift in Sources */,
|
D2B9D0E4265EEE9D0084735C /* MoleculeListProtocol.swift in Sources */,
|
||||||
D29C559625C099630082E7D6 /* VideoDataManager.swift in Sources */,
|
D29C559625C099630082E7D6 /* VideoDataManager.swift in Sources */,
|
||||||
|
EA7AE5472C73C01A00107C74 /* CheckboxesModel.swift in Sources */,
|
||||||
8D4687E2242E2DE400802879 /* ListFourColumnDataUsageListItemModel.swift in Sources */,
|
8D4687E2242E2DE400802879 /* ListFourColumnDataUsageListItemModel.swift in Sources */,
|
||||||
D29E28DD23D7404C00ACEA85 /* ContainerHelper.swift in Sources */,
|
D29E28DD23D7404C00ACEA85 /* ContainerHelper.swift in Sources */,
|
||||||
EA6642912BCDA97300D81DC4 /* TileContainer.swift in Sources */,
|
EA6642912BCDA97300D81DC4 /* TileContainer.swift in Sources */,
|
||||||
@ -3355,6 +3386,7 @@
|
|||||||
D2169301251E51E7002A6324 /* SectionListTemplate.swift in Sources */,
|
D2169301251E51E7002A6324 /* SectionListTemplate.swift in Sources */,
|
||||||
0A6682AA2435125F00AD3CA1 /* Styler.swift in Sources */,
|
0A6682AA2435125F00AD3CA1 /* Styler.swift in Sources */,
|
||||||
D264FAA7243FE13B00D98315 /* RadioBox.swift in Sources */,
|
D264FAA7243FE13B00D98315 /* RadioBox.swift in Sources */,
|
||||||
|
EA7AE54F2C74EB3700107C74 /* CalendarView.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
|||||||
51
MVMCoreUI/Atomic/Atoms/FormFields/DatePickerEntryField.swift
Normal file
51
MVMCoreUI/Atomic/Atoms/FormFields/DatePickerEntryField.swift
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
//
|
||||||
|
// DatePickerEntryField.swift
|
||||||
|
// MVMCoreUI
|
||||||
|
//
|
||||||
|
// Created by Matt Bruce on 8/20/24.
|
||||||
|
// Copyright © 2024 Verizon Wireless. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import VDS
|
||||||
|
|
||||||
|
open class DatePickerEntryField: VDS.DatePicker, VDSMoleculeViewProtocol {
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Public Properties
|
||||||
|
//--------------------------------------------------
|
||||||
|
public var viewModel: DatePickerEntryFieldModel!
|
||||||
|
public var delegateObject: MVMCoreUIDelegateObject?
|
||||||
|
public var additionalData: [AnyHashable : Any]?
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Public Methods
|
||||||
|
//--------------------------------------------------
|
||||||
|
open override func setup() {
|
||||||
|
super.setup()
|
||||||
|
//turn off internal required rule
|
||||||
|
useRequiredRule = false
|
||||||
|
|
||||||
|
publisher(for: .valueChanged)
|
||||||
|
.sink { [weak self] control in
|
||||||
|
guard let self, let viewModel, isEnabled else { return }
|
||||||
|
viewModel.selectedDate = control.selectedDate
|
||||||
|
_ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate)
|
||||||
|
}.store(in: &subscribers)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func viewModelDidUpdate() {
|
||||||
|
surface = viewModel.surface
|
||||||
|
labelText = viewModel.title
|
||||||
|
helperText = viewModel.feedback
|
||||||
|
helperTextPlacement = viewModel.feedbackTextPlacement
|
||||||
|
tooltipModel = viewModel.tooltip?.convertToVDSTooltipModel()
|
||||||
|
transparentBackground = viewModel.transparentBackground
|
||||||
|
width = viewModel.width
|
||||||
|
selectedDate = viewModel.selectedDate
|
||||||
|
calendarModel = viewModel.calendar.convertToVDSCalendarModel()
|
||||||
|
FormValidator.setupValidation(for: viewModel, delegate: delegateObject?.formHolderDelegate)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func updateView(_ size: CGFloat) {}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,121 @@
|
|||||||
|
//
|
||||||
|
// DatePickerEntryFieldModel.swift
|
||||||
|
// MVMCoreUI
|
||||||
|
//
|
||||||
|
// Created by Matt Bruce on 8/20/24.
|
||||||
|
// Copyright © 2024 Verizon Wireless. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import VDS
|
||||||
|
|
||||||
|
open class DatePickerEntryFieldModel: FormFieldModel {
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Properties
|
||||||
|
//--------------------------------------------------
|
||||||
|
public override static var identifier: String { "datePicker" }
|
||||||
|
|
||||||
|
public var dateFormatter: DateFormatter = {
|
||||||
|
let formatter = DateFormatter()
|
||||||
|
formatter.dateStyle = .medium
|
||||||
|
formatter.timeZone = NSTimeZone.system
|
||||||
|
formatter.locale = .current
|
||||||
|
formatter.formatterBehavior = .default
|
||||||
|
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 }
|
||||||
|
}
|
||||||
|
|
||||||
|
public var selectedDate: Date?
|
||||||
|
public var calendar: CalendarViewModel = .init()
|
||||||
|
public var title: String?
|
||||||
|
public var feedback: String?
|
||||||
|
public var feedbackTextPlacement: VDS.DatePicker.HelperTextPlacement = .bottom
|
||||||
|
public var tooltip: TooltipModel?
|
||||||
|
public var transparentBackground: Bool = false
|
||||||
|
public var width: CGFloat?
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Keys
|
||||||
|
//--------------------------------------------------
|
||||||
|
private enum CodingKeys: String, CodingKey {
|
||||||
|
case dateFormat
|
||||||
|
case selectedDate
|
||||||
|
case calendar
|
||||||
|
case title
|
||||||
|
case feedback
|
||||||
|
case feedbackTextPlacement
|
||||||
|
case tooltip
|
||||||
|
case transparentBackground
|
||||||
|
case width
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Form Validation
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
|
/// Returns the fieldValue of the selectedDate.
|
||||||
|
public override func formFieldValue() -> AnyHashable? {
|
||||||
|
guard let selectedDate, enabled else { return nil }
|
||||||
|
return dateFormatter.string(from: selectedDate)
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Codec
|
||||||
|
//--------------------------------------------------
|
||||||
|
required public init(from decoder: Decoder) throws {
|
||||||
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
|
||||||
|
if let dateFormat = try container.decodeIfPresent(String.self, forKey: .dateFormat) {
|
||||||
|
self.dateFormat = dateFormat
|
||||||
|
dateFormatter.dateFormat = dateFormat
|
||||||
|
}
|
||||||
|
|
||||||
|
if let date = try container.decodeIfPresent(String.self, forKey: .selectedDate) {
|
||||||
|
selectedDate = calendar.dateFormatter.date(from: date)
|
||||||
|
}
|
||||||
|
|
||||||
|
if let calendar = try container.decodeIfPresent(CalendarViewModel.self, forKey: .calendar) {
|
||||||
|
self.calendar = calendar
|
||||||
|
}
|
||||||
|
|
||||||
|
title = try container.decodeIfPresent(String.self, forKey: .title)
|
||||||
|
feedback = try container.decodeIfPresent(String.self, forKey: .feedback)
|
||||||
|
feedbackTextPlacement = try container.decodeIfPresent(VDS.EntryFieldBase.HelperTextPlacement.self, forKey: .feedbackTextPlacement) ?? .bottom
|
||||||
|
|
||||||
|
tooltip = try container.decodeIfPresent(TooltipModel.self, forKey: .tooltip)
|
||||||
|
transparentBackground = try container.decodeIfPresent(Bool.self, forKey: .transparentBackground) ?? false
|
||||||
|
width = try container.decodeIfPresent(CGFloat.self, forKey: .width)
|
||||||
|
|
||||||
|
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.encodeIfPresent(selectedDate, forKey: .selectedDate)
|
||||||
|
try container.encode(calendar, forKey: .calendar)
|
||||||
|
try container.encodeIfPresent(title, forKey: .title)
|
||||||
|
try container.encodeIfPresent(feedback, forKey: .feedback)
|
||||||
|
try container.encode(feedbackTextPlacement, forKey: .feedbackTextPlacement)
|
||||||
|
try container.encodeIfPresent(tooltip, forKey: .tooltip)
|
||||||
|
try container.encode(transparentBackground, forKey: .transparentBackground)
|
||||||
|
try container.encodeIfPresent(width, forKey: .width)
|
||||||
|
}
|
||||||
|
|
||||||
|
open override func isEqual(to model: any ModelComparisonProtocol) -> Bool {
|
||||||
|
guard super.isEqual(to: model), let model = model as? Self else { return false }
|
||||||
|
return dateFormat == model.dateFormat
|
||||||
|
&& selectedDate == model.selectedDate
|
||||||
|
&& calendar == model.calendar
|
||||||
|
&& title == model.title
|
||||||
|
&& feedback == model.feedback
|
||||||
|
&& feedbackTextPlacement == model.feedbackTextPlacement
|
||||||
|
&& tooltip == model.tooltip
|
||||||
|
&& transparentBackground == model.transparentBackground
|
||||||
|
&& width == model.width
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -15,6 +15,8 @@ import VDS
|
|||||||
// MARK: - Properties
|
// MARK: - Properties
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
public class var identifier: String { "" }
|
public class var identifier: String { "" }
|
||||||
|
public var moleculeName: String { Self.identifier }
|
||||||
|
|
||||||
public var id: String = UUID().uuidString
|
public var id: String = UUID().uuidString
|
||||||
|
|
||||||
public var backgroundColor: Color?
|
public var backgroundColor: Color?
|
||||||
@ -23,7 +25,7 @@ import VDS
|
|||||||
public var enabled: Bool = true
|
public var enabled: Bool = true
|
||||||
public var required: Bool = true
|
public var required: Bool = true
|
||||||
public var readOnly: Bool = false
|
public var readOnly: Bool = false
|
||||||
public var showError: Bool?
|
public var showError: Bool = false
|
||||||
public var errorMessage: String?
|
public var errorMessage: String?
|
||||||
public var initialErrorMessage: String?
|
public var initialErrorMessage: String?
|
||||||
|
|
||||||
@ -66,6 +68,7 @@ import VDS
|
|||||||
case moleculeName
|
case moleculeName
|
||||||
case accessibilityIdentifier
|
case accessibilityIdentifier
|
||||||
case errorMessage
|
case errorMessage
|
||||||
|
case showError
|
||||||
case enabled
|
case enabled
|
||||||
case readOnly
|
case readOnly
|
||||||
case required
|
case required
|
||||||
@ -107,6 +110,7 @@ import VDS
|
|||||||
accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier)
|
accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier)
|
||||||
errorMessage = try typeContainer.decodeIfPresent(String.self, forKey: .errorMessage)
|
errorMessage = try typeContainer.decodeIfPresent(String.self, forKey: .errorMessage)
|
||||||
initialErrorMessage = errorMessage
|
initialErrorMessage = errorMessage
|
||||||
|
showError = try typeContainer.decodeIfPresent(Bool.self, forKey: .showError) ?? false
|
||||||
enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) ?? true
|
enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) ?? true
|
||||||
required = try typeContainer.decodeIfPresent(Bool.self, forKey: .required) ?? true
|
required = try typeContainer.decodeIfPresent(Bool.self, forKey: .required) ?? true
|
||||||
readOnly = try typeContainer.decodeIfPresent(Bool.self, forKey: .readOnly) ?? false
|
readOnly = try typeContainer.decodeIfPresent(Bool.self, forKey: .readOnly) ?? false
|
||||||
@ -126,9 +130,30 @@ import VDS
|
|||||||
try container.encodeIfPresent(errorMessage, forKey: .errorMessage)
|
try container.encodeIfPresent(errorMessage, forKey: .errorMessage)
|
||||||
try container.encodeIfPresent(fieldKey, forKey: .fieldKey)
|
try container.encodeIfPresent(fieldKey, forKey: .fieldKey)
|
||||||
try container.encodeIfPresent(groupName, forKey: .groupName)
|
try container.encodeIfPresent(groupName, forKey: .groupName)
|
||||||
|
try container.encode(showError, forKey: .showError)
|
||||||
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)
|
try container.encode(inverted, forKey: .inverted)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open func isEqual(to model: any ModelComparisonProtocol) -> Bool {
|
||||||
|
guard let model = model as? Self else { return false }
|
||||||
|
return moleculeName == model.moleculeName
|
||||||
|
&& enabled == model.enabled
|
||||||
|
&& showError == model.showError
|
||||||
|
&& errorMessage == model.errorMessage
|
||||||
|
&& readOnly == model.readOnly
|
||||||
|
&& required == model.required
|
||||||
|
&& inverted == model.inverted
|
||||||
|
&& fieldKey == model.fieldKey
|
||||||
|
&& groupName == model.groupName
|
||||||
|
&& accessibilityText == model.accessibilityText
|
||||||
|
&& accessibilityIdentifier == model.accessibilityIdentifier
|
||||||
|
&& accessibilityTraits == model.accessibilityTraits
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension FormFieldModel {
|
||||||
|
public var isEnabled: Bool { enabled && !readOnly }
|
||||||
}
|
}
|
||||||
|
|||||||
@ -146,7 +146,7 @@ open class ItemDropdownEntryField: VDS.DropdownSelect, VDSMoleculeViewProtocol,
|
|||||||
isEnabled = viewModel.enabled
|
isEnabled = viewModel.enabled
|
||||||
isReadOnly = viewModel.readOnly
|
isReadOnly = viewModel.readOnly
|
||||||
isRequired = viewModel.required
|
isRequired = viewModel.required
|
||||||
tooltipModel = viewModel.tooltip?.toVDSTooltipModel()
|
tooltipModel = viewModel.tooltip?.convertToVDSTooltipModel()
|
||||||
width = viewModel.width
|
width = viewModel.width
|
||||||
transparentBackground = viewModel.transparentBackground
|
transparentBackground = viewModel.transparentBackground
|
||||||
|
|
||||||
|
|||||||
@ -78,4 +78,13 @@ import VDS
|
|||||||
try container.encode(feedbackTextPlacement, forKey: .feedbackTextPlacement)
|
try container.encode(feedbackTextPlacement, forKey: .feedbackTextPlacement)
|
||||||
try container.encodeModelIfPresent(action, forKey: .action)
|
try container.encodeModelIfPresent(action, forKey: .action)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open override func isEqual(to model: any ModelComparisonProtocol) -> Bool {
|
||||||
|
guard super.isEqual(to: model), let model = model as? Self else { return false }
|
||||||
|
return options == model.options
|
||||||
|
&& selectedIndex == model.selectedIndex
|
||||||
|
&& showInlineLabel == model.showInlineLabel
|
||||||
|
&& feedbackTextPlacement == model.feedbackTextPlacement
|
||||||
|
&& action.isEqual(to: model.action)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -34,7 +34,6 @@ import Foundation
|
|||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|
||||||
private enum CodingKeys: String, CodingKey {
|
private enum CodingKeys: String, CodingKey {
|
||||||
case backgroundColor
|
|
||||||
case title
|
case title
|
||||||
case feedback
|
case feedback
|
||||||
case errorTextColor
|
case errorTextColor
|
||||||
@ -86,7 +85,6 @@ import Foundation
|
|||||||
required public init(from decoder: Decoder) throws {
|
required public init(from decoder: Decoder) throws {
|
||||||
try super.init(from: decoder)
|
try super.init(from: decoder)
|
||||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
|
||||||
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)
|
||||||
errorTextColor = try typeContainer.decodeIfPresent(Color.self, forKey: .errorTextColor)
|
errorTextColor = try typeContainer.decodeIfPresent(Color.self, forKey: .errorTextColor)
|
||||||
@ -106,7 +104,6 @@ import Foundation
|
|||||||
open override func encode(to encoder: Encoder) throws {
|
open override func encode(to encoder: Encoder) throws {
|
||||||
try super.encode(to: encoder)
|
try super.encode(to: encoder)
|
||||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
|
||||||
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)
|
||||||
@ -116,4 +113,16 @@ import Foundation
|
|||||||
try container.encode(hideBorders, forKey: .hideBorders)
|
try container.encode(hideBorders, forKey: .hideBorders)
|
||||||
try container.encode(shouldMaskRecordedView, forKey: .shouldMaskRecordedView)
|
try container.encode(shouldMaskRecordedView, forKey: .shouldMaskRecordedView)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open override func isEqual(to model: any ModelComparisonProtocol) -> Bool {
|
||||||
|
guard super.isEqual(to: model), let model = model as? Self else { return false }
|
||||||
|
return selected == model.selected
|
||||||
|
&& title == model.title
|
||||||
|
&& feedback == model.feedback
|
||||||
|
&& errorTextColor == model.errorTextColor
|
||||||
|
&& locked == model.locked
|
||||||
|
&& hideBorders == model.hideBorders
|
||||||
|
&& text == model.text
|
||||||
|
&& shouldMaskRecordedView == model.shouldMaskRecordedView
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -173,7 +173,7 @@ import VDS
|
|||||||
isEnabled = viewModel.enabled
|
isEnabled = viewModel.enabled
|
||||||
isReadOnly = viewModel.readOnly
|
isReadOnly = viewModel.readOnly
|
||||||
isRequired = viewModel.required
|
isRequired = viewModel.required
|
||||||
tooltipModel = viewModel.tooltip?.toVDSTooltipModel()
|
tooltipModel = viewModel.tooltip?.convertToVDSTooltipModel()
|
||||||
width = viewModel.width
|
width = viewModel.width
|
||||||
transparentBackground = viewModel.transparentBackground
|
transparentBackground = viewModel.transparentBackground
|
||||||
|
|
||||||
|
|||||||
@ -218,4 +218,21 @@ import VDS
|
|||||||
try container.encode(transparentBackground, forKey: .transparentBackground)
|
try container.encode(transparentBackground, forKey: .transparentBackground)
|
||||||
try container.encodeIfPresent(width, forKey: .width)
|
try container.encodeIfPresent(width, forKey: .width)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open override func isEqual(to model: any ModelComparisonProtocol) -> Bool {
|
||||||
|
guard super.isEqual(to: model), let model = model as? Self else { return false }
|
||||||
|
return placeholder == model.placeholder
|
||||||
|
&& textAlignment == model.textAlignment
|
||||||
|
&& enabledTextColor == model.enabledTextColor
|
||||||
|
&& disabledTextColor == model.disabledTextColor
|
||||||
|
&& keyboardOverride == model.keyboardOverride
|
||||||
|
&& type == model.type
|
||||||
|
&& clearTextOnTap == model.clearTextOnTap
|
||||||
|
&& displayFormat == model.displayFormat
|
||||||
|
&& displayMask == model.displayMask
|
||||||
|
&& enableClipboardActions == model.enableClipboardActions
|
||||||
|
&& tooltip == model.tooltip
|
||||||
|
&& transparentBackground == model.transparentBackground
|
||||||
|
&& width == model.width
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -126,7 +126,7 @@ open class TextViewEntryField: VDS.TextArea, VDSMoleculeViewProtocol, ObservingT
|
|||||||
isEnabled = viewModel.enabled
|
isEnabled = viewModel.enabled
|
||||||
isReadOnly = viewModel.readOnly
|
isReadOnly = viewModel.readOnly
|
||||||
isRequired = viewModel.required
|
isRequired = viewModel.required
|
||||||
tooltipModel = viewModel.tooltip?.toVDSTooltipModel()
|
tooltipModel = viewModel.tooltip?.convertToVDSTooltipModel()
|
||||||
width = viewModel.width
|
width = viewModel.width
|
||||||
transparentBackground = viewModel.transparentBackground
|
transparentBackground = viewModel.transparentBackground
|
||||||
|
|
||||||
|
|||||||
@ -21,7 +21,7 @@ public class TextViewEntryFieldModel: TextEntryFieldModel {
|
|||||||
public var showsPlaceholder: Bool = false
|
public var showsPlaceholder: Bool = false
|
||||||
public var minHeight: VDS.TextArea.Height = .twoX
|
public var minHeight: VDS.TextArea.Height = .twoX
|
||||||
public var maxLength: Int?
|
public var maxLength: Int?
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Keys
|
// MARK: - Keys
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
@ -55,4 +55,13 @@ public class TextViewEntryFieldModel: TextEntryFieldModel {
|
|||||||
try container.encode(minHeight, forKey: .minHeight)
|
try container.encode(minHeight, forKey: .minHeight)
|
||||||
try container.encodeIfPresent(maxLength, forKey: .maxLength)
|
try container.encodeIfPresent(maxLength, forKey: .maxLength)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open override func isEqual(to model: any ModelComparisonProtocol) -> Bool {
|
||||||
|
guard super.isEqual(to: model), let model = model as? Self else { return false }
|
||||||
|
return accessibilityText == model.accessibilityText
|
||||||
|
&& editable == model.editable
|
||||||
|
&& minHeight == model.minHeight
|
||||||
|
&& maxLength == model.maxLength
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -131,7 +131,7 @@ import VDS
|
|||||||
}
|
}
|
||||||
|
|
||||||
//properties
|
//properties
|
||||||
isEnabled = viewModel.enabled && !viewModel.readOnly
|
isEnabled = viewModel.isEnabled
|
||||||
isAnimated = viewModel.animated
|
isAnimated = viewModel.animated
|
||||||
|
|
||||||
//call super here to go around the didSet
|
//call super here to go around the didSet
|
||||||
|
|||||||
@ -94,4 +94,12 @@ import VDS
|
|||||||
try container.encodeModelIfPresent(action, forKey: .action)
|
try container.encodeModelIfPresent(action, forKey: .action)
|
||||||
try container.encodeModelIfPresent(offAction, forKey: .offAction)
|
try container.encodeModelIfPresent(offAction, forKey: .offAction)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open override func isEqual(to model: any ModelComparisonProtocol) -> Bool {
|
||||||
|
guard super.isEqual(to: model), let model = model as? Self else { return false }
|
||||||
|
return selected == model.selected
|
||||||
|
&& animated == model.animated
|
||||||
|
&& offAction.isEqual(to: model.offAction)
|
||||||
|
&& action.isEqual(to: model.action)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
55
MVMCoreUI/Atomic/Atoms/Selectors/Checkboxes.swift
Normal file
55
MVMCoreUI/Atomic/Atoms/Selectors/Checkboxes.swift
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
//
|
||||||
|
// Checkboxes.swift
|
||||||
|
// MVMCoreUI
|
||||||
|
//
|
||||||
|
// Created by Matt Bruce on 8/19/24.
|
||||||
|
// Copyright © 2024 Verizon Wireless. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import VDS
|
||||||
|
|
||||||
|
open class Checkboxes: VDS.CheckboxGroup, VDSMoleculeViewProtocol {
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// MARK: - Properties
|
||||||
|
//------------------------------------------------------
|
||||||
|
open var viewModel: CheckboxesModel!
|
||||||
|
open var delegateObject: MVMCoreUIDelegateObject?
|
||||||
|
open var additionalData: [AnyHashable : Any]?
|
||||||
|
|
||||||
|
// Form Validation
|
||||||
|
var fieldKey: String?
|
||||||
|
var fieldValue: JSONValue?
|
||||||
|
var groupName: String?
|
||||||
|
|
||||||
|
/// The models for the molecules.
|
||||||
|
public var checkboxes: [CheckboxLabelModel]?
|
||||||
|
|
||||||
|
// MARK: - MoleculeViewProtocol
|
||||||
|
public func viewModelDidUpdate() {
|
||||||
|
surface = viewModel.surface
|
||||||
|
showError = viewModel.showError
|
||||||
|
isEnabled = viewModel.enabled && !viewModel.readOnly
|
||||||
|
checkboxes = viewModel.checkboxes
|
||||||
|
checkboxes?.forEach {
|
||||||
|
FormValidator.setupValidation(for: $0.checkbox, delegate: delegateObject?.formHolderDelegate)
|
||||||
|
}
|
||||||
|
|
||||||
|
selectorModels = viewModel.checkboxes.convertToVDSCheckboxItemModel(surface: surface,
|
||||||
|
delegateObject: delegateObject,
|
||||||
|
additionalData: additionalData)
|
||||||
|
}
|
||||||
|
|
||||||
|
open func updateView(_ size: CGFloat) {}
|
||||||
|
|
||||||
|
open override func didSelect(_ selectedControl: CheckboxItem) {
|
||||||
|
super.didSelect(selectedControl)
|
||||||
|
|
||||||
|
// since the checkboxes has the state being tracked, we need to update the values here.
|
||||||
|
if let index = items.firstIndex(where: {$0 === selectedControl}), let selected = checkboxes?[index] {
|
||||||
|
selected.checkbox.selected = true
|
||||||
|
}
|
||||||
|
_ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate)
|
||||||
|
}
|
||||||
|
}
|
||||||
101
MVMCoreUI/Atomic/Atoms/Selectors/CheckboxesModel.swift
Normal file
101
MVMCoreUI/Atomic/Atoms/Selectors/CheckboxesModel.swift
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
//
|
||||||
|
// CheckboxesModel.swift
|
||||||
|
// MVMCoreUI
|
||||||
|
//
|
||||||
|
// Created by Matt Bruce on 8/19/24.
|
||||||
|
// Copyright © 2024 Verizon Wireless. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import MVMCore
|
||||||
|
import VDS
|
||||||
|
|
||||||
|
public class CheckboxesModel: MoleculeModelProtocol, ParentMoleculeModelProtocol {
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Properties
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
|
public static var identifier: String { "checkboxes" }
|
||||||
|
public var id: String = UUID().uuidString
|
||||||
|
|
||||||
|
public var backgroundColor: Color?
|
||||||
|
public var accessibilityIdentifier: String?
|
||||||
|
|
||||||
|
public var enabled: Bool = true
|
||||||
|
public var required: Bool = true
|
||||||
|
public var readOnly: Bool = false
|
||||||
|
public var showError: Bool = false
|
||||||
|
public var inverted: Bool = false
|
||||||
|
public var surface: Surface { inverted ? .dark : .light }
|
||||||
|
|
||||||
|
public var checkboxes: [CheckboxLabelModel]
|
||||||
|
|
||||||
|
public var children: [any MoleculeModelProtocol] { checkboxes }
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Keys
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
|
private enum CodingKeys: String, CodingKey {
|
||||||
|
case id
|
||||||
|
case moleculeName
|
||||||
|
case accessibilityIdentifier
|
||||||
|
case inverted
|
||||||
|
case enabled
|
||||||
|
case readOnly
|
||||||
|
case showError
|
||||||
|
case checkboxes
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Initializer
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
|
public init(with checkboxes: [CheckboxLabelModel]){
|
||||||
|
self.checkboxes = checkboxes
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Codec
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
|
required public init(from decoder: Decoder) throws {
|
||||||
|
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
|
||||||
|
id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString
|
||||||
|
accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier)
|
||||||
|
showError = try typeContainer.decodeIfPresent(Bool.self, forKey: .showError) ?? false
|
||||||
|
enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) ?? true
|
||||||
|
readOnly = try typeContainer.decodeIfPresent(Bool.self, forKey: .readOnly) ?? false
|
||||||
|
|
||||||
|
if let inverted = try typeContainer.decodeIfPresent(Bool.self, forKey: .inverted) {
|
||||||
|
self.inverted = inverted
|
||||||
|
}
|
||||||
|
checkboxes = try typeContainer.decode([CheckboxLabelModel].self, forKey: .checkboxes)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func encode(to encoder: Encoder) throws {
|
||||||
|
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||||
|
try container.encode(id, forKey: .id)
|
||||||
|
try container.encodeIfPresent(moleculeName, forKey: .moleculeName)
|
||||||
|
try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier)
|
||||||
|
try container.encode(readOnly, forKey: .readOnly)
|
||||||
|
try container.encode(enabled, forKey: .enabled)
|
||||||
|
try container.encode(inverted, forKey: .inverted)
|
||||||
|
try container.encode(checkboxes, forKey: .checkboxes)
|
||||||
|
}
|
||||||
|
|
||||||
|
open func isEqual(to model: any ModelComparisonProtocol) -> Bool {
|
||||||
|
guard let model = model as? Self else { return false }
|
||||||
|
return moleculeName == model.moleculeName
|
||||||
|
&& enabled == model.enabled
|
||||||
|
&& showError == model.showError
|
||||||
|
&& readOnly == model.readOnly
|
||||||
|
&& required == model.required
|
||||||
|
&& inverted == model.inverted
|
||||||
|
&& accessibilityText == model.accessibilityText
|
||||||
|
&& accessibilityIdentifier == model.accessibilityIdentifier
|
||||||
|
&& accessibilityTraits == model.accessibilityTraits
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -8,47 +8,33 @@
|
|||||||
import MVMCore
|
import MVMCore
|
||||||
import VDS
|
import VDS
|
||||||
|
|
||||||
@objcMembers public class RadioBoxModel: MoleculeModelProtocol, EnableableModelProtocol {
|
public class RadioBoxModel: FormFieldModel {
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Properties
|
// MARK: - Properties
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|
||||||
public static var identifier: String = "radioBox"
|
public override static var identifier: String { "radioBox" }
|
||||||
public var id: String = UUID().uuidString
|
|
||||||
|
|
||||||
public var text: String
|
public var text: String
|
||||||
public var subText: String?
|
public var subText: String?
|
||||||
public var subTextRight: String?
|
public var subTextRight: String?
|
||||||
public var backgroundColor: Color?
|
|
||||||
public var accessibilityIdentifier: String?
|
|
||||||
public var selected: Bool = false
|
public var selected: Bool = false
|
||||||
public var enabled: Bool = true
|
|
||||||
public var readOnly: Bool = false
|
|
||||||
public var strikethrough: Bool = false
|
public var strikethrough: Bool = false
|
||||||
public var fieldValue: String?
|
|
||||||
public var action: ActionModelProtocol?
|
public var action: ActionModelProtocol?
|
||||||
public var inverted: Bool = false
|
public var fieldValue: String?
|
||||||
public var surface: Surface { inverted ? .dark : .light }
|
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Keys
|
// MARK: - Keys
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|
||||||
private enum CodingKeys: String, CodingKey {
|
private enum CodingKeys: String, CodingKey {
|
||||||
case id
|
|
||||||
case moleculeName
|
|
||||||
case text
|
case text
|
||||||
case subText
|
case subText
|
||||||
case subTextRight
|
case subTextRight
|
||||||
case backgroundColor
|
|
||||||
case accessibilityIdentifier
|
|
||||||
case selected
|
case selected
|
||||||
case enabled
|
|
||||||
case strikethrough
|
case strikethrough
|
||||||
case fieldValue
|
|
||||||
case action
|
case action
|
||||||
case readOnly
|
case fieldValue
|
||||||
case inverted
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
@ -57,8 +43,19 @@ import VDS
|
|||||||
|
|
||||||
public init(text: String) {
|
public init(text: String) {
|
||||||
self.text = text
|
self.text = text
|
||||||
|
super.init()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Form Validation
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
|
/// Returns the fieldValue of the selected box, otherwise the text of the selected box.
|
||||||
|
public override func formFieldValue() -> AnyHashable? {
|
||||||
|
guard enabled else { return nil }
|
||||||
|
return fieldValue
|
||||||
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Codec
|
// MARK: - Codec
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
@ -66,45 +63,42 @@ import VDS
|
|||||||
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)
|
||||||
|
|
||||||
id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString
|
|
||||||
text = try typeContainer.decode(String.self, forKey: .text)
|
text = try typeContainer.decode(String.self, forKey: .text)
|
||||||
subText = try typeContainer.decodeIfPresent(String.self, forKey: .subText)
|
subText = try typeContainer.decodeIfPresent(String.self, forKey: .subText)
|
||||||
subTextRight = try typeContainer.decodeIfPresent(String.self, forKey: .subTextRight)
|
subTextRight = try typeContainer.decodeIfPresent(String.self, forKey: .subTextRight)
|
||||||
accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier)
|
|
||||||
|
|
||||||
if let isSelected = try typeContainer.decodeIfPresent(Bool.self, forKey: .selected) {
|
if let isSelected = try typeContainer.decodeIfPresent(Bool.self, forKey: .selected) {
|
||||||
selected = isSelected
|
selected = isSelected
|
||||||
}
|
}
|
||||||
|
|
||||||
enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) ?? true
|
|
||||||
readOnly = try typeContainer.decodeIfPresent(Bool.self, forKey: .readOnly) ?? false
|
|
||||||
|
|
||||||
if let isStrikeTrough = try typeContainer.decodeIfPresent(Bool.self, forKey: .strikethrough) {
|
if let isStrikeTrough = try typeContainer.decodeIfPresent(Bool.self, forKey: .strikethrough) {
|
||||||
strikethrough = isStrikeTrough
|
strikethrough = isStrikeTrough
|
||||||
}
|
}
|
||||||
|
|
||||||
if let inverted = try typeContainer.decodeIfPresent(Bool.self, forKey: .inverted) {
|
|
||||||
self.inverted = inverted
|
|
||||||
}
|
|
||||||
|
|
||||||
fieldValue = try typeContainer.decodeIfPresent(String.self, forKey: .fieldValue)
|
fieldValue = try typeContainer.decodeIfPresent(String.self, forKey: .fieldValue)
|
||||||
action = try typeContainer.decodeModelIfPresent(codingKey: .action)
|
action = try typeContainer.decodeModelIfPresent(codingKey: .action)
|
||||||
|
try super.init(from: decoder)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func encode(to encoder: Encoder) throws {
|
public 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.encode(moleculeName, forKey: .moleculeName)
|
|
||||||
try container.encode(text, forKey: .text)
|
try container.encode(text, forKey: .text)
|
||||||
try container.encodeIfPresent(subText, forKey: .subText)
|
try container.encodeIfPresent(subText, forKey: .subText)
|
||||||
try container.encodeIfPresent(subTextRight, forKey: .subTextRight)
|
try container.encodeIfPresent(subTextRight, forKey: .subTextRight)
|
||||||
try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier)
|
|
||||||
try container.encode(selected, forKey: .selected)
|
try container.encode(selected, forKey: .selected)
|
||||||
try container.encode(enabled, forKey: .enabled)
|
|
||||||
try container.encode(readOnly, forKey: .readOnly)
|
|
||||||
try container.encode(strikethrough, forKey: .strikethrough)
|
try container.encode(strikethrough, forKey: .strikethrough)
|
||||||
try container.encodeIfPresent(fieldValue, forKey: .fieldValue)
|
|
||||||
try container.encodeModelIfPresent(action, forKey: .action)
|
try container.encodeModelIfPresent(action, forKey: .action)
|
||||||
try container.encode(inverted, forKey: .inverted)
|
}
|
||||||
|
|
||||||
|
open override func isEqual(to model: any ModelComparisonProtocol) -> Bool {
|
||||||
|
guard super.isEqual(to: model), let model = model as? Self else { return false }
|
||||||
|
return text == model.text
|
||||||
|
&& subText == model.subText
|
||||||
|
&& subTextRight == model.subTextRight
|
||||||
|
&& selected == model.selected
|
||||||
|
&& strikethrough == model.strikethrough
|
||||||
|
&& fieldValue == model.fieldValue
|
||||||
|
&& action.isEqual(to: model.action)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -9,10 +9,6 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import VDS
|
import VDS
|
||||||
|
|
||||||
public protocol RadioBoxSelectionDelegate: AnyObject {
|
|
||||||
func selected(radioBox: RadioBoxModel)
|
|
||||||
}
|
|
||||||
|
|
||||||
open class RadioBoxes: VDS.RadioBoxGroup, VDSMoleculeViewProtocol {
|
open class RadioBoxes: VDS.RadioBoxGroup, VDSMoleculeViewProtocol {
|
||||||
|
|
||||||
//------------------------------------------------------
|
//------------------------------------------------------
|
||||||
@ -29,13 +25,12 @@ open class RadioBoxes: VDS.RadioBoxGroup, VDSMoleculeViewProtocol {
|
|||||||
|
|
||||||
/// The models for the molecules.
|
/// The models for the molecules.
|
||||||
public var boxes: [RadioBoxModel]?
|
public var boxes: [RadioBoxModel]?
|
||||||
public weak var radioDelegate: RadioBoxSelectionDelegate?
|
|
||||||
|
|
||||||
// MARK: - MoleculeViewProtocol
|
// MARK: - MoleculeViewProtocol
|
||||||
public func viewModelDidUpdate() {
|
public func viewModelDidUpdate() {
|
||||||
boxes = viewModel.boxes
|
boxes = viewModel.boxes
|
||||||
surface = viewModel.surface
|
surface = viewModel.surface
|
||||||
selectorModels = viewModel.selectorModels
|
selectorModels = viewModel.boxes.convertToVDSRadioBoxModel(surface: surface)
|
||||||
FormValidator.setupValidation(for: viewModel, delegate: delegateObject?.formHolderDelegate)
|
FormValidator.setupValidation(for: viewModel, delegate: delegateObject?.formHolderDelegate)
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -50,7 +45,8 @@ open class RadioBoxes: VDS.RadioBoxGroup, VDSMoleculeViewProtocol {
|
|||||||
boxes?.forEach { $0.selected = false }
|
boxes?.forEach { $0.selected = false }
|
||||||
selectedBox.selected = true
|
selectedBox.selected = true
|
||||||
_ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate)
|
_ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate)
|
||||||
radioDelegate?.selected(radioBox: selectedBox)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -8,7 +8,8 @@
|
|||||||
import MVMCore
|
import MVMCore
|
||||||
import VDS
|
import VDS
|
||||||
|
|
||||||
@objcMembers public class RadioBoxesModel: FormFieldModel {
|
public class RadioBoxesModel: FormFieldModel, ParentMoleculeModelProtocol {
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Properties
|
// MARK: - Properties
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
@ -16,20 +17,9 @@ import VDS
|
|||||||
public override static var identifier: String { "radioBoxes" }
|
public override static var identifier: String { "radioBoxes" }
|
||||||
|
|
||||||
public var boxes: [RadioBoxModel]
|
public var boxes: [RadioBoxModel]
|
||||||
|
|
||||||
|
public var children: [any MoleculeModelProtocol] { boxes }
|
||||||
|
|
||||||
public var selectorModels: [VDS.RadioBoxGroup.RadioBoxItemModel] {
|
|
||||||
boxes.compactMap({ item in
|
|
||||||
var radioBox = RadioBoxGroup.RadioBoxItemModel()
|
|
||||||
radioBox.text = item.text
|
|
||||||
radioBox.subText = item.subText
|
|
||||||
radioBox.subTextRight = item.subTextRight
|
|
||||||
radioBox.surface = surface
|
|
||||||
radioBox.selected = item.selected
|
|
||||||
radioBox.strikethrough = item.strikethrough
|
|
||||||
radioBox.disabled = !(item.enabled && !item.readOnly)
|
|
||||||
return radioBox
|
|
||||||
})
|
|
||||||
}
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Form Validation
|
// MARK: - Form Validation
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
@ -40,7 +30,7 @@ import VDS
|
|||||||
let selectedBox = boxes.first { (box) -> Bool in
|
let selectedBox = boxes.first { (box) -> Bool in
|
||||||
return box.selected
|
return box.selected
|
||||||
}
|
}
|
||||||
return selectedBox?.fieldValue ?? selectedBox?.text
|
return selectedBox?.formFieldValue() ?? selectedBox?.text
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
@ -83,3 +73,19 @@ import VDS
|
|||||||
try container.encode(boxes, forKey: .boxes)
|
try container.encode(boxes, forKey: .boxes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension Array where Element == RadioBoxModel {
|
||||||
|
internal func convertToVDSRadioBoxModel(surface: Surface) -> [RadioBoxGroup.RadioBoxItemModel] {
|
||||||
|
compactMap({ item in
|
||||||
|
var radioBox = RadioBoxGroup.RadioBoxItemModel()
|
||||||
|
radioBox.text = item.text
|
||||||
|
radioBox.subText = item.subText
|
||||||
|
radioBox.subTextRight = item.subTextRight
|
||||||
|
radioBox.surface = surface
|
||||||
|
radioBox.selected = item.selected
|
||||||
|
radioBox.strikethrough = item.strikethrough
|
||||||
|
radioBox.enabled = item.isEnabled
|
||||||
|
return radioBox
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -101,7 +101,7 @@ import VDS
|
|||||||
}
|
}
|
||||||
|
|
||||||
isSelected = viewModel.state
|
isSelected = viewModel.state
|
||||||
isEnabled = viewModel.enabled && !viewModel.readOnly
|
isEnabled = viewModel.isEnabled
|
||||||
RadioButtonSelectionHelper.setupForRadioButtonGroup(viewModel, self, delegateObject: delegateObject)
|
RadioButtonSelectionHelper.setupForRadioButtonGroup(viewModel, self, delegateObject: delegateObject)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -83,4 +83,11 @@ open class RadioButtonModel: FormFieldModel {
|
|||||||
try container.encodeIfPresent(fieldValue, forKey: .fieldValue)
|
try container.encodeIfPresent(fieldValue, forKey: .fieldValue)
|
||||||
try container.encodeModelIfPresent(action, forKey: .action)
|
try container.encodeModelIfPresent(action, forKey: .action)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open override func isEqual(to model: any ModelComparisonProtocol) -> Bool {
|
||||||
|
guard super.isEqual(to: model), let model = model as? Self else { return false }
|
||||||
|
return state == model.state
|
||||||
|
&& fieldValue == model.fieldValue
|
||||||
|
&& action.isEqual(to: model.action)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
54
MVMCoreUI/Atomic/Atoms/Selectors/RadioButtons.swift
Normal file
54
MVMCoreUI/Atomic/Atoms/Selectors/RadioButtons.swift
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
//
|
||||||
|
// RadioButtons.swift
|
||||||
|
// MVMCoreUI
|
||||||
|
//
|
||||||
|
// Created by Matt Bruce on 8/20/24.
|
||||||
|
// Copyright © 2024 Verizon Wireless. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import VDS
|
||||||
|
|
||||||
|
open class RadioButtons: VDS.RadioButtonGroup, VDSMoleculeViewProtocol {
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// MARK: - Properties
|
||||||
|
//------------------------------------------------------
|
||||||
|
open var viewModel: RadioButtonsModel!
|
||||||
|
open var delegateObject: MVMCoreUIDelegateObject?
|
||||||
|
open var additionalData: [AnyHashable : Any]?
|
||||||
|
|
||||||
|
// Form Validation
|
||||||
|
var fieldKey: String?
|
||||||
|
var fieldValue: JSONValue?
|
||||||
|
var groupName: String?
|
||||||
|
|
||||||
|
/// The models for the molecules.
|
||||||
|
public var radioButtons: [RadioButtonLabelModel]?
|
||||||
|
|
||||||
|
// MARK: - MoleculeViewProtocol
|
||||||
|
public func viewModelDidUpdate() {
|
||||||
|
showError = viewModel.showError
|
||||||
|
isEnabled = viewModel.isEnabled
|
||||||
|
surface = viewModel.surface
|
||||||
|
|
||||||
|
radioButtons = viewModel.radioButtons
|
||||||
|
selectorModels = viewModel.radioButtons.convertToVDSRadioButtonItemModel(surface: surface,
|
||||||
|
delegateObject: delegateObject,
|
||||||
|
additionalData: additionalData)
|
||||||
|
FormValidator.setupValidation(for: viewModel, delegate: delegateObject?.formHolderDelegate)
|
||||||
|
}
|
||||||
|
|
||||||
|
open func updateView(_ size: CGFloat) {}
|
||||||
|
|
||||||
|
open override func didSelect(_ selectedControl: RadioButtonItem) {
|
||||||
|
super.didSelect(selectedControl)
|
||||||
|
|
||||||
|
// since the radiobutton has the state being tracked, we need to update the values here.
|
||||||
|
if let index = items.firstIndex(where: {$0 === selectedControl}), let selected = radioButtons?[index] {
|
||||||
|
radioButtons?.forEach { $0.radioButton.state = false }
|
||||||
|
selected.radioButton.state = true
|
||||||
|
}
|
||||||
|
_ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate)
|
||||||
|
}
|
||||||
|
}
|
||||||
74
MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonsModel.swift
Normal file
74
MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonsModel.swift
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
//
|
||||||
|
// RadioButtonsModel.swift
|
||||||
|
// MVMCoreUI
|
||||||
|
//
|
||||||
|
// Created by Matt Bruce on 8/20/24.
|
||||||
|
// Copyright © 2024 Verizon Wireless. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import MVMCore
|
||||||
|
import VDS
|
||||||
|
|
||||||
|
public class RadioButtonsModel: FormFieldModel, ParentMoleculeModelProtocol {
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Properties
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
|
public override static var identifier: String { "radioButtons" }
|
||||||
|
|
||||||
|
public var radioButtons: [RadioButtonLabelModel]
|
||||||
|
|
||||||
|
public var children: [any MoleculeModelProtocol] { radioButtons }
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Form Validation
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
|
/// Returns the fieldValue of the selected RadioButton.
|
||||||
|
public override func formFieldValue() -> AnyHashable? {
|
||||||
|
guard enabled else { return nil }
|
||||||
|
let selected = radioButtons.first { $0.radioButton.state }
|
||||||
|
return selected?.radioButton.formFieldValue()
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Server Value
|
||||||
|
//--------------------------------------------------
|
||||||
|
open override func formFieldServerValue() -> AnyHashable? {
|
||||||
|
return formFieldValue()
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Keys
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
|
private enum CodingKeys: String, CodingKey {
|
||||||
|
case radioButtons
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Initializer
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
|
public init(with radioButtons: [RadioButtonLabelModel]){
|
||||||
|
self.radioButtons = radioButtons
|
||||||
|
super.init()
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Codec
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
|
required public init(from decoder: Decoder) throws {
|
||||||
|
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
radioButtons = try typeContainer.decode([RadioButtonLabelModel].self, forKey: .radioButtons)
|
||||||
|
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(radioButtons, forKey: .radioButtons)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -108,7 +108,7 @@ public typealias ActionBlockConfirmation = () -> (Bool)
|
|||||||
isOn = viewModel.selected
|
isOn = viewModel.selected
|
||||||
surface = viewModel.surface
|
surface = viewModel.surface
|
||||||
isAnimated = viewModel.animated
|
isAnimated = viewModel.animated
|
||||||
isEnabled = viewModel.enabled && !viewModel.readOnly
|
isEnabled = viewModel.isEnabled
|
||||||
showText = viewModel.showText
|
showText = viewModel.showText
|
||||||
if let onText = viewModel.onText {
|
if let onText = viewModel.onText {
|
||||||
self.onText = onText
|
self.onText = onText
|
||||||
|
|||||||
@ -7,26 +7,18 @@
|
|||||||
//
|
//
|
||||||
import VDS
|
import VDS
|
||||||
|
|
||||||
public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol {
|
public class ToggleModel: FormFieldModel {
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Properties
|
// MARK: - Properties
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|
||||||
public static var identifier: String = "toggle"
|
public override static var identifier: String { "toggle" }
|
||||||
public var id: String = UUID().uuidString
|
|
||||||
|
|
||||||
public var accessibilityIdentifier: String?
|
|
||||||
public var backgroundColor: Color?
|
|
||||||
public var selected: Bool = false
|
public var selected: Bool = false
|
||||||
public var animated: Bool = true
|
public var animated: Bool = true
|
||||||
public var enabled: Bool = true
|
|
||||||
public var readOnly: Bool = false
|
|
||||||
public var action: ActionModelProtocol?
|
public var action: ActionModelProtocol?
|
||||||
public var alternateAction: ActionModelProtocol?
|
public var alternateAction: ActionModelProtocol?
|
||||||
public var accessibilityText: String?
|
public var accessibilityText: String?
|
||||||
|
|
||||||
public var surface: Surface { inverted ? .dark : .light }
|
|
||||||
public var inverted: Bool = false
|
|
||||||
public var showText: Bool = false
|
public var showText: Bool = false
|
||||||
public var onText: String?
|
public var onText: String?
|
||||||
public var offText: String?
|
public var offText: String?
|
||||||
@ -34,61 +26,41 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol {
|
|||||||
public var textWeight: VDS.Toggle.TextWeight = .regular
|
public var textWeight: VDS.Toggle.TextWeight = .regular
|
||||||
public var textPosition: VDS.Toggle.TextPosition = .left
|
public var textPosition: VDS.Toggle.TextPosition = .left
|
||||||
|
|
||||||
public var fieldKey: String?
|
|
||||||
public var groupName: String = FormValidator.defaultGroupName
|
|
||||||
public var baseValue: AnyHashable?
|
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Keys
|
// MARK: - Keys
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|
||||||
private enum CodingKeys: String, CodingKey {
|
private enum CodingKeys: String, CodingKey {
|
||||||
case id
|
|
||||||
case moleculeName
|
|
||||||
case state
|
case state
|
||||||
case animated
|
case animated
|
||||||
case enabled
|
|
||||||
case readOnly
|
|
||||||
case action
|
case action
|
||||||
case backgroundColor
|
|
||||||
case accessibilityIdentifier
|
|
||||||
case alternateAction
|
case alternateAction
|
||||||
case accessibilityText
|
case accessibilityText
|
||||||
|
|
||||||
case inverted
|
|
||||||
case showText
|
case showText
|
||||||
case onText
|
case onText
|
||||||
case offText
|
case offText
|
||||||
case textSize
|
case textSize
|
||||||
case textWeight
|
case textWeight
|
||||||
case textPosition
|
case textPosition
|
||||||
|
|
||||||
case fieldKey
|
|
||||||
case groupName
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Form Valdiation
|
// MARK: - Form Valdiation
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|
||||||
public func formFieldValue() -> AnyHashable? {
|
public override func formFieldValue() -> AnyHashable? {
|
||||||
guard enabled else { return nil }
|
guard enabled else { return nil }
|
||||||
return selected
|
return selected
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
|
||||||
// MARK: - Server Value
|
|
||||||
//--------------------------------------------------
|
|
||||||
open func formFieldServerValue() -> AnyHashable? {
|
|
||||||
return formFieldValue()
|
|
||||||
}
|
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Initializer
|
// MARK: - Initializer
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|
||||||
public init(_ state: Bool, id: String = UUID().uuidString) {
|
public init(_ state: Bool, id: String = UUID().uuidString) {
|
||||||
self.selected = state
|
selected = state
|
||||||
|
super.init()
|
||||||
baseValue = state
|
baseValue = state
|
||||||
self.id = id
|
self.id = id
|
||||||
}
|
}
|
||||||
@ -100,8 +72,6 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol {
|
|||||||
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)
|
||||||
|
|
||||||
id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString
|
|
||||||
|
|
||||||
if let state = try typeContainer.decodeIfPresent(Bool.self, forKey: .state) {
|
if let state = try typeContainer.decodeIfPresent(Bool.self, forKey: .state) {
|
||||||
self.selected = state
|
self.selected = state
|
||||||
}
|
}
|
||||||
@ -112,44 +82,28 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol {
|
|||||||
|
|
||||||
action = try typeContainer.decodeModelIfPresent(codingKey: .action)
|
action = try typeContainer.decodeModelIfPresent(codingKey: .action)
|
||||||
alternateAction = try typeContainer.decodeModelIfPresent(codingKey: .alternateAction)
|
alternateAction = try typeContainer.decodeModelIfPresent(codingKey: .alternateAction)
|
||||||
accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier)
|
|
||||||
|
|
||||||
accessibilityText = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityText)
|
accessibilityText = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityText)
|
||||||
|
|
||||||
baseValue = selected
|
|
||||||
fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey)
|
|
||||||
if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) {
|
|
||||||
self.groupName = groupName
|
|
||||||
}
|
|
||||||
enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) ?? true
|
|
||||||
readOnly = try typeContainer.decodeIfPresent(Bool.self, forKey: .readOnly) ?? false
|
|
||||||
|
|
||||||
inverted = try typeContainer.decodeIfPresent(Bool.self, forKey: .inverted) ?? false
|
|
||||||
showText = try typeContainer.decodeIfPresent(Bool.self, forKey: .showText) ?? false
|
showText = try typeContainer.decodeIfPresent(Bool.self, forKey: .showText) ?? false
|
||||||
onText = try typeContainer.decodeIfPresent(String.self, forKey: .onText)
|
onText = try typeContainer.decodeIfPresent(String.self, forKey: .onText)
|
||||||
offText = try typeContainer.decodeIfPresent(String.self, forKey: .offText)
|
offText = try typeContainer.decodeIfPresent(String.self, forKey: .offText)
|
||||||
textSize = try typeContainer.decodeIfPresent(VDS.Toggle.TextSize.self, forKey: .textSize) ?? .small
|
textSize = try typeContainer.decodeIfPresent(VDS.Toggle.TextSize.self, forKey: .textSize) ?? .small
|
||||||
textWeight = try typeContainer.decodeIfPresent(VDS.Toggle.TextWeight.self, forKey: .textWeight) ?? .regular
|
textWeight = try typeContainer.decodeIfPresent(VDS.Toggle.TextWeight.self, forKey: .textWeight) ?? .regular
|
||||||
textPosition = try typeContainer.decodeIfPresent(VDS.Toggle.TextPosition.self, forKey: .textPosition) ?? .left
|
textPosition = try typeContainer.decodeIfPresent(VDS.Toggle.TextPosition.self, forKey: .textPosition) ?? .left
|
||||||
|
|
||||||
|
try super.init(from: decoder)
|
||||||
|
baseValue = selected
|
||||||
}
|
}
|
||||||
|
|
||||||
public func encode(to encoder: Encoder) throws {
|
public 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(backgroundColor, forKey: .backgroundColor)
|
|
||||||
try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier)
|
|
||||||
try container.encodeModelIfPresent(action, forKey: .action)
|
try container.encodeModelIfPresent(action, forKey: .action)
|
||||||
try container.encodeModelIfPresent(alternateAction, forKey: .alternateAction)
|
try container.encodeModelIfPresent(alternateAction, forKey: .alternateAction)
|
||||||
try container.encode(moleculeName, forKey: .moleculeName)
|
|
||||||
try container.encode(selected, forKey: .state)
|
try container.encode(selected, forKey: .state)
|
||||||
try container.encode(animated, forKey: .animated)
|
try container.encode(animated, forKey: .animated)
|
||||||
try container.encode(enabled, forKey: .enabled)
|
|
||||||
try container.encodeIfPresent(accessibilityText, forKey: .accessibilityText)
|
try container.encodeIfPresent(accessibilityText, forKey: .accessibilityText)
|
||||||
try container.encodeIfPresent(fieldKey, forKey: .fieldKey)
|
|
||||||
try container.encodeIfPresent(groupName, forKey: .groupName)
|
|
||||||
try container.encode(readOnly, forKey: .readOnly)
|
|
||||||
|
|
||||||
try container.encode(inverted, forKey: .inverted)
|
|
||||||
try container.encode(showText, forKey: .showText)
|
try container.encode(showText, forKey: .showText)
|
||||||
try container.encodeIfPresent(onText, forKey: .onText)
|
try container.encodeIfPresent(onText, forKey: .onText)
|
||||||
try container.encodeIfPresent(offText, forKey: .offText)
|
try container.encodeIfPresent(offText, forKey: .offText)
|
||||||
@ -157,4 +111,19 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol {
|
|||||||
try container.encode(textWeight, forKey: .textWeight)
|
try container.encode(textWeight, forKey: .textWeight)
|
||||||
try container.encode(textPosition, forKey: .textPosition)
|
try container.encode(textPosition, forKey: .textPosition)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open override func isEqual(to model: any ModelComparisonProtocol) -> Bool {
|
||||||
|
guard super.isEqual(to: model), let model = model as? Self else { return false }
|
||||||
|
return selected == model.selected
|
||||||
|
&& animated == model.animated
|
||||||
|
&& action.isEqual(to: model.action)
|
||||||
|
&& alternateAction.isEqual(to: model.alternateAction)
|
||||||
|
&& accessibilityText == model.accessibilityText
|
||||||
|
&& showText == model.showText
|
||||||
|
&& onText == model.onText
|
||||||
|
&& offText == model.offText
|
||||||
|
&& textSize == model.textSize
|
||||||
|
&& textWeight == model.textWeight
|
||||||
|
&& textPosition == model.textPosition
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
12
MVMCoreUI/Atomic/Atoms/Views/Calendar.swift
Normal file
12
MVMCoreUI/Atomic/Atoms/Views/Calendar.swift
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
//
|
||||||
|
// Calendar.swift
|
||||||
|
// MVMCoreUI
|
||||||
|
//
|
||||||
|
// Created by Matt Bruce on 8/20/24.
|
||||||
|
// Copyright © 2024 Verizon Wireless. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import VDS
|
||||||
|
|
||||||
|
open class CalendarView: VDS.CalendarBase, VDSMoleculeViewProtocol
|
||||||
62
MVMCoreUI/Atomic/Atoms/Views/CalendarView.swift
Normal file
62
MVMCoreUI/Atomic/Atoms/Views/CalendarView.swift
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
//
|
||||||
|
// Calendar.swift
|
||||||
|
// MVMCoreUI
|
||||||
|
//
|
||||||
|
// Created by Matt Bruce on 8/20/24.
|
||||||
|
// Copyright © 2024 Verizon Wireless. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import VDS
|
||||||
|
|
||||||
|
open class CalendarView: VDS.CalendarBase, VDSMoleculeViewProtocol {
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Public Properties
|
||||||
|
//--------------------------------------------------
|
||||||
|
public var viewModel: CalendarViewModel!
|
||||||
|
public var delegateObject: MVMCoreUIDelegateObject?
|
||||||
|
public var additionalData: [AnyHashable : Any]?
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Public Methods
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
|
public func viewModelDidUpdate() {
|
||||||
|
if let _selectedDate = viewModel.selectedDate {
|
||||||
|
selectedDate = _selectedDate
|
||||||
|
}
|
||||||
|
|
||||||
|
if let _activeDates = viewModel.activeDates {
|
||||||
|
activeDates = _activeDates
|
||||||
|
}
|
||||||
|
|
||||||
|
if let _hideContainerBorder = viewModel.hideContainerBorder {
|
||||||
|
hideContainerBorder = _hideContainerBorder
|
||||||
|
}
|
||||||
|
|
||||||
|
if let _hideCurrentDateIndicator = viewModel.hideCurrentDateIndicator {
|
||||||
|
hideCurrentDateIndicator = _hideCurrentDateIndicator
|
||||||
|
}
|
||||||
|
|
||||||
|
if let _inactiveDates = viewModel.inactiveDates {
|
||||||
|
inactiveDates = _inactiveDates
|
||||||
|
}
|
||||||
|
|
||||||
|
if let _indicators = viewModel.indicators {
|
||||||
|
indicators = _indicators
|
||||||
|
}
|
||||||
|
|
||||||
|
if let _maxDate = viewModel.maxDate {
|
||||||
|
maxDate = _maxDate
|
||||||
|
}
|
||||||
|
|
||||||
|
if let _minDate = viewModel.minDate {
|
||||||
|
minDate = _minDate
|
||||||
|
}
|
||||||
|
|
||||||
|
surface = viewModel.surface
|
||||||
|
}
|
||||||
|
|
||||||
|
public func updateView(_ size: CGFloat) {}
|
||||||
|
|
||||||
|
}
|
||||||
153
MVMCoreUI/Atomic/Atoms/Views/CalendarViewModel.swift
Normal file
153
MVMCoreUI/Atomic/Atoms/Views/CalendarViewModel.swift
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
//
|
||||||
|
// CalendarModel.swift
|
||||||
|
// MVMCoreUI
|
||||||
|
//
|
||||||
|
// Created by Matt Bruce on 8/20/24.
|
||||||
|
// Copyright © 2024 Verizon Wireless. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import VDS
|
||||||
|
|
||||||
|
open class CalendarViewModel: MoleculeModelProtocol {
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Properties
|
||||||
|
//--------------------------------------------------
|
||||||
|
public static var identifier: String = "calendar"
|
||||||
|
public var id: String = UUID().uuidString
|
||||||
|
public var backgroundColor: Color?
|
||||||
|
|
||||||
|
public var dateFormatter: DateFormatter = {
|
||||||
|
let formatter = DateFormatter()
|
||||||
|
formatter.dateStyle = .medium
|
||||||
|
formatter.timeZone = NSTimeZone.system
|
||||||
|
formatter.locale = .current
|
||||||
|
formatter.formatterBehavior = .default
|
||||||
|
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 }
|
||||||
|
}
|
||||||
|
|
||||||
|
public var hideContainerBorder: Bool?
|
||||||
|
public var hideCurrentDateIndicator: Bool?
|
||||||
|
public var activeDates: [Date]?
|
||||||
|
public var inactiveDates: [Date]?
|
||||||
|
public var selectedDate: Date?
|
||||||
|
public var minDate: Date?
|
||||||
|
public var maxDate: Date?
|
||||||
|
public var indicators: [CalendarBase.CalendarIndicatorModel]?
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - VDS Properties
|
||||||
|
//--------------------------------------------------
|
||||||
|
public var surface: Surface { inverted ? .dark : .light }
|
||||||
|
public var inverted: Bool = false
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Keys
|
||||||
|
//--------------------------------------------------
|
||||||
|
private enum CodingKeys: String, CodingKey {
|
||||||
|
case id
|
||||||
|
case inverted
|
||||||
|
case dateFormat
|
||||||
|
case hideContainerBorder
|
||||||
|
case hideCurrentDateIndicator
|
||||||
|
case activeDates
|
||||||
|
case inactiveDates
|
||||||
|
case selectedDate
|
||||||
|
case minDate
|
||||||
|
case maxDate
|
||||||
|
case indicators
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Initializers
|
||||||
|
//--------------------------------------------------
|
||||||
|
public init() {}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Codec
|
||||||
|
//--------------------------------------------------
|
||||||
|
required public init(from decoder: Decoder) throws {
|
||||||
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
id = try container.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString
|
||||||
|
inverted = try container.decodeIfPresent(Bool.self, forKey: .inverted) ?? false
|
||||||
|
|
||||||
|
hideContainerBorder = try container.decodeIfPresent(Bool.self, forKey: .hideContainerBorder)
|
||||||
|
hideCurrentDateIndicator = try container.decodeIfPresent(Bool.self, forKey: .hideCurrentDateIndicator)
|
||||||
|
|
||||||
|
if let dateFormat = try container.decodeIfPresent(String.self, forKey: .dateFormat) {
|
||||||
|
self.dateFormat = dateFormat
|
||||||
|
dateFormatter.dateFormat = dateFormat
|
||||||
|
}
|
||||||
|
|
||||||
|
if let dates = try container.decodeIfPresent([String].self, forKey: .activeDates) {
|
||||||
|
activeDates = dates.compactMap { dateFormatter.date(from: $0) }
|
||||||
|
}
|
||||||
|
|
||||||
|
if let dates = try container.decodeIfPresent([String].self, forKey: .inactiveDates) {
|
||||||
|
inactiveDates = dates.compactMap { dateFormatter.date(from: $0) }
|
||||||
|
}
|
||||||
|
|
||||||
|
if let date = try container.decodeIfPresent(String.self, forKey: .selectedDate) {
|
||||||
|
selectedDate = dateFormatter.date(from: date)
|
||||||
|
}
|
||||||
|
|
||||||
|
if let date = try container.decodeIfPresent(String.self, forKey: .minDate) {
|
||||||
|
minDate = dateFormatter.date(from: date)
|
||||||
|
}
|
||||||
|
|
||||||
|
if let date = try container.decodeIfPresent(String.self, forKey: .maxDate) {
|
||||||
|
maxDate = dateFormatter.date(from: date)
|
||||||
|
}
|
||||||
|
|
||||||
|
indicators = try container.decodeIfPresent([CalendarBase.CalendarIndicatorModel].self, forKey: .indicators)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public func encode(to encoder: Encoder) throws {
|
||||||
|
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||||
|
try container.encode(id, forKey: .id)
|
||||||
|
try container.encode(inverted, forKey: .inverted)
|
||||||
|
try container.encode(dateFormat, forKey: .dateFormat)
|
||||||
|
try container.encode(hideContainerBorder, forKey: .hideContainerBorder)
|
||||||
|
try container.encode(hideCurrentDateIndicator, forKey: .hideCurrentDateIndicator)
|
||||||
|
try container.encode(activeDates, forKey: .activeDates)
|
||||||
|
try container.encode(selectedDate, forKey: .selectedDate)
|
||||||
|
try container.encode(minDate, forKey: .minDate)
|
||||||
|
try container.encode(maxDate, forKey: .maxDate)
|
||||||
|
try container.encode(indicators, forKey: .indicators)
|
||||||
|
}
|
||||||
|
|
||||||
|
open func isEqual(to model: any ModelComparisonProtocol) -> Bool {
|
||||||
|
guard let model = model as? Self else { return false }
|
||||||
|
return inverted == model.inverted
|
||||||
|
&& dateFormat == model.dateFormat
|
||||||
|
&& hideContainerBorder == model.hideContainerBorder
|
||||||
|
&& hideCurrentDateIndicator == model.hideCurrentDateIndicator
|
||||||
|
&& activeDates == model.activeDates
|
||||||
|
&& inactiveDates == model.inactiveDates
|
||||||
|
&& selectedDate == model.selectedDate
|
||||||
|
&& minDate == model.minDate
|
||||||
|
&& maxDate == model.maxDate
|
||||||
|
&& indicators == model.indicators
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension CalendarViewModel {
|
||||||
|
public func convertToVDSCalendarModel() -> DatePicker.CalendarModel {
|
||||||
|
let defaults = DatePicker.CalendarModel()
|
||||||
|
return .init(hideContainerBorder: hideContainerBorder ?? defaults.hideContainerBorder ,
|
||||||
|
hideCurrentDateIndicator: hideCurrentDateIndicator ?? defaults.hideCurrentDateIndicator,
|
||||||
|
activeDates: activeDates ?? defaults.activeDates,
|
||||||
|
inactiveDates: inactiveDates ?? defaults.inactiveDates,
|
||||||
|
selectedDate: selectedDate ?? defaults.selectedDate,
|
||||||
|
minDate: minDate ?? defaults.minDate,
|
||||||
|
maxDate: maxDate ?? defaults.maxDate,
|
||||||
|
indicators: indicators ?? defaults.indicators)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -64,7 +64,7 @@ import VDS
|
|||||||
|
|
||||||
//properties
|
//properties
|
||||||
isAnimated = viewModel.checkbox.animated
|
isAnimated = viewModel.checkbox.animated
|
||||||
isEnabled = viewModel.checkbox.enabled && !viewModel.checkbox.readOnly
|
isEnabled = viewModel.checkbox.isEnabled
|
||||||
|
|
||||||
//call super here to go around the didSet
|
//call super here to go around the didSet
|
||||||
//in this class
|
//in this class
|
||||||
@ -78,7 +78,7 @@ import VDS
|
|||||||
//TODO: Fix issue with default state
|
//TODO: Fix issue with default state
|
||||||
//showError = !isValid
|
//showError = !isValid
|
||||||
errorText = viewModel.checkbox.errorMessage
|
errorText = viewModel.checkbox.errorMessage
|
||||||
isEnabled = viewModel.checkbox.enabled
|
isEnabled = viewModel.checkbox.isEnabled
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -36,5 +36,36 @@ import VDS
|
|||||||
self.label = label
|
self.label = label
|
||||||
self.subTitle = subTitle
|
self.subTitle = subTitle
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open func isEqual(to model: any ModelComparisonProtocol) -> Bool {
|
||||||
|
guard let model = model as? Self else { return false }
|
||||||
|
return moleculeName == model.moleculeName
|
||||||
|
&& inverted == model.inverted
|
||||||
|
&& accessibilityText == model.accessibilityText
|
||||||
|
&& accessibilityIdentifier == model.accessibilityIdentifier
|
||||||
|
&& accessibilityTraits == model.accessibilityTraits
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Array where Element == CheckboxLabelModel {
|
||||||
|
internal func convertToVDSCheckboxItemModel(surface: Surface,
|
||||||
|
delegateObject: MVMCoreUIDelegateObject?,
|
||||||
|
additionalData: [AnyHashable: Any]?) -> [CheckboxGroup.CheckboxItemModel] {
|
||||||
|
return compactMap({ model in
|
||||||
|
var item = CheckboxGroup.CheckboxItemModel()
|
||||||
|
item.inputId = model.checkbox.fieldKey
|
||||||
|
item.labelText = model.label.text
|
||||||
|
if let attributes = model.label.attributes?.toVDSLabelAttributeModel(delegateObject: delegateObject, additionalData: additionalData) {
|
||||||
|
item.labelTextAttributes = attributes
|
||||||
|
}
|
||||||
|
item.childText = model.subTitle?.text
|
||||||
|
if let attributes = model.subTitle?.attributes?.toVDSLabelAttributeModel(delegateObject: delegateObject, additionalData: additionalData) {
|
||||||
|
item.childTextAttributes = attributes
|
||||||
|
}
|
||||||
|
item.surface = surface
|
||||||
|
item.selected = model.checkbox.selected
|
||||||
|
item.enabled = model.checkbox.isEnabled
|
||||||
|
return item
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -98,7 +98,7 @@ open class TooltipModel: MoleculeModelProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extension TooltipModel {
|
extension TooltipModel {
|
||||||
public func toVDSTooltipModel() -> Tooltip.TooltipModel {
|
public func convertToVDSTooltipModel() -> Tooltip.TooltipModel {
|
||||||
var moleculeView: MoleculeViewProtocol?
|
var moleculeView: MoleculeViewProtocol?
|
||||||
if let molecule, let view = ModelRegistry.createMolecule(molecule) {
|
if let molecule, let view = ModelRegistry.createMolecule(molecule) {
|
||||||
moleculeView = view
|
moleculeView = view
|
||||||
|
|||||||
@ -9,6 +9,7 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import VDS
|
import VDS
|
||||||
import VDSCoreTokens
|
import VDSCoreTokens
|
||||||
|
import MVMCore
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Codable Extensions
|
// MARK: - Codable Extensions
|
||||||
@ -57,6 +58,52 @@ extension VDS.Button.Size: RawRepresentableCodable {
|
|||||||
public static var defaultValue: VDS.Button.Size? { nil }
|
public static var defaultValue: VDS.Button.Size? { nil }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension VDS.CalendarBase.CalendarIndicatorModel: Codable, ModelComparisonProtocol, MoleculeModelComparisonProtocol {
|
||||||
|
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case label
|
||||||
|
case date
|
||||||
|
case dateFormat
|
||||||
|
}
|
||||||
|
|
||||||
|
public init(from decoder: any Decoder) throws {
|
||||||
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
let label = try container.decode(String.self, forKey: .label)
|
||||||
|
let formatter = Self.formatter()
|
||||||
|
formatter.dateFormat = try container.decodeIfPresent(String.self, forKey: .dateFormat) ?? "MMM d, y"
|
||||||
|
let foundDate = try container.decode(String.self, forKey: .date)
|
||||||
|
let date = formatter.date(from: foundDate)!
|
||||||
|
self = .init(label: label, date: date)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func encode(to encoder: any Encoder) throws {
|
||||||
|
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||||
|
try container.encode(label, forKey: .label)
|
||||||
|
try container.encode(Self.formatter().string(from: date), forKey: .date)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func formatter() -> DateFormatter {
|
||||||
|
let formatter = DateFormatter()
|
||||||
|
formatter.dateStyle = .medium
|
||||||
|
formatter.timeZone = NSTimeZone.system
|
||||||
|
formatter.locale = .current
|
||||||
|
formatter.formatterBehavior = .default
|
||||||
|
return formatter
|
||||||
|
}
|
||||||
|
|
||||||
|
public func isEqual(to model: any ModelComparisonProtocol) -> Bool {
|
||||||
|
guard let model = model as? Self else { return false }
|
||||||
|
return label == model.label
|
||||||
|
&& date == model.date
|
||||||
|
}
|
||||||
|
|
||||||
|
public func isVisuallyEquivalent(to model: any MoleculeModelComparisonProtocol) -> Bool {
|
||||||
|
guard let model = model as? Self else { return false }
|
||||||
|
return label == model.label
|
||||||
|
&& date == model.date
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Decodable Defaults
|
// MARK: - Decodable Defaults
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|||||||
@ -16,7 +16,7 @@ extension Array where Element: MVMCoreUI.LabelAttributeModel {
|
|||||||
var attributes: [any VDS.LabelAttributeModel] = []
|
var attributes: [any VDS.LabelAttributeModel] = []
|
||||||
forEach { atomicLabelAttribute in
|
forEach { atomicLabelAttribute in
|
||||||
if let attr = atomicLabelAttribute as? (any VDSLabelAttributeConvertable),
|
if let attr = atomicLabelAttribute as? (any VDSLabelAttributeConvertable),
|
||||||
let vds = attr.convertToVDSLabelAttirbute(delegateObject: delegateObject,
|
let vds = attr.convertToVDSLabelAttribute(delegateObject: delegateObject,
|
||||||
additionalData: additionalData){
|
additionalData: additionalData){
|
||||||
attributes.append(vds)
|
attributes.append(vds)
|
||||||
}
|
}
|
||||||
@ -28,12 +28,12 @@ extension Array where Element: MVMCoreUI.LabelAttributeModel {
|
|||||||
//VDS Convertable Protocol and Extensions
|
//VDS Convertable Protocol and Extensions
|
||||||
public protocol VDSLabelAttributeConvertable<LabelAttributeType> {
|
public protocol VDSLabelAttributeConvertable<LabelAttributeType> {
|
||||||
associatedtype LabelAttributeType: VDS.LabelAttributeModel
|
associatedtype LabelAttributeType: VDS.LabelAttributeModel
|
||||||
func convertToVDSLabelAttirbute(delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) -> LabelAttributeType?
|
func convertToVDSLabelAttribute(delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) -> LabelAttributeType?
|
||||||
}
|
}
|
||||||
|
|
||||||
extension LabelAttributeUnderlineModel: VDSLabelAttributeConvertable {
|
extension LabelAttributeUnderlineModel: VDSLabelAttributeConvertable {
|
||||||
|
|
||||||
public func convertToVDSLabelAttirbute(delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) -> UnderlineLabelAttribute? {
|
public func convertToVDSLabelAttribute(delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) -> UnderlineLabelAttribute? {
|
||||||
guard let style = UnderlineLabelAttribute.Style(rawValue: style.rawValue) else { return nil }
|
guard let style = UnderlineLabelAttribute.Style(rawValue: style.rawValue) else { return nil }
|
||||||
|
|
||||||
var pattern: UnderlineLabelAttribute.Pattern?
|
var pattern: UnderlineLabelAttribute.Pattern?
|
||||||
@ -50,7 +50,7 @@ extension LabelAttributeUnderlineModel: VDSLabelAttributeConvertable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extension LabelAttributeActionModel: VDSLabelAttributeConvertable {
|
extension LabelAttributeActionModel: VDSLabelAttributeConvertable {
|
||||||
public func convertToVDSLabelAttirbute(delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) -> ActionLabelAttribute? {
|
public func convertToVDSLabelAttribute(delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) -> ActionLabelAttribute? {
|
||||||
var vdsAttribute = VDS.ActionLabelAttribute(location: location, length: length)
|
var vdsAttribute = VDS.ActionLabelAttribute(location: location, length: length)
|
||||||
vdsAttribute.subscriber = vdsAttribute.action.sink { [weak self] in
|
vdsAttribute.subscriber = vdsAttribute.action.sink { [weak self] in
|
||||||
guard let self else { return }
|
guard let self else { return }
|
||||||
@ -64,7 +64,7 @@ extension LabelAttributeActionModel: VDSLabelAttributeConvertable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extension LabelAttributeFontModel: VDSLabelAttributeConvertable {
|
extension LabelAttributeFontModel: VDSLabelAttributeConvertable {
|
||||||
public func convertToVDSLabelAttirbute(delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) -> TextStyleLabelAttribute? {
|
public func convertToVDSLabelAttribute(delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) -> TextStyleLabelAttribute? {
|
||||||
|
|
||||||
var textStyle: TextStyle?
|
var textStyle: TextStyle?
|
||||||
if let found = style?.vdsTextStyle() {
|
if let found = style?.vdsTextStyle() {
|
||||||
@ -82,7 +82,7 @@ extension LabelAttributeFontModel: VDSLabelAttributeConvertable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extension LabelAttributeColorModel: VDSLabelAttributeConvertable {
|
extension LabelAttributeColorModel: VDSLabelAttributeConvertable {
|
||||||
public func convertToVDSLabelAttirbute(delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) -> ColorLabelAttribute? {
|
public func convertToVDSLabelAttribute(delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) -> ColorLabelAttribute? {
|
||||||
guard let textColor else { return nil }
|
guard let textColor else { return nil }
|
||||||
return ColorLabelAttribute(location: location,
|
return ColorLabelAttribute(location: location,
|
||||||
length: length,
|
length: length,
|
||||||
@ -91,14 +91,14 @@ extension LabelAttributeColorModel: VDSLabelAttributeConvertable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extension LabelAttributeStrikeThroughModel: VDSLabelAttributeConvertable {
|
extension LabelAttributeStrikeThroughModel: VDSLabelAttributeConvertable {
|
||||||
public func convertToVDSLabelAttirbute(delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) -> StrikeThroughLabelAttribute? {
|
public func convertToVDSLabelAttribute(delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) -> StrikeThroughLabelAttribute? {
|
||||||
return StrikeThroughLabelAttribute(location: location,
|
return StrikeThroughLabelAttribute(location: location,
|
||||||
length: length)
|
length: length)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension LabelAttributeImageModel: VDSLabelAttributeConvertable {
|
extension LabelAttributeImageModel: VDSLabelAttributeConvertable {
|
||||||
public func convertToVDSLabelAttirbute(delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) -> AtomicImageLabelAttribute? {
|
public func convertToVDSLabelAttribute(delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) -> AtomicImageLabelAttribute? {
|
||||||
var frame: CGRect?
|
var frame: CGRect?
|
||||||
if let size {
|
if let size {
|
||||||
frame = CGRect(x: 0, y: 0, width: size, height: size)
|
frame = CGRect(x: 0, y: 0, width: size, height: size)
|
||||||
|
|||||||
@ -106,7 +106,7 @@ import VDS
|
|||||||
}
|
}
|
||||||
|
|
||||||
//properties
|
//properties
|
||||||
isEnabled = viewModel.radioButton.enabled && !viewModel.radioButton.readOnly
|
isEnabled = viewModel.radioButton.isEnabled
|
||||||
isSelected = viewModel.radioButton.state
|
isSelected = viewModel.radioButton.state
|
||||||
|
|
||||||
//forms
|
//forms
|
||||||
|
|||||||
@ -40,5 +40,36 @@ import VDS
|
|||||||
self.label = label
|
self.label = label
|
||||||
self.subTitle = subTitle
|
self.subTitle = subTitle
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open func isEqual(to model: any ModelComparisonProtocol) -> Bool {
|
||||||
|
guard let model = model as? Self else { return false }
|
||||||
|
return moleculeName == model.moleculeName
|
||||||
|
&& inverted == model.inverted
|
||||||
|
&& accessibilityText == model.accessibilityText
|
||||||
|
&& accessibilityIdentifier == model.accessibilityIdentifier
|
||||||
|
&& accessibilityTraits == model.accessibilityTraits
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Array where Element == RadioButtonLabelModel {
|
||||||
|
internal func convertToVDSRadioButtonItemModel(surface: Surface,
|
||||||
|
delegateObject: MVMCoreUIDelegateObject?,
|
||||||
|
additionalData: [AnyHashable: Any]?) -> [RadioButtonGroup.RadioButtonItemModel] {
|
||||||
|
return compactMap({ model in
|
||||||
|
var item = RadioButtonGroup.RadioButtonItemModel()
|
||||||
|
item.inputId = model.radioButton.fieldKey
|
||||||
|
item.labelText = model.label.text
|
||||||
|
if let attributes = model.label.attributes?.toVDSLabelAttributeModel(delegateObject: delegateObject, additionalData: additionalData) {
|
||||||
|
item.labelTextAttributes = attributes
|
||||||
|
}
|
||||||
|
item.childText = model.subTitle?.text
|
||||||
|
if let attributes = model.subTitle?.attributes?.toVDSLabelAttributeModel(delegateObject: delegateObject, additionalData: additionalData) {
|
||||||
|
item.childTextAttributes = attributes
|
||||||
|
}
|
||||||
|
item.surface = surface
|
||||||
|
item.selected = model.radioButton.state
|
||||||
|
item.enabled = model.radioButton.isEnabled
|
||||||
|
return item
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -70,3 +70,43 @@ public extension Optional where Wrapped: Collection {
|
|||||||
return self.isVisuallyEquivalent(to: models)
|
return self.isVisuallyEquivalent(to: models)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func == (lhs: (any MoleculeModelComparisonProtocol)?, rhs: (any MoleculeModelComparisonProtocol)?) -> Bool {
|
||||||
|
switch (lhs, rhs) {
|
||||||
|
case (.some(let lhs), .some(let rhs)):
|
||||||
|
return lhs.isEqual(to: rhs)
|
||||||
|
case (.none, .none):
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func != (lhs: (any MoleculeModelComparisonProtocol)?, rhs: (any MoleculeModelComparisonProtocol)?) -> Bool {
|
||||||
|
return !(lhs == rhs)
|
||||||
|
}
|
||||||
|
|
||||||
|
func == (lhs: [any MoleculeModelComparisonProtocol]?, rhs: [any MoleculeModelComparisonProtocol]?) -> Bool {
|
||||||
|
switch (lhs, rhs) {
|
||||||
|
case (.some(let lhs), .some(let rhs)):
|
||||||
|
return lhs == rhs
|
||||||
|
case (.none, .none):
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func != (lhs: [any MoleculeModelComparisonProtocol]?, rhs: [any MoleculeModelComparisonProtocol]?) -> Bool {
|
||||||
|
return !(lhs == rhs)
|
||||||
|
}
|
||||||
|
|
||||||
|
func == (lhs: [any MoleculeModelComparisonProtocol], rhs: [any MoleculeModelComparisonProtocol]) -> Bool {
|
||||||
|
return lhs.elementsEqual(rhs, by: { (lhsElement, rhsElement) -> Bool in
|
||||||
|
return lhsElement == rhsElement
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func != (lhs: [any MoleculeModelComparisonProtocol], rhs: [any MoleculeModelComparisonProtocol]) -> Bool {
|
||||||
|
return !(lhs == rhs)
|
||||||
|
}
|
||||||
|
|||||||
@ -14,10 +14,12 @@ import MVMCore
|
|||||||
///-----------------------------------------------------------------------------
|
///-----------------------------------------------------------------------------
|
||||||
public protocol VDSMoleculeViewProtocol: MoleculeViewProtocol, MVMCoreViewProtocol {
|
public protocol VDSMoleculeViewProtocol: MoleculeViewProtocol, MVMCoreViewProtocol {
|
||||||
associatedtype ViewModel: MoleculeModelProtocol
|
associatedtype ViewModel: MoleculeModelProtocol
|
||||||
|
var shouldUpdateView: Bool { get set }
|
||||||
var viewModel: ViewModel! { get set }
|
var viewModel: ViewModel! { get set }
|
||||||
var delegateObject: MVMCoreUIDelegateObject? { get set }
|
var delegateObject: MVMCoreUIDelegateObject? { get set }
|
||||||
var additionalData: [AnyHashable: Any]? { get set }
|
var additionalData: [AnyHashable: Any]? { get set }
|
||||||
func viewModelDidUpdate()
|
func viewModelDidUpdate()
|
||||||
|
func setNeedsUpdate()
|
||||||
}
|
}
|
||||||
|
|
||||||
extension VDSMoleculeViewProtocol {
|
extension VDSMoleculeViewProtocol {
|
||||||
@ -32,7 +34,10 @@ extension VDSMoleculeViewProtocol {
|
|||||||
self.delegateObject = delegateObject
|
self.delegateObject = delegateObject
|
||||||
self.additionalData = additionalData
|
self.additionalData = additionalData
|
||||||
viewModel = castedModel
|
viewModel = castedModel
|
||||||
|
shouldUpdateView = false
|
||||||
viewModelDidUpdate()
|
viewModelDidUpdate()
|
||||||
|
shouldUpdateView = true
|
||||||
|
setNeedsUpdate()
|
||||||
}
|
}
|
||||||
|
|
||||||
public func update(viewModel: ViewModel){
|
public func update(viewModel: ViewModel){
|
||||||
|
|||||||
@ -41,6 +41,7 @@ open class CoreUIModelMapping: ModelMapping {
|
|||||||
ModelRegistry.register(handler: ButtonGroup.self, for: ButtonGroupModel.self)
|
ModelRegistry.register(handler: ButtonGroup.self, for: ButtonGroupModel.self)
|
||||||
|
|
||||||
// MARK:- Entry Field
|
// MARK:- Entry Field
|
||||||
|
ModelRegistry.register(handler: DatePickerEntryField.self, for: DatePickerEntryFieldModel.self)
|
||||||
ModelRegistry.register(handler: InputEntryField.self, for: TextEntryFieldModel.self)
|
ModelRegistry.register(handler: InputEntryField.self, for: TextEntryFieldModel.self)
|
||||||
ModelRegistry.register(handler: MdnEntryField.self, for: MdnEntryFieldModel.self)
|
ModelRegistry.register(handler: MdnEntryField.self, for: MdnEntryFieldModel.self)
|
||||||
ModelRegistry.register(handler: DigitEntryField.self, for: DigitEntryFieldModel.self)
|
ModelRegistry.register(handler: DigitEntryField.self, for: DigitEntryFieldModel.self)
|
||||||
@ -50,8 +51,10 @@ open class CoreUIModelMapping: ModelMapping {
|
|||||||
|
|
||||||
// MARK:- Selectors
|
// MARK:- Selectors
|
||||||
ModelRegistry.register(handler: RadioButton.self, for: RadioButtonModel.self)
|
ModelRegistry.register(handler: RadioButton.self, for: RadioButtonModel.self)
|
||||||
|
ModelRegistry.register(handler: RadioButtons.self, for: RadioButtonsModel.self)
|
||||||
ModelRegistry.register(handler: RadioBoxes.self, for: RadioBoxesModel.self)
|
ModelRegistry.register(handler: RadioBoxes.self, for: RadioBoxesModel.self)
|
||||||
ModelRegistry.register(handler: Checkbox.self, for: CheckboxModel.self)
|
ModelRegistry.register(handler: Checkbox.self, for: CheckboxModel.self)
|
||||||
|
ModelRegistry.register(handler: Checkboxes.self, for: CheckboxesModel.self)
|
||||||
ModelRegistry.register(handler: RadioSwatches.self, for: RadioSwatchesModel.self)
|
ModelRegistry.register(handler: RadioSwatches.self, for: RadioSwatchesModel.self)
|
||||||
ModelRegistry.register(handler: Tags.self, for: TagsModel.self)
|
ModelRegistry.register(handler: Tags.self, for: TagsModel.self)
|
||||||
ModelRegistry.register(handler: Tag.self, for: TagModel.self)
|
ModelRegistry.register(handler: Tag.self, for: TagModel.self)
|
||||||
@ -60,6 +63,7 @@ open class CoreUIModelMapping: ModelMapping {
|
|||||||
ModelRegistry.register(handler: Star.self, for: StarModel.self)
|
ModelRegistry.register(handler: Star.self, for: StarModel.self)
|
||||||
|
|
||||||
// MARK:- Other Atoms
|
// MARK:- Other Atoms
|
||||||
|
ModelRegistry.register(handler: CalendarView.self, for: CalendarViewModel.self)
|
||||||
ModelRegistry.register(handler: ProgressBar.self, for: ProgressBarModel.self)
|
ModelRegistry.register(handler: ProgressBar.self, for: ProgressBarModel.self)
|
||||||
ModelRegistry.register(handler: MultiProgress.self, for: MultiProgressBarModel.self)
|
ModelRegistry.register(handler: MultiProgress.self, for: MultiProgressBarModel.self)
|
||||||
ModelRegistry.register(handler: CaretView.self, for: CaretViewModel.self)
|
ModelRegistry.register(handler: CaretView.self, for: CaretViewModel.self)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user